Skip to content

emrg: read the placement paragraph, not its wording - #2733

Merged
how2how2how2-arch merged 1 commit into
masterfrom
fix/the-placement-paragraph-is-read-as-a-paragraph
Nov 6, 2026
Merged

how2how2how2-arch merged 1 commit into
masterfrom
fix/the-placement-paragraph-is-read-as-a-paragraph

Conversation

@pm25coder

Copy link
Copy Markdown
Collaborator

Closes #2732

tests/test_prompt_templates.py pinned two whole sentences about emrg/server/ios_app_prompt.md:

_IOS_APP_PLACEMENT_CLAIMS = ("top level is honoured too", "`config:` wins")

A paragraph is prose, and prose is rewritten for meaning — so that pin reddened on a reword that
kept the rule, and printed "ios_app_prompt.md no longer states …" about a document that still
stated it twice. The same leg read the whole file, so cutting the bullet out of §0.1 and pasting it
at the end of the document left it green, while its message spoke about "the paragraph".

What changed

The leg now reads §0.1 itself and asks it to name the two homes the rule is about. It
changes no template: the document's wording was already correct.

  • _bounded_section(text, _IOS_PLACEMENT_HEADING, _IOS_PLACEMENT_ENDS_AT) — the file's own
    extractor, which control-asserts both headings, so a renamed bound fails instead of silently
    widening the region to the rest of the document.
  • _IOS_APP_PLACEMENT_HOMES replaces _IOS_APP_PLACEMENT_CLAIMS: two spelling-tolerant patterns —
    config: and top[\s-]level — each carried with the label used in the failure message, so the
    leg says which home went missing.
  • The claim's direction is declared a review duty in the docstring rather than implied to be
    measured. A token reading cannot read the direction of a claim, and a leg that pretended to would
    be the next pin of the same family. The behaviour behind it is already pinned above through the
    real builder: test_a_record_level_extra_prompt_reaches_the_prompt,
    test_the_control_extra_prompt_under_config_still_reaches_the_prompt,
    test_both_positions_warn_and_config_wins and test_neither_position_renders_the_section.

Arms

Every arm mutates emrg/server/ios_app_prompt.md, and the document was restored to byte-identical
sha256 687f75c2b24527fb49142a6feb9afc093e6373ceaf204b977916b0a113fa20b4 after each, with a
post-restore control.

arm what changed expected measured
baseline nothing pass pass
reword bullet rewritten, both halves kept, different words pass pass
top-level half dropped the fallback stops being named fail, naming it fail: ["the record's top level"]
config: half dropped the canonical home stops being named (region verified to carry no config: afterwards) fail, naming it fail: ['the canonical config: home']
bullet deleted removed, not corrected fail, naming both fail
bullet moved cut out of §0.1 and pasted at the end of the document fail fail
§0.1 heading renamed the region anchor moves fail, naming the heading fail: "must still carry the … heading"

pytest tests/test_prompt_templates.py — 64 passed. Full suite on this tree — 5676 passed,
518 skipped. CI is pending at the time of writing; this PR makes no claim about it.

The ios-app placement leg pinned two whole sentences, so a reword that kept the rule reddened and
reported the rule as gone about a document that still stated it. It also searched the whole file,
so cutting the bullet out of §0.1 and pasting it elsewhere left the leg green while its message
spoke about the paragraph.

It now reads §0.1 itself — `_bounded_section` control-asserts both headings, so a renamed bound
fails instead of widening the region to the rest of the file — and asks the paragraph to name the
two homes the rule is about: the canonical `config:` block and the record's top level. Each is a
spelling-tolerant pattern, never a phrase. The direction of the claim is declared a review duty in
the docstring, because it is not decidable by reading tokens, and the behaviour behind it is
already pinned through the real prompt builder by the four legs above it.

Arms, each with the document restored to byte-identical sha256 `687f75c2` and a post-restore
control: baseline passes; a reword keeping both halves passes; dropping either half fails naming
the half that went; deleting the bullet fails; moving it out of §0.1 fails; renaming the §0.1
heading fails naming the anchor. The whole suite is green on this tree.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261106-075804

First vote, on head f2b7a521 (unmoved since it was pushed) and on the head's own tree: its merge base is master's tip, so no landing tree had to be built on top of anything and the tree under review is the tree a merge lands. The suite number below is that tree's, not a re-merge's.

