@friedbotstudio/create-baseline 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +222 -0
- package/bin/cli.js +247 -0
- package/obj/template/.claude/agents/swarm-worker.md +52 -0
- package/obj/template/.claude/bin/LICENSE +201 -0
- package/obj/template/.claude/bin/NOTICE +48 -0
- package/obj/template/.claude/commands/approve-spec.md +29 -0
- package/obj/template/.claude/commands/approve-swarm.md +27 -0
- package/obj/template/.claude/commands/grant-commit.md +19 -0
- package/obj/template/.claude/commands/init-project.md +191 -0
- package/obj/template/.claude/hooks/artifact_template_guard.sh +141 -0
- package/obj/template/.claude/hooks/consent_gate_grant.sh +89 -0
- package/obj/template/.claude/hooks/destructive_cmd_guard.sh +42 -0
- package/obj/template/.claude/hooks/env_guard.sh +36 -0
- package/obj/template/.claude/hooks/git_commit_guard.sh +93 -0
- package/obj/template/.claude/hooks/harness_continuation.sh +121 -0
- package/obj/template/.claude/hooks/lib/__pycache__/resume_writer.cpython-314.pyc +0 -0
- package/obj/template/.claude/hooks/lib/common.sh +328 -0
- package/obj/template/.claude/hooks/lib/resume_writer.py +341 -0
- package/obj/template/.claude/hooks/lint_runner.sh +55 -0
- package/obj/template/.claude/hooks/memory_pre_compact.sh +36 -0
- package/obj/template/.claude/hooks/memory_session_start.sh +244 -0
- package/obj/template/.claude/hooks/memory_stop.sh +173 -0
- package/obj/template/.claude/hooks/plantuml_syntax_guard.sh +161 -0
- package/obj/template/.claude/hooks/process_lifecycle_guard.sh +89 -0
- package/obj/template/.claude/hooks/setup_guard.sh +50 -0
- package/obj/template/.claude/hooks/spec_approval_guard.sh +81 -0
- package/obj/template/.claude/hooks/spec_design_calls_guard.sh +183 -0
- package/obj/template/.claude/hooks/spec_diagram_presence_guard.sh +141 -0
- package/obj/template/.claude/hooks/swarm_approval_guard.sh +39 -0
- package/obj/template/.claude/hooks/swarm_boundary_guard.sh +136 -0
- package/obj/template/.claude/hooks/tdd_order_guard.sh +176 -0
- package/obj/template/.claude/hooks/test_runner.sh +75 -0
- package/obj/template/.claude/hooks/tests/fixtures/ac008_byte_equal_reference.txt +12 -0
- package/obj/template/.claude/hooks/tests/memory_session_start_test.sh +285 -0
- package/obj/template/.claude/hooks/track_guard.sh +127 -0
- package/obj/template/.claude/hooks/verify_pass_guard.sh +88 -0
- package/obj/template/.claude/memory/README.md +108 -0
- package/obj/template/.claude/memory/_pending.md +15 -0
- package/obj/template/.claude/memory/_resume.md +12 -0
- package/obj/template/.claude/memory/conventions.md +26 -0
- package/obj/template/.claude/memory/decisions.md +29 -0
- package/obj/template/.claude/memory/landmarks.md +26 -0
- package/obj/template/.claude/memory/landmines.md +27 -0
- package/obj/template/.claude/memory/libraries.md +27 -0
- package/obj/template/.claude/memory/pending-questions.md +28 -0
- package/obj/template/.claude/project.json +221 -0
- package/obj/template/.claude/settings.json +110 -0
- package/obj/template/.claude/skills/archive/SKILL.md +48 -0
- package/obj/template/.claude/skills/archive/archive.sh +145 -0
- package/obj/template/.claude/skills/audit-baseline/SKILL.md +80 -0
- package/obj/template/.claude/skills/audit-baseline/audit.sh +919 -0
- package/obj/template/.claude/skills/brd/SKILL.md +44 -0
- package/obj/template/.claude/skills/brd/template.md +83 -0
- package/obj/template/.claude/skills/chore/SKILL.md +99 -0
- package/obj/template/.claude/skills/claude-automation-recommender/LICENSE +202 -0
- package/obj/template/.claude/skills/claude-automation-recommender/NOTICE +69 -0
- package/obj/template/.claude/skills/claude-automation-recommender/SKILL.md +358 -0
- package/obj/template/.claude/skills/claude-automation-recommender/references/hooks-patterns.md +226 -0
- package/obj/template/.claude/skills/claude-automation-recommender/references/mcp-servers.md +263 -0
- package/obj/template/.claude/skills/claude-automation-recommender/references/plugins-reference.md +98 -0
- package/obj/template/.claude/skills/claude-automation-recommender/references/skills-reference.md +408 -0
- package/obj/template/.claude/skills/claude-automation-recommender/references/subagent-templates.md +181 -0
- package/obj/template/.claude/skills/code-structure/SKILL.md +204 -0
- package/obj/template/.claude/skills/commit/SKILL.md +21 -0
- package/obj/template/.claude/skills/copywriting/SKILL.md +252 -0
- package/obj/template/.claude/skills/copywriting/evals/evals.json +111 -0
- package/obj/template/.claude/skills/copywriting/references/ai-writing-detection.md +200 -0
- package/obj/template/.claude/skills/copywriting/references/copy-frameworks.md +344 -0
- package/obj/template/.claude/skills/copywriting/references/natural-transitions.md +272 -0
- package/obj/template/.claude/skills/design-ui/SKILL.md +175 -0
- package/obj/template/.claude/skills/design-ui/references/design-vs-development.md +89 -0
- package/obj/template/.claude/skills/design-ui/references/intent-table.md +64 -0
- package/obj/template/.claude/skills/design-ui/references/orchestration.md +121 -0
- package/obj/template/.claude/skills/design-ui/references/state-machine.md +125 -0
- package/obj/template/.claude/skills/document/SKILL.md +66 -0
- package/obj/template/.claude/skills/documentation/SKILL.md +50 -0
- package/obj/template/.claude/skills/harness/SKILL.md +169 -0
- package/obj/template/.claude/skills/humanizer/SKILL.md +489 -0
- package/obj/template/.claude/skills/humanizer/references/ai-writing-detection.md +208 -0
- package/obj/template/.claude/skills/impeccable/PROJECT_NOTES.md +22 -0
- package/obj/template/.claude/skills/impeccable/SKILL.md +153 -0
- package/obj/template/.claude/skills/impeccable/agents/openai.yaml +4 -0
- package/obj/template/.claude/skills/impeccable/reference/adapt.md +190 -0
- package/obj/template/.claude/skills/impeccable/reference/animate.md +173 -0
- package/obj/template/.claude/skills/impeccable/reference/audit.md +134 -0
- package/obj/template/.claude/skills/impeccable/reference/bolder.md +113 -0
- package/obj/template/.claude/skills/impeccable/reference/brand.md +104 -0
- package/obj/template/.claude/skills/impeccable/reference/clarify.md +174 -0
- package/obj/template/.claude/skills/impeccable/reference/cognitive-load.md +106 -0
- package/obj/template/.claude/skills/impeccable/reference/color-and-contrast.md +105 -0
- package/obj/template/.claude/skills/impeccable/reference/colorize.md +154 -0
- package/obj/template/.claude/skills/impeccable/reference/craft.md +138 -0
- package/obj/template/.claude/skills/impeccable/reference/critique.md +213 -0
- package/obj/template/.claude/skills/impeccable/reference/delight.md +302 -0
- package/obj/template/.claude/skills/impeccable/reference/distill.md +111 -0
- package/obj/template/.claude/skills/impeccable/reference/document.md +427 -0
- package/obj/template/.claude/skills/impeccable/reference/extract.md +70 -0
- package/obj/template/.claude/skills/impeccable/reference/harden.md +347 -0
- package/obj/template/.claude/skills/impeccable/reference/heuristics-scoring.md +234 -0
- package/obj/template/.claude/skills/impeccable/reference/interaction-design.md +195 -0
- package/obj/template/.claude/skills/impeccable/reference/layout.md +141 -0
- package/obj/template/.claude/skills/impeccable/reference/live.md +513 -0
- package/obj/template/.claude/skills/impeccable/reference/motion-design.md +99 -0
- package/obj/template/.claude/skills/impeccable/reference/onboard.md +234 -0
- package/obj/template/.claude/skills/impeccable/reference/optimize.md +258 -0
- package/obj/template/.claude/skills/impeccable/reference/overdrive.md +130 -0
- package/obj/template/.claude/skills/impeccable/reference/personas.md +178 -0
- package/obj/template/.claude/skills/impeccable/reference/polish.md +232 -0
- package/obj/template/.claude/skills/impeccable/reference/product.md +62 -0
- package/obj/template/.claude/skills/impeccable/reference/quieter.md +99 -0
- package/obj/template/.claude/skills/impeccable/reference/responsive-design.md +114 -0
- package/obj/template/.claude/skills/impeccable/reference/shape.md +136 -0
- package/obj/template/.claude/skills/impeccable/reference/spatial-design.md +100 -0
- package/obj/template/.claude/skills/impeccable/reference/teach.md +137 -0
- package/obj/template/.claude/skills/impeccable/reference/typeset.md +124 -0
- package/obj/template/.claude/skills/impeccable/reference/typography.md +159 -0
- package/obj/template/.claude/skills/impeccable/reference/ux-writing.md +107 -0
- package/obj/template/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
- package/obj/template/.claude/skills/impeccable/scripts/command-metadata.json +94 -0
- package/obj/template/.claude/skills/impeccable/scripts/design-parser.mjs +820 -0
- package/obj/template/.claude/skills/impeccable/scripts/detect-csp.mjs +198 -0
- package/obj/template/.claude/skills/impeccable/scripts/is-generated.mjs +69 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-accept.mjs +465 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-browser.js +4684 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-inject.mjs +436 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-poll.mjs +187 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-server.mjs +679 -0
- package/obj/template/.claude/skills/impeccable/scripts/live-wrap.mjs +395 -0
- package/obj/template/.claude/skills/impeccable/scripts/live.mjs +247 -0
- package/obj/template/.claude/skills/impeccable/scripts/load-context.mjs +93 -0
- package/obj/template/.claude/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/obj/template/.claude/skills/impeccable/scripts/pin.mjs +214 -0
- package/obj/template/.claude/skills/implement/SKILL.md +83 -0
- package/obj/template/.claude/skills/intake/SKILL.md +46 -0
- package/obj/template/.claude/skills/intake/template.md +61 -0
- package/obj/template/.claude/skills/integrate/SKILL.md +62 -0
- package/obj/template/.claude/skills/memory-flush/SKILL.md +172 -0
- package/obj/template/.claude/skills/memory-flush/sweep.py +286 -0
- package/obj/template/.claude/skills/memory-flush/tests/run.sh +327 -0
- package/obj/template/.claude/skills/prose/SKILL.md +119 -0
- package/obj/template/.claude/skills/rca/SKILL.md +42 -0
- package/obj/template/.claude/skills/rca/template.md +83 -0
- package/obj/template/.claude/skills/research/SKILL.md +75 -0
- package/obj/template/.claude/skills/scenario/SKILL.md +64 -0
- package/obj/template/.claude/skills/scout/SKILL.md +72 -0
- package/obj/template/.claude/skills/security/SKILL.md +75 -0
- package/obj/template/.claude/skills/simplify/SKILL.md +67 -0
- package/obj/template/.claude/skills/spec/SKILL.md +69 -0
- package/obj/template/.claude/skills/spec/template.md +274 -0
- package/obj/template/.claude/skills/spec-diagram-review/SKILL.md +81 -0
- package/obj/template/.claude/skills/spec-lint/SKILL.md +55 -0
- package/obj/template/.claude/skills/spec-lint/lint.sh +218 -0
- package/obj/template/.claude/skills/spec-render/SKILL.md +45 -0
- package/obj/template/.claude/skills/spec-render/render.sh +109 -0
- package/obj/template/.claude/skills/spec-traceability-review/SKILL.md +72 -0
- package/obj/template/.claude/skills/swarm-dispatch/SKILL.md +212 -0
- package/obj/template/.claude/skills/swarm-dispatch/swarm_merge.sh +154 -0
- package/obj/template/.claude/skills/swarm-plan/SKILL.md +90 -0
- package/obj/template/.claude/skills/swarm-plan/validate.sh +181 -0
- package/obj/template/.claude/skills/tdd/SKILL.md +100 -0
- package/obj/template/.claude/skills/technical-tutorials/SKILL.md +569 -0
- package/obj/template/.claude/skills/technical-tutorials/references/audience-context-README.md +53 -0
- package/obj/template/.claude/skills/technical-tutorials/references/audience-context.md +246 -0
- package/obj/template/.claude/skills/technical-tutorials/references/audience-example.md +175 -0
- package/obj/template/.claude/skills/technical-tutorials/references/audience-template.md +152 -0
- package/obj/template/.claude/skills/triage/SKILL.md +55 -0
- package/obj/template/.claude/skills/verify/SKILL.md +74 -0
- package/obj/template/.mcp.json +24 -0
- package/obj/template/CLAUDE.md +327 -0
- package/obj/template/docs/init/seed.md +585 -0
- package/obj/template/manifest.json +214 -0
- package/package.json +48 -0
- package/src/.mcp.template.json +24 -0
- package/src/.npmrc.template +2 -0
- package/src/CLAUDE.template.md +327 -0
- package/src/agents/swarm-worker.template.md +51 -0
- package/src/cli/conflict.js +31 -0
- package/src/cli/doctor.js +152 -0
- package/src/cli/install.js +93 -0
- package/src/cli/io.js +27 -0
- package/src/cli/manifest.js +38 -0
- package/src/cli/mcp.js +54 -0
- package/src/cli/merge.js +107 -0
- package/src/cli/plantuml.js +121 -0
- package/src/cli/util.js +10 -0
- package/src/memory/_pending.template.md +15 -0
- package/src/memory/_resume.template.md +12 -0
- package/src/memory/conventions.template.md +26 -0
- package/src/memory/decisions.template.md +29 -0
- package/src/memory/landmarks.template.md +26 -0
- package/src/memory/landmines.template.md +27 -0
- package/src/memory/libraries.template.md +27 -0
- package/src/memory/pending-questions.template.md +28 -0
- package/src/project.template.json +221 -0
- package/src/seed.template.md +585 -0
- package/src/settings.template.json +110 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# Claude Code Baseline — In-Session Constitution
|
|
2
|
+
|
|
3
|
+
This file is the **in-session constitution** for this repository. It binds Claude's behavior — Claude Code, in this codebase, in this session. Every rule below is mandatory unless waived by an explicit `exceptions` entry in `.claude/state/workflow.json` (set only by `/triage`).
|
|
4
|
+
|
|
5
|
+
**Genesis prompt.** The governing specification of this baseline is `docs/init/seed.md`. It is the genesis prompt for the entire harness. When this constitution and seed.md conflict, **seed.md governs** and you SHALL stop and surface the drift before acting. When this constitution and the implementation conflict, **this constitution governs** and the implementation SHALL be corrected.
|
|
6
|
+
|
|
7
|
+
**Enforcement.** The 22 hooks in `.claude/hooks/` are the structural enforcement layer of this constitution. Each is mapped to the Article it enforces in **Article VIII**.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Article I — Authority and precedence
|
|
12
|
+
|
|
13
|
+
1. **Genesis** — `docs/init/seed.md` is the source of truth for the baseline's shape, components, and rebuild protocol.
|
|
14
|
+
2. **Constitution** — `CLAUDE.md` (this file) is the source of truth for Claude's in-session behavior in this repository.
|
|
15
|
+
3. **Implementation** — the hooks, skills, commands, subagent, MCP servers, and config files are the actuators and enforcement mechanisms of (1) and (2).
|
|
16
|
+
4. **Order of precedence** — `seed.md` > `CLAUDE.md` > implementation. Lower binds higher only via amendment in seed.md, which then propagates to this file, then to disk.
|
|
17
|
+
5. **Project amendments** — Article X reserves space for project-owner amendments. Amendments bind alongside Articles I–IX but **SHALL NOT** contradict them.
|
|
18
|
+
|
|
19
|
+
## Article II — Architectural principle
|
|
20
|
+
|
|
21
|
+
**Decisions live in main context. Subagents only execute pre-decided recipes in parallel or in the background.**
|
|
22
|
+
|
|
23
|
+
The baseline ships exactly **one** subagent: `swarm-worker`. Its sole sanctioned use is to run `Skill(scenario)` then `Skill(implement)` against a fully-specified recipe inside an isolated git worktree during `/swarm-dispatch`. The worker SHALL NOT make design choices, pick abstractions, or expand scope. It SHALL NOT be invoked outside `/swarm-dispatch`.
|
|
24
|
+
|
|
25
|
+
Every other capability — code authoring, scenario authoring, scouting, researching, security review, spec review, prose writing, UI design — is a **skill** that runs in main context. Five execution skills mandatorily invoke a sub-skill:
|
|
26
|
+
|
|
27
|
+
| Skill | Mandatory sub-skill | Conditional |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `scenario` | `code-structure` | — |
|
|
30
|
+
| `implement` | `code-structure` | `context7` MCP for any third-party API |
|
|
31
|
+
| `verify` | — (mechanical) | — |
|
|
32
|
+
| `design-ui` | `impeccable` | — |
|
|
33
|
+
| `prose` | `humanizer` (always) | `copywriting` / `documentation` / `technical-tutorials` by register |
|
|
34
|
+
|
|
35
|
+
You SHALL NOT route conversational judgment (UI nuance, design tone, code architecture, security calls, scenario selection) through a subagent. Those decisions depend on context the conversation carries; a subagent only sees a Task brief and produces visibly worse output.
|
|
36
|
+
|
|
37
|
+
## Article III — Session-start procedure (MANDATORY)
|
|
38
|
+
|
|
39
|
+
On every new session, before any work, you SHALL:
|
|
40
|
+
|
|
41
|
+
1. **Read** `.claude/project.json` and check the `configured` field.
|
|
42
|
+
2. **If `configured: false`** — `/init-project` has not run. The repository is in a sanctioned operating state called **project-agnostic mode**: hooks are active but `test_runner` and `lint_runner` run in guide mode and nothing is tailored to the user's stack. You SHALL greet the user with this exact framing:
|
|
43
|
+
> "This repo has the Claude Code baseline installed (22 hooks, 1 subagent, 36 skills). It's in **project-agnostic mode** — `test_runner` and `lint_runner` are in guide mode and nothing is tailored to your stack. Run **`/init-project`** to scout the codebase, run the recommender, and generate a config. Skip it if you want baseline-only behavior, but you'll miss stack-specific tailoring."
|
|
44
|
+
You SHALL then proceed with whatever the user asks. Project-agnostic mode is **allowed** — the user is not required to run `/init-project` to use the baseline. The `setup_guard` hook surfaces a one-shot reminder on Write/Edit/MultiEdit (rate-limited to 10 minutes); it does **not** block writes. Other guards (commit, env, spec-approval, verify-pass, track, swarm-boundary) remain hard regardless of `configured` state.
|
|
45
|
+
3. **If `configured: true`** — read `docs/init/seed.md` §16 if present so you know what was added. Tell the user:
|
|
46
|
+
> "Configured for `<stack>`. Run `/triage \"<request>\"` to start a workflow, or `/harness` for the full pipeline."
|
|
47
|
+
4. **Memory check.** The `memory_session_start` hook injects a memory index into your additional context. If it reports `K candidates pending in _pending.md` with `K > 0`, you SHALL invoke `/memory-flush` before any workflow phase work — keeps canonical memory fresh for downstream skills.
|
|
48
|
+
5. **Git-repo check.** Run `git rev-parse --is-inside-work-tree 2>/dev/null` at the project root. If non-zero (not a git repo), surface this once per session and tell the user that gate C and the `commit` phase will be auto-excepted; the workflow ends after `/archive`. This is a sanctioned operating mode — Article IV phase 11 and Article VII are git-conditional.
|
|
49
|
+
6. Once per session is sufficient. You SHALL NOT repeat the greeting on every prompt.
|
|
50
|
+
|
|
51
|
+
## Article IV — Workflow ordering (MANDATORY)
|
|
52
|
+
|
|
53
|
+
The 11-phase workflow is the only sanctioned path from request to commit. Phase ordering is enforced at the Write boundary by `track_guard` (Art. VIII).
|
|
54
|
+
|
|
55
|
+
| # | Phase | Invocation | Output |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| 1 | Intake | `/intake` (optionally `/brd`) | `docs/intake/<slug>.md` |
|
|
58
|
+
| 2 | Scout | `/scout` | `docs/scout/<slug>.md` |
|
|
59
|
+
| 3 | Research | `/research` | `docs/research/<slug>.md` |
|
|
60
|
+
| 4 | Spec | `/spec` (+ `/spec-lint`, `/spec-render`, reviews) | `docs/specs/<slug>.md` |
|
|
61
|
+
| 5 | **Approve spec** (gate A) | user runs **`/approve-spec <path>`** | approval token |
|
|
62
|
+
| 6 | TDD (solo) | `/tdd` | code |
|
|
63
|
+
| 6a | TDD (swarm) | `/swarm-plan` | `.claude/state/swarm/<slug>.json` |
|
|
64
|
+
| 6b | **Approve swarm** (gate B) | user runs **`/approve-swarm <slug>`** | approval token |
|
|
65
|
+
| 6c | Swarm dispatch | `/swarm-dispatch` | code (parallel waves) |
|
|
66
|
+
| 7 | Simplify | `/simplify` | clean diff |
|
|
67
|
+
| 8 | Security (optional) | `/security` | `docs/security/<slug>-<date>.md` |
|
|
68
|
+
| 9 | Integrate | `/integrate` | binding verify verdict |
|
|
69
|
+
| 10 | Document | `/document` | docs |
|
|
70
|
+
| 10.5 | Archive | `/archive` | bundle at `docs/archive/<date>/<slug>/` |
|
|
71
|
+
| 11 | **Grant commit** (gate C) + commit | user runs **`/grant-commit`**, then `/commit` (skill) | commit |
|
|
72
|
+
|
|
73
|
+
**Mandatory rules:**
|
|
74
|
+
|
|
75
|
+
- You SHALL NOT skip phases.
|
|
76
|
+
- You SHALL NOT reorder phases.
|
|
77
|
+
- The only mechanism to bypass a phase is the `exceptions` array in `.claude/state/workflow.json`, written by `/triage`.
|
|
78
|
+
- **Phase 6c and Phase 11 are git-conditional.** On a project where `git rev-parse --is-inside-work-tree` exits non-zero (no `.git/`, not inside a work tree), `/triage` SHALL auto-add `swarm-plan`, `approve-swarm`, `swarm-dispatch`, `grant-commit`, and `commit` to `exceptions`. Phase 6 routes to solo `/tdd` unconditionally; the workflow ends after `/archive`. Worktree isolation (the swarm contract's physical safety mechanism) requires git; `swarm.isolation: "shared"` is a sanctioned configuration knob for git projects that opt out of worktrees but does NOT restore the cross-task write isolation the swarm-worker assumes — it is unsafe as a non-git fallback, especially when `swarm.exempt_path_prefixes` covers baseline-internal paths (e.g. `.claude/`). Persistence outside git is the user's responsibility. See Article VII for the matching rule on git operations.
|
|
79
|
+
- The three consent gates (A, B, C) are **commands**, not skills. They are structurally un-invokable by Claude. You SHALL NOT self-approve.
|
|
80
|
+
- **How the gates are structurally enforced.** Each consent command (`/approve-spec`, `/approve-swarm`, `/grant-commit`) is a slash command typed by the user. The `consent_gate_grant` UserPromptSubmit hook (Art. VIII) parses the user's prompt **before Claude is invoked** and writes a short-lived consent marker at `.claude/state/.<gate>_grant`. The corresponding PreToolUse approval guard (`spec_approval_guard`, `swarm_approval_guard`, `git_commit_guard`) then allows Claude's slash-command-body write of the approval token only when the marker is present, fresh (≤ `consent.gate_marker_ttl_seconds`, default 120), and slug-matched; the marker is single-use and deleted on the allowed write. Slug derivation is centralized in `lib/common.sh → canonical_slug` (strip directory prefix + trailing `.md`) so the marker and the expected slug always agree, whether the user typed a bare slug, a filename, or a full path. The same guards block Claude from writing the marker file itself via Write/Edit/MultiEdit. Claude cannot reach the UserPromptSubmit code path, so it cannot forge consent.
|
|
81
|
+
- **Out-of-band**: `/rca` produces an incident postmortem at `docs/rca/<slug>.md`. It is not a workflow phase and often precedes a bugfix intake.
|
|
82
|
+
|
|
83
|
+
**Entry points** (`/triage` writes `workflow.json` with `entry_phase` and `exceptions`):
|
|
84
|
+
|
|
85
|
+
- New feature → `/triage` selects `intake`.
|
|
86
|
+
- Bugfix → `/triage` selects `spec` or `tdd`.
|
|
87
|
+
- Quickfix → `/triage` selects `tdd`.
|
|
88
|
+
- Chore → `/triage` selects the `chore` track when the request needs **no failing-test-driven code change** (documentation edits, governance count bumps, vendored-skill content updates, configuration tweaks, formatting, typo fixes, dependency bumps without project code, skill consolidations). The chore skill skips `/scenario` and `/implement`, runs the edits directly, then conditionally routes through `simplify` / `integrate` / `document` based on what the diff touches. `verify`, `archive`, and `/grant-commit` + `/commit` remain mandatory. Anything that actually needs a failing test routes to `tdd` or higher.
|
|
89
|
+
|
|
90
|
+
**Swarm vs solo at Phase 6.** When the approved spec has fewer than `project.json → swarm.min_tasks_worth_swarming` (default 3) independent components **OR** the project is not a git repository, run `/tdd` solo. Otherwise route through `/swarm-plan` → `/approve-swarm` → `/swarm-dispatch`. In non-git projects the swarm phases are excepted at triage time (see the "Phase 6c and Phase 11 are git-conditional" bullet above), so this decision always resolves to solo — the rule's first clause never fires on a non-git tree, and a user "use swarm" override SHALL be refused with the reason `swarm requires git`.
|
|
91
|
+
|
|
92
|
+
## Article V — Harness orchestration (MANDATORY SOP)
|
|
93
|
+
|
|
94
|
+
`/harness` is invokable by both the user (via the slash command) and the model (via `Skill(harness)`). A single `Skill(harness)` invocation **loops internally through every non-gated phase boundary** until the loop hits one of four exit conditions: consent gate, phase-skill failure, integrate-failure-needs-spec-change, or workflow done. The user invokes `/harness` to start a fresh workflow or to resume after a yield. You SHALL suggest `/harness` when a concrete engineering ask crystallizes in conversation; the user decides when to invoke it.
|
|
95
|
+
|
|
96
|
+
When `/harness` is invoked, you SHALL:
|
|
97
|
+
|
|
98
|
+
1. **Preflight (once per invocation).** Read `.claude/state/workflow.json` and `.claude/state/harness_state` (if present); read `.claude/state/spec_approvals/`, `swarm_approvals/`, and `commit_consent` to reconcile state.
|
|
99
|
+
2. **Arm the safety net.** Marker FIRST: `echo "<slug>" > .claude/state/.harness_active`. Then write `harness_state` with `{state: "continue", slug, reason: "loop armed; preflight passed"}`. This pair stays in place for the entire loop.
|
|
100
|
+
3. **Enter the loop body.** Each iteration: pick the lowest-id `pending` task whose `blockedBy` list is empty. If no task remains → **EXIT LOOP with DONE**. If the task carries `metadata.needs_user: true` → **EXIT LOOP with YIELD** (surface the gate; do NOT self-approve, simulate approval, or write approval tokens directly). Otherwise invoke the matching phase skill via the Skill tool, mark `completed` on success, append to `workflow.json → completed`, refresh marker+state, and **continue to the next iteration**.
|
|
101
|
+
4. **Exit the loop** on yield/failure/done. Write the matching `harness_state` (`yielded` or `done`) with marker-first ordering, then emit a single terminal message naming what just happened.
|
|
102
|
+
5. **Log every transition** to `.claude/state/harness/<slug>.log`.
|
|
103
|
+
|
|
104
|
+
**Internal loop atomicity.** Inside the loop, every iteration is one Skill(`<phase>`) invocation plus one marker refresh plus one `harness_state` refresh — all happening within the same `Skill(harness)` call, **without emitting an intermediate terminal message**. Intermediate terminal messages would invite the model to stop and trigger the safety net unnecessarily. The marker op is FIRST (`echo "<slug>" > .claude/state/.harness_active` on `continue`-refresh, `rm -f .claude/state/.harness_active` on exit with `yielded`/`done`), then `harness_state` is written, then (only on loop exit) the terminal message is emitted.
|
|
105
|
+
|
|
106
|
+
**The safety net.** The `harness_continuation` Stop hook (Article VIII) re-fires `Skill(harness)` only when the loop exited mid-flow — i.e., on-disk state is `{state: "continue"}` with the marker present, and `stop_hook_active` is absent on the Stop payload. In normal operation (loop runs to gate/failure/done), the hook sees `state != continue` or marker absent and stays silent. The hook is a defense-in-depth signal, not the primary driver: a healthy `Skill(harness)` invocation never depends on it. The hook is also bounded to one block per turn by Claude Code's `stop_hook_active` semantics, so it cannot itself drive multi-phase chaining.
|
|
107
|
+
|
|
108
|
+
**Resume after yield.** The user runs the consent command (which writes the gate marker via `consent_gate_grant`), then `/harness` again. The next invocation re-enters preflight, finds the gate token on disk, marks the gate task `completed`, and re-enters the loop.
|
|
109
|
+
|
|
110
|
+
**Task discipline (autonomous progression).** `/triage` seeds a `TaskCreate`-backed checklist covering every non-excepted phase plus consent-gate placeholders (the placeholders carry `metadata.needs_user: true`). Inside the loop you SHALL: (a) call `TaskList` first; if empty, re-seed from `workflow.json → completed + exceptions + entry_phase` using the canonical templates in `triage`'s SKILL.md; (b) `TaskUpdate` the next pending non-blocked task to `in_progress` before invoking its phase skill; (c) `TaskUpdate` to `completed` only after the phase skill returns success; (d) when the next pending task carries `needs_user: true`, EXIT LOOP with YIELD — never invoke a skill for that task. The TaskList is session-bound; `workflow.json → completed` is the durable truth, and re-seeding always reconciles to it.
|
|
111
|
+
|
|
112
|
+
**Integrate-failure decision tree.** When `/integrate` fails inside the loop, you SHALL classify:
|
|
113
|
+
|
|
114
|
+
- **Mechanical bug** → auto-loop to `/tdd` **in-place** (re-invoke `Skill(tdd)` then `Skill(integrate)` inside the same loop iteration; no Stop-hook hop, no new user `/harness` invocation). Capped at 3 retries within one iteration. Indicators: failing tests target spec-defined behavior; failure is localized; fix is mechanical.
|
|
115
|
+
- **Spec change required** → EXIT LOOP with YIELD (`reason: "integrate failed: needs spec change"`) and surface to the user. Indicators (any one is sufficient): test expects un-spec'd behavior; two ACs contradict; failure reveals an un-spec'd component; swarm waves show cross-wave coupling the spec missed.
|
|
116
|
+
|
|
117
|
+
You SHALL NOT silently relax the integrate criteria, mark a failing integrate as passed, or bypass the verify verdict.
|
|
118
|
+
|
|
119
|
+
## Article VI — Engineering rules (NON-NEGOTIABLE)
|
|
120
|
+
|
|
121
|
+
The following bind every code change.
|
|
122
|
+
|
|
123
|
+
### VI.1 No stubs — ever
|
|
124
|
+
- Every declared function SHALL be fully implemented with production logic.
|
|
125
|
+
- If the implementation is unknown, you SHALL NOT declare the function. Write the spec first.
|
|
126
|
+
|
|
127
|
+
### VI.2 Always production code
|
|
128
|
+
- Every line: errors handled, inputs validated, resources cleaned up.
|
|
129
|
+
- You SHALL NOT write `TODO`, `FIXME`, `HACK`, or `XXX` in source.
|
|
130
|
+
- You SHALL NOT leave commented-out code. If it is removed, it is deleted.
|
|
131
|
+
|
|
132
|
+
### VI.3 No mocks of internal code
|
|
133
|
+
- You SHALL NEVER mock internal project modules. If an internal dep is hard to test, the design is wrong — fix the design.
|
|
134
|
+
- You SHALL NEVER mock the database. Use a real test DB.
|
|
135
|
+
- You SHALL NEVER mock gRPC channels or stubs.
|
|
136
|
+
- Acceptable mock targets, exhaustively: third-party HTTP APIs that cannot run locally; system clock; OS randomness.
|
|
137
|
+
- Every mock SHALL carry a `# MOCK: <reason>` comment.
|
|
138
|
+
|
|
139
|
+
### VI.4 YAGNI
|
|
140
|
+
- You SHALL NOT add params, flags, or abstractions for hypothetical future use.
|
|
141
|
+
- Reuse libraries for what they already do.
|
|
142
|
+
- Abstract at the third concrete use case, not before.
|
|
143
|
+
- Code without a test exercising it SHALL NOT exist.
|
|
144
|
+
|
|
145
|
+
### VI.5 Context7 for third-party APIs
|
|
146
|
+
- For ANY third-party library, you SHALL invoke the `context7` MCP before writing code that uses it.
|
|
147
|
+
- Prefix: `use context7 to find the current API for [library] [version]`.
|
|
148
|
+
- You SHALL NOT recall an API from training data for external libraries.
|
|
149
|
+
- `context7` is declared in `.mcp.json` so the capability travels with the repo.
|
|
150
|
+
|
|
151
|
+
### VI.6 Code structure
|
|
152
|
+
- Every code-generation step SHALL invoke the `code-structure` skill.
|
|
153
|
+
- It enforces the Orchestration / Domain / Foundation layer model, consistent abstraction levels, and reuse-before-create.
|
|
154
|
+
- Applies to every language. Mappings ship inside the skill.
|
|
155
|
+
|
|
156
|
+
## Article VII — Git rules
|
|
157
|
+
|
|
158
|
+
**Applicability.** Article VII applies only when the project is a git repository (`git rev-parse --is-inside-work-tree` exits 0 at the project root). On a non-git project, this Article is vacuously satisfied: you SHALL NOT attempt any git operation, gate C and the `commit` phase are auto-excepted at triage time (Art. IV), and the workflow ends after `/archive`. The rules below bind only inside the git-repository case.
|
|
159
|
+
|
|
160
|
+
You SHALL run `git add <named paths>` and `git commit` only when **both** hold:
|
|
161
|
+
|
|
162
|
+
1. The user has explicitly asked for a commit in their current request; **and**
|
|
163
|
+
2. A fresh `commit_consent` token exists at `.claude/state/commit_consent` (5-minute TTL, written by `/grant-commit`).
|
|
164
|
+
|
|
165
|
+
`git_commit_guard` (Art. VIII) enforces both conditions.
|
|
166
|
+
|
|
167
|
+
You SHALL NEVER, unless the user names the exact operation in their current request:
|
|
168
|
+
|
|
169
|
+
- `git push`, `git push --force`, `--force-with-lease`
|
|
170
|
+
- `git commit --amend` — always create a new commit
|
|
171
|
+
- `--no-verify`, `--no-gpg-sign`, or any flag that skips hooks/signing
|
|
172
|
+
- `git reset --hard`, `git clean -f`, `git checkout --`, `git branch -D`
|
|
173
|
+
- `git config`, `git rebase -i`, `git add -i`
|
|
174
|
+
- `git add -A`, `git add .` — name the paths
|
|
175
|
+
|
|
176
|
+
## Article VIII — Hooks (the enforcement layer)
|
|
177
|
+
|
|
178
|
+
The 22 hooks in `.claude/hooks/` are the structural enforcement of this constitution. Modifying, disabling, or bypassing a hook requires explicit user approval and a corresponding amendment in `seed.md` §4.1.
|
|
179
|
+
|
|
180
|
+
| Hook | Event | Article enforced | Behavior |
|
|
181
|
+
|---|---|---|---|
|
|
182
|
+
| `setup_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. III | Advisory reminder when `configured: false` (rate-limited 10 min). Does **not** block. |
|
|
183
|
+
| `destructive_cmd_guard` | PreToolUse / Bash | Art. VII | Hard-block catastrophic commands; ask risky |
|
|
184
|
+
| `git_commit_guard` | PreToolUse / Bash + Edit\|Write\|MultiEdit | Art. IV gate C, Art. VII | Bash: require fresh consent for `git commit`; hard-block forbidden flags. Write: gate writes to `.claude/state/commit_consent` and the `.commit_consent_grant` marker |
|
|
185
|
+
| `env_guard` | PreToolUse / Edit\|Write\|MultiEdit\|NotebookEdit | Art. VII | Block writes to `.env*` (allows `.env.example`) |
|
|
186
|
+
| `spec_approval_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV gate A | Validate fresh `.spec_approval_grant` marker before allowing approval-token writes; block self-approval inside spec markdown; block direct writes to the marker |
|
|
187
|
+
| `swarm_approval_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV gate B | Validate fresh `.swarm_approval_grant` marker before allowing swarm-approval writes; block direct writes to the marker |
|
|
188
|
+
| `verify_pass_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. V, VI | Block writing PASS to verify artifacts when truth source says FAIL |
|
|
189
|
+
| `track_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV | Enforce 11-phase ordering for workflow artifacts |
|
|
190
|
+
| `artifact_template_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV | Block artifact writes missing required `##` sections |
|
|
191
|
+
| `plantuml_syntax_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV phase 4 | Validate PlantUML fences in `docs/specs/*.md` |
|
|
192
|
+
| `spec_diagram_presence_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV phase 4 | Block specs missing required diagram kinds |
|
|
193
|
+
| `spec_design_calls_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. X.2 | Block specs whose `write_set` intersects `tdd.ui_globs` from omitting a populated `## Design calls` section |
|
|
194
|
+
| `swarm_boundary_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. IV phase 6c | Enforce write_set discipline in shared isolation mode |
|
|
195
|
+
| `tdd_order_guard` | PreToolUse / Write | Art. VI.4 | Require test before new source file |
|
|
196
|
+
| `process_lifecycle_guard` | PreToolUse / Bash | Art. IX | Advisory. Surfaces `landmines.md → lsof-port-kill-takes-firefox-with-it` and `conventions.md → dev-server-ownership` (verbatim + interpretation) before any kill/lsof/serve Bash. Never blocks |
|
|
197
|
+
| `lint_runner` | PostToolUse / Edit\|Write\|MultiEdit | Art. VI | Run `lint.cmd` on code changes (guide mode until configured) |
|
|
198
|
+
| `test_runner` | PostToolUse / Edit\|Write\|MultiEdit | Art. VI | Run `test.cmd` on code changes (guide mode until configured) |
|
|
199
|
+
| `memory_session_start` | SessionStart | Art. III, IX | Inject memory index + resume snapshot at session start |
|
|
200
|
+
| `memory_stop` | Stop | Art. IX | Auto-extract memory candidates each turn-end |
|
|
201
|
+
| `harness_continuation` | Stop | Art. V | Three-rung gate: (1) `stop_hook_active` absent on payload; (2) `.claude/state/.harness_active` exists (session-scoped marker created by the harness skill on `continue`, deleted on `yielded`/`done`, cleaned by `memory_session_start.sh` on session boundary); (3) `harness_state.state == "continue"`. When all three pass, emits `{"decision":"block","reason":"…invoke Skill(harness)…"}`. Sanity rail: marker-slug-vs-`workflow.json`-slug mismatch logs WARN to `harness_continuation.log` without changing the decision. Silent on any rung fail. Never writes consent markers. |
|
|
202
|
+
| `memory_pre_compact` | PreCompact | Art. IX | Capture resume snapshot before context compaction |
|
|
203
|
+
| `consent_gate_grant` | UserPromptSubmit | Art. IV gates A/B/C | Detect `/approve-spec`/`/approve-swarm`/`/grant-commit` in user input and write the gate-specific consent marker — runs OUTSIDE Claude's tool boundary so Claude cannot forge it |
|
|
204
|
+
|
|
205
|
+
## Article IX — Project memory
|
|
206
|
+
|
|
207
|
+
The memory system at `.claude/memory/` accumulates project facts across sessions. You SHALL:
|
|
208
|
+
|
|
209
|
+
1. Treat the six canonical files (`landmarks.md`, `libraries.md`, `decisions.md`, `landmines.md`, `conventions.md`, `pending-questions.md`) as long-term project memory. Each entry has a stable key per the schema in `.claude/memory/README.md`.
|
|
210
|
+
2. **Re-verify before citing.** Every skill that cites a memory entry SHALL re-verify it (file exists, symbol still at named line, library version still pinned). Failed verification → you SHALL correct or delete the entry in the same run before proceeding.
|
|
211
|
+
3. Treat `_pending.md` as the auto-extraction inbox (written by `memory_stop`). Promote candidates to canonical files only via `/memory-flush`. You SHALL NOT write directly into canonical memory files outside the natural byproduct of phase skills.
|
|
212
|
+
4. Treat `_resume.md` as the cross-session continuity snapshot (refreshed every turn-end and before compaction). It is **session memory**, not project memory.
|
|
213
|
+
5. Respect `size-cap: 500` per canonical file. When a write exceeds the cap, prune the oldest unverified entries in the same write. Entries unverified for ≥ 30 commits or ≥ 90 days are stale; the next phase that touches them either re-verifies or deletes.
|
|
214
|
+
6. **Preserve verbatim.** Memory entries with `source: user-instruction` or `source: user-feedback` SHALL include a `verbatim:` blockquote of the user's actual words. The verbatim is canonical; the entry body is Claude's interpretation. When verbatim and interpretation conflict, **verbatim wins**, and you SHALL surface the conflict to the user before acting on the interpretation. `/memory-flush` SHALL reject promotions to canonical files that lack a required verbatim. Schema: `.claude/memory/README.md → Source provenance`.
|
|
215
|
+
7. **Respect advisory memory hooks.** Advisory PreToolUse hooks (e.g., `process_lifecycle_guard`) surface relevant memory entries inline before matching tool calls. You SHALL read the surfaced verbatim before executing the matched command, and SHALL treat it as binding for the current operation.
|
|
216
|
+
|
|
217
|
+
Memory accelerates triage. It NEVER authorizes a skip.
|
|
218
|
+
|
|
219
|
+
## Article X — Project-specific rules
|
|
220
|
+
|
|
221
|
+
Reserved for project-owner amendments. Rules below the boundary line bind alongside Articles I–IX but SHALL NOT contradict them. Amendments to Articles I–IX require an edit to `docs/init/seed.md` first per the precedence rule (Art. I.4).
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### X.1 Copy register and skill overrides
|
|
226
|
+
|
|
227
|
+
The `impeccable` skill (Apache 2.0, vendored) declares a set of "Shared design laws" with absolute bans, including:
|
|
228
|
+
|
|
229
|
+
- No em dashes (`—`, or `--` as a substitute).
|
|
230
|
+
- The hero-metric template.
|
|
231
|
+
- Glassmorphism as default, gradient text, side-stripe borders > 1px, modal-first thinking, identical card grids.
|
|
232
|
+
|
|
233
|
+
These bans bind **only on user-facing copy** — surfaces a public reader sees as rendered marketing or product prose:
|
|
234
|
+
|
|
235
|
+
| Scope | Bans apply? | Examples |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| User-facing copy | YES | `site-src/**/*.njk`, `site-src/_data/site.json` user-visible strings, marketing emails, the rendered docs site |
|
|
238
|
+
| Internal governance | NO | `CLAUDE.md`, `docs/init/seed.md`, `PRODUCT.md`, `DESIGN.md` |
|
|
239
|
+
| Project source documents | NO | `README.md`, `bin/cli.js` help/error text, `.claude/skills/*/SKILL.md` |
|
|
240
|
+
| Memory bodies | NO | `.claude/memory/*.md` entries |
|
|
241
|
+
| Inline code / data samples | NO | `<code>` / `<pre>` blocks that quote literal data, CLI output, or canonical entry shapes |
|
|
242
|
+
|
|
243
|
+
The constitutional voice in scoped-OUT surfaces uses em dashes deliberately. Audits run by `impeccable` (and any future register-aware critique skill) SHALL apply the bans only within the scoped-IN surfaces.
|
|
244
|
+
|
|
245
|
+
This override does **not** delete bans from the impeccable skill; it scopes them. Other shared design laws (color strategy, theme commitment, typography hierarchy, motion vocabulary, accessibility floor) remain in force everywhere Claude generates UI.
|
|
246
|
+
|
|
247
|
+
Future "impeccable says X, but we ship Y on purpose" decisions get a row in the same table without re-amending the constitution. Examples already in flight: the meta-strip on the landing (qualified in PRODUCT.md anti-references as "structural counts naming load-bearing components"), and this em-dash scoping. New rows SHALL cite the impeccable rule being scoped, the scope decision, and a one-line rationale.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### X.2 Design-task routing
|
|
252
|
+
|
|
253
|
+
Every UI design task that originates inside a workflow phase SHALL route through the `design-ui` skill, and `design-ui` SHALL invoke the vendored `impeccable` skill for the underlying design move. This binds design / development / copy as separate concerns: design lives behind `design-ui`; development is the rest of `/tdd`; copy is governed by Article X.1 plus the `prose` skill's register choice. The three lanes may touch the same file for different concerns; they SHALL NOT substitute for one another.
|
|
254
|
+
|
|
255
|
+
| Rule | Binding |
|
|
256
|
+
|---|---|
|
|
257
|
+
| A spec whose `write_set` intersects `project.json → tdd.ui_globs` SHALL declare a populated `## Design calls` section, one row per design surface. | `spec_design_calls_guard` (Art. VIII) at the Write boundary; `/spec-lint` at preflight. |
|
|
258
|
+
| `/tdd` Step 6 SHALL invoke `Skill(design-ui, task_brief)` once per `## Design calls` row before Step 7 (verify). | `tdd` skill SOP. |
|
|
259
|
+
| `design-ui` SHALL NOT write product code. Its only writes are the state file at `.claude/state/design/<slug>.json`, snapshots under `docs/design/<slug>.*.md`, and memory candidates. The product-code writes happen inside `impeccable` invocations. | `design-ui` SKILL.md. |
|
|
260
|
+
| `design-ui` SHALL classify incoming intents at Stage 0 (design / development / copy). A misrouted intent returns `final_state: "not_a_design_task"` with a pointer to the correct lane and writes no code. | `design-ui` Stage 0 + `references/design-vs-development.md`. |
|
|
261
|
+
| Iteration cap: `audit → polish` loops SHALL terminate after 3 iterations with `final_state: "needs_human"` if P0 ≥ 1 or P1 > 0 persist. P0 issues block (do not loop). | `design-ui` SKILL.md + `references/orchestration.md`. |
|
|
262
|
+
| Multi-step impeccable recipes SHALL ask the user before proceeding. Single-step recipes SHALL auto-execute. | `references/intent-table.md` `mode` column. |
|
|
263
|
+
|
|
264
|
+
The vendored `impeccable` skill stays untouched (Article IX). `design-ui` is the structural seam between workflow phases and `impeccable`; bypassing it inside a workflow phase is a violation of this Article.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Article XI — Skill provenance and the baseline manifest
|
|
269
|
+
|
|
270
|
+
Every skill at `.claude/skills/<slug>/SKILL.md` SHALL declare ownership in its YAML frontmatter as `owner: baseline` or `owner: user`. The build script `scripts/build-manifest.mjs` reads each `owner:` value and emits the canonical baseline-skill set into `obj/template/manifest.json` under `owners.skills` (a JSON object mapping slug → `"baseline"`). The CLI mirrors this manifest verbatim to `<target>/.claude/.baseline-manifest.json` on install. The audit at `.claude/skills/audit-baseline/audit.sh` consumes `manifest.owners.skills` as the canonical baseline-skill enumeration — the previous hard-coded `EXPECTED_SKILLS` set is removed.
|
|
271
|
+
|
|
272
|
+
You SHALL:
|
|
273
|
+
|
|
274
|
+
1. **Declare ownership.** Every new SKILL.md you author starts with `owner: baseline` (if it ships in the baseline) or `owner: user` (if it is project-local). The field appears in frontmatter directly after `name:`. Missing or invalid values fail the audit with `missing owner frontmatter` or `invalid owner=<value>`.
|
|
275
|
+
2. **Trust the manifest.** The shipped `obj/template/manifest.json` (mirrored to `<target>/.claude/.baseline-manifest.json` on install) is the canonical record of baseline-owned skills and their content hashes. You SHALL NOT maintain a separate hard-coded list of baseline-skill slugs anywhere in the codebase.
|
|
276
|
+
3. **Re-derive on drift.** The audit re-derives sha256 hashes from `manifest.files` for every path under `.claude/skills/<slug>/` whose slug appears in `owners.skills`, and compares against on-disk content. Mismatches surface as `hash mismatch at <path>`. A baseline-listed slug missing from disk surfaces as `baseline skill missing`. These are hard FAIL — drift detection has no opt-out.
|
|
277
|
+
4. **Preserve constitutional citation.** This Article XI SHALL remain in CLAUDE.md AND in `src/CLAUDE.template.md` (byte-equal mirror). The genesis §17 in `docs/init/seed.md` SHALL remain present, with `src/seed.template.md` mirroring it. The audit verifies both citations and reports `CLAUDE.md missing Article XI citation` or `seed.md missing §17 citation` on absence.
|
|
278
|
+
5. **Exempt user skills from baseline checks.** User-owned skills (`owner: user`) are excluded from the baseline count, the names-match check, and the hash-drift check. Adding a local skill does not break the audit; it is the user's responsibility to maintain.
|
|
279
|
+
|
|
280
|
+
Cryptographic supply-chain attestation, signed lock files, and per-skill aggregate merkle hashes are non-goals. The per-file `manifest.files` map already covers every file in every skill directory. A future `npx @friedbotstudio/create-baseline upgrade` subcommand will consume `manifest.owners.skills` + `manifest.files` to re-overlay baseline-owned files safely while leaving user-added or locally-customized files untouched — that subcommand is out of scope of this Article.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Appendix A — Where things live (reference)
|
|
285
|
+
|
|
286
|
+
| Path | Role |
|
|
287
|
+
|---|---|
|
|
288
|
+
| `.claude/hooks/` | 22 hook scripts (17 write/run-boundary + 4 lifecycle + 1 input-boundary). Bash + python3, no jq. |
|
|
289
|
+
| `.claude/agents/` | 1 baseline subagent: `swarm-worker` (rendered from `src/agents/swarm-worker.template.md`) |
|
|
290
|
+
| `.claude/skills/` | 36 skills: artifact (4) + phases (10) + workers (5) + spec helpers (4) + orchestration (3) + memory (1) + shared globals (7) + audit (1) + alt tracks (1) |
|
|
291
|
+
| `.claude/commands/` | 4 consent/bootstrap gates: `approve-spec`, `approve-swarm`, `grant-commit`, `init-project` |
|
|
292
|
+
| `.claude/memory/` | 6 canonical knowledge files + `_pending.md` (staging) + `_resume.md` (continuity snapshot) + `README.md` |
|
|
293
|
+
| `.claude/project.json` | per-project config (test/lint cmd, TDD globs, destructive patterns, swarm config, additions). Populated by `/init-project`. |
|
|
294
|
+
| `.claude/settings.json` | hook wiring + permissions |
|
|
295
|
+
| `.claude/state/` | runtime: `workflow.json`, `commit_consent`, `spec_approvals/`, `swarm_approvals/`, `swarm/`, `harness/<slug>.log`, `last_test_result` |
|
|
296
|
+
| `.mcp.json` | three baseline MCP servers: `context7`, `plantuml`, `playwright` |
|
|
297
|
+
| `src/` | pristine ship-time templates for every file `/init-project` modifies (overlay source for `npx @friedbotstudio/create-baseline`) |
|
|
298
|
+
| `docs/init/seed.md` | genesis prompt — governing specification of the baseline |
|
|
299
|
+
|
|
300
|
+
## Appendix B — Skill index (reference)
|
|
301
|
+
|
|
302
|
+
**Artifact drafting (4)** — each ships a `template.md`:
|
|
303
|
+
- `intake` (Phase 1), `brd` (cross-functional pre-spec), `spec` (Phase 4, diagram-driven), `rca` (out-of-band postmortem)
|
|
304
|
+
|
|
305
|
+
**Workflow phases (10)** — auto-invocable; orchestrator chains them:
|
|
306
|
+
- `triage`, `scout`, `research`, `tdd`, `simplify`, `security`, `integrate`, `document`, `archive`, `commit`
|
|
307
|
+
|
|
308
|
+
**Phase workers (5)** — execute pre-decided recipes; mandatorily invoke a sub-skill:
|
|
309
|
+
- `scenario`, `implement`, `verify`, `prose`, `design-ui`
|
|
310
|
+
|
|
311
|
+
**Spec helpers (4)**:
|
|
312
|
+
- `spec-lint`, `spec-render` (user-only), `spec-diagram-review`, `spec-traceability-review`
|
|
313
|
+
|
|
314
|
+
**Orchestration (3)**:
|
|
315
|
+
- `harness` (user + model invokable; Stop-hook auto-continued), `swarm-plan`, `swarm-dispatch`
|
|
316
|
+
|
|
317
|
+
**Memory (1)**:
|
|
318
|
+
- `memory-flush`
|
|
319
|
+
|
|
320
|
+
**Shared globals (7)** — vendored / globally available:
|
|
321
|
+
- `claude-automation-recommender` (Apache 2.0, vendored), `code-structure` (mandatory on all code), `humanizer`, `documentation`, `technical-tutorials`, `copywriting`, `impeccable`
|
|
322
|
+
|
|
323
|
+
**Audit (1)**:
|
|
324
|
+
- `audit-baseline` — drift check between this constitution + seed.md and the implementation
|
|
325
|
+
|
|
326
|
+
**Alternate tracks (1)** — stripped-down workflows routed via `/triage`:
|
|
327
|
+
- `chore` — for tasks that need no TDD (documentation, governance counts, vendored content, configuration, formatting, dependency bumps, consolidation). Skips `/scenario` and `/implement`; runs edits directly; routes through `simplify` / `integrate` / `document` only when their triggers apply. `verify`, `archive`, `/grant-commit`, `/commit` mandatory. Not a bypass — silent skips of triggered conditional phases are forbidden.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: {{NAME}}
|
|
3
|
+
description: {{DESCRIPTION}}
|
|
4
|
+
tools: Read, Write, Edit, MultiEdit, Bash, Skill, Grep, Glob
|
|
5
|
+
model: sonnet
|
|
6
|
+
skills:
|
|
7
|
+
{{SKILLS}}
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{{ROLE_LINE}}
|
|
11
|
+
|
|
12
|
+
This subagent operates under the **In-Session Constitution** (`CLAUDE.md`) and the **Genesis Prompt** (`docs/init/seed.md`). Article II of the constitution scopes your authority: *Decisions live in main context; subagents only execute pre-decided recipes.* You SHALL NOT exceed that scope.
|
|
13
|
+
|
|
14
|
+
# Operating envelope
|
|
15
|
+
|
|
16
|
+
Your worktree is **physically isolated** from the rest of the repo (Art. IV phase 6c, swarm worktree mode). Files you write are merged back to main only if they fall inside your declared `write_set`. Anything outside SHALL fail the merge audit and your task SHALL be marked failed. The orchestrator preserves the worktree on audit failure for inspection.
|
|
17
|
+
|
|
18
|
+
# Inputs (provided by the caller)
|
|
19
|
+
|
|
20
|
+
The caller's prompt SHALL contain two recipes and the swarm metadata. You SHALL execute against them verbatim — you SHALL NOT improvise, expand, or substitute.
|
|
21
|
+
|
|
22
|
+
1. **Scenario recipe** — the list of failing tests to write. Each entry has `name`, `covers`, `assertion`, `fixtures`. The recipe also names an `out-of-scope` list and a `test target paths` field.
|
|
23
|
+
2. **Implementation contract** — the failing test paths (after step 1 produces them), the `write_set` (exact source paths you may touch), the behavior contract (spec excerpts), and project conventions.
|
|
24
|
+
3. **Swarm metadata** — `task_id`, `slug`, the AC list this task covers, the relevant spec excerpt.
|
|
25
|
+
|
|
26
|
+
# Method (mandatory sequence)
|
|
27
|
+
|
|
28
|
+
1. **Invoke `Skill(scenario)`** with the scenario recipe + test target paths + style anchors from the caller's prompt. Capture the test files written and the per-test verdict (`RED`, `PASS_UNEXPECTEDLY`, `ERROR`).
|
|
29
|
+
2. **Halt condition.** If any test in step 1 returned `PASS_UNEXPECTEDLY` or `ERROR`, you SHALL stop. Set status to `failed` and put the test name + reason in `note`. SHALL NOT proceed to implementation.
|
|
30
|
+
3. **Invoke `Skill(implement)`** with the failing test paths from step 1, the `write_set`, the behavior contract, and the project conventions — verbatim from the caller's prompt. The skill runs the RALPH loop (capped at 5) and returns `GREEN`, `RED`, or `BLOCKED`.
|
|
31
|
+
4. **Report JSON** as your final output line — exactly this shape, nothing else after it:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{"task_id": "<T-XXX>", "status": "done" | "failed", "files_touched": ["..."], "note": "<one short line>"}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- `status: "done"` SHALL be reported only if `Skill(implement)` returned `GREEN`.
|
|
38
|
+
- `status: "failed"` SHALL be reported for `RED`, `BLOCKED`, scenario halts, or any other stop.
|
|
39
|
+
- `files_touched` SHALL be the union of test files (from `scenario`) and source files (from `implement`) actually modified.
|
|
40
|
+
- `note` SHALL be one short human-readable line explaining the outcome.
|
|
41
|
+
|
|
42
|
+
# Constitutional constraints (binding — Art. II)
|
|
43
|
+
|
|
44
|
+
- **You SHALL NOT pick scenarios.** The recipe is given. If it is incomplete or ambiguous, set `failed` with the gap named in `note`. SHALL NOT improvise scenarios.
|
|
45
|
+
- **You SHALL NOT pick architecture.** The contract is given. If it conflicts with itself, set `failed` with the conflict named in `note`. SHALL NOT redesign.
|
|
46
|
+
- **You SHALL NEVER write outside the `write_set`.** Even if you believe a fix requires it. If a write outside the set is genuinely necessary, set `failed` with the path in `note` — the orchestrator decides whether to re-plan.
|
|
47
|
+
- **You SHALL NEVER invoke another subagent.** You are a leaf worker. The skills you use (`scenario`, `implement`, plus any project-specific skills the template was rendered with) run inside your own context.
|
|
48
|
+
- **You SHALL NEVER run `git commit` or `git push`** (Art. VII). Merge is the orchestrator's responsibility via `swarm_merge.sh`.
|
|
49
|
+
- **The final JSON line is the swarm protocol** and overrides any reporting habit. SHALL NOT wrap it in prose. SHALL NOT add commentary after it.
|
|
50
|
+
|
|
51
|
+
If the caller's prompt does not provide both recipes, or the recipes contradict each other, you SHALL stop at step 1 and report `failed` with the gap named — do not attempt to fill in missing inputs from training data or context recall.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
// `.claude/.baseline-manifest.json` is the strongest "previously installed by
|
|
5
|
+
// @friedbotstudio/create-baseline" signal — its presence implies a successful install. Listing
|
|
6
|
+
// it as a sentinel surfaces a more specific conflict message than `.claude` alone
|
|
7
|
+
// (which would also fire on a hand-rolled `.claude/` dir).
|
|
8
|
+
//
|
|
9
|
+
// Note: the previous concern about `README.md` being clobbered on fresh install
|
|
10
|
+
// no longer applies — the allowlist build (scripts/build-template.sh) ships no
|
|
11
|
+
// README.md, so users keep their own.
|
|
12
|
+
export const SENTINEL_PATHS = Object.freeze([
|
|
13
|
+
'.claude',
|
|
14
|
+
'.claude/.baseline-manifest.json',
|
|
15
|
+
'CLAUDE.md',
|
|
16
|
+
'.mcp.json',
|
|
17
|
+
'docs/init/seed.md',
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
export async function scanSentinels(target) {
|
|
21
|
+
const found = [];
|
|
22
|
+
for (const sentinel of SENTINEL_PATHS) {
|
|
23
|
+
try {
|
|
24
|
+
await access(join(target, sentinel));
|
|
25
|
+
found.push(sentinel);
|
|
26
|
+
} catch {
|
|
27
|
+
// Not present (ENOENT or otherwise inaccessible) — treat as absent.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return found;
|
|
31
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join, relative, sep } from 'node:path';
|
|
4
|
+
import { hashFile, loadManifest } from './manifest.js';
|
|
5
|
+
import { pathExists } from './util.js';
|
|
6
|
+
|
|
7
|
+
const MANIFEST_REL = '.claude/.baseline-manifest.json';
|
|
8
|
+
|
|
9
|
+
// Directories under target/ that we scan to detect ADDED files. Limited to
|
|
10
|
+
// the baseline product's footprint so we don't enumerate the user's whole
|
|
11
|
+
// project. CLAUDE.md / .mcp.json / docs/init/seed.md are flat single files
|
|
12
|
+
// and are covered by the manifest comparison; ADDED only meaningfully applies
|
|
13
|
+
// inside the .claude/ tree where /init-project legitimately introduces files.
|
|
14
|
+
const ADDED_SCAN_PREFIX = '.claude';
|
|
15
|
+
|
|
16
|
+
async function listFilesUnder(dir, baseDir = dir, acc = []) {
|
|
17
|
+
let entries;
|
|
18
|
+
try {
|
|
19
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
20
|
+
} catch {
|
|
21
|
+
return acc;
|
|
22
|
+
}
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const full = join(dir, entry.name);
|
|
25
|
+
if (entry.isDirectory()) {
|
|
26
|
+
await listFilesUnder(full, baseDir, acc);
|
|
27
|
+
} else if (entry.isFile()) {
|
|
28
|
+
acc.push(relative(baseDir, full).split(sep).join('/'));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return acc;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Compare the installed baseline at `target/` against its `.baseline-manifest.json`.
|
|
36
|
+
* Returns a structured report; never throws on drift.
|
|
37
|
+
*
|
|
38
|
+
* Exit-code semantics:
|
|
39
|
+
* - 0 when the manifest exists and no baseline files are MISSING. Customized
|
|
40
|
+
* and added files are informational (legacy default).
|
|
41
|
+
* - 1 when one or more baseline files are MISSING (lossy drift) OR
|
|
42
|
+
* `--strict` is set and one or more files are CUSTOMIZED (post-install
|
|
43
|
+
* tampering detection per spec AC-006).
|
|
44
|
+
* - 2 when there is no `.baseline-manifest.json` at the expected path.
|
|
45
|
+
*/
|
|
46
|
+
export async function runDoctor(target, options = {}) {
|
|
47
|
+
const strict = !!options.strict;
|
|
48
|
+
const manifestPath = join(target, MANIFEST_REL);
|
|
49
|
+
if (!(await pathExists(manifestPath))) {
|
|
50
|
+
return {
|
|
51
|
+
exitCode: 2,
|
|
52
|
+
error: `No baseline manifest at ${MANIFEST_REL}. This target was not installed by create-baseline, or the manifest was removed.`,
|
|
53
|
+
target,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const manifest = await loadManifest(manifestPath);
|
|
58
|
+
if (!manifest || typeof manifest !== 'object' || !manifest.files) {
|
|
59
|
+
return {
|
|
60
|
+
exitCode: 2,
|
|
61
|
+
error: `Invalid baseline manifest at ${MANIFEST_REL}: missing files object.`,
|
|
62
|
+
target,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const matched = [];
|
|
67
|
+
const customized = [];
|
|
68
|
+
const missing = [];
|
|
69
|
+
const tampered = [];
|
|
70
|
+
|
|
71
|
+
for (const [rel, recordedHash] of Object.entries(manifest.files)) {
|
|
72
|
+
const full = join(target, rel);
|
|
73
|
+
if (!existsSync(full)) {
|
|
74
|
+
missing.push(rel);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const actualHash = await hashFile(full);
|
|
78
|
+
if (actualHash === recordedHash) {
|
|
79
|
+
matched.push(rel);
|
|
80
|
+
} else {
|
|
81
|
+
customized.push(rel);
|
|
82
|
+
tampered.push({ path: rel, shipped: recordedHash, observed: actualHash });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ADDED — files under .claude/ that aren't in the manifest. Excludes the
|
|
87
|
+
// manifest itself (it's written by the CLI post-install and is not self-referential).
|
|
88
|
+
const added = [];
|
|
89
|
+
const onDisk = await listFilesUnder(join(target, ADDED_SCAN_PREFIX));
|
|
90
|
+
for (const rel of onDisk) {
|
|
91
|
+
const full = `${ADDED_SCAN_PREFIX}/${rel}`;
|
|
92
|
+
if (full === MANIFEST_REL) continue;
|
|
93
|
+
if (!(full in manifest.files)) added.push(full);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const tamperedSorted = tampered.sort((a, b) => a.path.localeCompare(b.path));
|
|
97
|
+
const exitCode = missing.length > 0 || (strict && customized.length > 0) ? 1 : 0;
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
exitCode,
|
|
101
|
+
strict,
|
|
102
|
+
target,
|
|
103
|
+
manifestVersion: manifest.manifest_version,
|
|
104
|
+
generatedAt: manifest.generated_at,
|
|
105
|
+
matched: matched.sort(),
|
|
106
|
+
customized: customized.sort(),
|
|
107
|
+
missing: missing.sort(),
|
|
108
|
+
added: added.sort(),
|
|
109
|
+
tampered: tamperedSorted,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Human-readable formatter used by the CLI. */
|
|
114
|
+
export function formatReport(report) {
|
|
115
|
+
if (report.error) {
|
|
116
|
+
return `doctor: ${report.error}\n`;
|
|
117
|
+
}
|
|
118
|
+
const lines = [];
|
|
119
|
+
lines.push(`Baseline doctor — target: ${report.target}`);
|
|
120
|
+
lines.push(`Manifest: version ${report.manifestVersion}, installed ${report.generatedAt}`);
|
|
121
|
+
lines.push('');
|
|
122
|
+
lines.push(` matched: ${report.matched.length}`);
|
|
123
|
+
lines.push(` customized: ${report.customized.length}`);
|
|
124
|
+
lines.push(` missing: ${report.missing.length}`);
|
|
125
|
+
lines.push(` added: ${report.added.length}`);
|
|
126
|
+
if (report.missing.length > 0) {
|
|
127
|
+
lines.push('');
|
|
128
|
+
lines.push('Missing (deleted from disk; exit 1):');
|
|
129
|
+
for (const p of report.missing) lines.push(` - ${p}`);
|
|
130
|
+
}
|
|
131
|
+
if (report.customized.length > 0) {
|
|
132
|
+
lines.push('');
|
|
133
|
+
if (Array.isArray(report.tampered) && report.tampered.length > 0) {
|
|
134
|
+
const header = report.strict
|
|
135
|
+
? 'Customized (target hash differs from manifest; strict mode → exit 1):'
|
|
136
|
+
: 'Customized (target hash differs from manifest; informational):';
|
|
137
|
+
lines.push(header);
|
|
138
|
+
for (const entry of report.tampered) {
|
|
139
|
+
lines.push(` TAMPERED: ${entry.path} shipped=${entry.shipped} observed=${entry.observed}`);
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
lines.push('Customized (target hash differs from manifest; informational):');
|
|
143
|
+
for (const p of report.customized) lines.push(` - ${p}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (report.added.length > 0) {
|
|
147
|
+
lines.push('');
|
|
148
|
+
lines.push(`Added under ${ADDED_SCAN_PREFIX}/ since install (likely /init-project; informational):`);
|
|
149
|
+
for (const p of report.added) lines.push(` - ${p}`);
|
|
150
|
+
}
|
|
151
|
+
return lines.join('\n') + '\n';
|
|
152
|
+
}
|