Visitar URL original
The guard reported zero on 32 French values: short noun phrases were invisible (ZED-69) by Zedzed75 · Pull Request #58 · Zedzed75/forge · GitHub
Skip to content

The guard reported zero on 32 French values: short noun phrases were invisible (ZED-69) - #58

Merged
Zedzed75 merged 2 commits into
masterfrom
test/french-noun-phrase-signal
Oct 8, 2026
Merged

Zedzed75 merged 2 commits into
masterfrom
test/french-noun-phrase-signal

Conversation

@Zedzed75

@Zedzed75 Zedzed75 commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Closes ZED-69. Rebased onto master and retargeted after #54 was squash-merged.

ZED-50's [baseline] is empty and its docstring read that as "tests/ carries
exactly one French line". True of what the two signals detect, false of the
tree: ten test modules hold short French noun phrases — the description and
owner values that get copied verbatim into the golden trees — that both
signals call clean. Boutique en ligne has no accent and one function word;
Equipe Plateforme has neither. ZED-27 and ZED-60 found every one of them by
reading diffs.

The third signal

Lowering MIN_WORDS_PER_LINE to 1 is not on the table — ZED-50 tried it and got
75 English false positives. So nouns changes both halves at once: a different
list, read in a narrower place.

  • CONTENT_WORDS is French nouns and adjectives with no English spelling,
    where FUNCTION_WORDS is grammar. REJECTED_CONTENT_WORDS records the
    candidates left out and why — demonstration, service and catalogue
    because they are spelled the same in both languages, and boutique because
    it is the fixture service name in some 60 paths, hostnames and slugs.
  • _prose_values reads only the value side of a line (quoted spans, plus
    unquoted key: value so a French default in a plugin template counts) and
    drops anything identifier-shaped — no uppercase, no whitespace. That filter is
    what makes a threshold of one content word safe, and what keeps
    "name": "boutique", plateforme@example.net, helm/charts/boutique/ and
    fins-de-ligne.txt out of a signal that does not own renaming them.

The measurement

Run over the blobs at the ZED-60 merge base (master @ e2a81e5, unchanged on
master @ 068c1e0): 32 lines across ten test modules, and nothing anywhere
else
— zero in src/forge/**/*.py, zero in every plugin template, zero in the
other nine test modules. Not one false positive.

tests/french_values_pre_zed60.txt holds those 32 lines verbatim, and
test_every_pre_zed60_french_value_fires asserts each one is exactly
{NOUNS} — which pins that the signal is new information rather than a third
reading of something accent or words already caught.

The issue says 22 lines across eleven modules; the fixture header reconciles
that against the machine's 32 across ten, rather than quietly picking one.

What it still cannot see

ZED-69 happened because an empty [baseline] was read as "no French here", so
that is now written down rather than left to be rediscovered: the module
docstring has a "What none of the three detects" section,
test_the_value_blind_spots_are_known pins it on real lines, and
french_baseline.txt points at it before the data. The known gaps are French
values that are only identifiers ("Boutique_Web" — ZED-59's scope), phrases
built only from words spelled the same in English, and a noun broken by a string
concatenation.

This PR is correct and early: it needs #57, and only #57

test_no_french_outside_the_baseline fails here on the 32 real French lines.
The D6 matrix run on ZED-74 confirmed it 3/3, and the conclusion was right —
this lands after the translations. Adding those 32 lines to [baseline] would
invert the mechanism the PR exists to build, so they are not there and
[baseline] is still empty.

Measured, not assumed: splicing #57 alone (ZED-60, the eleven inline-spec
modules) into this branch gives unknown (path, signal): [] across 267 scanned
files, with every allowlist entry still matching something.

ZED-74 sequenced this behind #55, #57, #60 and #46. Only #57 is load-bearing
for the gate — #55 (ZED-27) touches tests/golden/**, tests/specs/*.yml and
tests/fingerprints/*.json, none of which any SCANNED_GLOBS entry matches
(tests/**/*.py is the only tests/ glob), and #60 and #46 touch files the
signal already reports clean. That is a note for the sequencer, not a request to
jump the queue: #57 has not merged either, so the order costs nothing.

🤖 Generated with Claude Code

@Zedzed75
Zedzed75 force-pushed the test/french-regression-guard branch from 62a11da to 5ac08a2 Compare October 8, 2026 21:58
@Zedzed75
Zedzed75 force-pushed the test/french-noun-phrase-signal branch from 8860b62 to 0b98cbf Compare October 8, 2026 22:04
@Zedzed75
Zedzed75 changed the base branch from test/french-regression-guard to master October 8, 2026 22:04
Zedzed75 and others added 2 commits October 9, 2026 00:24
ZED-50 shipped two signals and an empty `[baseline]`, and its docstring read
that as "`tests/` carries exactly one French line". The claim was true of what
the signals detect and false of the tree: eleven test modules held short French
noun phrases -- `description` and `owner` values -- that both signals call
clean. `Boutique en ligne` has no accent and one function word; `Equipe
Plateforme` has neither. ZED-27 and ZED-60 found every one of them by reading
the diff.

Lowering `MIN_WORDS_PER_LINE` to 1 is not available: ZED-50 tried it and got 75
English false positives. So the third signal changes both halves at once -- a
different list, read in a narrower place:

- `CONTENT_WORDS` is French nouns and adjectives with no English spelling,
  where `FUNCTION_WORDS` is grammar. `REJECTED_CONTENT_WORDS` records the
  candidates left out and why, `boutique` above all: it is the fixture service
  name and appears in some 60 paths, hostnames and slugs.
- `_prose_values` reads only the value side of a line -- quoted spans, plus
  unquoted `key: value` so a French default in a plugin template counts -- and
  drops anything identifier-shaped. That filter is what makes a threshold of
  one content word safe, and what keeps `"name": "boutique"` and
  `fins-de-ligne.txt` out of a signal that does not own renaming them.

Measured on the pre-ZED-60 blobs: 32 lines across ten modules, zero elsewhere.
Nothing in `src/forge/` or any plugin template fires, so `[baseline]` stays
empty. `french_values_pre_zed60.txt` holds those 32 lines verbatim and
`test_every_pre_zed60_french_value_fires` asserts each one is `{NOUNS}` --
which pins that the signal is new information, not a third reading of something
`accent` or `words` already had.

The docstring now also lists what none of the three signals can see, since
ZED-69 happened because an empty `[baseline]` was read as "no French here".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both documents that explain the guard to a reader said "two signals" and
stopped there. Nothing told you that an empty `[baseline]` is a statement about
what the signals detect rather than about the tree -- which is exactly the
inference that let 32 French values sit in `tests/` for the length of ZED-50.

`french_baseline.txt` now points at the blind-spot list before the data, and
records why the section is *still* empty after a signal that fires on 32 lines:
ZED-60 translated them. A new signal is allowed to find French; it is not
allowed to park it here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Zedzed75
Zedzed75 force-pushed the test/french-noun-phrase-signal branch from 0b98cbf to ff6d1ea Compare October 8, 2026 22:29
@Zedzed75

Zedzed75 commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

D6 local matrix: 3/3 PASS — re-sequenced after the translations

Evidence under ZED-74 / decision D6, because Actions assigns no runner (ZED-66).

  • Commit tested: ff6d1ea (test/french-noun-phrase-signal, rebased onto master at 3efc873)
  • Runner: ./scripts/docker-matrix.sh --ref test/french-noun-phrase-signal — Docker 29.8.0, OSType=linux, Ubuntu 24.04, Python 3.11/3.12/3.13, FORGE_REQUIRE_TOOLS=1
Python 3.11  PASS  774 passed, 2 skipped in 204.03s
Python 3.12  PASS  774 passed, 2 skipped in 212.29s
Python 3.13  PASS  774 passed, 2 skipped in 208.66s

All 12 integration tests ran across the five domains; the only skips are the 2 non-integration ones CI also reports.

Why this was not merged in the originally planned position

Run against master with only #54 in, this was 3/3 FAIL: test_no_french_outside_the_baseline found 32 French lines in tests/*.py inline spec prose across 8 files — the new noun-phrase signal working correctly on French that #55 and #57 owned. The baseline could not absorb them, because by this guard's own doctrine it only ever shrinks. So the order became #54 → #55 → #57 → #60 → #58, and the PR goes green unchanged in that position.

Rebase note: #54 was squash-merged, so git rebase --onto origin/master 62a11da is the incantation here, not git rebase origin/master.

@Zedzed75
Zedzed75 merged commit eb7e2a9 into master Oct 8, 2026
0 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant