sprint-oracle
The sprint completeness oracle — a mechanical, exit-code-driven check that every feature in a sprint manifest is provably complete across three dimensions (a done-record reference, resolvable edge tes
SKILL.md.claude/skills/sprint-oracle/SKILL.md
GitHubsprint-oracle — mechanical completeness gate for a sprint
sprint-oracle reads a sprint manifest (authored by sprint-plan), scans the test tree for the @sprint-feature / @kind tags, and reports whether every feature is complete. It is the answer to "the final system ships incomplete": a sprint is not done until the oracle exits 0. Read-only — it reports, it never edits.
What it checks (per feature)
A feature is complete only when all three hold:
- done-record —
done_recordis non-empty (the feature traces to a spec AC). - edge — at least one name in
edge_testsresolves to a test tagged// @sprint-feature:<id> @kind:edge. - wiring —
wiring_testresolves to a test tagged// @sprint-feature:<id> @kind:wiring.
"Resolves" means: the named test exists in a scanned .mjs file and its tag's feature id and kind match. A test tagged @kind:happy never satisfies an edge or wiring requirement — the happy path does not count as completion.
Exit codes (fail loud, fail distinct)
| Code | Meaning |
|---|---|
0 |
every feature complete (or the manifest has zero features — vacuously complete) |
2 |
gaps found — at least one feature is missing a dimension; a per-feature gap list is printed to stderr |
1 |
operational error — the manifest could not be read or parsed (distinct from a completeness gap) |
A gap is {feature, dimension, detail} where dimension is one of done-record / edge / wiring, and detail names the unresolved test(s).
How to use
node .claude/skills/sprint-oracle/oracle.mjs <manifest-path> [test-root]
test-root defaults to tests. The CLI prints each gap as GAP <feature>: <dimension> — <detail> and exits with the code above. For programmatic use, import runOracle({manifestPath, testRoot}) → {code, gaps, error?}.
Example gap output:
GAP search: edge — no resolvable @kind:edge test among [search_empty_query]
GAP search: wiring — wiring_test 'search_end_to_end' does not resolve to a @kind:wiring test
The honest limit
No script can prove a test is semantically an edge case or a true end-to-end exercise. The oracle verifies that the manifest's claims resolve to tagged tests — it trades unbounded gameability for mechanical checkability. That is a deliberate, documented bound (see the locked Q3 decision in the mvp-sprint-parallel-cycles spec): far better than today's no-record-of-done, and crisp enough to grep.
Constraints
- Read-only. The oracle never writes; it reports an exit code + a gap list.
- Mechanical only. It does not judge test quality — it resolves references against tags.
- Pairs with
sprint-plan(which authors the manifest + validates its shape). Keep authoring and gating separate.