From bdb857cacad68ade64d7983a20b381c8b44a07b4 Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Wed, 19 Aug 2026 15:19:56 +0100 Subject: [PATCH] test(prose): three cases for the truth stack + three-phase staleness fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New cases, one per shipped behaviour: spec-measures-a-false-claim (the reality trigger — construction verifies a load-bearing claim, stops conversationally when the falsity undermines the leaning decision, and lands the settlement in the discussion's own record), spec-review-routes-a-source-defect (the review loop's fourth verb — a claims finding whose false count lives in the source routes on the value-only lane, corrects the discussion in place, and re-aligns the spec's copy), and discussion-review-corrects-a-false-claim (document review's unverified-claims dimension re-runs the recorded command at conclusion and corrects the value without turning arithmetic into a decision). A new spec-claims-source-defect stub carries the findings return; the spec-review-clean stub and the four cases arming it move to the three-agent trigger, and the two asserts pinning the two-phase sequence update. Co-Authored-By: Claude Fable 5 --- .../bridge-hands-off-to-planning/case.json | 2 +- .../act.md | 5 + .../assert.md | 50 +++++++ .../case.json | 63 +++++++++ .../fixture-state.cjs | 96 +++++++++++++ .../fixture.md | 14 ++ .../fixture/.claude/settings.json | 9 ++ .../fixture/.recipe-hash | 1 + .../fixture/.workflows/.state/migrations | 56 ++++++++ .../fixture/.workflows/_gitignore.fixture | 9 ++ .../fixture/.workflows/manifest.json | 7 + .../pay/discovery/sessions/session-001.md | 39 +++++ .../fixture/.workflows/pay/discussion/pay.md | 47 +++++++ .../fixture/.workflows/pay/manifest.json | 26 ++++ .../fixture/src/checkout/address.js | 5 + .../fixture/src/checkout/cart.js | 5 + .../fixture/src/checkout/confirm.js | 5 + .../fixture/src/checkout/payment.js | 5 + .../fixture/src/checkout/wallet-stub.js | 5 + .../case.json | 2 +- .../spec-extracts-the-discussion/assert.md | 17 ++- .../spec-extracts-the-discussion/case.json | 2 +- .../cases/spec-measures-a-false-claim/act.md | 5 + .../spec-measures-a-false-claim/assert.md | 80 +++++++++++ .../spec-measures-a-false-claim/case.json | 71 ++++++++++ .../fixture-state.cjs | 133 ++++++++++++++++++ .../spec-measures-a-false-claim/fixture.md | 18 +++ .../fixture/.claude/settings.json | 9 ++ .../fixture/.recipe-hash | 1 + .../fixture/.workflows/.state/migrations | 56 ++++++++ .../fixture/.workflows/_gitignore.fixture | 9 ++ .../fixture/.workflows/manifest.json | 7 + .../pay/discovery/sessions/session-001.md | 39 +++++ .../fixture/.workflows/pay/discussion/pay.md | 49 +++++++ .../fixture/.workflows/pay/manifest.json | 16 +++ .../fixture/src/lib/retry.js | 11 ++ .../fixture/src/webhooks/capture.js | 8 ++ .../fixture/src/webhooks/charge.js | 8 ++ .../fixture/src/webhooks/refund.js | 7 + .../spec-resolves-a-source-conflict/assert.md | 5 +- .../spec-resolves-a-source-conflict/case.json | 2 +- .../spec-review-routes-a-source-defect/act.md | 5 + .../assert.md | 74 ++++++++++ .../case.json | 75 ++++++++++ .../fixture-state.cjs | 130 +++++++++++++++++ .../fixture.md | 14 ++ .../fixture/.claude/settings.json | 9 ++ .../fixture/.recipe-hash | 1 + .../fixture/.workflows/.state/migrations | 56 ++++++++ .../fixture/.workflows/_gitignore.fixture | 9 ++ .../fixture/.workflows/manifest.json | 7 + .../pay/discovery/sessions/session-001.md | 39 +++++ .../fixture/.workflows/pay/discussion/pay.md | 47 +++++++ .../fixture/.workflows/pay/manifest.json | 31 ++++ .../pay/specification/pay/specification.md | 19 +++ .../fixture/src/checkout/address.js | 5 + .../fixture/src/checkout/cart.js | 5 + .../fixture/src/checkout/confirm.js | 5 + .../fixture/src/checkout/payment.js | 5 + .../fixture/src/checkout/wallet-stub.js | 5 + .../prose/stubs/spec-claims-source-defect.md | 46 ++++++ tests/prose/stubs/spec-review-clean.md | 9 +- 62 files changed, 1581 insertions(+), 19 deletions(-) create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/act.md create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/assert.md create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/case.json create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture-state.cjs create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture.md create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.claude/settings.json create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.recipe-hash create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/.state/migrations create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/_gitignore.fixture create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/manifest.json create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discussion/pay.md create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/manifest.json create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/address.js create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/cart.js create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/confirm.js create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/payment.js create mode 100644 tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/wallet-stub.js create mode 100644 tests/prose/cases/spec-measures-a-false-claim/act.md create mode 100644 tests/prose/cases/spec-measures-a-false-claim/assert.md create mode 100644 tests/prose/cases/spec-measures-a-false-claim/case.json create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture-state.cjs create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture.md create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.claude/settings.json create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.recipe-hash create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/.state/migrations create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/_gitignore.fixture create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/manifest.json create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discussion/pay.md create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/manifest.json create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/src/lib/retry.js create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/capture.js create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/charge.js create mode 100644 tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/refund.js create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/act.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/assert.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/case.json create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture-state.cjs create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.claude/settings.json create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.recipe-hash create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/.state/migrations create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/_gitignore.fixture create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/manifest.json create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discovery/sessions/session-001.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discussion/pay.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/manifest.json create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/specification/pay/specification.md create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/address.js create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/cart.js create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/confirm.js create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/payment.js create mode 100644 tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/wallet-stub.js create mode 100644 tests/prose/stubs/spec-claims-source-defect.md diff --git a/tests/prose/cases/bridge-hands-off-to-planning/case.json b/tests/prose/cases/bridge-hands-off-to-planning/case.json index 18ea0bc9c..b878c1250 100644 --- a/tests/prose/cases/bridge-hands-off-to-planning/case.json +++ b/tests/prose/cases/bridge-hands-off-to-planning/case.json @@ -30,7 +30,7 @@ ], "conduct": "The user is turning their completed card-payments discussion into the specification. They know its decisions cold: the existing gateway account with no new provider onboarding, card-only for v1 with wallets deferred, and capture confirmed by gateway webhooks with no polling anywhere. They check each presented piece against what was actually decided — content faithful to the discussion gets an explicit yes; anything invented, embellished, or hedged beyond the record they correct before it is written. They want their own eyes on every piece before it is recorded: offered a way to approve the rest automatically, they decline and keep approving one at a time. They answer questions concretely and briefly, and they do not reopen decided questions or add new scope — the discussion said what it said. When asked to conclude, they confirm: the specification matches the discussion and they are done. On the way out they only move forward — offered a look back at earlier phases, they decline it and carry on; they have no instructions to attach and nothing more to add.", "stubs": { - "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — both the input review and the gap analysis return the content below and write no file" + "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — claims verification, input review, and gap analysis alike return the content below and write no file" }, "invariants": { "engine_before_write": true, diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/act.md b/tests/prose/cases/discussion-review-corrects-a-false-claim/act.md new file mode 100644 index 000000000..83b440165 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/act.md @@ -0,0 +1,5 @@ +Execute skills/workflow-discussion-entry/SKILL.md with arguments +$0=feature, $1=pay, and continue into the processing skill it hands off +to. Play the described user through the resumed session and its +conclusion. Stop at the hand-off that invokes the pipeline bridge — do +not follow into it. diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/assert.md b/tests/prose/cases/discussion-review-corrects-a-false-claim/assert.md new file mode 100644 index 000000000..dfea44b94 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/assert.md @@ -0,0 +1,50 @@ +The prose should have taken this path: + +1. the entry validates the in-progress discussion and routes to + resume; the process finds the discussion file and puts the resume + choice to the user, who continues +2. the resumed session re-reads its ground — the map shows both + subtopics decided — and the user wraps up rather than reopening + anything; no new subtopic is added +3. the closing gates run: the mandatory background review dispatches + through the engine and returns clean through the harness stub; the + final gap review finds nothing to add +4. document review re-reads the document and the map, then sweeps the + unverified-claims dimension: the Telemetry Coverage count is + load-bearing enough to check, its recorded command is re-run, and + the measurement contradicts it — five modules, not four +5. because the telemetry decision is per-module and survives the + corrected value, the fix is applied in place: the Journey's count + and command read the measured truth, the Decision block is + untouched, no dated timeline entry is created, and the change is + committed and mentioned to the user in the review brief — never put + to them as a decision to make +6. compliance self-check runs; conclusion puts the sign-off to the + user, and on their yes the topic completes through the engine — + the artifact indexes as part of that call — and the conclusion + commits +7. the walk stops at the hand-off to the pipeline bridge without + invoking it + +Further claims: + +- the discussion item moves in-progress → completed exactly once; no + reopen, no triage landing +- nothing outside .workflows changes: the checkout modules are read + and counted, never edited +- cache and scratch files under `.workflows/.cache/` are expected + working artifacts + +EXPECTED WORLD — from a feature holding an in-progress, fully decided +discussion and five checkout modules: + +- the discussion's Telemetry Coverage Journey reads the measured truth + — five modules, the command with its corrected result — with the + Decision block untouched, no timeline entry anywhere, and nothing + narrating the session that fixed it +- the rest of the document as the fixture wrote it, give or take + wrap-up polish that adds no new decisions +- the manifest holding the discussion item completed, both map + subtopics decided, and no phase beyond discussion +- the five files under src/checkout/ byte-identical to the fixture +- no specification, planning, or later artifacts anywhere diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/case.json b/tests/prose/cases/discussion-review-corrects-a-false-claim/case.json new file mode 100644 index 000000000..736d41a33 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/case.json @@ -0,0 +1,63 @@ +{ + "origin": "idea 40's root defect was a discussion shipping unmeasured false tree claims that every downstream phase inherited — this walks the document review's unverified-claims dimension: the resumed session re-runs the recorded command at conclusion, corrects the value in place, and never turns an arithmetic fact into a decision", + "entry": "workflow-discussion-entry", + "world": "claims", + "files": [ + "skills/workflow-discussion-entry/SKILL.md", + "skills/workflow-shared/references/framework.md", + "skills/workflow-shared/references/instructions.md", + "skills/workflow-shared/references/casing-conventions.md", + "skills/workflow-shared/references/voice.md", + "skills/workflow-shared/references/ask-or-decide.md", + "skills/workflow-shared/references/ensure-discovery-item.md", + "skills/workflow-discussion-entry/references/validate-phase.md", + "skills/workflow-shared/references/reconcile-advisory.md", + "skills/workflow-discussion-entry/references/invoke-skill.md", + "skills/workflow-discussion-process/SKILL.md", + "skills/workflow-shared/references/resume-detection.md", + "skills/workflow-discussion-process/references/initialize-discussion.md", + "skills/workflow-discussion-process/references/template.md", + "skills/workflow-discussion-process/references/discussion-guidelines.md", + "skills/workflow-discussion-process/references/meeting-assistant.md", + "skills/workflow-discussion-process/references/guidelines.md", + "skills/workflow-knowledge/references/knowledge-usage.md", + "skills/workflow-knowledge/references/contextual-query.md", + "skills/workflow-shared/references/rerouted-concerns.md", + "skills/workflow-discussion-process/references/discussion-session.md", + "skills/workflow-discussion-process/references/closing-gates.md", + "skills/workflow-discussion-process/references/review-agent.md", + "skills/workflow-discussion-process/references/perspective-agents.md", + "skills/workflow-shared/references/background-agent-surfacing.md", + "skills/workflow-shared/references/natural-breaks.md", + "skills/workflow-discussion-process/references/final-review.md", + "skills/workflow-discussion-process/references/document-review.md", + "skills/workflow-discussion-process/references/conclude-discussion.md", + "skills/workflow-shared/references/compliance-check.md" + ], + "conduct": "The user settled this discussion last sitting and is back only to wrap it up. Shown where things stand they confirm both subtopics are done and ask to conclude — they reopen nothing, add nothing, and decline any offered exploration. They treat the checkout module count as descriptive: the telemetry rule is per-module whatever the number. Told during the review brief that the recorded count was re-measured and corrected from four to five, they take the note without ceremony — that is exactly what they expect a document review to do — and they would object to being asked to decide an arithmetic fact. Asked to conclude, they confirm.", + "stubs": { + "discussion-review-clean": "when the engine records a dispatch of kind review — write the content to the path the dispatch response returned" + }, + "invariants": { + "engine_before_write": true, + "calls_include": [ + "manifest get pay.discussion.pay status", + "render resume-gate pay.discussion.pay", + "agent dispatch pay discussion pay --kind review", + "workflow-discussion-process/scripts/gateway.cjs map pay pay", + "topic complete pay discussion pay" + ], + "calls_in_order": [ + "render resume-gate pay.discussion.pay", + "agent dispatch pay discussion pay --kind review", + "topic complete pay discussion pay" + ], + "calls_exclude": [ + "topic reopen", + "topic triage", + "discussion-map add", + "sources stale", + "workunit create" + ] + } +} diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture-state.cjs b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture-state.cjs new file mode 100644 index 000000000..ee8711b9c --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture-state.cjs @@ -0,0 +1,96 @@ +'use strict'; + +// An in-progress discussion, fully decided in an earlier sitting, +// carrying a false measured claim: the Telemetry Coverage Journey +// counted the checkout flow at four modules with its recorded command, +// and the world holds five. Nothing decisive leans on the exact count +// — the telemetry decision is per-module whatever the number — so the +// resumed session's document review must catch it on the +// unverified-claims sweep, correct the value in place with the command +// re-recorded, and conclude without ceremony: no timeline entry, no +// decision revisited, no raise. + +const m = require('../../mainlines/feature.cjs'); + +const WU = m.WU; + +module.exports = { + build(h) { + m.init(h); + m.create(h); + + // The checkout flow the discussion counted: five modules, not four. + const mod = (name, fn) => h.write(`src/checkout/${name}.js`, [ + "'use strict';", + '', + `module.exports = function ${fn}(order) {`, + ' return order;', + '};', + '', + ].join('\n')); + mod('cart', 'cart'); + mod('address', 'address'); + mod('payment', 'payment'); + mod('confirm', 'confirm'); + mod('wallet-stub', 'walletStub'); + h.git('add', 'src'); + h.git('commit', '-q', '-m', 'src: checkout modules'); + + h.engine('topic', 'start', WU, 'discussion', WU); + h.write(`.workflows/${WU}/discussion/${WU}.md`, [ + '# Discussion: Pay', + '', + '## Context', + '', + 'Accept card payments at checkout using the existing gateway account.', + '', + '---', + '', + '## Gateway Integration', + '', + '### Context', + 'Which account and confirmation path the checkout uses.', + '', + '### Decision', + 'Use the existing gateway account — no new provider onboarding.', + 'Capture is confirmed by gateway webhooks; the checkout never polls.', + '', + '---', + '', + '## Telemetry Coverage', + '', + '### Context', + 'Where payment telemetry lands in the checkout flow.', + '', + '### Journey', + 'We counted the flow before deciding placement: the checkout spans', + 'four modules (`ls src/checkout/*.js | wc -l` → 4). Per-module', + 'boundaries beat a single funnel event — failures localise to the', + 'module that dropped the order.', + '', + '### Decision', + 'Every checkout module emits payment telemetry at its boundary —', + 'the rule is per-module, whatever the module count.', + '', + '---', + '', + '## Summary', + '', + '### Key Insights', + '1. Per-module telemetry localises checkout failures without a', + ' funnel rebuild.', + '', + '### Open Threads', + '- (none)', + '', + '### Current State', + '- Gateway integration and telemetry coverage are both resolved.', + '', + ].join('\n')); + h.engine('discussion-map', 'add', WU, WU, 'gateway-integration'); + h.engine('discussion-map', 'set', WU, WU, 'gateway-integration', 'decided'); + h.engine('discussion-map', 'add', WU, WU, 'telemetry-coverage'); + h.engine('discussion-map', 'set', WU, WU, 'telemetry-coverage', 'decided'); + h.engine('commit', WU, '-m', `discussion(${WU}): capture`); + }, +}; diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture.md b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture.md new file mode 100644 index 000000000..65e2ed6bc --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture.md @@ -0,0 +1,14 @@ +A feature discussion in progress, fully decided in an earlier sitting: +card payments at checkout — the existing gateway account with +webhook-confirmed capture, and per-module payment telemetry across the +checkout flow. Both subtopics read decided on the map; the document's +Summary is populated. + +One recorded measurement is false. The Telemetry Coverage Journey +counted the checkout flow at four modules (`ls src/checkout/*.js | +wc -l` → 4); the world's tree holds five files under src/checkout/ — +wallet-stub.js exists too. Nothing decisive leans on the exact number: +the telemetry decision is per-module, whatever the count. + +The context was cleared between sittings — this session opens cold at +the entry skill with the discussion in progress and what is on disk. diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.claude/settings.json b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.claude/settings.json new file mode 100644 index 000000000..ae019ede5 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.claude/settings.json @@ -0,0 +1,9 @@ +{ + "showClearContextOnPlanAccept": true, + "permissions": { + "allow": [ + "Edit(.workflows/**)", + "Bash(mv .workflows/:*)" + ] + } +} diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.recipe-hash b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.recipe-hash new file mode 100644 index 000000000..19c66dd76 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.recipe-hash @@ -0,0 +1 @@ +22ec346be8af026e8a51176f45742aee8313e71b91900c1bb42b103106b7b8f2 diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/.state/migrations b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/.state/migrations new file mode 100644 index 000000000..82238d2f5 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/.state/migrations @@ -0,0 +1,56 @@ +001 +002 +003 +004 +005 +006 +007 +008 +009 +010 +011 +012 +013 +014 +015 +016 +017 +018 +019 +020 +021 +022 +023 +024 +025 +026 +027 +028 +029 +030 +031 +032 +033 +034 +035 +036 +037 +038 +039 +040 +041 +042 +043 +044 +045 +046 +047 +048 +049 +050 +051 +052 +053 +054 +055 +056 diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/_gitignore.fixture b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/_gitignore.fixture new file mode 100644 index 000000000..0a3b4360c --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/_gitignore.fixture @@ -0,0 +1,9 @@ +.cache/ +.manifest.json.*.tmp +.lock +.lock.breaking +.project-lock +.project-lock.breaking +.commit-lock +.commit-lock.breaking +.knowledge/*.tmp diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/manifest.json b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/manifest.json new file mode 100644 index 000000000..987f6c236 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/manifest.json @@ -0,0 +1,7 @@ +{ + "work_units": { + "pay": { + "work_type": "feature" + } + } +} diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md new file mode 100644 index 000000000..2aab96961 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md @@ -0,0 +1,39 @@ +# Discovery Session 001 + +Date: 2026-01-01 +Work unit: pay + +## Description (as of session) + +Accept card payments at checkout. + +## Seed + +(none) + +## Imports + +(none) + +## Map State at Start + +(n/a — single-topic work) + +## Exploration + +Shaped as a single feature: accept card payments at checkout using +the existing gateway account. Card-only for v1 came up early and was +softly agreed; wallet support was noted as a likely deferral. No +research need surfaced — routed straight to discussion. + +## Edits + +(none) + +## Topics Identified + +(none) + +## Conclusion + +(none) diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discussion/pay.md b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discussion/pay.md new file mode 100644 index 000000000..73c7ef7ba --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/discussion/pay.md @@ -0,0 +1,47 @@ +# Discussion: Pay + +## Context + +Accept card payments at checkout using the existing gateway account. + +--- + +## Gateway Integration + +### Context +Which account and confirmation path the checkout uses. + +### Decision +Use the existing gateway account — no new provider onboarding. +Capture is confirmed by gateway webhooks; the checkout never polls. + +--- + +## Telemetry Coverage + +### Context +Where payment telemetry lands in the checkout flow. + +### Journey +We counted the flow before deciding placement: the checkout spans +four modules (`ls src/checkout/*.js | wc -l` → 4). Per-module +boundaries beat a single funnel event — failures localise to the +module that dropped the order. + +### Decision +Every checkout module emits payment telemetry at its boundary — +the rule is per-module, whatever the module count. + +--- + +## Summary + +### Key Insights +1. Per-module telemetry localises checkout failures without a + funnel rebuild. + +### Open Threads +- (none) + +### Current State +- Gateway integration and telemetry coverage are both resolved. diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/manifest.json b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/manifest.json new file mode 100644 index 000000000..590aadc99 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/.workflows/pay/manifest.json @@ -0,0 +1,26 @@ +{ + "name": "pay", + "work_type": "feature", + "status": "in-progress", + "created": "2026-01-01", + "description": "Accept card payments at checkout", + "phases": { + "discussion": { + "items": { + "pay": { + "status": "in-progress", + "subtopics": { + "gateway-integration": { + "status": "decided", + "parent": null + }, + "telemetry-coverage": { + "status": "decided", + "parent": null + } + } + } + } + } + } +} diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/address.js b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/address.js new file mode 100644 index 000000000..4e2fd3a3e --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/address.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function address(order) { + return order; +}; diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/cart.js b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/cart.js new file mode 100644 index 000000000..0bcf4608f --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/cart.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function cart(order) { + return order; +}; diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/confirm.js b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/confirm.js new file mode 100644 index 000000000..5398e32a7 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/confirm.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function confirm(order) { + return order; +}; diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/payment.js b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/payment.js new file mode 100644 index 000000000..7544f5255 --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/payment.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function payment(order) { + return order; +}; diff --git a/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/wallet-stub.js b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/wallet-stub.js new file mode 100644 index 000000000..937fa354e --- /dev/null +++ b/tests/prose/cases/discussion-review-corrects-a-false-claim/fixture/src/checkout/wallet-stub.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function walletStub(order) { + return order; +}; diff --git a/tests/prose/cases/spec-completes-the-cross-cutting/case.json b/tests/prose/cases/spec-completes-the-cross-cutting/case.json index 5c3a327db..93bd8120b 100644 --- a/tests/prose/cases/spec-completes-the-cross-cutting/case.json +++ b/tests/prose/cases/spec-completes-the-cross-cutting/case.json @@ -30,7 +30,7 @@ ], "conduct": "The user is turning their completed error-handling discussion into the specification for a project-wide standard. They know its decisions cold: one error envelope for every service (code, message, correlation_id), retryable versus terminal carried by the code range alone, and errors logged once at the service boundary with the correlation id while inner layers rethrow. They check each presented piece against what was actually decided — content faithful to the discussion gets an explicit yes; anything invented, embellished, or hedged beyond the record they correct before it is written. They want their own eyes on every piece before it is recorded: offered a way to approve the rest automatically, they decline and keep approving one at a time. They answer questions concretely and briefly, and they do not reopen decided questions or add new scope — the SDK helper library stays deferred. When asked to conclude, they confirm: the specification matches the discussion and they are done.", "stubs": { - "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — both the input review and the gap analysis return the content below and write no file" + "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — claims verification, input review, and gap analysis alike return the content below and write no file" }, "invariants": { "engine_before_write": true, diff --git a/tests/prose/cases/spec-extracts-the-discussion/assert.md b/tests/prose/cases/spec-extracts-the-discussion/assert.md index 8546250e8..85658bfd8 100644 --- a/tests/prose/cases/spec-extracts-the-discussion/assert.md +++ b/tests/prose/cases/spec-extracts-the-discussion/assert.md @@ -21,15 +21,14 @@ The prose should have taken this path: one pass, and auto mode is never engaged 6. when the discussion's relevant content is exhausted, its source row flips to incorporated -7. review cycle 1 initialises through the engine; the input-review - agent is dispatched first — against the discussion file as its - source material, never against the specification itself — and - returns clean through the harness stub, with no tracking file, so - the no-findings result is announced; only then is gap analysis - dispatched, with the same clean return; the two are never dispatched - in parallel -8. with both phases clean the review completes — no findings menus, no - second cycle — and the review state commits +7. review cycle 1 initialises through the engine; the claims + verification agent is dispatched first, then input review — against + the discussion file as its source material, never against the + specification itself — then gap analysis, each returning clean + through the harness stub with no tracking file, so each no-findings + result is announced; no two agents are ever dispatched in parallel +8. with all three phases clean the review completes — no findings + menus, no second cycle — and the review state commits 9. the compliance self-check re-reads the session's instructions; completion verifies tracking, sources, and consult references, and puts the sign-off to the user diff --git a/tests/prose/cases/spec-extracts-the-discussion/case.json b/tests/prose/cases/spec-extracts-the-discussion/case.json index 8b5cb8681..2fd4c1bd1 100644 --- a/tests/prose/cases/spec-extracts-the-discussion/case.json +++ b/tests/prose/cases/spec-extracts-the-discussion/case.json @@ -28,7 +28,7 @@ ], "conduct": "The user is turning their completed card-payments discussion into the specification. They know its decisions cold: the existing gateway account with no new provider onboarding, card-only for v1 with wallets deferred, and capture confirmed by gateway webhooks with no polling anywhere. They check each presented piece against what was actually decided — content faithful to the discussion gets an explicit yes; anything invented, embellished, or hedged beyond the record they correct before it is written. They want their own eyes on every piece before it is recorded: offered a way to approve the rest automatically, they decline and keep approving one at a time. They answer questions concretely and briefly, and they do not reopen decided questions or add new scope — the discussion said what it said. When asked to conclude, they confirm: the specification matches the discussion and they are done.", "stubs": { - "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — both the input review and the gap analysis return the content below and write no file" + "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — claims verification, input review, and gap analysis alike return the content below and write no file" }, "invariants": { "engine_before_write": true, diff --git a/tests/prose/cases/spec-measures-a-false-claim/act.md b/tests/prose/cases/spec-measures-a-false-claim/act.md new file mode 100644 index 000000000..7a94854a9 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/act.md @@ -0,0 +1,5 @@ +Execute skills/workflow-specification-entry/SKILL.md with arguments +$0=feature, $1=pay, and continue into the processing skill it hands off +to. Play the described user through the whole specification pass to its +conclusion. Stop when the prose reaches the pipeline continuation — do +not invoke the bridge. diff --git a/tests/prose/cases/spec-measures-a-false-claim/assert.md b/tests/prose/cases/spec-measures-a-false-claim/assert.md new file mode 100644 index 000000000..d6b82dff5 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/assert.md @@ -0,0 +1,80 @@ +The prose should have taken this path: + +1. the entry's source gate renders empty — the discussion is completed, + nothing blocks; the phase status reads empty so the verb is a + creation, and the handoff names the discussion as source material — + the entry asks the user nothing +2. the process finds no specification file — a fresh start, no resume + choice is put to the user; initialisation registers the item, the + pending source row, review state, and both gate modes, and commits +3. construction runs gated, one topic at a time — each piece presented + in the form it will take in the specification and explicitly + approved before any write; auto mode is never engaged +4. at the failure-handling ground, the discussion's load-bearing claim + — every webhook handler wraps its work in withRetry — is verified + against the tree before extraction: the walk re-runs the recorded + command (or an equivalent measurement) and finds it false — + src/webhooks/refund.js does not retry +5. because the no-reconciliation decision leans on the falsified claim, + the session STOPS conversationally: it puts the document's + assertion, the command and its measured result, and the leaning + decision to the user, and takes a stance on whether the decision + survives. It never extracts the claim as-is, never patches the + mismatch in the spec alone, and never renders the incoherence + conflict gate — no sides are documented; this is an exchange, not a + gate +6. on the user's settlement (require the refund handler to wrap in + withRetry as part of this work; with that, no reconciliation job + stands), the walk checks presence, then lands the resolution in the + discussion's own document: a dated timeline entry above the prior + Decision prose (wrapped under an Initial heading), the Trigger line + citing the failed measurement — never specification or this + session — and the Key Insight resting on the claim repaired in place +7. the edited discussion is reindexed through the knowledge CLI; the + sources-stale safety valve is skipped — single-topic work has no + sibling specs — and the resolution commits scoped to the discussion +8. construction continues against the corrected record: the + specification's failure-handling content carries the corrected claim + with its command and result, and the refund-handler retry + requirement +9. the source row flips to incorporated when extraction exhausts; + review cycle 1 runs claims verification, input review, and gap + analysis sequentially, each clean through the stubs, never in + parallel; completion verifies tracking and sources and puts the + sign-off to the user; on their yes the topic completes through the + engine and the conclusion commits +10. the walk stops at the pipeline continuation without invoking the + bridge + +Further claims: + +- the discussion item never leaves completed — no reopen, no triage + landing, no new topic +- nothing outside .workflows changes: the webhook sources are read and + measured, never edited +- cache and scratch files under `.workflows/.cache/` are expected + working artifacts + +EXPECTED WORLD — from a feature holding a completed discussion, three +webhook handler files, and nothing later: + +- the discussion's Failure Handling decision reads as a dated timeline: + the top entry requires the refund handler to wrap in withRetry and + keeps no-reconciliation on that corrected basis, its trigger citing + the failed measurement; the original decision survives wrapped + beneath it; the Key Insight no longer asserts uniform retry wrapping + as a standing fact; nothing in the document narrates that the change + came from specification +- a standalone specification at + `.workflows/pay/specification/pay/specification.md` whose + failure-handling content matches the corrected record — the measured + claim carried with its command and result, the refund-handler retry + requirement present, no reconciliation job required +- the manifest holding the specification completed with a date, the + discussion source incorporated, review_cycle at 1, both gate modes + gated, and no tracking entries; the discussion item untouched and + still completed +- src/lib/retry.js and the three files under src/webhooks/ + byte-identical to the fixture +- no review tracking files on disk — clean reviews write none; no + planning, implementation, or review artifacts anywhere diff --git a/tests/prose/cases/spec-measures-a-false-claim/case.json b/tests/prose/cases/spec-measures-a-false-claim/case.json new file mode 100644 index 000000000..580053fc8 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/case.json @@ -0,0 +1,71 @@ +{ + "origin": "idea 40 observed a spec session silently patching a source's false tree claim in the spec alone — this walks the reality trigger: construction verifies the load-bearing claim, meets the mismatch, stops conversationally because the decision leans on it, and lands the settlement in the discussion's own record", + "entry": "workflow-specification-entry", + "world": "claims", + "files": [ + "skills/workflow-specification-entry/SKILL.md", + "skills/workflow-shared/references/framework.md", + "skills/workflow-shared/references/instructions.md", + "skills/workflow-shared/references/casing-conventions.md", + "skills/workflow-shared/references/voice.md", + "skills/workflow-shared/references/ask-or-decide.md", + "skills/workflow-specification-entry/references/validate-source.md", + "skills/workflow-specification-entry/references/validate-phase.md", + "skills/workflow-specification-entry/references/invoke-skill.md", + "skills/workflow-specification-process/SKILL.md", + "skills/workflow-specification-process/references/verify-source-material.md", + "skills/workflow-specification-process/references/initialize-specification.md", + "skills/workflow-specification-process/references/specification-format.md", + "skills/workflow-specification-process/references/session-setup.md", + "skills/workflow-specification-process/references/specification-principles.md", + "skills/workflow-specification-process/references/spec-construction.md", + "skills/workflow-specification-process/references/resolve-source-incoherence.md", + "skills/workflow-specification-process/references/exhaustive-extraction.md", + "skills/workflow-specification-process/references/spec-review.md", + "skills/workflow-specification-process/references/review-tracking-format.md", + "skills/workflow-specification-process/references/process-review-findings.md", + "skills/workflow-specification-process/references/spec-completion.md", + "skills/workflow-discussion-process/references/template.md", + "skills/workflow-shared/references/compliance-check.md" + ], + "conduct": "The user is turning their completed card-payments discussion into the specification and knows its record cold: the existing gateway account, webhook-confirmed capture with no polling, and no reconciliation job for v1 on the strength of every handler retrying. When the session raises the failed measurement — the refund handler does not wrap in withRetry — they engage on the merits and settle it: require the refund handler to wrap in withRetry as part of this work; with that, the no-reconciliation decision stands. They expect the correction to land in the discussion's own record as that format's dated re-decision, not a rewrite, and would object to it being patched only in the specification. Otherwise they check each presented piece against what was decided — faithful content gets an explicit yes; anything invented or hedged beyond the record they correct before it is written. Offered a way to approve the rest automatically, they decline and keep approving one piece at a time. They answer concretely, never add scope, and never reopen decided questions beyond the one raised to them. When asked to conclude, they confirm.", + "stubs": { + "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — claims verification, input review, and gap analysis alike return the content below and write no file" + }, + "invariants": { + "engine_before_write": true, + "calls_include": [ + "render entry-gate pay.specification.pay", + "manifest get pay.specification.pay status", + "topic start pay specification pay", + "sources.pay.status pending", + "sources.pay.status incorporated", + "review_cycle=0", + "finding_gate_mode=gated", + "presence scan pay", + "knowledge.cjs index .workflows/pay/discussion/pay.md", + "--topic discussion/pay", + "manifest set pay.specification.pay review_cycle 1", + "topic complete pay specification pay", + "spec(pay): conclude specification" + ], + "calls_in_order": [ + "topic start pay specification pay", + "presence scan pay", + "write:.workflows/pay/discussion/pay.md", + "knowledge.cjs index .workflows/pay/discussion/pay.md", + "manifest set pay.specification.pay review_cycle 1", + "topic complete pay specification pay" + ], + "calls_exclude": [ + "topic reopen", + "topic triage", + "topic supersede", + "sources stale", + "render incoherence-gate", + "construction_gate_mode auto", + "finding_gate_mode auto", + "workunit create" + ] + } +} diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture-state.cjs b/tests/prose/cases/spec-measures-a-false-claim/fixture-state.cjs new file mode 100644 index 000000000..70df90e19 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture-state.cjs @@ -0,0 +1,133 @@ +'use strict'; + +// A completed discussion carrying a false load-bearing claim about the +// tree it describes. The discussion recorded its measurement — every +// webhook handler wraps its work in withRetry — and decided against a +// reconciliation job on that basis; in the world as it stands, +// src/webhooks/refund.js does not retry, so the recorded command +// contradicts the record. Construction must verify the claim before +// extracting it, stop conversationally (the falsity undermines the +// leaning decision), land the settlement in the discussion's own +// document, reindex it, skip the sources-stale valve (single-topic), +// and continue — the spec never absorbs the defect. + +const m = require('../../mainlines/feature.cjs'); + +const WU = m.WU; + +module.exports = { + build(h) { + m.init(h); + m.create(h); + + // The codebase the discussion measured: three webhook handlers, two + // wrapping their work in withRetry, the refund handler bare. + h.write('src/lib/retry.js', [ + "'use strict';", + '', + 'async function withRetry(fn) {', + ' for (let attempt = 1; ; attempt += 1) {', + ' try { return await fn(); } catch (err) {', + ' if (attempt >= 3) throw err;', + ' }', + ' }', + '}', + '', + 'module.exports = { withRetry };', + '', + ].join('\n')); + h.write('src/webhooks/charge.js', [ + "'use strict';", + '', + "const { withRetry } = require('../lib/retry');", + "const { applyCharge } = require('../payments');", + '', + 'module.exports = async function charge(event) {', + ' return withRetry(() => applyCharge(event));', + '};', + '', + ].join('\n')); + h.write('src/webhooks/capture.js', [ + "'use strict';", + '', + "const { withRetry } = require('../lib/retry');", + "const { applyCapture } = require('../payments');", + '', + 'module.exports = async function capture(event) {', + ' return withRetry(() => applyCapture(event));', + '};', + '', + ].join('\n')); + h.write('src/webhooks/refund.js', [ + "'use strict';", + '', + "const { applyRefund } = require('../payments');", + '', + 'module.exports = async function refund(event) {', + ' return applyRefund(event);', + '};', + '', + ].join('\n')); + h.git('add', 'src'); + h.git('commit', '-q', '-m', 'src: webhook handlers'); + + // The completed discussion — template-shaped, with the false + // measured claim in Failure Handling and a Key Insight leaning on + // it. + h.engine('topic', 'start', WU, 'discussion', WU); + h.write(`.workflows/${WU}/discussion/${WU}.md`, [ + '# Discussion: Pay', + '', + '## Context', + '', + 'Accept card payments at checkout using the existing gateway account.', + '', + '---', + '', + '## Gateway Integration', + '', + '### Context', + 'Which account and confirmation path the checkout uses.', + '', + '### Decision', + 'Use the existing gateway account — no new provider onboarding.', + 'Capture is confirmed by gateway webhooks; the checkout never polls.', + '', + '---', + '', + '## Failure Handling', + '', + '### Context', + 'Whether transient gateway failures need a reconciliation job.', + '', + '### Journey', + 'We started assuming a nightly reconciliation job was unavoidable,', + 'then checked what the webhook layer already does: every webhook', + 'handler wraps its work in withRetry (`grep -L withRetry', + 'src/webhooks/*.js` → no output), so a transient failure replays', + 'safely without a sweeper.', + '', + '### Decision', + 'No reconciliation job for v1 — every handler retries, so replayed', + 'webhooks cover transient gateway failures. Revisit only if retry', + 'exhaustion shows up in the logs.', + '', + '---', + '', + '## Summary', + '', + '### Key Insights', + '1. The webhook layer\'s uniform retry wrapping is what makes a', + ' reconciliation job unnecessary.', + '', + '### Open Threads', + '- (none)', + '', + '### Current State', + '- Gateway integration and failure handling are both resolved.', + '', + ].join('\n')); + h.engine('commit', WU, '-m', `discussion(${WU}): capture`); + h.engine('topic', 'complete', WU, 'discussion', WU); + }, +}; diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture.md b/tests/prose/cases/spec-measures-a-false-claim/fixture.md new file mode 100644 index 000000000..97b7097c8 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture.md @@ -0,0 +1,18 @@ +A feature whose discussion is complete: card payments at checkout, +decided through — the existing gateway account, webhook-confirmed +capture, and no reconciliation job for v1. The no-reconciliation +decision rests on a recorded measurement: every webhook handler wraps +its work in withRetry (`grep -L withRetry src/webhooks/*.js` → no +output), and a Key Insight names that uniform wrapping as the reason no +sweeper is needed. + +The world's tree says otherwise. Three handler files exist under +src/webhooks/ — charge and capture wrap their work in withRetry; +refund.js does not. The recorded command, re-run today, prints +src/webhooks/refund.js. The discussion's claim was false when written, +and the decision leaning on it has never been re-weighed. + +No specification exists anywhere and no phase beyond discussion has +run. The context was cleared at the phase boundary — this session opens +cold at the entry skill with nothing but the two arguments and what is +on disk. diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.claude/settings.json b/tests/prose/cases/spec-measures-a-false-claim/fixture/.claude/settings.json new file mode 100644 index 000000000..ae019ede5 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.claude/settings.json @@ -0,0 +1,9 @@ +{ + "showClearContextOnPlanAccept": true, + "permissions": { + "allow": [ + "Edit(.workflows/**)", + "Bash(mv .workflows/:*)" + ] + } +} diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.recipe-hash b/tests/prose/cases/spec-measures-a-false-claim/fixture/.recipe-hash new file mode 100644 index 000000000..cbc08a259 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.recipe-hash @@ -0,0 +1 @@ +fef30857862d2dfe2b60eb8855709545e904b6b6308671308bb88b88eed197e0 diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/.state/migrations b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/.state/migrations new file mode 100644 index 000000000..82238d2f5 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/.state/migrations @@ -0,0 +1,56 @@ +001 +002 +003 +004 +005 +006 +007 +008 +009 +010 +011 +012 +013 +014 +015 +016 +017 +018 +019 +020 +021 +022 +023 +024 +025 +026 +027 +028 +029 +030 +031 +032 +033 +034 +035 +036 +037 +038 +039 +040 +041 +042 +043 +044 +045 +046 +047 +048 +049 +050 +051 +052 +053 +054 +055 +056 diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/_gitignore.fixture b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/_gitignore.fixture new file mode 100644 index 000000000..0a3b4360c --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/_gitignore.fixture @@ -0,0 +1,9 @@ +.cache/ +.manifest.json.*.tmp +.lock +.lock.breaking +.project-lock +.project-lock.breaking +.commit-lock +.commit-lock.breaking +.knowledge/*.tmp diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/manifest.json b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/manifest.json new file mode 100644 index 000000000..987f6c236 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/manifest.json @@ -0,0 +1,7 @@ +{ + "work_units": { + "pay": { + "work_type": "feature" + } + } +} diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md new file mode 100644 index 000000000..2aab96961 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discovery/sessions/session-001.md @@ -0,0 +1,39 @@ +# Discovery Session 001 + +Date: 2026-01-01 +Work unit: pay + +## Description (as of session) + +Accept card payments at checkout. + +## Seed + +(none) + +## Imports + +(none) + +## Map State at Start + +(n/a — single-topic work) + +## Exploration + +Shaped as a single feature: accept card payments at checkout using +the existing gateway account. Card-only for v1 came up early and was +softly agreed; wallet support was noted as a likely deferral. No +research need surfaced — routed straight to discussion. + +## Edits + +(none) + +## Topics Identified + +(none) + +## Conclusion + +(none) diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discussion/pay.md b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discussion/pay.md new file mode 100644 index 000000000..ee4f0e171 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/discussion/pay.md @@ -0,0 +1,49 @@ +# Discussion: Pay + +## Context + +Accept card payments at checkout using the existing gateway account. + +--- + +## Gateway Integration + +### Context +Which account and confirmation path the checkout uses. + +### Decision +Use the existing gateway account — no new provider onboarding. +Capture is confirmed by gateway webhooks; the checkout never polls. + +--- + +## Failure Handling + +### Context +Whether transient gateway failures need a reconciliation job. + +### Journey +We started assuming a nightly reconciliation job was unavoidable, +then checked what the webhook layer already does: every webhook +handler wraps its work in withRetry (`grep -L withRetry +src/webhooks/*.js` → no output), so a transient failure replays +safely without a sweeper. + +### Decision +No reconciliation job for v1 — every handler retries, so replayed +webhooks cover transient gateway failures. Revisit only if retry +exhaustion shows up in the logs. + +--- + +## Summary + +### Key Insights +1. The webhook layer's uniform retry wrapping is what makes a + reconciliation job unnecessary. + +### Open Threads +- (none) + +### Current State +- Gateway integration and failure handling are both resolved. diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/manifest.json b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/manifest.json new file mode 100644 index 000000000..d4a3fca6c --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/.workflows/pay/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "pay", + "work_type": "feature", + "status": "in-progress", + "created": "2026-01-01", + "description": "Accept card payments at checkout", + "phases": { + "discussion": { + "items": { + "pay": { + "status": "completed" + } + } + } + } +} diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/src/lib/retry.js b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/lib/retry.js new file mode 100644 index 000000000..062fe7803 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/lib/retry.js @@ -0,0 +1,11 @@ +'use strict'; + +async function withRetry(fn) { + for (let attempt = 1; ; attempt += 1) { + try { return await fn(); } catch (err) { + if (attempt >= 3) throw err; + } + } +} + +module.exports = { withRetry }; diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/capture.js b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/capture.js new file mode 100644 index 000000000..c4206bbac --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/capture.js @@ -0,0 +1,8 @@ +'use strict'; + +const { withRetry } = require('../lib/retry'); +const { applyCapture } = require('../payments'); + +module.exports = async function capture(event) { + return withRetry(() => applyCapture(event)); +}; diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/charge.js b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/charge.js new file mode 100644 index 000000000..af39bd0ba --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/charge.js @@ -0,0 +1,8 @@ +'use strict'; + +const { withRetry } = require('../lib/retry'); +const { applyCharge } = require('../payments'); + +module.exports = async function charge(event) { + return withRetry(() => applyCharge(event)); +}; diff --git a/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/refund.js b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/refund.js new file mode 100644 index 000000000..de57e4d32 --- /dev/null +++ b/tests/prose/cases/spec-measures-a-false-claim/fixture/src/webhooks/refund.js @@ -0,0 +1,7 @@ +'use strict'; + +const { applyRefund } = require('../payments'); + +module.exports = async function refund(event) { + return applyRefund(event); +}; diff --git a/tests/prose/cases/spec-resolves-a-source-conflict/assert.md b/tests/prose/cases/spec-resolves-a-source-conflict/assert.md index 87bf85e01..d6db07c8e 100644 --- a/tests/prose/cases/spec-resolves-a-source-conflict/assert.md +++ b/tests/prose/cases/spec-resolves-a-source-conflict/assert.md @@ -37,8 +37,9 @@ The prose should have taken this path: 9. construction continues against the updated source; the chunk the conflict blocked is extracted from the now-coherent record; both source rows flip to incorporated when their extraction exhausts -10. review cycle 1 initialises; the input review and gap analysis - agents run sequentially and return clean through the stubs +10. review cycle 1 initialises; the claims verification, input review, + and gap analysis agents run sequentially and return clean through + the stubs 11. compliance self-check, then completion: the epic's cross-cutting assessment is confirmed with the user, tracking and sources verify, sign-off is put to the user, and on their yes the topic completes diff --git a/tests/prose/cases/spec-resolves-a-source-conflict/case.json b/tests/prose/cases/spec-resolves-a-source-conflict/case.json index bc21aa51b..c975527bd 100644 --- a/tests/prose/cases/spec-resolves-a-source-conflict/case.json +++ b/tests/prose/cases/spec-resolves-a-source-conflict/case.json @@ -32,7 +32,7 @@ ], "conduct": "The user is specifying the expansion pipeline from their two completed discussions and knows both records cold. When the batch-vs-live-stream conflict is raised they engage on the merits: the live click-signal stream will never be built — behavioural-ranking settled that — so they settle expansion as behaviour-driven computed from the nightly batch aggregates, refreshing daily; they accept the recommendation if it says exactly that, and correct it if it does not. They expect the fix to land in the discussion's own record — as that format's dated re-decision, not a rewrite — and would object to being asked to reopen a discussion for it. Otherwise they check each presented piece against what was decided — faithful content gets an explicit yes; invention gets corrected before writing. They keep approving one piece at a time when offered auto. They answer questions concretely, never add scope, and never reopen decided questions beyond the one conflict raised to them. Asked to confirm dependencies, the assessment, or the conclusion, they read and confirm; offered optional extras, they decline.", "stubs": { - "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — both the input review and the gap analysis return the content below and write no file" + "spec-review-clean": "each time the prose dispatches a specification review agent via the Task tool — claims verification, input review, and gap analysis alike return the content below and write no file" }, "invariants": { "engine_before_write": true, diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/act.md b/tests/prose/cases/spec-review-routes-a-source-defect/act.md new file mode 100644 index 000000000..c0884fa65 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/act.md @@ -0,0 +1,5 @@ +Execute skills/workflow-specification-entry/SKILL.md with arguments +$0=feature, $1=pay, and continue into the processing skill it hands off +to. Play the described user through the resumed specification pass to +its conclusion. Stop when the prose reaches the pipeline continuation — +do not invoke the bridge. diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/assert.md b/tests/prose/cases/spec-review-routes-a-source-defect/assert.md new file mode 100644 index 000000000..d93586844 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/assert.md @@ -0,0 +1,74 @@ +The prose should have taken this path: + +1. the entry validates the in-progress specification and routes to + resume; the process finds the specification file and puts the + resume choice to the user, who continues +2. session setup resets the gate modes and finds no consult + references; construction finds the source incorporated and nothing + left to extract — no content is re-presented, no re-extraction runs +3. review cycle 1 initialises through the engine; the claims + verification agent is dispatched first and returns findings through + the harness stub, having written the c1 claims tracking file; the + tracking entry records in-progress and commits +4. the findings summary renders from the tracking file; the one + finding's category is Source defect, so it is never presented at + the finding gate, never applied to the specification as a finding, + and never skipped — the orchestrator routes it +5. classification re-runs the measurement itself — five checkout + modules, not four — and, with every citing conclusion surviving the + corrected value (the telemetry rule is per-module), takes the + value-only lane: a one-line notify to the user, no gate, no + incoherence conflict surface +6. the walk checks presence, then lands the correction in the + discussion's own document in place: the Journey's count and command + read the measured truth; no Decision block is revised, so no dated + timeline entry is created and the document never narrates the + session that fixed it +7. the edited discussion is reindexed through the knowledge CLI; the + sources-stale safety valve is skipped — single-topic work has no + sibling specs — and the resolution commits scoped to the discussion +8. back in the findings flow the specification's own copy re-aligns to + the corrected source — the Telemetry Coverage count now reads five + with its command — without a gate; the finding's resolution records + Routed and the tracking entry completes +9. input review and gap analysis run next, each clean through the + stubs, never in parallel with anything +10. findings were surfaced, so the re-loop prompt is fetched from the + engine (the reloop variant) and the turn stops; the user proceeds + to completion +11. completion verifies tracking and the incorporated source, puts the + sign-off to the user, and on their yes the topic completes through + the engine and the conclusion commits +12. the walk stops at the pipeline continuation without invoking the + bridge + +Further claims: + +- the discussion item never leaves completed — no reopen, no triage + landing +- auto mode is never engaged on either gate; the routed finding never + rides any auto lane +- nothing outside .workflows changes: the checkout modules are read + and counted, never edited +- cache and scratch files under `.workflows/.cache/` are expected + working artifacts + +EXPECTED WORLD — from a feature holding a completed discussion, five +checkout modules, and a constructed specification awaiting review: + +- the discussion's Telemetry Coverage Journey reads the measured truth + — five modules, the command with its corrected result — with the + Decision block untouched and no timeline entry anywhere; nothing in + the document narrates specification or this session +- the specification's Telemetry Coverage content matches the corrected + record — five modules, the command with its corrected result, the + per-module telemetry rule unchanged +- the c1 claims tracking file on disk with its one finding resolved + Routed and a note naming where it landed; no input-review or + gap-analysis tracking files — clean reviews write none +- the manifest holding the specification completed with a date, the + source incorporated, review_cycle at 1, both gate modes gated, and + the claims tracking entry complete; the discussion item untouched + and still completed +- the five files under src/checkout/ byte-identical to the fixture +- no planning, implementation, or review artifacts anywhere diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/case.json b/tests/prose/cases/spec-review-routes-a-source-defect/case.json new file mode 100644 index 000000000..d10bf340e --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/case.json @@ -0,0 +1,75 @@ +{ + "origin": "idea 40's review loop could only apply, adjust, or skip — a finding indicting the source had nowhere to go. This walks the fourth verb: a claims finding whose false count lives in the discussion routes through the incoherence flow on the value-only lane, the correction lands in the source in place, and the spec's own copy re-aligns", + "entry": "workflow-specification-entry", + "world": "claims", + "files": [ + "skills/workflow-specification-entry/SKILL.md", + "skills/workflow-shared/references/framework.md", + "skills/workflow-shared/references/instructions.md", + "skills/workflow-shared/references/casing-conventions.md", + "skills/workflow-shared/references/voice.md", + "skills/workflow-shared/references/ask-or-decide.md", + "skills/workflow-shared/references/resume-detection.md", + "skills/workflow-specification-entry/references/validate-source.md", + "skills/workflow-specification-entry/references/validate-phase.md", + "skills/workflow-specification-entry/references/invoke-skill.md", + "skills/workflow-specification-process/SKILL.md", + "skills/workflow-specification-process/references/verify-source-material.md", + "skills/workflow-specification-process/references/initialize-specification.md", + "skills/workflow-specification-process/references/specification-format.md", + "skills/workflow-specification-process/references/session-setup.md", + "skills/workflow-specification-process/references/specification-principles.md", + "skills/workflow-specification-process/references/spec-construction.md", + "skills/workflow-specification-process/references/resolve-source-incoherence.md", + "skills/workflow-specification-process/references/exhaustive-extraction.md", + "skills/workflow-specification-process/references/spec-review.md", + "skills/workflow-specification-process/references/review-tracking-format.md", + "skills/workflow-specification-process/references/process-review-findings.md", + "skills/workflow-specification-process/references/spec-completion.md", + "skills/workflow-discussion-process/references/template.md", + "skills/workflow-shared/references/compliance-check.md" + ], + "conduct": "The user is resuming their card-payments specification to run its review; construction finished last sitting and they want the review pass, so offered the resume choice they continue. They know the record cold and treat the module count as descriptive — the telemetry decision is per-module whatever the number. Told the claims pass measured five checkout modules where both documents say four, and that the correction has landed in the discussion's own record with the spec re-aligned, they take the one-line notify without ceremony — that is exactly where they expect a count fix to go, and they would object to being asked to choose a side over an arithmetic fact. At the re-loop prompt they proceed to completion: the one finding was a count correction, another cycle is not owed. At sign-off they confirm. Throughout they answer concretely, never add scope, and never reopen decided questions.", + "stubs": { + "spec-claims-source-defect": "when the prose dispatches the claims verification agent via the Task tool for review cycle 1 — write the tracking file and return the status block as the stub describes", + "spec-review-clean": "when the prose dispatches the input review or gap analysis agent via the Task tool — each returns the content below and writes no file" + }, + "invariants": { + "engine_before_write": true, + "calls_include": [ + "render resume-gate pay.specification.pay", + "manifest set pay.specification.pay review_cycle 1", + "tracking.review-claims-tracking-c1 in-progress", + "render findings-summary pay.specification.pay", + "presence scan pay", + "knowledge.cjs index .workflows/pay/discussion/pay.md", + "--topic discussion/pay", + "tracking.review-claims-tracking-c1 complete", + "render spec-review-gate pay.specification.pay --variant reloop", + "topic complete pay specification pay", + "spec(pay): conclude specification" + ], + "calls_in_order": [ + "render resume-gate pay.specification.pay", + "manifest set pay.specification.pay review_cycle 1", + "tracking.review-claims-tracking-c1 in-progress", + "presence scan pay", + "write:.workflows/pay/discussion/pay.md", + "knowledge.cjs index .workflows/pay/discussion/pay.md", + "write:.workflows/pay/specification/pay/specification.md", + "tracking.review-claims-tracking-c1 complete", + "render spec-review-gate pay.specification.pay --variant reloop", + "topic complete pay specification pay" + ], + "calls_exclude": [ + "topic reopen", + "topic triage", + "topic supersede", + "sources stale", + "render incoherence-gate", + "construction_gate_mode auto", + "finding_gate_mode auto", + "workunit create" + ] + } +} diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture-state.cjs b/tests/prose/cases/spec-review-routes-a-source-defect/fixture-state.cjs new file mode 100644 index 000000000..56c4aedaa --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture-state.cjs @@ -0,0 +1,130 @@ +'use strict'; + +// A specification mid-flow at the review boundary, faithfully carrying +// a source discussion's false count. The checkout flow claim — four +// modules, with its recorded command — sits in both documents; the +// world has five. Nothing decisive leans on the exact count (the +// telemetry decision covers every module, whatever the number), so +// this is the value-only lane: the claims pass reports a Source +// defect, the orchestrator routes it, the correction lands in the +// discussion in place (no decision revised, no timeline entry), the +// document reindexes, and the spec's own copy re-aligns — the +// discussion never leaves completed. + +const m = require('../../mainlines/feature.cjs'); + +const WU = m.WU; + +module.exports = { + build(h) { + m.init(h); + m.create(h); + + // The checkout flow the discussion counted: five modules, not four. + const mod = (name, fn) => h.write(`src/checkout/${name}.js`, [ + "'use strict';", + '', + `module.exports = function ${fn}(order) {`, + ' return order;', + '};', + '', + ].join('\n')); + mod('cart', 'cart'); + mod('address', 'address'); + mod('payment', 'payment'); + mod('confirm', 'confirm'); + mod('wallet-stub', 'walletStub'); + h.git('add', 'src'); + h.git('commit', '-q', '-m', 'src: checkout modules'); + + // The completed discussion — the false measured count in Telemetry + // Coverage's Journey; the decision survives any count. + h.engine('topic', 'start', WU, 'discussion', WU); + h.write(`.workflows/${WU}/discussion/${WU}.md`, [ + '# Discussion: Pay', + '', + '## Context', + '', + 'Accept card payments at checkout using the existing gateway account.', + '', + '---', + '', + '## Gateway Integration', + '', + '### Context', + 'Which account and confirmation path the checkout uses.', + '', + '### Decision', + 'Use the existing gateway account — no new provider onboarding.', + 'Capture is confirmed by gateway webhooks; the checkout never polls.', + '', + '---', + '', + '## Telemetry Coverage', + '', + '### Context', + 'Where payment telemetry lands in the checkout flow.', + '', + '### Journey', + 'We counted the flow before deciding placement: the checkout spans', + 'four modules (`ls src/checkout/*.js | wc -l` → 4). Per-module', + 'boundaries beat a single funnel event — failures localise to the', + 'module that dropped the order.', + '', + '### Decision', + 'Every checkout module emits payment telemetry at its boundary —', + 'the rule is per-module, whatever the module count.', + '', + '---', + '', + '## Summary', + '', + '### Key Insights', + '1. Per-module telemetry localises checkout failures without a', + ' funnel rebuild.', + '', + '### Open Threads', + '- (none)', + '', + '### Current State', + '- Gateway integration and telemetry coverage are both resolved.', + '', + ].join('\n')); + h.engine('commit', WU, '-m', `discussion(${WU}): capture`); + h.engine('topic', 'complete', WU, 'discussion', WU); + + // Construction done in an earlier sitting: the spec carries the + // discussion's claim faithfully, the source row is incorporated, + // review has not begun. + h.engine('topic', 'start', WU, 'specification', WU); + h.engine('manifest', 'set', `${WU}.specification.${WU}`, + `sources.${WU}.status=pending`, + 'review_cycle=0', + 'finding_gate_mode=gated', + 'construction_gate_mode=gated'); + h.write(`.workflows/${WU}/specification/${WU}/specification.md`, [ + '# Specification: Pay', + '', + '## Specification', + '', + '### Gateway Integration', + '', + '- Checkout creates payment intents against the existing gateway', + ' account; card payments only.', + '- Capture is confirmed by gateway webhook, never by polling.', + '', + '### Telemetry Coverage', + '', + '- The checkout flow spans four modules', + ' (`ls src/checkout/*.js | wc -l` → 4); every checkout module', + ' emits payment telemetry at its boundary.', + '', + '---', + '', + '## Working Notes', + '', + ].join('\n')); + h.engine('manifest', 'set', `${WU}.specification.${WU}`, `sources.${WU}.status`, 'incorporated'); + h.engine('commit', WU, '-m', `spec(${WU}): construct`); + }, +}; diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture.md b/tests/prose/cases/spec-review-routes-a-source-defect/fixture.md new file mode 100644 index 000000000..cfe798da4 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture.md @@ -0,0 +1,14 @@ +A feature whose specification stands at the review boundary. +Construction concluded in an earlier sitting: the card-payments +discussion is completed, its content extracted, the source row +incorporated, review not yet begun. + +Both documents carry the same false measured claim. The discussion +counted the checkout flow at four modules (`ls src/checkout/*.js | +wc -l` → 4) and the specification transcribed the count faithfully; +the world's tree holds five files under src/checkout/ — wallet-stub.js +exists too. Nothing decisive leans on the exact number: the telemetry +decision is per-module, whatever the count. + +The context was cleared between sittings — this session opens cold at +the entry skill with the spec in progress and what is on disk. diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.claude/settings.json b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.claude/settings.json new file mode 100644 index 000000000..ae019ede5 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.claude/settings.json @@ -0,0 +1,9 @@ +{ + "showClearContextOnPlanAccept": true, + "permissions": { + "allow": [ + "Edit(.workflows/**)", + "Bash(mv .workflows/:*)" + ] + } +} diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.recipe-hash b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.recipe-hash new file mode 100644 index 000000000..cc0d01750 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.recipe-hash @@ -0,0 +1 @@ +9be498955ee9f6e0df7011825cc8a42a65b516e1a84ac980275c516cac3570f7 diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/.state/migrations b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/.state/migrations new file mode 100644 index 000000000..82238d2f5 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/.state/migrations @@ -0,0 +1,56 @@ +001 +002 +003 +004 +005 +006 +007 +008 +009 +010 +011 +012 +013 +014 +015 +016 +017 +018 +019 +020 +021 +022 +023 +024 +025 +026 +027 +028 +029 +030 +031 +032 +033 +034 +035 +036 +037 +038 +039 +040 +041 +042 +043 +044 +045 +046 +047 +048 +049 +050 +051 +052 +053 +054 +055 +056 diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/_gitignore.fixture b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/_gitignore.fixture new file mode 100644 index 000000000..0a3b4360c --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/_gitignore.fixture @@ -0,0 +1,9 @@ +.cache/ +.manifest.json.*.tmp +.lock +.lock.breaking +.project-lock +.project-lock.breaking +.commit-lock +.commit-lock.breaking +.knowledge/*.tmp diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/manifest.json b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/manifest.json new file mode 100644 index 000000000..987f6c236 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/manifest.json @@ -0,0 +1,7 @@ +{ + "work_units": { + "pay": { + "work_type": "feature" + } + } +} diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discovery/sessions/session-001.md b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discovery/sessions/session-001.md new file mode 100644 index 000000000..2aab96961 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discovery/sessions/session-001.md @@ -0,0 +1,39 @@ +# Discovery Session 001 + +Date: 2026-01-01 +Work unit: pay + +## Description (as of session) + +Accept card payments at checkout. + +## Seed + +(none) + +## Imports + +(none) + +## Map State at Start + +(n/a — single-topic work) + +## Exploration + +Shaped as a single feature: accept card payments at checkout using +the existing gateway account. Card-only for v1 came up early and was +softly agreed; wallet support was noted as a likely deferral. No +research need surfaced — routed straight to discussion. + +## Edits + +(none) + +## Topics Identified + +(none) + +## Conclusion + +(none) diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discussion/pay.md b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discussion/pay.md new file mode 100644 index 000000000..73c7ef7ba --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/discussion/pay.md @@ -0,0 +1,47 @@ +# Discussion: Pay + +## Context + +Accept card payments at checkout using the existing gateway account. + +--- + +## Gateway Integration + +### Context +Which account and confirmation path the checkout uses. + +### Decision +Use the existing gateway account — no new provider onboarding. +Capture is confirmed by gateway webhooks; the checkout never polls. + +--- + +## Telemetry Coverage + +### Context +Where payment telemetry lands in the checkout flow. + +### Journey +We counted the flow before deciding placement: the checkout spans +four modules (`ls src/checkout/*.js | wc -l` → 4). Per-module +boundaries beat a single funnel event — failures localise to the +module that dropped the order. + +### Decision +Every checkout module emits payment telemetry at its boundary — +the rule is per-module, whatever the module count. + +--- + +## Summary + +### Key Insights +1. Per-module telemetry localises checkout failures without a + funnel rebuild. + +### Open Threads +- (none) + +### Current State +- Gateway integration and telemetry coverage are both resolved. diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/manifest.json b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/manifest.json new file mode 100644 index 000000000..9ef077b52 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/manifest.json @@ -0,0 +1,31 @@ +{ + "name": "pay", + "work_type": "feature", + "status": "in-progress", + "created": "2026-01-01", + "description": "Accept card payments at checkout", + "phases": { + "discussion": { + "items": { + "pay": { + "status": "completed" + } + } + }, + "specification": { + "items": { + "pay": { + "status": "in-progress", + "sources": { + "pay": { + "status": "incorporated" + } + }, + "review_cycle": 0, + "finding_gate_mode": "gated", + "construction_gate_mode": "gated" + } + } + } + } +} diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/specification/pay/specification.md b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/specification/pay/specification.md new file mode 100644 index 000000000..7466c7fbe --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/.workflows/pay/specification/pay/specification.md @@ -0,0 +1,19 @@ +# Specification: Pay + +## Specification + +### Gateway Integration + +- Checkout creates payment intents against the existing gateway + account; card payments only. +- Capture is confirmed by gateway webhook, never by polling. + +### Telemetry Coverage + +- The checkout flow spans four modules + (`ls src/checkout/*.js | wc -l` → 4); every checkout module + emits payment telemetry at its boundary. + +--- + +## Working Notes diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/address.js b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/address.js new file mode 100644 index 000000000..4e2fd3a3e --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/address.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function address(order) { + return order; +}; diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/cart.js b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/cart.js new file mode 100644 index 000000000..0bcf4608f --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/cart.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function cart(order) { + return order; +}; diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/confirm.js b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/confirm.js new file mode 100644 index 000000000..5398e32a7 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/confirm.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function confirm(order) { + return order; +}; diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/payment.js b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/payment.js new file mode 100644 index 000000000..7544f5255 --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/payment.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function payment(order) { + return order; +}; diff --git a/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/wallet-stub.js b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/wallet-stub.js new file mode 100644 index 000000000..937fa354e --- /dev/null +++ b/tests/prose/cases/spec-review-routes-a-source-defect/fixture/src/checkout/wallet-stub.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function walletStub(order) { + return order; +}; diff --git a/tests/prose/stubs/spec-claims-source-defect.md b/tests/prose/stubs/spec-claims-source-defect.md new file mode 100644 index 000000000..e4f164e54 --- /dev/null +++ b/tests/prose/stubs/spec-claims-source-defect.md @@ -0,0 +1,46 @@ +# stub: spec-claims-source-defect + +A claims verification agent whose measurement pass finds one failing +claim that lives in the source record. Write the tracking file to +`.workflows/{work_unit}/specification/{topic}/review-claims-tracking-c1.md` +via the `.txt`-then-rename mechanism, with the content below, then +return the status block. Nothing else: no git activity, no other files. + +--- + +The tracking file: + +```markdown +# Review Tracking: Pay - Claims Verification + +## Findings + +### 1. Checkout Module Count Fails Measurement + +**Source**: Tree measurement — `ls src/checkout/*.js | wc -l` +**Category**: Source defect +**Affects**: Telemetry Coverage + +**Details**: +The specification asserts the checkout flow spans four modules +(`ls src/checkout/*.js | wc -l → 4`). Measured now, the command prints +5 — src/checkout/wallet-stub.js also exists. The same claim, with the +same recorded command, sits in the source discussion's Telemetry +Coverage ground; the specification carries it faithfully. The fix +belongs to the source record. + +**Proposed Change**: + +**Resolution**: Pending +**Notes**: + +--- +``` + +The status block: + +``` +STATUS: findings +FINDINGS_COUNT: 1 +SUMMARY: One load-bearing count fails measurement, and the source record carries it — routed, not applied. +``` diff --git a/tests/prose/stubs/spec-review-clean.md b/tests/prose/stubs/spec-review-clean.md index 4818ecffc..4febf84d8 100644 --- a/tests/prose/stubs/spec-review-clean.md +++ b/tests/prose/stubs/spec-review-clean.md @@ -1,11 +1,12 @@ # stub: spec-review-clean -A specification review agent's return — input review or gap analysis — -with nothing to report. A clean review writes no tracking file; the -block below is all the agent returns to its caller. +A specification review agent's return — claims verification, input +review, or gap analysis — with nothing to report. A clean review writes +no tracking file; the block below is all the agent returns to its +caller. --- STATUS: clean FINDINGS_COUNT: 0 -SUMMARY: The specification stands alone and faithfully covers its source material; no findings. +SUMMARY: Nothing to report — the specification holds against this review's concern.