Skip to content

feat: reach scenarios — test how a change is met, not only what it is given (v0.19.0) - #14

Merged
cskwork merged 3 commits into
mainfrom
feat/reach-scenarios
Sep 28, 2026
Merged

cskwork merged 3 commits into
mainfrom
feat/reach-scenarios

Conversation

@cskwork

@cskwork cskwork commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Why

The verifier's per-requirement floor (happy, boundary, negative) varies the input and runs through the caller the change was built against. A change can pass all of it and still fail for a second caller of the same behavior that sends an older or smaller request. Origin: a fix whose new validation refused a request another screen had always sent.

What

  • Reach scenarios (roles/verifier.md Lens 1 step 5): per change, one entry (another caller — the one whose request differs most), one state (a record the change did not create), one context (a condition no requirement names). Named <id>.entry|state|context; an empty axis gets a gap line.
    • The state is reached through the product's own steps (earlier step, leave, return, continue), not by acting on seeded data; picks that can happen in one real use also run together, since a defect needing two axes at once passes every single-axis run.
  • plan.md Reach section + skills/3-plan: every caller found across repositories and tiers, with what each sends; compact route gets a - Reach: line in intent.md.
  • Contract tightening = contract change: AGENTS.md rule 3 wording, tripwire.sh pattern, plan Gate tier reads public API/contract.
  • Adversary: plans must list every caller when input is newly refused; diffs with a new refusal and no caller check block.
  • profile: strict coverage requires a proving check or gap per reach axis (reach.<axis> uncovered otherwise).

Verification

  • gates/selftest.sh → SELFTEST PASS.
  • The two new selftest assertions fail against main (contract wire not tripped; strict coverage passed with no reach scenario) and pass here.

Upgrade note

profile: strict features need three more check/gap lines (entry, state, context). Advisory recipes, records, and gate formats are unchanged.

… given (v0.19.0)

The per-requirement floor varies the input through the caller a change was
built against. Each change now also runs three reach scenarios: another
caller of the same behavior (entry), a record the change did not create
(state), and a condition no requirement names (context), picked from a new
plan.md Reach list of every caller found across repositories and tiers.
Refusing input existing callers send is named a contract change and trips
the plan gate; the adversary blocks a new refusal with no caller check; and
profile: strict coverage requires a check or gap per reach axis.
… can co-occur

A state scenario that acts on seeded data skips the return trip where the
product rebuilds the request, and single-axis runs miss a defect that needs
two axes at once. The verifier now reaches the picked state the way a user
does (earlier step, leave, return, continue) and also runs picks that can
happen in one real use together; plan.md's Reach records both.
@cskwork
cskwork merged commit 0b5ea70 into main Sep 28, 2026
3 checks passed
@cskwork
cskwork deleted the feat/reach-scenarios branch October 11, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant