Skip to content
Merged
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/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ labels: bug

## For skill/pipeline bugs

<!-- Which stage (forge / anvil / temper / quench / smithy), and the relevant
<!-- Which stage (forge / anvil / temper / quench / hone / smithy), and the relevant
artifact paths (.prd/NNN_*.md, specs/NNN-*/...) if applicable. -->
8 changes: 5 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
version: 2
updates:
# vendor/superpowers and vendor/spec-kit — the CI smoke test validates each
# bump (KEEP-class linking fails if upstream renames or removes a skill).
# Policy (see CLAUDE.md): only merge bumps that land on an upstream tag.
# vendor/superpowers and vendor/spec-kit. Dependabot targets head commits, and CI
# requires each pointer to sit on an upstream tag named in the README, so these PRs
# fail by design — treat them as "a new upstream release may exist", close them, and
# bump to the tag by hand (policy in CLAUDE.md). The smoke test and the KEEP/DENY
# classification check then validate the deliberate bump.
- package-ecosystem: gitsubmodule
directory: /
schedule:
Expand Down
63 changes: 60 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
submodules: recursive

- name: bash syntax check
run: bash -n install.sh tests/smoke.sh
Expand All @@ -29,14 +31,39 @@ jobs:
[ -f "$l/SKILL.md" ] || { echo "::error::$l does not resolve to a skill"; exit 1; }
done

