Skip to content

Mirror stated structure instead of asking, and keep the user's negation - #3

Merged
nhyiramante1 merged 6 commits into
mainfrom
fix/mirror-polarity-and-structure-prompt
Oct 4, 2026
Merged

nhyiramante1 merged 6 commits into
mainfrom
fix/mirror-polarity-and-structure-prompt

Conversation

@nhyiramante1

Copy link
Copy Markdown
Contributor

Summary

Two fixes to how the coach mirrors what the user says.

Stated structure is mirrored, not questioned (prompt). When the user lays out a list, an outline, first/second points, or a relationship word ("because", "leads to", "under", "part of"), the coach now mirrors it in that turn instead of asking about it. Each stated idea gets its own claim. A hierarchy or connection claim is added only where the relationship and both ideas sit in one Source Bank sentence or list line, as the gateway already requires. The rule holds at every assistance level and Think/Map setting. It takes precedence over the turn-shape, pacing and reflection-rhythm facts, and yields to an explicit user request. Related wording:

  • "Large turn → ask" now applies only to turns that don't state their structure.
  • At L0, "one recorded user moment" now explicitly means one user turn, which can contain several sentences and claims.

Mirrors keep the user's negation (validator). Negation words were free glue in lexical grounding, so a mirror could add or drop a "not" and reverse the user's meaning while every content word matched. A new polarity check requires a claim to use exactly the negation words of the userPhrases and relationSpan it cites.

  • It verifies pointers, not meaning: there is no regex, no clause parsing and no idiom list, so negation elsewhere in the user's sentence never blocks a mirror.
  • Inside this check, "isn't", "is not" and "isnt" compare equal. Lexical grounding still requires the user's own spelling, as on main.
  • The failure message and grounded-recap rejections carry a specific repair hint. The prompt asks the model to keep negating words in its pointers and to cite only the words it reproduces.
  • Known gap: a negation dropped by citing the words on either side of it is not caught. Per-chunk user confirmation covers it. English only.

docs/airtightness-report.md records the new constraint.

Behavior change

  • Mirrors of explicitly stated structure should arrive on the first turn instead of a clarifying question. This is prompt-only and not yet measured against the live model.
  • A mirror is rejected if it adds or drops a negation inside its cited phrases, or if it cites a wider phrase that carries a negation the mirror leaves out. The repair call receives the hint; a test shows the narrower pointer passing on call 2 without reaching the forced question.

Testing

  • npm test: 393 passed. New polarity tests in validator.test.ts, repair-ladder and recap-hint tests in stage1-loop.test.ts, and prompt assertions in api.test.ts.
  • npx tsc --noEmit, npm run build:pages and npm run verify:pages pass.

Suggest squash-merging; the branch history includes an earlier version of the polarity check that later commits replace.

🤖 Generated with Claude Code

nhyiramante1 and others added 6 commits October 3, 2026 19:42
Negators are function words, so lexical and span grounding both ignored them:
"Money is not the main problem" validated as a mirror of "Money is the main
problem", and a mirror could drop a "never" by citing the words on either side
of it.

Add a third per-claim check, polarity: a claim must be negated exactly when its
cited wording is. Cited wording counts as negated if the userPhrase contains a
negator or one appears in the two tokens just before it in the cited utterance.
English only; Chinese negation characters also occur inside non-negative words,
so a token list would misfire. A polarity failure follows the existing
reflection_validation_failed repair path, with a message naming the fix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ut it

The prompt told the model to "favor one focusing question" for any large or
abstract turn, and the context labels most outlines "large" (>=4 sentences or
>=45 content words). Combined with sentence-level relation grounding, an
outline usually couldn't be mirrored completely, so the coach asked instead.

- New level-independent STATED STRUCTURE section: when the user lays out
  structure explicitly, mirror it that turn, one claim per idea, plus a
  relationship claim wherever the relationship and both ideas share one Source
  Bank sentence (it now says each [id] is one sentence). A relationship spread
  across sentences is left for the user, without blocking the rest of the
  mirror. Don't ask the user to restate what they already said clearly; turn
  length alone is never a reason to ask.
- The large-turn rule now applies only to turns that don't state their
  structure, and only when no mirror of the main points is possible.
- The L0 objective points at the new section.

Grounding, contract and confirmation rules are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- State precedence: the rule holds at every assistance level and Think/Map
  setting and outranks the turn-shape, map-pacing and reflection-rhythm facts.
  The slider (default 25, Think-leaning) told the model to "tune conversational
  eagerness", which pulled against mirroring.
- Clarify L0's "one recorded user moment" as one user turn that may contain
  several sentences and claims, so a multi-claim mirror of one turn doesn't
  read as forbidden.
- Lines of a list are their own Source Bank entries too (segmentation splits
  on newlines), so say "one sentence, or one line of a list".
- Defer to an explicit user request for something else (e.g. "Go deeper").

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The first polarity check read a two-token window before the cited phrase and
treated every standalone "t" as a negator. That rejected faithful mirrors
("Not only money matters…", "Without delay, submit the draft", "Section T: …"),
and two such rejections force a question, the outcome this branch is meant
to prevent. Growing it into clause and idiom handling would put the kind of
keyword bank that docs/refactor-plan.md §1.0 removed back into the
enforcement path.

Now negation words are simply taken out of the free-glue exemption: a claim
must use exactly the negation words of the userPhrases it cites (n't, "not"
and apostrophe-less spellings compare equal; n't is expanded with a literal
split, no regex). This catches an added negation and one dropped from inside
a cited phrase. A negation dropped by citing the words around it is a
documented gap covered by per-chunk user confirmation.

Also forwards the polarity hint on grounded-recap rejections, adds a prompt
line telling the model to cite negating words, and records the constraint in
docs/airtightness-report.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Spelling equivalence (isn't = is not) holds only inside the polarity check;
lexical grounding still requires the user's own spelling, exactly as on
main. Tests now assert the full validator result, pin that end-to-end
behavior, and the prompt asks the model to keep the user's spelling.

A pointer wider than the claim that carries a negation the claim leaves out
("Not only money matters" cited for "money matters") is rejected by the
polarity check. The prompt and repair note now ask for the narrower pointer,
and a stage1-loop test shows that rejection repairing on call 2 without
reaching the forced question. Another stage1-loop test pins the polarity
note in grounded-recap rejections.

Docs row clarified: equivalence is polarity-only, relationSpan participates,
broad-pointer behavior described.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Aligns the prompt with the validator, which already counts relationSpan
negation, and pins that case in a focused test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@nhyiramante1
nhyiramante1 merged commit ae55265 into main Oct 4, 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.

1 participant