Skip to content

fix: parse scenarios on every non-singular spec kind (protocol et al.)#49

Merged
markmals merged 1 commit into
mainfrom
fix/protocol-scenarios
Jun 16, 2026
Merged

fix: parse scenarios on every non-singular spec kind (protocol et al.)#49
markmals merged 1 commit into
mainfrom
fix/protocol-scenarios

Conversation

@markmals

Copy link
Copy Markdown
Owner

What

Kind.CarriesScenarios() gated scenario parsing to story/domain, so a kind: protocol spec's <!-- id: scenario… --> was never parsed into Spec.Scenarios. It never entered the declared set in joinTarget, so a test's // [scenario…] binding joined to nothing and Join reported it as a Dangling binding — a spurious D12 violation. Trove needs to own scenarios from kind: protocol specs.

Change

Gate on !k.Singular(): every per-file behavioral contract kind (story, domain, protocol, use-case, flow, view-model, command, error) carries scenarios; the singular cross-cutting doc kinds (narrative, architecture, design-system, conventions) stay excluded.

That exclusion is load-bearing — specs/CONVENTIONS.md carries an illustrative <!-- id: scenario.item.create.happy-path --> that must never be parsed as a real declaration. A blanket "all kinds" would have polluted SpecKit's own library; specify scan on this repo stays clean.

Tests

  • TestVerifyProtocolScenarioJoins (engine) — drives the real Verify path over a kind: protocol fixture + a Go // [scenario.troved.search.returns-mapped-results] binding; asserts the scenario joins (no Dangling), passes, and locks. Watched it fail RED with the exact dangling binding before the fix.
  • TestCarriesScenarios (specmodel) — pins the non-singular contract (8 behavioral kinds carry; 4 singular kinds don't).

Verification

mise run ci green (fmt, build, vet, go test ./...). specify scan on this repo: clean.

Follow-up (not in this PR)

specs/CONVENTIONS.md describes scenario-carrying using only story/domain as examples — now incomplete (not false). Worth a focused wording pass since it's normative spec truth.

CarriesScenarios() gated scenario parsing to story/domain, so a
`kind: protocol` spec's `<!-- id: scenario… -->` was never parsed into
Spec.Scenarios. It never entered the declared set, so a test's
`// [scenario…]` binding joined to nothing and Join reported it as a
Dangling binding — a spurious D12 violation. Trove blocks on owning
scenarios from protocol specs.

Gate on `!k.Singular()` instead: every per-file behavioral contract kind
(story, domain, protocol, use-case, flow, view-model, command, error)
carries scenarios; the singular cross-cutting doc kinds (narrative,
architecture, design-system, conventions) stay excluded. That exclusion
is load-bearing — specs/CONVENTIONS.md carries an illustrative
`<!-- id: scenario.item.create.happy-path -->` that must never be parsed
as a real declaration.

Regression: TestVerifyProtocolScenarioJoins drives the real Verify path
over a kind: protocol fixture + a Go `// [scenario…]` binding and asserts
the scenario joins (no Dangling), passes, and locks. TestCarriesScenarios
pins the non-singular contract.
@markmals markmals merged commit 8dcb23a into main Jun 16, 2026
1 of 4 checks passed
@markmals markmals deleted the fix/protocol-scenarios branch June 16, 2026 19:17
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