- name: every stage skill and agent named in install.sh exists on disk
# The name lists come from install.sh itself (sourced, not executed), so a rename
# on disk or in the script cannot pass CI unless both sides agree.
- name: every skill, alias, agent and KEEP skill named in install.sh exists on disk
run: |
for s in forge anvil temper quench hone smithy; do
# shellcheck disable=SC1091
source ./install.sh
for s in "${STAGE_SKILLS[@]}"; do
[ -f "skills/$s/SKILL.md" ] || { echo "::error::skills/$s/SKILL.md missing"; exit 1; }
done
for a in bdd-scenario-writer tdd-test-generator playwright-e2e-tester fastapi-implementer labcoat; do
for pair in "${ALIASES[@]}"; do
alias="${pair%%:*}" stage="${pair#*:}"
[ -L "skills/$alias" ] || { echo "::error::skills/$alias is not a symlink"; exit 1; }
[ "$(readlink "skills/$alias")" = "$stage" ] || { echo "::error::skills/$alias should point at $stage"; exit 1; }
done
for a in "${AGENTS[@]}"; do
[ -f "agents/$a.md" ] || { echo "::error::agents/$a.md missing"; exit 1; }
done
for s in "${SUPERPOWERS_KEEP[@]}"; do
[ -f "vendor/superpowers/skills/$s/SKILL.md" ] || { echo "::error::KEEP skill $s missing upstream — update SUPERPOWERS_KEEP"; exit 1; }
done
# every stage dir on disk is either a stage or an alias (no orphan skills)
for d in skills/*; do
name="$(basename "$d")"
printf '%s\n' "${STAGE_SKILLS[@]}" "${ALIASES[@]%%:*}" | grep -Fxq "$name" \
|| { echo "::error::$d is not listed in install.sh"; exit 1; }
done
# every upstream skill has a policy: KEEP (linked) or DENY (named in README)
for d in vendor/superpowers/skills/*; do
name="$(basename "$d")"
printf '%s\n' "${SUPERPOWERS_KEEP[@]}" | grep -Fxq "$name" && continue
grep -Eq "^\| \`$name\` \| DENY \|" README.md \
|| { echo "::error::upstream skill '$name' is neither KEEP in install.sh nor DENY in README.md — classify it"; exit 1; }
done

- name: frontmatter lint (name + description)
run: |
Expand All @@ -46,6 +73,36 @@ jobs:
|| { echo "::error::$f frontmatter is missing name or description"; exit 1; }
done

# Policy (CLAUDE.md): vendor pointers sit on upstream tags, and the README names
# the tag. Dependabot bumps to head commits fail here by design — re-pin to a tag.
- name: vendor submodules are pinned to upstream tags named in the README
run: |
for sub in vendor/superpowers vendor/spec-kit; do
git -C "$sub" fetch --quiet --tags origin
tag="$(git -C "$sub" describe --tags --exact-match HEAD 2>/dev/null)" \
|| { echo "::error::$sub is at $(git -C "$sub" rev-parse --short HEAD), which is not an upstream tag"; exit 1; }
grep -Fq "| $tag |" README.md \
|| { echo "::error::README.md vendored-submodules table does not list $sub at $tag"; exit 1; }
echo "$sub @ $tag"
done

- name: example artifact trail covers every smithy state
run: |
ex=examples/cart-discounts
for f in .prd/001_cart-discount-codes.md \
specs/001-cart-discount-codes/spec.md specs/001-cart-discount-codes/plan.md \
specs/001-cart-discount-codes/tasks.md specs/001-cart-discount-codes/review.md \
specs/001-cart-discount-codes/quench-log.md specs/001-cart-discount-codes/code-review.md \
specs/001-cart-discount-codes/smithy-log.md; do
[ -f "$ex/$f" ] || { echo "::error::$ex/$f missing"; exit 1; }
done
spec="$ex/specs/001-cart-discount-codes"
grep -q 'A++' "$spec/review.md" || { echo "::error::review.md never reaches A++"; exit 1; }
grep -q 'A++' "$spec/code-review.md" || { echo "::error::code-review.md never reaches A++"; exit 1; }
grep -q '^FINISH:\|FINISH:' "$spec/smithy-log.md" || { echo "::error::smithy-log.md has no FINISH entry"; exit 1; }
grep -q '^- \[ \]' "$spec/tasks.md" && { echo "::error::tasks.md has unchecked tasks at pipeline end"; exit 1; }
echo "example trail complete"

smoke:
name: install/uninstall smoke test
strategy:
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Release

# Pushing a vX.Y.Z tag publishes a GitHub Release whose body is that version's
# CHANGELOG.md section, verbatim (the ritual in CLAUDE.md). The tag must match a
# `## [X.Y.Z] - YYYY-MM-DD` heading; a tag with no changelog section fails here
# instead of shipping empty notes.
on:
push:
tags: ['v[0-9]+.[0-9]+.[0-9]+']

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: extract this version's changelog section
run: |
version="${GITHUB_REF_NAME#v}"
awk -v v="$version" '
/^## \[/ { if (found) exit; if (index($0, "## [" v "]") == 1) { found = 1; next } }
found { print }
' CHANGELOG.md > release-notes.md
if ! grep -q '[^[:space:]]' release-notes.md; then
echo "::error::CHANGELOG.md has no '## [$version]' section — move [Unreleased] under it first (see CLAUDE.md)"
exit 1
fi
cat release-notes.md

- name: create the GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file release-notes.md
48 changes: 12 additions & 36 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,18 @@ All notable changes to this project are documented here, following [Common Chang

## [Unreleased]

### Added
Everything below is new; there is no earlier release to change or fix against. This section becomes `[0.1.0]` in the release PR (see CLAUDE.md, Releasing).

- Add `hone` (alias `code-review-loop`) — stage 5: local adversarial review of the implementation diff (spec-conformance / security / simplicity lenses with mandatory active procedures, ≤400-changed-line review units, A++ = two consecutive zero-blocking rounds, max 3 rounds), between quench and merge
- Add quench hardening gates: diff-scoped mutation testing (line coverage reported, never gated), host-repo static/type/security checks, an FR ↔ test traceability sweep (`@pytest.mark.fr("FR-NNN")` / `@FR-NNN` Gherkin tags), and a stable-green rule (new tests pass 3× in randomized order; a flake is red, never a retry)
- Add the test freeze: from amber onward a test changes only after `spec.md`/`tasks.md` change first; test agents never write implementation and `fastapi-implementer` treats test files as read-only
- Add `specs/NNN-<slug>/quench-log.md` — append-only per-task cycle log (red/amber/green timestamps, amber's failure message, diff size, gate results, waivers)
- Add property-based tests (Hypothesis) derived from PRD Safeguards and SC invariants, characterization-test-first handling for `[REFACTOR]` tasks, and sample-and-select (2–3 independent candidates judged by the frozen tests) for `[HARD]` tasks
- Add active reading procedures to temper's critics (re-derive sections, trace a data flow, draft per-FR test skeletons — findings without the artifact are discarded) and a capture-recapture overlap signal that caps near-disjoint rounds at B+ in both review loops
### Added

- Add the five SPDD pipeline skills: `forge` (PRD authoring), `anvil` (spec/plan/tasks decomposition), `temper` (adversarial review loop), `quench` (BDD-first red-amber-green execution), `smithy` (state-machine orchestrator)
- Add invocation aliases: `prd-authoring`, `speckit-decomposition`, `adversarial-review-loop`, `bdd-tdd-execution`, `spdd-pipeline`
- Add the five quench dispatch agents: `bdd-scenario-writer`, `tdd-test-generator`, `playwright-e2e-tester`, `fastapi-implementer`, `labcoat`
- Add `install.sh` for symlinking skills and agents into a consumer repo's `.claude/`
- Vendor [obra/superpowers](https://github.com/obra/superpowers) v4.3.1 and [github/spec-kit](https://github.com/github/spec-kit) v0.10.1 as pinned submodules
- Add `docs/production-readiness.md` — phased single-founder plan (licensing, CI, releases, installer hardening, automated maintenance)
- Add MIT `LICENSE` (vendored submodules retain their upstream licenses)
- Add CI workflow: shellcheck + syntax checks, alias-symlink and frontmatter integrity, install/uninstall smoke test on Ubuntu and macOS (including stock bash 3.2), and a changelog-updated gate on PRs
- Add `tests/smoke.sh` — end-to-end installer test against a throwaway consumer repo (idempotency, ownership guarantee, pruning, verify, dry-run, uninstall)
- Add `install.sh --verify` (link health report for bug reports) and `--dry-run` (print planned actions without touching anything)
- Add stale-link pruning: install now sweeps damascus-owned links whose names are no longer shipped; uninstall removes every owned link, not just known names
- Add the five SPDD pipeline stage skills and their orchestrator: `forge` (PRD authoring on Fowler's REASONS Canvas; Norms in machine-checkable form, each Safeguard the source of a property test), `anvil` (spec/plan/tasks decomposition via spec-kit slash commands or the vendored templates; `[UX]`/`[REFACTOR]`/`[HARD]` task tags and a ≤400-changed-line task budget), `temper` (local adversarial review of the spec triplet: three critics with mandatory active procedures, a judge with a capture-recapture overlap signal, A++ = two consecutive zero-blocking rounds, max 5 rounds), `quench` (BDD-first red-amber-green execution with the amber test freeze, diff-scoped mutation gate, static gates, FR ↔ test traceability, stable-green 3× rule, property tests, characterization-first `[REFACTOR]`, sample-and-select `[HARD]`, append-only `quench-log.md`), `hone` (the same adversarial loop pointed at the implementation diff: conformance / security / simplicity lenses, ≤400-changed-line review units, every fix shown to fail without itself, max 3 rounds), and `smithy` (stateless orchestrator whose every state is decidable from disk artifacts, halting at every gate; finish step updates README/CHANGELOG, runs Atlas if installed, and logs `FINISH:` to `smithy-log.md`)
- Add invocation aliases: `prd-authoring`, `speckit-decomposition`, `adversarial-review-loop`, `bdd-tdd-execution`, `code-review-loop`, `spdd-pipeline`
- Add the five quench dispatch agents — `bdd-scenario-writer`, `tdd-test-generator`, `playwright-e2e-tester`, `fastapi-implementer`, `labcoat` — each a concise contract (amber = fails for the right reason, tests frozen from amber, test agents never implement, the implementer never edits tests, coverage reported never gated) with one short example per concept; quench's dispatch table states how to bind another stack to the same contract
- Add `install.sh` for symlinking skills and agents into a consumer repo's `.claude/`: idempotent, bash 3.2 / stock macOS compatible, relative links only (pure-bash relative-path computation, no `realpath --relative-to`), touches only links that resolve into the damascus checkout, prunes damascus-owned links whose names are no longer shipped, refuses missing targets, and exits non-zero when any link could not be placed; `--verify` reports link health for bug reports, `--dry-run` prints planned actions, `--uninstall` removes every owned link
- Add `tests/smoke.sh` — end-to-end installer test against a throwaway consumer repo: idempotency, the ownership guarantee, relative links, DENY skills never linked, pruning, verify, dry-run, a non-damascus path in the way fails the run, clean uninstall
- Add CI: shellcheck + syntax checks; repo integrity sourced from `install.sh`'s own name arrays (stage skills, aliases, agents, KEEP skills all exist; every upstream superpowers skill is classified KEEP or DENY); frontmatter lint; vendor submodules must sit on an upstream tag named in the README; the example artifact trail must be complete; the smoke test on Ubuntu and macOS (including stock bash 3.2); a changelog-updated gate on PRs
- Add a tag-triggered `Release` workflow that publishes the GitHub Release from the matching `CHANGELOG.md` section
- Vendor [obra/superpowers](https://github.com/obra/superpowers) v6.3.0 and [github/spec-kit](https://github.com/github/spec-kit) v1.0.5 as pinned submodules, with the DENY / KEEP / CONDITIONAL policy: `brainstorming`, `writing-plans`, `executing-plans`, `requesting-code-review`, `using-superpowers`, `subagent-driven-development` are DENY (a stage replaces them, or they route into one that does); `test-driven-development` is linked but overridden by red-amber-green; the remaining seven are linked as-is
- Add `examples/cart-discounts/` — one feature's complete artifact trail through all five gates (`.prd/`, spec triplet, `review.md`, `quench-log.md`, `code-review.md`, `smithy-log.md`) with a gate-by-gate reading guide and a "which stage do I start at?" note, also surfaced in the README
- Add Dependabot config for monthly vendor-submodule and GitHub Actions bumps, and a bug-report issue template
- Add README sections: requirements, pinned-tag install, upgrading, support posture and licensing; document the release ritual and submodule bump policy in CLAUDE.md

### Changed

- Redraw `docs/assets/hero.png` with a real alpha channel: the previous file carried an opaque cream background remnant above the forge and 250 speckle regions of keying debris, and it showed four stages with `forge anvil temper quench` painted into its pixels. The new plate is five objects and no lettering — 5 regions for 5 objects, 2.06% partial alpha, no border bleed — with the stage names moved to a README caption
- Make `install.sh` portable to bash 3.2 / stock macOS (replace `declare -A` and `readlink -f` with portable equivalents)
- Replace the external-API review gate in `temper` with a fully local adversarial panel (3 critic lenses + judge; A++ = two consecutive zero-blocking rounds, max 5 rounds)
- Change forge's Norms section to require machine-checkable form (the tool + config that enforces each norm, installed as gates by quench) and mark each Safeguard as the source of a property test or runtime assertion
- Change anvil's task format: optional `[UX]`/`[REFACTOR]`/`[HARD]` tags and a ≤400-changed-line sizing budget per task (oversized tasks come back as anvil feedback via the quench log)
- Change smithy's state machine to drive hone after quench and halt on hone's 3-round cap
- Add a smithy finish step at the end of the cycle: after hone reaches A++, update `README.md` and `CHANGELOG.md` for the feature, then run the `atlas` skill scoped to the completed feature if it is available (silent no-op otherwise, like the kanban sync)
- Move `superpowers:requesting-code-review` from KEEP to DENY — `hone` replaces it; `receiving-code-review` stays KEEP for applying findings
- Replace the 95% line-coverage gate in `tdd-test-generator`'s pytest config with mutation-testing guidance and a registered `fr` marker for requirement traceability

### Fixed

- Make the README hero image background transparent (renders cleanly on dark and light themes)
- Fix three quench agents (`tdd-test-generator`, `labcoat`, `fastapi-implementer`) that defined Amber as "minimal implementation", contradicting quench's fails-for-the-right-reason contract
- Add README (pipeline table, review-loop and finish-step descriptions, requirements incl. the shipped agents' Python/FastAPI shape, pinned-tag install, upgrading, vendored-submodule pins, policy table, support posture, credits), `docs/production-readiness.md` (the phased single-founder plan), MIT `LICENSE` (vendored submodules retain their upstream licenses), and the release ritual and bump policy in CLAUDE.md
Loading