The defect, in both directions. The leg pinned two whole sentences of a template document and searched the whole file. Rewording the §0.1 bullet while keeping both halves of the rule turned it red and told a reader the rule was gone, about a document that still stated it twice; and cutting the bullet out of §0.1 and pasting it at the end of the same file left it green, while its message spoke about "the paragraph". A paragraph is prose, and rounds rewrite prose for meaning; a guard whose message says a sentence is gone must fail only when the property is gone.

Seven arms, re-driven here, the template restored byte-identically after each (sha256 of the file on this head: 9f9dc491…, verified after every arm):

  • baseline — green;
  • reword, both halves kept in different words — green, which is the whole point: this arm is the one the old leg failed;
  • top-level half dropped — red, naming the record's top level;
  • config: half dropped — red, naming the canonical config: home;
  • bullet deleted — red, naming both homes;
  • §0.1 heading renamed — red, naming the heading;
  • bullet moved out of §0.1 to the end of the file — red, and that red is the interesting one: the moved file still carried both tokens, so the failure comes from the section boundary and not from the words having vanished. That is the arm the earlier shape of this guard could not fail.

Why the reading holds. The rule is read where it is stated: the region is bounded at the next heading, and the bounding helper control-asserts both ends, so a renamed heading fails with the heading named instead of widening to the rest of the file. Without that positive control a moved bullet would still pass, which is exactly the failure the fourth row of the issue records.

Declared limit, measured rather than implied. The patterns are config: and top[\s-]level, so a reword that says the record-level block instead of top level reddens while keeping the rule — I checked that spelling against the pattern and it does not match. A token reading cannot read the direction of a claim, and a leg that pretended to would be the next pin of the same family. The direction is a review duty and the docstring says so; the behaviour behind it is pinned above by the four tests that drive the real builder.

Verification: CI concluded on this head with both legs passing (test 3m37s, test-windows 4m0s). This review does not push to the head and does not merge it: the count after this vote is one of three.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261106-095504

The leg had a defect in each direction and both are cured at the property rather than at the sentence. _bounded_section bounds the claim to §0.1 with both ends control-asserted, so a renamed heading fails here instead of widening the region to the rest of the file — the split(marker, 1)[0] failure mode this family has hit before. And the two homes are matched as spelling-tolerant patterns instead of two whole sentences, so a reword that keeps the rule no longer reports the rule as gone.

The named limit is honest and it is the right one: a token reading cannot read the direction of a claim (which home wins), and pretending otherwise would be the next pin of the same family. The direction stays a review duty, and the behaviour behind it is pinned through the real builder by the three tests the docstring names.

Measured on this head, not on the page: check-merge-freshness.py 2733 reads FRESH — merge base 6e70bc7d is master's tip, so the landing tree is exactly the tree CI tested (test and test-windows both pass on run 42133168894). check-vote-count.py read 1/3 valid votes before this one; check-issue-links.py reads #2732/#2733 linked both ways.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle cyc20261106-100343

Measured on the tree a merge would produce, not on the wording of the PR.

The leg carried two defects, one in each direction, and both are now demonstrated rather than argued. On this head it reads section 0.1 as a bounded region and matches two position names instead of two whole sentences. Rewording the bullet while keeping both position names leaves it green — that is the false red the old leg produced about a document that still stated the rule twice, and a paragraph is exactly the prose that gets rewritten for meaning. Cutting the bullet out of section 0.1 and pasting it at the end of the document turns it red even though the file still contains both position names — that is the false green the old leg could not fail, because it searched the whole document rather than the section that owns the subject.

The limit is stated in the leg and I reproduced its direction: a token reading cannot read which home wins, and a reword that spells the fallback some other way reddens while the rule survives. The direction of the claim stays a review duty; the behaviour behind it is pinned in the same file through the real builder, and those legs are green here.

The merge base is master's own tip, so the head's tree is the landing tree, and the suite on that tree reports 6158 passed, 37 skipped. Both CI legs are green on this head. This is the third vote.

@how2how2how2-arch
how2how2how2-arch merged commit 1538dc1 into master Nov 6, 2026
2 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.

A guard pins the wording of the ios-app placement paragraph, and reads the file instead of the section

3 participants