11 KiB
CHATGPT REMOTE BRIEF — work to do while Shay is away from the library
Audience: ChatGPT, acting through its GitHub connector (read repo + open PRs). Reviewer: Claude Code (Opus), at the library. Claude ratifies and fixes minor issues. Date scoped: 2026-05-28. Status: active.
You (ChatGPT) read this file directly from the repo. Shay will send a short dispatch line from a phone (see §8). Each line points you back here. Do only the task named, open one PR, and stop. Do not merge. Claude verifies with the CLI (which you cannot run) and merges.
1. The one rule that overrides everything: wrong=0
CORE is a deterministic engine that refuses rather than guesses. The serving
math lane is frozen at exactly 3 solved / 47 refused / 0 wrong (3/47/0). A
single wrong answer is a worse outcome than a thousand refusals. Your job never
makes the engine answer more confidently; it makes the engine read more of the
text so the existing gate has better inputs to either verify or refuse.
You cannot run the test suite or the core CLI from the connector. That is
fine, because every task in this brief is scoped to a lane where the worst case
of a mistake is "more refusals," never "a wrong answer." Claude runs the
invariant gate before anything merges.
2. The safety boundary (why these tasks are safe to hand you)
There are two lanes in this codebase:
- Sealed practice lane —
generate/derivation/*. Experimental composition.chat/(serving) does not import it. Changes here cannot move the3/47/0serving number. All your build work lives here. - Serving lane —
chat/, and the shared grounding helpergenerate/math_roundtrip.py::_value_grounds. wrong=0-sensitive. Off-limits to you (see §6).
generate/derivation/extract.py is in the sealed lane (confirmed: extract_quantities
is imported only within generate/derivation/*). Over-extraction there is caught
downstream by the self-verification gate, which is refuse-preferring. That is
the property that makes this delegable.
3. State of play (what just shipped — context for your audit)
- ADR-0176 (merged): multi-step chain model, question-targeting, comparatives
pack, self-verification gate (
generate/derivation/verify.py). - ADR-0178 / Gap B (active, multi-phase): comprehension-guided sequential
composer. GB-1 =
generate/derivation/clauses.py(clause segmentation). GB-2 =generate/derivation/compose.py(sequential combination). Both just merged as a 2-PR stack. GB-3 (lookback), GB-4 (held hypotheses), GB-5 (DAG), GB-6 (measurement) are not yet built. - ADR-0179 (proposed, doc-only, open PR #446): diagnoses that the structure
machinery is built but starved —
extract.py'sdigit + single wordregex loses word-numbers, multi-word units, currency/decimals, sentence-final numbers, and mis-attributes units. Sub-phases EX-1…EX-6. This is your build work.
Read these before starting:
docs/decisions/ADR-0178-compositional-structure.md(esp. §"wrong=0 obligations", §"Sub-phases")docs/decisions/ADR-0179-extraction-richness.md(the full extraction plan)generate/derivation/extract.py(~40 lines — the file you mostly edit)generate/derivation/clauses.py,generate/derivation/compose.py(GB-1/GB-2)tests/test_adr_0178_gb1_clauses.py,tests/test_adr_0178_gb2_compose.py(test style to mirror)- Gold cases:
evals/gsm8k_math/train_sample/v1/cases.jsonl(grep ids0003 0019 0021 0024 0033 0041)
4. STREAM A — the double-check (do this FIRST, it's read-only)
CLAUDE.md mandates a lookback review before the next phase of a multi-phase
ADR. GB-1 and GB-2 are a 2-PR stack on generate/derivation/ and GB-3 is next, so
this is owed. You are well-suited to the read-only half: you read, you report,
you cannot break anything.
Task: audit GB-1 (clauses.py) + GB-2 (compose.py) against the ADR-0178
claims and produce a findings report. Do not change any code in this stream.
Check, and write down findings for, each of:
- Doc-vs-impl drift. Does
clauses.py/compose.pyactually do what ADR-0178 §"Sub-phases" GB-1/GB-2 says? Note any signature/scope differences, anything the ADR promised that isn't there, anything present that the ADR didn't scope. - wrong=0 obligation coverage (ADR-0178 §"wrong=0 obligations", items 1–5).
For each obligation, find the test in
tests/test_adr_0178_gb*that would fail if the obligation were violated. If you can construct an input where a spurious / unlicensed structure (obligation #4) or an irreducible hold (#2) might be admitted/resolved, write it down as a candidate hazard — do not fix it, just flag it with the exact input string and why. - Refuse-preferring on ambiguity. Trace: when a clause's local op is
ambiguous, does
clause_local_results(GB-1) andcompose_sequential(GB-2) resolve to a hold (None/ refuse) rather than guess? Cite the line. - Determinism. Any iteration over a
set/dictwithout ordering, any reliance on insertion order that isn't guaranteed, any nondeterministic tie-break? - Cross-PR consistency. GB-2 builds on GB-1's
ClauseResult. Do the dataclass shapes,None/hold conventions, and unit handling compose cleanly?
Output: create a branch audit/adr-0178-gb1-gb2-lookback, add one markdown
file docs/handoff/AUDIT-ADR-0178-GB1-GB2.md, and open a PR titled
audit: ADR-0178 GB-1/GB-2 lookback (findings only — no code change). Categorise
findings as solid / gaps (no risk) / drift (need amendment) / hazards (live
wrong=0 risk). Every hazard must quote the exact triggering input. No code edits
in this PR.
5. STREAM B — the build (ADR-0179 extraction, sealed lane only)
The composer is starved by extract.py. Enrich it. One sub-phase = one PR.
Each sub-phase only touches generate/derivation/extract.py and its test file
tests/test_adr_0179_extract.py (create it; mirror the style of
tests/test_adr_0178_gb2_compose.py — plain input-string → assert). Stay
lexeme-level / orthographic (ADR-0165): patterns for "what a number-piece looks
like," never grammar templates for "how words combine to mean X" (combining is
the search's job, not the extractor's).
Do these four, in this order. Each is independent; each can ship alone:
- EX-1 — word-numbers.
"three","twelve","twenty-four"should extract as values. Reuse the existingWORD_NUMBERSmapping /en_numerics_v1if present (grep forWORD_NUMBERS); do not hand-roll a new number table if one exists. Tests:"three apples"→ value3.0; a sentence mixing digit and word numbers extracts both, left-to-right. - EX-3 — multi-word units.
"12 jumping jacks"should attach unit"jumping jacks", not just"jumping". Lexeme-level: a number followed by one or more lowercase word tokens. Be conservative — over-greedy units cause refusals (safe) not wrong answers, but keep it tight. Tests:"12 jumping jacks"→ unit"jumping jacks"; single-word units still work (don't regress GB-1/GB-2 tests). - EX-4 — list-unit inheritance (highest payoff — unblocks gold case 0024).
In a same-unit list like
"20, 36, 40 and 50 push-ups", the trailing unit attaches to every number in the list, so GB-2's same-unit list-sum can fire. Tests: that list extracts four quantities all with unit"push-ups". Verify against case0024incases.jsonl. - EX-5 — sentence-final numbers. A number with no following unit word (end of
sentence, or followed by punctuation) should still extract, with an empty/None
unit. Tests:
"She had 5."extracts value5.0.
For each PR: branch feat/adr-0179-exN-<slug>, title
ADR-0179 EX-N: <what> (sealed lane, do-not-merge until Claude verifies). In the
PR body, state: which gold case(s) it targets, that it touches only extract.py +
its test, and that serving is untouched (you did not edit chat/ or
math_roundtrip.py).
6. HARD RULES — forbidden, non-negotiable
- Never merge a PR. Leave every PR open. Claude merges after CLI verification.
- Never touch any of:
chat/**,generate/math_roundtrip.py(esp._value_grounds),algebra/**,field/**,vault/**,generate/stream.py,ingest/gate.py,language_packs/compiler.py, identity/safety/ethics packs, CI workflow files, or any test that currently passes (don't "fix" green tests). - Do EX-1, EX-3, EX-4, EX-5 only. Do NOT do EX-2 (currency/decimal) — it is
entangled with a wrong=0-sensitive grounding change in
_value_groundsthat only Claude does. Do NOT do EX-6 (measurement — needs the CLI). If you think EX-2 is needed, write a note in the PR body; don't touch the grounding. - No new dependencies, no network calls, no config/threshold changes. Do not
weaken any numeric threshold (e.g.
1e-6) to make something pass. - No grammar templates, no ML, no fuzzy/approximate matching. Lexeme/orthographic patterns only.
- Determinism: left-to-right order, no unordered-set iteration affecting output, no randomness, no timestamps in output.
- One sub-phase per PR. Small diffs. If a change grows beyond
extract.py+ its test, stop and leave a note instead. - If unsure, refuse the change and write a note in the PR body. A note Claude reads is worth more than a guess Claude has to revert.
7. What Claude does when back at the library (so you know the handoff)
For each open PR, Claude will: read the diff → run core test --suite full -q
and the relevant tests/test_adr_0179_extract.py → run the lane-SHA gate to
prove serving stays 3/47/0 byte-identical → run core eval on the gold cases to
see if any extraction-blocked case (0003/0024) now flips under self-verification →
fix minor issues (naming, a missed edge token, a test assertion) → merge or leave
review comments. Your audit report (Stream A) feeds Claude's GB-3 lookback.
8. MOBILE DISPATCH LINES (copy-paste one at a time from the phone)
Send these to ChatGPT one at a time. Each is self-contained; ChatGPT pulls the full brief from the repo itself.
Read docs/handoff/CHATGPT-REMOTE-BRIEF.md in the AssetOverflow/core repo, then do STREAM A exactly as written. Read-only audit, one findings PR, do not change code, do not merge.
Read docs/handoff/CHATGPT-REMOTE-BRIEF.md, then do STREAM B EX-4 (list-unit inheritance) exactly as written. Only edit generate/derivation/extract.py and its test. One PR. Do not merge.
Read docs/handoff/CHATGPT-REMOTE-BRIEF.md, then do STREAM B EX-1 (word-numbers). Reuse WORD_NUMBERS if it exists. Only extract.py + its test. One PR. Do not merge.
Read docs/handoff/CHATGPT-REMOTE-BRIEF.md, then do STREAM B EX-3 (multi-word units). Only extract.py + its test. Keep units tight. One PR. Do not merge.
Read docs/handoff/CHATGPT-REMOTE-BRIEF.md, then do STREAM B EX-5 (sentence-final numbers). Only extract.py + its test. One PR. Do not merge.
Suggested order: Stream A first (it's owed and risk-free), then EX-4 (best payoff), then EX-1 / EX-3 / EX-5 in any order. They don't depend on each other.
9. If ChatGPT gets confused or asks to do more
Tell it: "Stop. Do only the one task. Leave a note in the PR body for anything
else. Do not merge, do not touch serving, do not touch _value_grounds." Then
move to the next dispatch line, or save it for Claude.