Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Traceability

- **Task ID(s):** T0xx
- **Traces:** AC-… / FR-… / NFR-… (from `tasks.md` `**Traces**:` fields)
- **Traces:** AC-… / FR-… / NFR-… (from `tasks.md` `**Carries**:` fields)
- **PRD silent?** No / Yes — proposed PRD change: …

## Proof
Expand Down
10 changes: 5 additions & 5 deletions .specify/extensions.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
installed:
- agent-context
- clewseau-gate
- specassay-check
settings:
auto_execute_hooks: true
hooks:
Expand All @@ -23,11 +23,11 @@ hooks:
description: Refresh agent context after planning
condition: null
after_implement:
- extension: clewseau-gate
command: speckit.clewseau-gate.check
- extension: specassay-check
command: speckit.specassay.check
enabled: true
optional: true
priority: 10
prompt: Run Clewseau Gate 2 traceability check?
description: Refuse silent gaps after implementation; refresh clew.json
prompt: Run SpecAssay Check (Gate 2 traceability)?
description: Refuse silent gaps after implementation; refresh trace-manifest.json
condition: null
8 changes: 4 additions & 4 deletions .specify/extensions/.registry
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@
],
"installed_at": "2026-06-26T14:27:06.775090+00:00"
},
"clewseau-gate": {
"specassay-check": {
"version": "0.2.0",
"source": "local",
"manifest_hash": "sha256:3dc44c058e1bcfd5fb3f8d99ca3fc78ced48eb2a8dcb80a3d9fe1bb660c2fba4",
"manifest_hash": "sha256:899c9157055ff342d6785fc21d9cfc3e37fe753895e4413dafb51959cb5bad7f",
"enabled": true,
"priority": 10,
"registered_commands": {
"claude": [
"speckit.clewseau-gate.check"
"speckit.specassay.check"
]
},
"registered_skills": [],
"installed_at": "2026-08-06T18:45:20.408692+00:00"
}
}
}
}

This file was deleted.

11 changes: 0 additions & 11 deletions .specify/extensions/clewseau-gate/README.md

This file was deleted.

This file was deleted.

43 changes: 0 additions & 43 deletions .specify/extensions/clewseau-gate/extension.yml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: speckit-specassay-check
description: Run SpecAssay Check (Gate 2) — fail on silent gaps; emit trace-manifest.json
compatibility: Requires spec-kit project structure with .specify/ directory
metadata:
author: github-spec-kit
source: specassay-check:commands/speckit.specassay.check.md
---

# SpecAssay Check (Gate 2)

Run the portable Gate 2 script shipped with this extension. It checks that:

- registry IDs ≡ IDs in specs ≡ IDs in tasks (**exact-set** drift),
- durable IDs are either verified (named proof) or tracked as debt (open task) for **ACs**,
- coverage annotations / test-encoded IDs are not orphans,
- checkbox tasks declare `Carries:`,

and **always writes `trace-manifest.json`** (path configurable) — the SpecAssay matrix. The manifest is written even when the gate fails, so GAPs and `gate.failures` are visible.

`trace-manifest.json` is portable and vendor-neutral (`format: "trace-manifest"`, schemaVersion 3). It is not ReqIF/OSLC. Loupe (the viewer) consumes this file; it does not re-scan the target.

## Steps

1. Confirm `.specify/extensions/specassay-check/specassay-check-config.yml` exists (copy from `config-template.yml` if missing) and points at this project's registry, specs, tasks, and source/test trees. Set `manifest_path` if you do not want `trace-manifest.json` at the project root.
2. From the project root, run:

```bash
bash .specify/extensions/specassay-check/scripts/check-traceability.sh
```

3. Report the script's exit code, any `FAIL:` lines, and confirm `trace-manifest.json` (or configured `manifest_path`) was written.
4. Do **not** weaken the gate. If something is unfinished, it belongs as tracked debt (unchecked task with `Carries:`), not as a silenced gap.
5. Reminder: **verified** means a named proof exists — not that a full suite was asserted green by this script.
15 changes: 15 additions & 0 deletions .specify/extensions/specassay-check/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SpecAssay Check

Every **wish** is on the **Golden Thread** with its **work** and its **proof**; this check stops the line at any loose end, then strikes a hallmark on what it found — the **trace-manifest**.

Gate 2: compare the ID registry to specs, tasks, coverage annotations, and test names. **Exact-set** registry ≡ specs ≡ tasks. Silent AC gaps and untraced scope fail. **Always writes a trace-manifest** (default `trace-manifest.json`, configurable via `manifest_path`) for Loupe or any matrix consumer.

**CI is the property line.** Run this script on every PR / protected-branch push and fail the build on non-zero exit. Local runs are hygiene; CI is what stops a cowboy (or any machine without SpecAssay) from merging unmarked work. Keep the emitted trace-manifest from the CI run as evidence.

Install:

```bash
specify extension add --dev /path/to/specassay/extensions/specassay-check
```

Install scaffolds `specassay-check-config.yml` from `config-template.yml`. Edit `registry`, `manifest_path`, `specs`, `tasks`, `src_globs`, and `test_globs` for your repo.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
description: Run SpecAssay Check (Gate 2) — fail on silent gaps; emit trace-manifest.json
---

# SpecAssay Check (Gate 2)

Run the portable Gate 2 script shipped with this extension. It checks that:

- registry IDs ≡ IDs in specs ≡ IDs in tasks (**exact-set** drift),
- durable IDs are either verified (named proof) or tracked as debt (open task) for **ACs**,
- coverage annotations / test-encoded IDs are not orphans,
- checkbox tasks declare `Carries:`,

and **always writes a trace-manifest** (default `trace-manifest.json`, path configurable) — the SpecAssay matrix. The manifest is written even when the gate fails, so GAPs and `gate.failures` are visible.

`trace-manifest.json` is a portable, vendor-neutral matrix (`format: "trace-manifest"`, schemaVersion 3). It is not ReqIF/OSLC. Loupe (the viewer) consumes this file; it does not re-scan the target.

## Steps

1. Confirm `.specify/extensions/specassay-check/specassay-check-config.yml` exists (copy from `config-template.yml` if missing) and points at this project's registry, specs, tasks, and source/test trees. Set `manifest_path` if you do not want `trace-manifest.json` at the project root.
2. From the project root, run:

```bash
bash .specify/extensions/specassay-check/scripts/check-traceability.sh
```

3. Report the script's exit code, any `FAIL:` lines, and confirm `trace-manifest.json` (or configured `manifest_path`) was written.
4. Do **not** weaken the gate. If something is unfinished, it belongs as tracked debt (unchecked task with `Carries:`), not as a silenced gap.
5. Reminder: **verified** means a named proof exists — not that a full suite was asserted green by this script.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Clewseau Gate config (edit after install)
# SpecAssay Check config (edit after install)

# Authoritative ID registry (usually the PRD)
registry: "PRD.md"

# Optional display name in clew.json (defaults to project directory name)
# Optional display name in the trace-manifest (defaults to project directory name)
target_name: ""

# Where Gate 2 writes the clew (Clewseau native matrix; format: clew)
clew_path: "clew.json"
# Where the check writes the trace-manifest (SpecAssay native matrix; format: trace-manifest)
manifest_path: "trace-manifest.json"

# Spec Kit feature artifacts (globs relative to project root)
specs: "specs/**/spec.md"
Expand All @@ -27,5 +27,8 @@ id_regex: "(FR|NFR|AC|US)-[A-Z][A-Z0-9]{1,5}-[0-9]{2,}[a-z]?"
# How coverage annotations appear in source
covers_regex: "@covers[[:space:]]+.*"

# The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition.
carries_regex: "\*\*(Carries|Traces)\*\*:"

Comment on lines +30 to +32

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python - <<'PY'
from pathlib import Path
import sys

try:
    import yaml
except ModuleNotFoundError:
    sys.exit("PyYAML is required for this verification")

for name in (
    ".specify/extensions/specassay-check/config-template.yml",
    ".specify/extensions/specassay-check/specassay-check-config.yml",
):
    yaml.safe_load(Path(name).read_text())
    print(f"valid: {name}")
PY

Repository: rdryfoos/HomesFlow

Length of output: 3410


Use valid YAML quoting for carries_regex.

\* is not a valid double-quoted YAML escape, so these files fail to parse; use a single-quoted scalar instead.

  • .specify/extensions/specassay-check/config-template.yml#L30-L32
  • .specify/extensions/specassay-check/specassay-check-config.yml#L13
Proposed fix
-carries_regex: "\*\*(Carries|Traces)\*\*:"
+carries_regex: '\*\*(Carries|Traces)\*\*:'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition.
carries_regex: "\*\*(Carries|Traces)\*\*:"
# The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition.
carries_regex: '\*\*(Carries|Traces)\*\*:'
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 31-31: syntax error: found unknown escape character '*'

(syntax)

📍 Affects 2 files
  • .specify/extensions/specassay-check/config-template.yml#L30-L32 (this comment)
  • .specify/extensions/specassay-check/specassay-check-config.yml#L13-L13
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.specify/extensions/specassay-check/config-template.yml around lines 30 -
32, Replace the double-quoted carries_regex YAML scalar with a single-quoted
scalar in .specify/extensions/specassay-check/config-template.yml lines 30-32
and .specify/extensions/specassay-check/specassay-check-config.yml line 13,
preserving the existing Carries/Traces regex.

Source: Linters/SAST tools

# How AC IDs appear inside test names (e.g. test_AC_SYNC_04_...)
test_ac_regex: "AC_[A-Z][A-Z0-9]{1,5}_[0-9]{2,}[a-z]?"
43 changes: 43 additions & 0 deletions .specify/extensions/specassay-check/extension.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
schema_version: "1.0"

extension:
id: "specassay-check"
name: "SpecAssay Check"
version: "0.2.0"
description: "Gate 2 — refuse silent gaps and emit a trace-manifest (`trace-manifest.json`)."
category: "visibility"
effect: "read-write"
author: "Rik Dryfoos / Dryfoos Consulting"
license: "MIT"
homepage: "https://github.com/rdryfoos/specassay"
repository: "https://github.com/rdryfoos/specassay"

requires:
speckit_version: ">=0.14.0"
tools: []

provides:
commands:
- name: "speckit.specassay.check"
file: "commands/speckit.specassay.check.md"
description: "Run SpecAssay Check / Gate 2 (silent gaps fail; write trace-manifest.json)"

config:
- name: "specassay-check-config.yml"
template: "config-template.yml"
description: "Registry path, source/test globs, and ID grammar"
required: true

hooks:
after_implement:
command: "speckit.specassay.check"
optional: true
prompt: "Run SpecAssay Check (Gate 2 traceability)?"
description: "Refuse silent gaps after implementation; refresh trace-manifest.json"

tags:
- "traceability"
- "gate"
- "ci"
- "governance"
- "sdd"
Loading
Loading