Skip to content

Tier 1: engine readiness for trove adoption#17

Merged
markmals merged 3 commits into
mainfrom
tier1-trove-adoption
Jun 14, 2026
Merged

Tier 1: engine readiness for trove adoption#17
markmals merged 3 commits into
mainfrom
tier1-trove-adoption

Conversation

@markmals

Copy link
Copy Markdown
Owner

Makes the SpecKit engine able to scan + verify trove — the first real Workbench-shaped repo to convert. Holding for your review (not merged).

Validated end-to-end against ~/Developer/Projects/trove: scan went from 46 findings → clean, and a live verify (real go test) joins trove's Go bindings — 4 scenarios passed, 0 dangling, 0 unbound, 2 honestly unjoinable (cross-target). trove's tree left pristine.

What changed

specmodel — accept trove's spec shape

  • protocol kind — a contract kind (protocol.<producer>.<op>, dir specs/protocol/, no scenarios). Cleared trove's 17 I2s.
  • Filename rule accepts both the id-tail stem (engine.scan.md) and the full-id stem (story.engine.scan.md). Cleared trove's 29 I1s; backward-compatible (SpecKit's own specs unchanged).
  • Nested scenario headingsparseScenarios now reads ### Scenario N: under ## Acceptance Criteria, not just top-level ## Scenario. (An audit miss — without this, trove's scenarios parsed empty and every binding dangled.)

engine + reports — verify trove's Go suite

  • gotest format — parses go test -json (top-level funcs; subtests rolled up; skips omitted).
  • Leading // [scenario.id] binding reader.go added to the source walk; binds the tag to the next func Test… (Go) or it/test(…) title (TS). This is the form trove uses across 156 Go + 12 TS tags (the in-title Vitest + Swift-trait forms still work).
  • bindings: scoped mode (see decision below).

⚠️ One decision for you — the bindings mode

A blocker the audit didn't surface: trove's Go suite is deliberately partly-bound (it has plain unit tests like TestOutputPath with no scenario tag). SpecKit's documented philosophy is "any untagged test is a hard error" (unbound = D12 failure, blocks all locking) — so verify would lock nothing on trove.

I added an opt-in, per-target bindings mode:

  • strict (default, unchanged) — every test must bind a scenario. The scaffold + SpecKit's own repo are untouched.
  • scoped — untagged tests are out of scope, so a mixed suite verifies what it does bind. Dangling bindings + failing bound tests remain violations in both modes.

This softens a documented philosophy, but only when a target opts in. Confirm the name/shape (or reject in favor of "trove must fully-bind its suite").

Also note

  • The x-spec / OpenAPI protocol-coverage reader is deferred (protocol specs scan clean + drift-track as contract-only for now; covering them needs the OpenAPI reader — a separate milestone).
  • The trove .speckit/specs.json that worked (a go-service/gotest/scoped target) is in docs/config.md as the example.

Tests

New coverage for every change (protocol kind/prefix, both filename conventions, nested-scenario parsing, the Go + TS leading-comment readers, the gotest parser, the scoped-vs-strict integration, and config validation). mise run ci green; init goldens unaffected.

Deferred Tier-1 follow-ups (next milestone)

protocol x-spec coverage reader · an init-into-existing path that authors .speckit/specs.json · the go-service stack pack/scaffold.

markmals added 3 commits June 13, 2026 19:48
…s, nested scenarios)

- Add the `protocol` contract kind (protocol.<producer>.<op>, dir specs/protocol/);
  clears the 17 "unknown kind" I2s on trove's wire contracts. No scenarios required.
- I1 accepts both the id-tail stem (engine.scan.md) and the full dotted id stem
  (story.engine.scan.md) — clears trove's 29 I1s; backward-compatible.
- parseScenarios reads a Scenario heading at any level, so a nested `### Scenario N:`
  under `## Acceptance Criteria` (trove's form) yields its sub-id — without this the
  scenarios parse empty and every binding dangles.
…ngs, scoped mode)

- reports: add the `gotest` format parsing `go test -json` (top-level funcs; subtests
  rolled into their parent; skips omitted; join identity = the func name).
- engine: walk .go sources, and read the language-agnostic leading `// [scenario.id]`
  comment form (binds to the next `func Test…` in Go or `it/test(…)` title in JS/TS) —
  the form trove uses across 156 Go + 12 TS tags (the in-title/Swift forms still work).
- engine/config: a per-target `bindings` mode — `strict` (default, every test must bind
  a scenario) or `scoped` (untagged tests are out of scope), so a partially-bound real
  suite verifies what it does bind. Dangling + failing bound tests stay violations in both.
- config: validate the gotest format + the bindings mode; cli threads bindings through.
CONVENTIONS gains the protocol row + notes both filename conventions and any-level
scenario headings; docs/config.md documents format gotest + the bindings mode; README
softens 'every untagged test is a hard error' to the strict/scoped distinction. BACKLOG
records the Tier-1 trove-adoption milestone.
@markmals markmals merged commit f077969 into main Jun 14, 2026
4 checks passed
@markmals markmals deleted the tier1-trove-adoption branch June 14, 2026 01:59
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