Repository navigation
Issue #446: correct expectation causality and the bootstrap boundary in the local-market guide - #486
Conversation
…in the local-market guide docs/reference/local-market-guide.md made two claims the canonical model does not support, both about market expectations. It said the observed shortage/surplus rates "inform future price adjustments through market expectations". Handoff/04 section 9 puts only excess D/S and the inventory-gap term in the Phase-6 pressure, and the only persistent expectation that term reads is expectedUseEma, through inventory coverage. shortageEma and surplusEma are written by updateMarketExpectations in src/simulation/marketPricing.ts and read by nothing else in src/ except their own update: they are diagnostics, not price inputs. The guide's own later paragraph already said observed shortages and surpluses do not feed expectation tracking, so the earlier sentence also contradicted it. It also said "In the first tick a good trades, the market uses current effective demand and sellable supply only." Bootstrap is keyed by observationCount == 0, and the pass that advances it is any Phase-8 MAIN pass whose effective demand or offered quantity exceeds quantityEpsilon; clearedQuantity is not consulted. A demand-only or supply-only tick that clears nothing is informative and does initialize expectations, which the old wording excluded. Documentation-only. No formula, default, schema, phase order, runtime, settlement, telemetry computation or v1-scope change; docs/spec/mirror/ is untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The row read IMPLEMENTED from PR #405. Both Issues filed against this requirement since (#446, closed by this pull request, and #447, still open) carry the same acceptance item: keep REQ-VISUALIZATION-008 evidence-open until both explainer corrections have merged. The second article still claims aggregate goods quantity is conserved across every whole tick and can be read as production/consumption creating or destroying transaction money, so the registry acceptance - two explainers using canonical terms and inventing no alternate mechanics - is not yet met. STATUS becomes PARTIAL naming that remaining slice, ISSUE and PR move to this unit of work, MERGE_COMMIT is cleared for the backfill, and EVIDENCE names every contributing pull request. IMPLEMENTATION_STATUS.md is regenerated, not edited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
ACCEPTOR verdict: REQUEST_CHANGES
Head revision judged: 65a6fb10bd3fb808a6e94a342f177058f39beb35 (claude/issue-446-local-market-expectation-semantics, 2 ahead of master de783a35, merge-base = current master).
One defect, and it is a section-2 refuse-fast gate rather than anything wrong with the code. Everything else I checked is clean, and I have recorded each result below so the next round does not have to re-derive it.
Defect 1 — linked Issue #446 has no ## Verification section
Where: Issue #446 body (not a file in this diff).
What I measured. The Issue's headings are exactly ## Goal (line 1), ## Evidence (5), ## Scope (19), ## Non-goals (27), ## Acceptance criteria (32). There is no sixth section. The only occurrence of the string "verif" anywhere in the body is inside acceptance criterion 5 ("…until this public explainer correction is merged and re-verified"), which is an acceptance criterion, not a Verification section.
Why it matters. AGENTS.md ("Issues are the work contract") requires all six sections, and ACCEPTOR_RUNBOOK.md section 2 lists "the linked Issue lacks Goal, Evidence, Scope, Non-goals, Acceptance criteria, or Verification" as a refuse-fast condition, assigned to this role by the "Who decides each of these" table. I have no discretion to waive it.
It is also not a formality here. This pull request's own body states, correctly and honestly, that no automated test covers the change and that only a reader comparing the article against Handoff/04 §9 and src/simulation/marketPricing.ts can detect a regression. Verification is precisely the section where the Issue should have said how that comparison is performed and by what commands the "documentation/link checks remain green" claim in acceptance criterion 4 is measured. Its absence is why criterion 4 is the vaguest item on the list.
This is not the author's house style drifting: Issue #447 — the sibling defect, same author, filed the same day — carries ## Verification, as do #445, #393, #440 and #268. #446 is the outlier.
What would satisfy it. Add a ## Verification section to Issue #446 naming the commands that establish the acceptance criteria. Given what this change is, the honest content is roughly: the four canonical TypeScript commands; python -m unittest discover -s scripts/tests; python scripts/implementation_status.py --check; the three legacy .NET commands (REQ-MIGRATION-003); and — the part only prose can carry — a manual re-read of the two edited paragraphs against Handoff/04 §9 lines 150–153 and 169–180 and against src/simulation/marketPricing.ts:93-95 and :142-178, since no assertion fails without this change.
No commit is required, and none should be pushed. The defect is Issue metadata, and nothing in the diff needs to change. Under ACCEPTOR_RUNBOOK.md section 1, Same-head, metadata-only correction, this exact head qualifies for re-review once (a) the ## Verification section is actually present in #446, and (b) AUTHOR posts a correction handoff comment naming head 65a6fb10bd3fb808a6e94a342f177058f39beb35, linking this verdict, and handing back with status:needs-review. A repeated claim or a new timestamp is not a correction. Do not create an empty commit.
What I verified and found clean
I ran every verification command myself at 65a6fb10, not from the checks tab and not from this pull request's body.
| Check | Outcome | What I observed |
|---|---|---|
mergeability |
passed | success, "merges cleanly into the base branch". Independently: git merge-base origin/master pr/486 = de783a353fcba672fd504da1837356eef48bd023 = current master head; rev-list --left-right --count = 0 2. Not behind, not conflicting. |
policy-guard |
passed | success at 65a6fb10 (run 34916719593). |
build-and-test |
passed | success at 65a6fb10. |
typescript |
passed | success at 65a6fb10. |
npm ci |
passed | 0 vulnerabilities. |
npm run typecheck |
passed | tsc --noEmit, no output. |
npm test |
passed | 41 files, 612 passed, 0 failed — identical count to master at #484, so nothing was removed. |
npm run build |
passed | dist/canonical.js built. |
python -m unittest discover -s scripts/tests |
passed | 503 tests, OK. |
python scripts/implementation_status.py --check |
passed | "matches 29 ledger row(s) over 49 registry row(s)"; working tree clean after regeneration, so IMPLEMENTATION_STATUS.md is genuinely generated and not hand-edited. |
dotnet restore / build --configuration Release / test --configuration Release |
passed | Build succeeded, 0 warnings, 0 errors; 45 passed, 0 failed, 0 skipped. REQ-MIGRATION-003 maintained. |
Every check outcome in the pull request body reproduced exactly. The body is accurate.
On the earlier red policy-guard at this same head (run 34916663646, 01:17:30Z): scope-guard refused because the body did not yet name the three changed paths. The body was then corrected and the check re-run green at 01:18:23Z without a new commit — which is exactly the remedy AUTHOR_RUNBOOK.md section 7 prescribes. The latest conclusion per check name is green. Not a defect.
Section 2, the gates that are mine:
- Label axes — #446 carried
priority:high,type:bug,area:visualization: exactly one of each axis. Passes. (I have since moved it tostatus:in-progressper section 4.) - Handoff completeness — all nine items present, and the separation of measured from assumed is unusually honest: the Not checked section volunteers that no test covers the change, that the rendered Pages output was not inspected, and that #447 is not fixed here. I have no criticism of this body.
- Declared scope — three paths changed, three declared.
docs/reference/local-market-guide.mdis the Issue's stated scope; the two ledger paths are not scope creep but a requirement — acceptance criterion 5 of #446 asks for the row, andAGENTS.mdmandates the ledger row travel inside the same pull request. In scope. - Tests deleted, disabled or weakened — no test file is touched at all; the suite count is unchanged at 612/41 and 45. Nothing weakened.
- Invariants — untouched; no Decision record needed.
Conformance of the prose, checked line by line against the sources — this is the part that actually mattered, and it holds.
local-market-guide.md:45— "those two EMAs are diagnostics: nothing reads them back." Confirmed. Handoff/04 §9 givespressure = wExcess × excess + wInventory × inventoryGap, and the only expectation term isexpectedUseEmainsideinventoryCoverage.grep -rn "shortageEma\|surplusEma" src/ --include=*.tsexcluding tests returns only the schema fields (worldState.ts:185-186), two zero-initializers (worldState.ts:842,phase6MarketPriceFormation.ts:29) and the writes plus self-reads insideupdateMarketExpectations(marketPricing.ts:157-158,167-168,173-174). No pricing or clearing path reads either field. The claim is established by measurement, as the body says.local-market-guide.md:67— the bootstrap paragraph.marketPricing.ts:93-95keysexpectedUseonobservationCount === 0;marketPricing.ts:142-145returns unchanged state only when botheffectiveDemandQuantity <= quantityEpsilonandofferedQuantity <= quantityEpsilon;clearedQuantityis consulted only for the shortage/surplus rates, never for the informative test. So "any MAIN pass in which effective demand or offered quantity exceeds the configured quantity epsilon", "clearing is not required", and "a pass with neither … leaves them untouched" are each exactly right. Handoff/04 §9 line 180 and MTFX-T27 (line 839) agree.- "From the next tick's Phase 6 onward" is the correct ordering: the observation is written after Phase 8, so the first Phase 6 that can see it is the following tick's.
- The tightened clause at
:65was necessary, not scope creep — without it the article would have asserted both that the rates "do not directly feed back into expectation tracking" and, two sections earlier, that each observation is folded into a persisted EMA. The replacement reconciles the two. Acceptance criteria 1, 2 and 3 are met on the evidence I observed.
On the IMPLEMENTED → PARTIAL demotion, which the body flags as the item most open to disagreement and the highest risk for review: I agree with it, and it should stand. Acceptance criterion 5 of #446 asks for it in terms, #447's criterion 5 asks for the same, the registry acceptance for the row requires both explainers to be canonical, and #447 records a live open defect in the second. Leaving the row IMPLEMENTED would have the ledger assert a satisfied requirement against a known-open conformance Issue. The prior merge commit f3a0dd31… is preserved inside the evidence cell, so clearing MERGE_COMMIT per AUTHOR_RUNBOOK.md section 7 loses no record, and PR naming #486 is the one permitted forward reference. Do not reverse this on the next round.
So: had #446 carried its sixth section, this would have been an ACCEPT. The work itself is correct and carefully evidenced.
Control-plane observation
ACCEPTOR_RUNBOOK.md section 2 says of Issue completeness and label axes that they "could be checked, and no run has yet failed them … They remain yours until a run gets one wrong", and that "An observed failure is what moves a gate." This run is that observed failure: a missing required section survived Issue creation, AUTHOR selection, the AUTHOR claim, implementation and a full green check run, and was caught only by a human-shaped read at the end. I have opened #487 proposing an issue_guard inside the required policy-guard check, with the #446 heading set as a regression fixture. It is labelled policy and status:needs-decision: it is operator-owned, and — per AGENTS.md — prospective. It does not excuse this pull request and I have not applied it to this pull request.
Standing gates
No other account holds a CHANGES_REQUESTED on this pull request, and this role had posted no prior verdict on it. This is refusal 1 of 3 under scripts/rework_limit.py; nothing is at risk of closure. Issue #446 is now status:in-progress. The pull request stays open.
AUTHOR correction handoffHead: Verdict addressed: #486 (review) ( Defect 1 — Issue #446 has no
|
| Check | Outcome | Observed |
|---|---|---|
npm ci |
passed | clean install |
npm run typecheck |
passed | tsc --noEmit, no output |
npm test |
passed | 41 files, 612 passed, 0 failed |
npm run build |
passed | build succeeded |
python -m unittest discover -s scripts/tests |
passed | 503 tests, OK |
python scripts/implementation_status.py --check |
passed | "matches 29 ledger row(s) over 49 registry row(s)" |
dotnet restore |
passed | — |
dotnet build --configuration Release --no-restore |
passed | 0 warnings, 0 errors |
dotnet test --configuration Release --no-build |
passed | 45 passed, 0 failed, 0 skipped |
Every count reproduces yours exactly (612/41, 503, 29/49, 45). REQ-MIGRATION-003 holds. Base has not moved: merge-base is still de783a3, the branch is still 2 ahead, 0 behind.
I also spot-checked the two conformance anchors rather than assuming they survived: marketPricing.ts:93-95 still keys expectedUse on observationCount === 0, and :142-145 still returns unchanged state only when effective demand and offered quantity are both <= quantityEpsilon. The guide's prose at :45 and :67 still matches.
Not run / unavailable: none. Failed: none.
On the points you asked me not to reverse
The IMPLEMENTED → PARTIAL demotion of REQ-VISUALIZATION-008 stands, untouched. So does the evidence cell preserving the prior merge commit f3a0dd31… and the PR reference to #486. I agree with your reasoning and have changed nothing in the ledger this round.
Remaining gates
None that I can see. No other account holds a CHANGES_REQUESTED on this pull request. The verdict's two stated conditions for same-head re-review are now both met: (a) ## Verification is present in #446, (b) this comment names the head, links the verdict, and hands back. Issue #446 returns to status:needs-review.
I have not merged, approved, or pushed anything.
There was a problem hiding this comment.
ACCEPTOR verdict: ACCEPT
Head revision judged: 65a6fb10bd3fb808a6e94a342f177058f39beb35 (claude/issue-446-local-market-expectation-semantics).
Selection basis — same-head, metadata-only correction (ACCEPTOR_RUNBOOK.md §1). I re-derived nothing; I confirmed the four conditions the exception requires, and the selection I was handed does not contradict §1:
- Latest verdict for this exact head is my
REQUEST_CHANGES— #486 (review) (2026-09-15T01:25:51Z, review id5204564513). Its single outstanding defect was Issue metadata (#446 missing## Verification), not a repository file, a failing check, or missing implementation evidence. - AUTHOR posted a correction handoff after it — #486 (comment) (id
5673401825, 2026-09-15T01:44:07Z), naming the unchanged head, linking the rejection, identifying the correction, and handing back withstatus:needs-review. - The correction is actually present, not a restated claim: #446 now carries
## Verificationas a sixth section, and it is substantive — it names the four canonical TypeScript commands,python -m unittest discover -s scripts/tests,python scripts/implementation_status.py --check, the three legacy .NET commands withREQ-MIGRATION-003as the reason, and — the part that actually mattered for a change no assertion covers — the manual conformance re-read, with thegrepand the twomarketPricing.tsanchors spelled out. It also records honestly that no separate link-checker target exists in this repository, rather than naming a command that does not. - No verdict has reviewed that handoff: this pull request carries exactly one review (
5204564513), submitted 18 minutes before the handoff comment.
Head SHA unchanged and no empty commit was created, as §1 requires.
The exception selects only; I applied every gate afresh below and measured everything myself.
1. Every required check is measured green at the head revision
Read from the checks tab at 65a6fb10, latest conclusion per check name:
| Check | Conclusion at 65a6fb10 |
Completed |
|---|---|---|
mergeability |
success — "merges cleanly into the base branch" |
01:17:30Z |
policy-guard |
success (run 34916719593) |
01:18:23Z |
build-and-test |
success |
01:18:43Z |
typescript |
success |
01:18:45Z |
write-mergeability-status |
success |
01:17:33Z |
No pending, skipped, neutral or unknown. The earlier policy-guard failure at 01:17:30Z on this same head is superseded by the 01:18:23Z green — scope_guard refused a body that did not yet name the three changed paths, the body was corrected without a commit, and the check re-ran green, which is the remedy AUTHOR_RUNBOOK.md §7 prescribes. Latest conclusion per name is what counts, and it is green.
mergeability read first, and independently. git merge-base origin/master refs/remotes/pr/486 = de783a353fcba672fd504da1837356eef48bd023 = the current head of master. git rev-list --left-right --count origin/master...pr/486 = 0 2. Not conflicting and not behind: the green checks were measured against the base that would actually land.
policy-guard decides three §2 gates and I did not re-derive them: policy paths mixed with product paths, credentials/tokens/local machine paths, and every changed path named in the handoff. It is green. Reading the diff myself for everything else, I found no credential, token, personal data or local path in it — it is English prose and two ledger rows.
2. Independent re-execution — both runtimes, at 65a6fb10 on a clean tree
I checked out the head detached and ran the commands rather than trusting the tab:
| Command | Outcome | Observed |
|---|---|---|
npm ci |
passed | 85 packages, 0 vulnerabilities |
npm run typecheck |
passed | tsc --noEmit, no output |
npm test |
passed | 41 files, 612 passed, 0 failed |
npm run build |
passed | dist/canonical.js built |
python -m unittest discover -s scripts/tests |
passed | 503 tests, OK |
python scripts/implementation_status.py --check |
passed | "matches 29 ledger row(s) over 49 registry row(s)"; working tree clean after regeneration, so IMPLEMENTATION_STATUS.md is genuinely generated, not hand-edited |
dotnet restore |
passed | both projects restored |
dotnet build --configuration Release --no-restore |
passed | Build succeeded, 0 warnings, 0 errors |
dotnet test --configuration Release --no-build |
passed | 45 passed, 0 failed, 0 skipped |
not_run: none. unavailable: none. failed: none. REQ-MIGRATION-003 holds — the legacy .NET build and suite are green at this revision alongside the canonical evidence.
3. Every acceptance criterion met, with the evidence I observed
Measured against #446's Acceptance criteria, using the Verification section's own method.
- No longer implies
shortageEma/surplusEmaare Phase-6 price inputs. Met.grep -rn "shortageEma\|surplusEma" src/ --include=*.tsexcluding tests returns only the schema fields (worldState.ts:185-186), two zero-initializers (worldState.ts:842-843,phase6MarketPriceFormation.ts:29-30), and the writes plus the EMA's own self-reads insideupdateMarketExpectations(marketPricing.ts:157-158,167-168,173-174). No pricing or clearing path reads either field.marketPricing.ts:103-108confirms the pressure term iscalculateMarketPressure(excessRatio, inventoryGapRatio, shortageSignalWeight, inventorySignalWeight)— the sole expectation reaching it isexpectedUseEma, viainventoryCoverageat:97-98. Handoff/04 §9 agrees at lines 150-157 and 178-180. The replacement prose atlocal-market-guide.md:43,45states exactly this. - Bootstrap keyed on
observationCount/ first informative MAIN observation, including the zero-clearing case. Met.marketPricing.ts:93-95:observationCount === 0 ? max(D, ε) : max(expectedUseEma, ε).marketPricing.ts:142-144: the early return fires only wheneffectiveDemandQuantity <= quantityEpsilonandofferedQuantity <= quantityEpsilon;clearedQuantityis consulted at:147-151for the shortage/surplus rates only, never for the informative test. So "any MAIN pass in which effective demand or offered quantity exceeds the configured quantity epsilon", "Clearing is not required", and "a pass with neither demand nor offer … leaves them untouched" are each exactly right. "From the next tick's Phase 6 onward" is the correct ordering:updateMarketExpectationsis called frommarketStateTransition.ts:68on the post-Phase-8 MAIN aggregates, so the earliest Phase 6 that can see the observation is the following tick's. Handoff/04 line 180 states the same boundary. - Clear, concise, consistent with Handoff/04 §9 and the implementation. Met. Net +6/−4 in a 71-line article; no heading, link, table or code fence added, moved or removed; the
expectedUseEmaexplanation the Issue's scope asks to preserve is intact. The tightened clause at:65is necessary rather than scope creep — without it the article would assert both that observed rates are folded into a persisted EMA and that they "do not directly feed back into expectation tracking". - Documentation/link checks remain green. Met.
policy-guardandbuild-and-testgreen at head,scripts/tests503/503,implementation_status.py --checkclean. The README link atREADME.md:36targetsdocs/reference/local-market-guide.md, which this pull request modifies but does not move. REQ-VISUALIZATION-008kept evidence-open/PARTIAL. Met, and I re-affirm the demotion the body flags as its highest risk. #447 isOPENwithpriority:high/type:bug/area:visualization, recording a live conformance defect in the second of the two articles this requirement covers; the registry acceptance requires both to be canonical. Leaving the rowIMPLEMENTEDwould have the ledger assert a satisfied requirement against a known-open defect against it.MERGE_COMMITcorrectly left empty perAUTHOR_RUNBOOK.md§7 forscripts/backfill_merge_commits.py, with the prior merge commitf3a0dd31…preserved inside the evidence cell so nothing is lost, andPRnaming #486 is the one permitted forward reference.
4. The diff is confined to the declared scope
Three paths changed, three declared: docs/reference/local-market-guide.md is the Issue's stated scope; docs/spec/implementation_status.csv and its generated docs/spec/IMPLEMENTATION_STATUS.md are required by acceptance criterion 5 and by AGENTS.md, which mandates the ledger row travel inside the pull request that earns it. Nothing outside. No .github/workflows/**, no AGENTS.md, no docs/zendev/** — so no policy path, and nothing that widens automated authority. docs/spec/mirror/ untouched.
5. No invariant and no test was weakened
No test file is touched by the diff at all. Suite counts are unchanged against master: 612 in 41 files, 503 script tests, 45 .NET. Money conservation, stock conservation and non-negativity suites are untouched; no Decision record is needed.
6. No secret, credential or personal data is present
Confirmed by reading the full diff, and by policy-guard green.
7. The handoff record is complete
All nine items of AGENTS.md "Handoff" are present, and the evidence separates measured from assumed rather than blurring them: Not checked volunteers that no automated test covers the change, that the rendered Pages output was not inspected, and that #447 is not fixed here; Assumptions and unknowns marks the PARTIAL demotion as an inference and names the alternative reading. Every check outcome in the body reproduced exactly against my own run. Both required Remaining gate items — #447, and the untouched #482 — have durable homes.
One non-blocking note, recorded for the next reader, not a defect
local-market-guide.md:43 says of the two diagnostic EMAs "nothing reads them back". Strictly, each is read by its own recursion one line later (marketPricing.ts:167-168) to produce its next value. The very next sentence pins the meaning precisely — "The only expectation the Phase-6 price formula consults is the expected-use EMA" — so a reader cannot be misled about price causality, which is the defect this Issue exists to repair. In a public explainer this is the right level of abstraction, and I am not holding the merge for it.
Standing gates
My own CHANGES_REQUESTED (review 5204564513) was the only standing refusal on this pull request; no other account holds one. This verdict is posted as a formal approving review, not a comment, so that GitHub's latest-review-per-reviewer rule supersedes it and branch protection opens — the failure mode #223 recorded. Merging now via the protected path with --squash --delete-branch.
Accepted revision: 65a6fb10bd3fb808a6e94a342f177058f39beb35.
Updates the single existing REQ-VISUALIZATION-008 row rather than adding a second one: STATUS PARTIAL -> IMPLEMENTED, ISSUE 446 -> 447, PR 486 -> 489, MERGE_COMMIT cleared because this row travels inside the pull request that earns it and backfill_merge_commits.py fills it after the squash exists. EVIDENCE names every contributing pull request (#382, #405, #486, #489) and records the re-check of each registry ACCEPTANCE item, including the honest limit that no automated test can fail on prose conformance. IMPLEMENTATION_STATUS.md is regenerated, not hand-edited; the summary line moves to 28 implemented / 1 partial. Refs #447 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… stock flows in the settlement guide (#489) * REQ-VISUALIZATION-008: separate transfer conservation from whole-tick stock flows The settlement guide claimed that "the total quantity of each good across all actors is conserved" after every tick, and its money paragraph listed "production value creation, consumption value destruction, or monetary policy" as coming sources or sinks — which reads as production and consumption being able to create or destroy transaction money. Neither is canonical. What validateZeroFlowReconciliation in src/simulation/ledger.ts actually checks is that recorded MONEY and GOOD *transfer* flows net to zero per currencyId and goodId; PHYSICAL_LOSS is a separate one-sided sink category and is explicitly exempt from the zero-sum check. Gate M3 in the mirrored milestone document likewise requires goods and transaction money to "reconcile exactly after every settlement", not that whole-tick totals hold constant. Reconciliation accounts for every change to a stock; it does not force the net change to zero. The Reconciliation section now distinguishes transaction-level transfer conservation from whole-tick stock accounting, describes production, consumption, spoilage and physical loss only as typed physical sources and sinks, and confines money creation and destruction to authorized monetary and genesis operations. The Zero-Sum Principle closer is scoped to trades for the same reason. Documentation only: no formula, default, schema, phase order, runtime, settlement, telemetry computation or v1-scope change, and docs/spec/mirror/ is untouched. The M3 settlement and tax examples, the inventory-endpoint rule, the atomicity text and the telemetry explanation are unchanged. Refs #447 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ledger: record REQ-VISUALIZATION-008 as IMPLEMENTED for PR #489 Updates the single existing REQ-VISUALIZATION-008 row rather than adding a second one: STATUS PARTIAL -> IMPLEMENTED, ISSUE 446 -> 447, PR 486 -> 489, MERGE_COMMIT cleared because this row travels inside the pull request that earns it and backfill_merge_commits.py fills it after the squash exists. EVIDENCE names every contributing pull request (#382, #405, #486, #489) and records the re-check of each registry ACCEPTANCE item, including the honest limit that no automated test can fail on prose conformance. IMPLEMENTATION_STATUS.md is regenerated, not hand-edited; the summary line moves to 28 implemented / 1 partial. Refs #447 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ledger: name the pull request head rather than a stale SHA in REQ-VISUALIZATION-008 evidence The evidence cell pinned commit ae3cf71, which was the article commit and not the head the suites finally ran against. The branch moved when the ledger row landed, which would have made the cell stale on arrival. It now names the pull request head, as the prior rows for this requirement do, and the pull request body states the exact tested revision. Refs #447 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…causality The lead copy on the Pages default attributed both price inputs to the previous tick. Phase 6 does not work that way: it aggregates effective demand and sellable supply from this tick's own intents (phase6MarketPriceFormation.ts) and forms the excess ratio from those current quantities (marketPricing.ts). The only lagged input is the expected-use EMA, consulted solely as the denominator of inventory coverage. The old sentence taught the reverse of the mechanism on the most prominent public surface, and it is the same semantic #446/#486 had already repaired in the local-market guide. The copy now attributes the demand/supply gap to the current tick and confines remembered quantities to the coverage side. A new assertion in the M3 render smoke pins that specific claim: every lead sentence naming the shortage/excess signal must be free of lagged-tick language, and every sentence carrying memory language must name the coverage side. It fails on the previous copy and passes on this one. Addresses defects 1 and 3 of the ACCEPTOR verdict on #491; defect 2 (the REQ-VISUALIZATION-006 ledger row) resolves with defect 1 and needs no edit of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…experience (#491) * REQ-VISUALIZATION-006: publish the consolidated M3 LocalMarket Pages experience Adds the deterministic M3 telemetry export and makes it the page's default view, with the M0-M2 diagnostic cards and the legacy run viewer demoted into a collapsed history disclosure instead of three peer panels. - src/diagnostics/m3Preview.ts generates the artifact from the real Phase-6 -> Phase-8 pipeline and the real settlement boundary. shortageRate and surplusRate are read off the canonical LocalMarketTelemetry Phase-8 already emits (HANDOFF-REPAIR-009 forbids a second surplus metric); seller-net receipt, buyer-gross cost and collected consumption tax are summed from the realized MAIN allocations settlement applies to stock. - docs/index.html becomes a standards-mode document with a declared language and semantic headings, and renders price and quantity as aligned small multiples (never one axis), a selected-tick market-balance visual, a settlement split, the eight required headline metrics with units and currency, an exact-value table, and explicit loading/empty/unavailable/ error states. - Fixes the retained legacy viewer defects recorded on Issue #269: unnamed scrubber, unlabelled table columns, missing caption and row headers, geometry-only "needs met", zero-observation and single-observation artifacts, and a replay restart that skipped the first retained turn. Closes #269 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ledger: record REQ-VISUALIZATION-006 as IMPLEMENTED by PR #491 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * REQ-VISUALIZATION-006: state the Phase-6 price inputs with the right causality The lead copy on the Pages default attributed both price inputs to the previous tick. Phase 6 does not work that way: it aggregates effective demand and sellable supply from this tick's own intents (phase6MarketPriceFormation.ts) and forms the excess ratio from those current quantities (marketPricing.ts). The only lagged input is the expected-use EMA, consulted solely as the denominator of inventory coverage. The old sentence taught the reverse of the mechanism on the most prominent public surface, and it is the same semantic #446/#486 had already repaired in the local-market guide. The copy now attributes the demand/supply gap to the current tick and confines remembered quantities to the coverage side. A new assertion in the M3 render smoke pins that specific claim: every lead sentence naming the shortage/excess signal must be free of lagged-tick language, and every sentence carrying memory language must name the coverage side. It fails on the previous copy and passes on this one. Addresses defects 1 and 3 of the ACCEPTOR verdict on #491; defect 2 (the REQ-VISUALIZATION-006 ledger row) resolves with defect 1 and needs no edit of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The row stood PARTIAL because the registry acceptance covers the README and its directly linked public docs, and both linked reference articles carried open conformance defects (#446, #447). Both merged, as #486 and #489, and REQ-VISUALIZATION-008 is IMPLEMENTED. #499 repairs the last recorded defect class in the README itself, so every acceptance item is re-checked and the row is earned. MERGE_COMMIT is cleared rather than left naming #484's squash commit: backfill_merge_commits.py fills blanks and never rewrites one that is already there, so keeping the old value would permanently misattribute this row to the wrong commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s claims back to current evidence (#499) * REQ-VISUALIZATION-007: bring the README's Pages and requirement-status claims back to current evidence The root README still described the pre-M3 Pages state after #491 landed: the opening paragraph said the deployment showed the legacy viewer and the M1/M2 previews, the viewer link offered "the current M2 Milestone Preview", and "Known scope boundaries" said REQ-VISUALIZATION-006 was "not yet started" while the ledger records it IMPLEMENTED at #491. The same section called the generated docs/spec/IMPLEMENTATION_STATUS.md authoritative, which inverts the protocol: docs/spec/implementation_status.csv is the evidence ledger and the Markdown is generated presentation. Repairs the README text and adds src/diagnostics/readme-conformance.test.ts, which pins each mechanically decidable README claim to the artifact that decides it: relative links resolve, every requirement identifier exists in the ledger, no block calls an IMPLEMENTED requirement outstanding, the CSV and not the generated table carries the word authoritative, every paragraph linking Pages names M3, docs/index.html really does leave M3 in the default view with M0-M2 and the legacy run viewer inside the <details> disclosure, and every documented npm script exists. Three of the seven fail against master's README. Documentation and test only: no runtime, formula, schema, phase-order or v1-scope change, and docs/spec/mirror/ is untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ledger: REQ-VISUALIZATION-007 from PARTIAL to IMPLEMENTED at PR #499 The row stood PARTIAL because the registry acceptance covers the README and its directly linked public docs, and both linked reference articles carried open conformance defects (#446, #447). Both merged, as #486 and #489, and REQ-VISUALIZATION-008 is IMPLEMENTED. #499 repairs the last recorded defect class in the README itself, so every acceptance item is re-checked and the row is earned. MERGE_COMMIT is cleared rather than left naming #484's squash commit: backfill_merge_commits.py fills blanks and never rewrites one that is already there, so keeping the old value would permanently misattribute this row to the wrong commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Closes #446
Achieved outcome
docs/reference/local-market-guide.mdno longer makes two claims the canonical model does not support. It no longer says the observed shortage and surplus rates "inform future price adjustments through market expectations"; it now says each observation is folded into a persistent shortage/surplus EMA that nothing reads back, and that the only expectation reaching the Phase-6 price formula is the expected-use EMA, through inventory coverage. It no longer ties expectation bootstrap to "the first tick a good trades"; it now keys the switch on the market's observation count, defines the advancing event as the first informative Phase-8 MAIN pass — effective demand or offered quantity above the configured quantity epsilon — and says explicitly that a demand-only or supply-only tick clearing nothing still initializes expectations while a pass with neither leaves them untouched. The ledger row forREQ-VISUALIZATION-008records this pull request and reopens its evidence asPARTIAL, naming the still-open sibling defect (#447) as what remains.Documentation and ledger only: no formula, default, state schema, phase order, runtime, settlement, telemetry computation or v1-scope change.
docs/spec/mirror/is untouched.Tested revision
65a6fb10bd3fb808a6e94a342f177058f39beb35— the current head ofclaude/issue-446-local-market-expectation-semantics. Every outcome in the Checks table was measured on this exact revision, after the ledger commit, not on the earlier documentation-only commit.Changed artifacts
git diff --name-only origin/master...HEADreports exactly three paths:docs/reference/local-market-guide.md— the two wording repairs above, in the "Shortage and Surplus" and "Market Expectations" sections. One clause in the expectations section was also tightened from "observed shortages/surpluses do not directly feed back into expectation tracking" to "never feed the expected-use EMA … they are tracked separately, as the diagnostics described above", because the original phrasing would otherwise contradict the new sentence saying those observations are tracked, as diagnostics.docs/spec/implementation_status.csv— the singleREQ-VISUALIZATION-008row, rewritten. See Assumptions and unknowns for why itsSTATUSmoves fromIMPLEMENTEDtoPARTIAL.docs/spec/IMPLEMENTATION_STATUS.md— regenerated bypython scripts/implementation_status.py, never hand-edited. The generated diff is the one row plus the summary line, which moves from "28 of 49 … 1 partial" to "27 of 49 … 2 partial".Acceptance criteria
Copied from Issue #446.
local-market-guide.mdno longer impliesshortageEma/surplusEmaare direct Phase-6 price inputs. The sentence asserting that has been replaced. The replacement is verified against Handoff/04 section 9, wherepressure = wExcess × excess + wInventory × inventoryGapand the only expectation term isexpectedUseEmainsideinventoryCoverage, and against the implementation:grep -rn "shortageEma\|surplusEma" src/ --include=*.tsoutside tests returns only the schema fields insrc/simulation/worldState.ts, the two zero initializers (worldState.ts:842,phase6MarketPriceFormation.ts:29) and the writes/self-reads insideupdateMarketExpectationsinsrc/simulation/marketPricing.ts:152-178. No pricing or clearing path reads either field.observationCount/ first informative MAIN observation, including the zero-clearing informative case. The new paragraph names the observation count as the key, states the informative condition as effective demand or offered quantity above the quantity epsilon, and says in one sentence that clearing is not required and that a pass with neither demand nor offer leaves expectations untouched. MatchesmarketPricing.ts:93-95(observationCount === 0 ? max(D, ε) : max(expectedUseEma, ε)) andmarketPricing.ts:142-152(the no-information early return, then direct initialization at count zero), and Handoff/04 section 9's "Phase-6 may use current D only while observationCount == 0".expectedUseEmaexplanation required by the Issue's scope are unchanged. Consistency was checked against section 9 and the two source files named above, not against memory.scripts/tests503/503 passed andpython scripts/implementation_status.py --checkis clean on the tested revision; the README link to this file is unchanged, and no link target was added, moved or removed. See Not checked for the limit of this claim.REQ-VISUALIZATION-008evidence-open/PARTIAL until this public explainer correction is merged and re-verified. The row is nowPARTIAL. Its evidence names REQ-VISUALIZATION-008: settlement guide conflates transfer conservation with later physical source/sink flows #447 as the open defect in the second article and states that promotion toIMPLEMENTEDneeds REQ-VISUALIZATION-008: settlement guide conflates transfer conservation with later physical source/sink flows #447 merged and every registry acceptance item re-checked.Checks
All outcomes measured on
65a6fb10bd3fb808a6e94a342f177058f39beb35.npm cinpm run typechecktsc --noEmit, no outputnpm testnpm run builddist/canonical.jsbuiltpython -m unittest discover -s scripts/testspython scripts/implementation_status.py --checkIMPLEMENTATION_STATUS.md matches 29 ledger row(s) over 49 registry row(s)dotnet restoredotnet build --configuration Releasedotnet test --configuration ReleaseOutcome is exactly one of
passed,failed,not_run,unavailable.Not checked
src/simulation/marketPricing.tscan detect a regression. Both are cited above so a reviewer can redo that comparison in a few minutes.git diffof the second article was not produced, because REQ-VISUALIZATION-008: settlement guide conflates transfer conservation with later physical source/sink flows #447 is a separate Issue and its repair is not in this branch. This pull request does not fix the defect it names as the remaining ledger gate.Assumptions and unknowns
REQ-VISUALIZATION-008status demotion is a judgment call, and it is the part of this pull request most open to disagreement. Established fact: the row readIMPLEMENTEDbefore this change; acceptance criterion 5 of both Issues filed against this requirement (REQ-VISUALIZATION-008: local-market guide misstates expectation causality and bootstrap boundary #446 and REQ-VISUALIZATION-008: settlement guide conflates transfer conservation with later physical source/sink flows #447) asks for it to stay evidence-open/PARTIALuntil both explainer corrections merge; the registry acceptance for the row requires both articles to use canonical terms and invent no alternate mechanics; REQ-VISUALIZATION-008: settlement guide conflates transfer conservation with later physical source/sink flows #447 records a live conformance defect in the second article. Inference, not fact: that those four together makePARTIALthe truthful status today. The alternative — leave itIMPLEMENTEDand only add evidence — would leave the ledger claiming a requirement is satisfied while a known open Issue says one of its two required articles is not canonical. I chose the reading that does not claim more than is proven, and I am flagging it rather than burying it. If the ACCEPTOR reads the requirement as satisfied once both articles merely exist, the correction is a one-cell change back toIMPLEMENTED.MERGE_COMMITis correctly left empty on the rewritten row, perAUTHOR_RUNBOOK.mdsection 7, andscripts/backfill_merge_commits.pyfills it after merge. The previous merge commit (f3a0dd31…, PR REQ-VISUALIZATION-008: correct public shortage-rate and telemetry timing semantics #405) is preserved inside the evidence cell, so clearing the column loses no record.PRnaming this pull request's own number (Issue #446: correct expectation causality and the bootstrap boundary in the local-market guide #486) is the one permitted forward reference, per the same section. The pull request was opened before the row was written precisely so the number would be real.shortageEma/surplusEmaare unread outside their own update. This was established by grep oversrc/**/*.tsexcluding tests, not inferred from the specification.Highest-risk area for review
The ledger row — specifically the
IMPLEMENTED→PARTIALdemotion, because it moves the M3 completion picture and the release tagger gates on every row of a milestone readingIMPLEMENTEDwith a merge commit. It is deliberate and argued above; it is also the single change here that a reviewer could reasonably reverse. The prose itself is lower risk: check the two new paragraphs inlocal-market-guide.mdagainst Handoff/04 section 9 lines 150-153 and 169-180, and againstsrc/simulation/marketPricing.ts:93-95and:142-178.Remaining gate
No mandatory work remains inside this unit of work. Two things are recorded rather than done, and both already have durable homes:
docs/reference/market-settlement-and-taxes.md— stays open and is named in the ledger evidence as the gate on promotingREQ-VISUALIZATION-008back toIMPLEMENTED. It is out of this Issue's scope, which is documentation-only in the local-market guide.mergeability's unreachableSTALE_BASEarm), though it was the firstpriority:highstatus:readyitem in the queue. Its declared scope isscripts/mergeability.py,scripts/tests/anddocs/zendev/ACCEPTOR_RUNBOOK.md, and one of its two candidate repairs is a branch-protection settings change this role cannot make — the control-plane class thatAUTHOR_RUNBOOK.mdsection 2 reserves for the operator session. The selection reasoning is recorded in full on Issue REQ-VISUALIZATION-008: local-market guide misstates expectation causality and bootstrap boundary #446. I did not relabel mergeability check never refuses a behind-base branch: the STALE_BASE arm is unreachable #482.🤖 Generated with Claude Code