@friedbotstudio/create-baseline 0.2.0 → 0.3.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.
Files changed (88) hide show
  1. package/README.md +7 -3
  2. package/obj/template/.claude/commands/grant-push.md +19 -0
  3. package/obj/template/.claude/commands/init-project.md +26 -4
  4. package/obj/template/.claude/hooks/consent_gate_grant.mjs +107 -0
  5. package/obj/template/.claude/hooks/git_commit_guard.mjs +224 -0
  6. package/obj/template/.claude/hooks/harness_continuation.sh +101 -34
  7. package/obj/template/.claude/hooks/lib/common.mjs +283 -0
  8. package/obj/template/.claude/hooks/lib/common.sh +1 -1
  9. package/obj/template/.claude/hooks/memory_session_start.sh +20 -6
  10. package/obj/template/.claude/hooks/memory_stop.sh +161 -2
  11. package/obj/template/.claude/hooks/spec_approval_guard.sh +1 -1
  12. package/obj/template/.claude/hooks/swarm_approval_guard.sh +1 -1
  13. package/obj/template/.claude/hooks/tests/fixtures/ac008_byte_equal_reference.txt +7 -7
  14. package/obj/template/.claude/hooks/tests/fixtures/memory_stop_landmark_baseline.txt +21 -0
  15. package/obj/template/.claude/hooks/tests/fixtures/regenerate-ac008.sh +47 -0
  16. package/obj/template/.claude/hooks/tests/memory_session_start_test.sh +7 -3
  17. package/obj/template/.claude/hooks/tests/memory_stop_intent_test.sh +329 -0
  18. package/obj/template/.claude/hooks/tests/regenerate_ac008_test.sh +99 -0
  19. package/obj/template/.claude/memory/README.md +8 -3
  20. package/obj/template/.claude/memory/backlog.md +12 -0
  21. package/obj/template/.claude/project.json +6 -1
  22. package/obj/template/.claude/settings.json +3 -4
  23. package/obj/template/.claude/skills/audit-baseline/audit.sh +39 -21
  24. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/_pending_opener_only.md +3 -0
  25. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_full_empty_body.md +4 -0
  26. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_full_with_entries.md +9 -0
  27. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_no_opener.md +3 -0
  28. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_opener_only.md +3 -0
  29. package/obj/template/.claude/skills/audit-baseline/tests/preamble_check_test.sh +147 -0
  30. package/obj/template/.claude/skills/chore/SKILL.md +5 -3
  31. package/obj/template/.claude/skills/commit/SKILL.md +5 -4
  32. package/obj/template/.claude/skills/copywriting/LICENSE +21 -0
  33. package/obj/template/.claude/skills/copywriting/NOTICE +23 -0
  34. package/obj/template/.claude/skills/copywriting/SKILL.md +1 -1
  35. package/obj/template/.claude/skills/design-ui/SKILL.md +23 -5
  36. package/obj/template/.claude/skills/design-ui/references/design-vs-development.md +26 -5
  37. package/obj/template/.claude/skills/design-ui/references/orchestration.md +1 -0
  38. package/obj/template/.claude/skills/design-ui/references/state-machine.md +5 -3
  39. package/obj/template/.claude/skills/documentation/LICENSE +202 -0
  40. package/obj/template/.claude/skills/documentation/NOTICE +22 -0
  41. package/obj/template/.claude/skills/google-analytics/SKILL.md +129 -0
  42. package/obj/template/.claude/skills/google-analytics/references/audiences.md +389 -0
  43. package/obj/template/.claude/skills/google-analytics/references/bigquery.md +470 -0
  44. package/obj/template/.claude/skills/google-analytics/references/custom-dimensions.md +355 -0
  45. package/obj/template/.claude/skills/google-analytics/references/custom-events.md +383 -0
  46. package/obj/template/.claude/skills/google-analytics/references/data-management.md +416 -0
  47. package/obj/template/.claude/skills/google-analytics/references/debugview.md +364 -0
  48. package/obj/template/.claude/skills/google-analytics/references/events-fundamentals.md +398 -0
  49. package/obj/template/.claude/skills/google-analytics/references/gtag.md +502 -0
  50. package/obj/template/.claude/skills/google-analytics/references/gtm-integration.md +483 -0
  51. package/obj/template/.claude/skills/google-analytics/references/measurement-protocol.md +519 -0
  52. package/obj/template/.claude/skills/google-analytics/references/privacy.md +441 -0
  53. package/obj/template/.claude/skills/google-analytics/references/recommended-events.md +464 -0
  54. package/obj/template/.claude/skills/google-analytics/references/reporting.md +397 -0
  55. package/obj/template/.claude/skills/google-analytics/references/setup.md +344 -0
  56. package/obj/template/.claude/skills/google-analytics/references/user-tracking.md +417 -0
  57. package/obj/template/.claude/skills/harness/SKILL.md +3 -1
  58. package/obj/template/.claude/skills/humanizer/LICENSE +21 -0
  59. package/obj/template/.claude/skills/humanizer/NOTICE +21 -0
  60. package/obj/template/.claude/skills/impeccable/LICENSE +202 -0
  61. package/obj/template/.claude/skills/impeccable/NOTICE +24 -0
  62. package/obj/template/.claude/skills/memory-flush/SKILL.md +20 -4
  63. package/obj/template/.claude/skills/memory-flush/sweep.py +74 -6
  64. package/obj/template/.claude/skills/memory-flush/tests/run.sh +300 -1
  65. package/obj/template/.claude/skills/optimize-seo/SKILL.md +313 -0
  66. package/obj/template/.claude/skills/optimize-seo/scripts/pagespeed.mjs +197 -0
  67. package/obj/template/.claude/skills/pagespeed-insights/LICENSE.md +37 -0
  68. package/obj/template/.claude/skills/pagespeed-insights/SKILL.md +446 -0
  69. package/obj/template/.claude/skills/pagespeed-insights/reference.md +50 -0
  70. package/obj/template/.claude/skills/tdd/SKILL.md +2 -1
  71. package/obj/template/.claude/skills/tdd/drift_check.py +180 -0
  72. package/obj/template/.claude/skills/tdd/tests/drift_check_test.sh +190 -0
  73. package/obj/template/.claude/skills/tdd/tests/run.sh +21 -0
  74. package/obj/template/.claude/skills/technical-tutorials/LICENSE +21 -0
  75. package/obj/template/.claude/skills/technical-tutorials/NOTICE +23 -0
  76. package/obj/template/.claude/skills/technical-tutorials/SKILL.md +1 -1
  77. package/obj/template/.claude/skills/triage/SKILL.md +8 -3
  78. package/obj/template/CLAUDE.md +37 -26
  79. package/obj/template/docs/init/seed.md +38 -23
  80. package/obj/template/manifest.json +80 -33
  81. package/package.json +1 -1
  82. package/src/CLAUDE.template.md +37 -26
  83. package/src/memory/backlog.template.md +12 -0
  84. package/src/project.template.json +6 -1
  85. package/src/seed.template.md +38 -23
  86. package/src/settings.template.json +3 -4
  87. package/obj/template/.claude/hooks/consent_gate_grant.sh +0 -89
  88. package/obj/template/.claude/hooks/git_commit_guard.sh +0 -93
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env bash
2
+ # Fixture-based integration tests for the drift_check.py helper.
3
+ # Covers AC-002, AC-003, AC-004, AC-011 (and OQ-4) from
4
+ # docs/specs/workflow-loop-closing-hygiene.md.
5
+ #
6
+ # Contract under test (drift_check.py):
7
+ # python3 .claude/skills/tdd/drift_check.py --slug <slug> \
8
+ # [--project-root <path>] [--diff <path>]
9
+ # Reads docs/specs/<slug>.md, scores every numbered AC + ## Design calls row
10
+ # against either git diff or the --diff override, writes a markdown report at
11
+ # .claude/state/drift/<slug>.md inside the project-root. Exits:
12
+ # 0 — zero unresolved
13
+ # 1 — >=1 unresolved
14
+ # 2 — tool error (missing args, IO, etc.)
15
+ # Special case: missing spec at the named slug exits 0 with "no spec; skipped"
16
+ # on stdout and writes no report (chore-track support per AC-011).
17
+
18
+ set -uo pipefail
19
+
20
+ HERE="$(cd "$(dirname "$0")" && pwd)"
21
+ REPO_ROOT="$(cd "$HERE/../../../.." && pwd)"
22
+ DRIFT="$REPO_ROOT/.claude/skills/tdd/drift_check.py"
23
+
24
+ PASS=0; FAIL=0; FAILED=()
25
+
26
+ fail() { echo " FAIL: $*"; return 1; }
27
+
28
+ assert_file_contains() {
29
+ local path="$1" needle="$2" msg="$3"
30
+ if grep -qF "$needle" "$path" 2>/dev/null; then return 0; fi
31
+ fail "$msg :: file $path missing: $needle"
32
+ }
33
+
34
+ assert_contains() {
35
+ local haystack="$1" needle="$2" msg="$3"
36
+ case "$haystack" in
37
+ *"$needle"*) return 0 ;;
38
+ *) fail "$msg :: expected to contain: $needle" ;;
39
+ esac
40
+ }
41
+
42
+ # Run drift_check.py against a synthetic project-root, setting $OUT (combined
43
+ # stdout+stderr) and $EXIT in the caller's scope. Called without command
44
+ # substitution so the assignments survive into the test function.
45
+ run_drift() {
46
+ local root="$1" slug="$2" diff_path="${3:-}"
47
+ if [ ! -f "$DRIFT" ]; then
48
+ OUT='{"error":"drift_check.py missing"}'
49
+ EXIT=127
50
+ return
51
+ fi
52
+ local args=( --slug "$slug" --project-root "$root" )
53
+ [ -n "$diff_path" ] && args+=( --diff "$diff_path" )
54
+ OUT="$(python3 "$DRIFT" "${args[@]}" 2>&1)"
55
+ EXIT=$?
56
+ }
57
+
58
+ # Build a minimal synthetic project-root with docs/specs/<slug>.md present.
59
+ # $1 = root, $2 = slug, $3 = AC list (newline-sep `AC-NNN`), $4 = design-calls body
60
+ seed_project() {
61
+ local root="$1" slug="$2" acs="$3" dc="$4"
62
+ mkdir -p "$root/docs/specs" "$root/.claude/state"
63
+ {
64
+ printf '# Spec — %s\n\n' "$slug"
65
+ printf '## Goal\n\nMinimal synthetic spec for drift_check tests.\n\n'
66
+ printf '## Design\n\nN/A\n\n'
67
+ printf '## Design calls\n\n%s\n\n' "$dc"
68
+ printf '## Acceptance criteria\n\n| ID | Criterion | Upstream | Sequence |\n|---|---|---|---|\n'
69
+ while IFS= read -r ac; do
70
+ [ -z "$ac" ] && continue
71
+ printf '| %s | given X, when Y, then Z | upstream | §Behavior #1 |\n' "$ac"
72
+ done <<< "$acs"
73
+ printf '\n## Test plan\n\nN/A\n'
74
+ } > "$root/docs/specs/$slug.md"
75
+ }
76
+
77
+ # Synthesize a diff file. $1 = path, $2 = lines (literal text).
78
+ seed_diff() {
79
+ printf '%s' "$2" > "$1"
80
+ }
81
+
82
+ today() { date -u +%Y-%m-%d; }
83
+
84
+ run() {
85
+ local name="$1"
86
+ echo "RUN $name"
87
+ if "$name"; then
88
+ PASS=$((PASS+1)); echo "PASS $name"
89
+ else
90
+ FAIL=$((FAIL+1)); FAILED+=("$name"); echo "FAIL $name"
91
+ fi
92
+ }
93
+
94
+ # --- AC-002, AC-004 -----------------------------------------------------------
95
+
96
+ test_when_drift_check_on_spec_with_all_resolved_then_exit_0() {
97
+ local root; root="$(mktemp -d)"; trap "rm -rf $root" RETURN
98
+ seed_project "$root" "wf-all-resolved" "AC-001
99
+ AC-002" "*(none)*"
100
+ # Diff carrying test names that reference AC-001 and AC-002 substrings.
101
+ local diff_path="$root/diff.txt"
102
+ seed_diff "$diff_path" "+def test_when_AC-001_satisfied_then_x_works(): pass
103
+ +def test_when_AC-002_satisfied_then_y_works(): pass
104
+ "
105
+ OUT=""; EXIT=0
106
+ run_drift "$root" "wf-all-resolved" "$diff_path"
107
+ if [ "$EXIT" -ne 0 ]; then
108
+ fail "AC-002 expected exit 0 (all resolved), got $EXIT; stdout: $OUT"
109
+ return 1
110
+ fi
111
+ local report="$root/.claude/state/drift/wf-all-resolved.md"
112
+ [ -f "$report" ] || { fail "AC-002 report not written at $report"; return 1; }
113
+ assert_file_contains "$report" "AC-001" "AC-002 report missing AC-001" || return 1
114
+ assert_file_contains "$report" "AC-002" "AC-002 report missing AC-002" || return 1
115
+ assert_file_contains "$report" "resolved" "AC-002 report missing resolved verdict" || return 1
116
+ }
117
+
118
+ # --- AC-003 -------------------------------------------------------------------
119
+
120
+ test_when_drift_check_finds_unresolved_then_exit_1() {
121
+ local root; root="$(mktemp -d)"; trap "rm -rf $root" RETURN
122
+ seed_project "$root" "wf-unresolved" "AC-99" "*(none)*"
123
+ local diff_path="$root/diff.txt"
124
+ # Diff has no reference to AC-99 anywhere.
125
+ seed_diff "$diff_path" "+def test_when_unrelated_then_ok(): pass
126
+ "
127
+ OUT=""; EXIT=0
128
+ run_drift "$root" "wf-unresolved" "$diff_path"
129
+ if [ "$EXIT" -ne 1 ]; then
130
+ fail "AC-003 expected exit 1 (>=1 unresolved), got $EXIT; stdout: $OUT"
131
+ return 1
132
+ fi
133
+ local report="$root/.claude/state/drift/wf-unresolved.md"
134
+ [ -f "$report" ] || { fail "AC-003 report not written at $report"; return 1; }
135
+ assert_file_contains "$report" "AC-99" "AC-003 report missing AC-99" || return 1
136
+ assert_file_contains "$report" "unresolved" "AC-003 report missing unresolved verdict" || return 1
137
+ }
138
+
139
+ # --- AC-002 boundary, AC-011 --------------------------------------------------
140
+
141
+ test_when_drift_check_no_spec_then_exit_0_skipped() {
142
+ local root; root="$(mktemp -d)"; trap "rm -rf $root" RETURN
143
+ # No spec file is created at docs/specs/<slug>.md.
144
+ mkdir -p "$root/docs/specs" "$root/.claude/state"
145
+ OUT=""; EXIT=0
146
+ run_drift "$root" "nonexistent-slug"
147
+ if [ "$EXIT" -ne 0 ]; then
148
+ fail "AC-011 expected exit 0 (no spec → skip), got $EXIT; stdout: $OUT"
149
+ return 1
150
+ fi
151
+ assert_contains "$OUT" "no spec; skipped" "AC-011 expected 'no spec; skipped' on stdout (got: $OUT)" || return 1
152
+ local report="$root/.claude/state/drift/nonexistent-slug.md"
153
+ if [ -f "$report" ]; then
154
+ fail "AC-011 expected no report file when spec absent (found at $report)"
155
+ return 1
156
+ fi
157
+ }
158
+
159
+ # --- AC-002, OQ-4 -------------------------------------------------------------
160
+
161
+ test_when_drift_check_with_none_design_calls_then_section_renders_skipped() {
162
+ local root; root="$(mktemp -d)"; trap "rm -rf $root" RETURN
163
+ seed_project "$root" "wf-none-dc" "AC-001" "*(none)*"
164
+ local diff_path="$root/diff.txt"
165
+ seed_diff "$diff_path" "+def test_when_AC-001_then_ok(): pass
166
+ "
167
+ OUT=""; EXIT=0
168
+ run_drift "$root" "wf-none-dc" "$diff_path"
169
+ if [ "$EXIT" -ne 0 ]; then
170
+ fail "OQ-4 expected exit 0 (none design calls, AC resolved), got $EXIT; stdout: $OUT"
171
+ return 1
172
+ fi
173
+ local report="$root/.claude/state/drift/wf-none-dc.md"
174
+ assert_file_contains "$report" "no design calls" "OQ-4 expected 'no design calls — skipped' notice in report" || return 1
175
+ }
176
+
177
+ # --- runner -------------------------------------------------------------------
178
+
179
+ run test_when_drift_check_on_spec_with_all_resolved_then_exit_0
180
+ run test_when_drift_check_finds_unresolved_then_exit_1
181
+ run test_when_drift_check_no_spec_then_exit_0_skipped
182
+ run test_when_drift_check_with_none_design_calls_then_section_renders_skipped
183
+
184
+ echo "----"
185
+ echo "Passed: $PASS Failed: $FAIL"
186
+ if [ "$FAIL" -gt 0 ]; then
187
+ echo "Failed tests:"
188
+ for t in "${FAILED[@]}"; do echo " - $t"; done
189
+ fi
190
+ exit $((FAIL > 0))
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ # Aggregate test runner for .claude/skills/tdd/.
3
+ # Invokes each sibling *_test.sh and exits non-zero if any fail.
4
+
5
+ set -uo pipefail
6
+
7
+ HERE="$(cd "$(dirname "$0")" && pwd)"
8
+ FAIL=0
9
+
10
+ for t in "$HERE"/*_test.sh; do
11
+ [ -f "$t" ] || continue
12
+ echo "=== $(basename "$t") ==="
13
+ bash "$t" || FAIL=$((FAIL+1))
14
+ done
15
+
16
+ if [ "$FAIL" -gt 0 ]; then
17
+ echo "tdd/tests: $FAIL suite(s) failed"
18
+ exit 1
19
+ fi
20
+ echo "tdd/tests: all suites passed"
21
+ exit 0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) jonathimer (https://github.com/jonathimer/devmarketing-skills)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ technical-tutorials
2
+ ===================
3
+
4
+ This skill is vendored from the `technical-tutorials` skill in the
5
+ `devmarketing-skills` collection published by jonathimer and is redistributed
6
+ here under the terms of the MIT License (see LICENSE in this directory).
7
+
8
+ Upstream:
9
+ Repository: https://github.com/jonathimer/devmarketing-skills
10
+ Author: jonathimer
11
+ Skill: technical-tutorials/
12
+
13
+ Vendored into: .claude/skills/technical-tutorials/
14
+ Vendored on: 2026-05-15 (this commit) — prior install date unknown; LICENSE
15
+ + NOTICE added retroactively as part of the licensing-attribution
16
+ drift fix in the branch-aware-git-policy workflow.
17
+
18
+ Local changes:
19
+ - 2026-04-28: consolidated the upstream `developer-audience-context`
20
+ standalone skill into this skill's `references/audience-context.md`,
21
+ per the SKILL.md note in the body. No other behavior changes.
22
+ - Frontmatter `owner: baseline` added so the audit-baseline drift check
23
+ tracks this file as a shipped baseline artifact.
@@ -561,7 +561,7 @@ Before publishing, verify:
561
561
 
562
562
  ## Related Skills
563
563
 
564
- These four are upstream companion skills (from the `claude-code-setup` plugin family) and **do not ship with this baseline**. Listed here for reference only; if you need their capabilities, ask the user inline or install the plugin separately.
564
+ These four are upstream companion skills from the same source repo as `technical-tutorials` ([`jonathimer/devmarketing-skills`](https://github.com/jonathimer/devmarketing-skills)) and **do not ship with this baseline**. Listed here for reference only; if you need their capabilities, ask the user inline or vendor them separately following the same MIT terms.
565
565
 
566
566
  - `developer-audience-context` — Understand skill level and environment
567
567
  - `devrel-content` — General technical writing principles
@@ -23,26 +23,31 @@ Triage the user's request and set up `.claude/state/workflow.json` so downstream
23
23
  ```json
24
24
  {
25
25
  "request": "<the request>",
26
+ "slug": "<workflow slug>",
26
27
  "entry_phase": "<intake|spec|tdd|chore>",
27
28
  "exceptions": ["<phase>", ...],
28
29
  "completed": [],
30
+ "source_backlog_keys": ["<backlog stable key>", ...],
29
31
  "created_at": <epoch>,
30
32
  "updated_at": <epoch>
31
33
  }
32
34
  ```
35
+
36
+ The `source_backlog_keys` field is optional. When the user's request explicitly names one or more backlog entries this workflow picks up (the common framing is a `Source:` line listing backlog keys), populate the array with those keys. `/commit` (Phase 11) reads this field and invokes `sweep.py --mode stamp-closure` after the commit lands, stamping each named entry with `status: picked-up` + `superseded-at: <today>` so the next `/memory-flush` Step 0a auto-closes them. Absent / empty array → `/commit` skips the stamp step entirely (backward-compatible for any workflow that pre-dates the field). `/triage` does NOT auto-detect backlog keys from free-form prose — the user populates the field (or names them in the triage prompt and you populate it during step 4).
33
37
  5. **Seed the workflow tasklist.** Use the `TaskCreate` tool to register one task per non-excepted phase plus each applicable consent gate. The tasks are the running checklist that `/harness` (or any direct phase invocation) reads to decide the next action; consent-gate tasks block the workflow until the user runs the corresponding command. **When `grant-commit` and `commit` are in exceptions (non-git project), do NOT seed those two tasks** — the workflow ends after `/archive`. Use these canonical templates:
34
38
 
35
- **For `chore` track** (single phase + commit gate):
39
+ **For `chore` track** (single phase + memory-flush + commit gate):
36
40
  - `Run /chore for <slug>` — activeForm: "Running chore", metadata: `{"phase": "chore"}`
41
+ - `Run /memory-flush for <slug>` — activeForm: "Running memory-flush", metadata: `{"phase": "memory-flush"}`, addBlockedBy previous
37
42
  - `Wait for /grant-commit` — metadata: `{"phase": "grant-commit", "needs_user": true}`, addBlockedBy previous
38
43
  - `Run /commit for <slug>` — activeForm: "Running commit", metadata: `{"phase": "commit"}`, addBlockedBy previous
39
44
 
40
45
  **For `tdd`-entry quickfix track** (skip intake/scout/research/spec/review):
41
- - `Run /tdd`, `Run /simplify`, `Run /security` (only if not in exceptions), `Run /integrate`, `Run /document`, `Run /archive`, `Wait for /grant-commit` (`needs_user`), `Run /commit` — each with `addBlockedBy` set to the previous task's id.
46
+ - `Run /tdd`, `Run /simplify`, `Run /security` (only if not in exceptions), `Run /integrate`, `Run /document`, `Run /archive`, `Run /memory-flush`, `Wait for /grant-commit` (`needs_user`), `Run /commit` — each with `addBlockedBy` set to the previous task's id.
42
47
 
43
48
  **For `spec`-entry track** (skip upstream): start from `Run /spec`, then `Wait for /approve-spec <path>` (`needs_user`), then continue per the full track.
44
49
 
45
- **For `intake`-entry full track**: `Run /intake`, `Run /brd` (only if stakeholder-heavy), `Run /scout`, `Run /research`, `Run /spec`, `Wait for /approve-spec <path>` (`needs_user`), `Run /tdd` OR (`Run /swarm-plan`, `Wait for /approve-swarm <slug>` (`needs_user`), `Run /swarm-dispatch`), `Run /simplify`, `Run /security` (unless excepted), `Run /integrate`, `Run /document`, `Run /archive`, `Wait for /grant-commit` (`needs_user`), `Run /commit`. **On non-git projects the swarm branch SHALL NOT be seeded** — only `Run /tdd` goes in the list, regardless of expected component count. Swarm-vs-solo is a Phase-6 main-context decision (per CLAUDE.md Article V) only on git projects; non-git workflows resolve to solo at triage time because `swarm-plan`, `approve-swarm`, and `swarm-dispatch` are already in `exceptions`.
50
+ **For `intake`-entry full track**: `Run /intake`, `Run /brd` (only if stakeholder-heavy), `Run /scout`, `Run /research`, `Run /spec`, `Wait for /approve-spec <path>` (`needs_user`), `Run /tdd` OR (`Run /swarm-plan`, `Wait for /approve-swarm <slug>` (`needs_user`), `Run /swarm-dispatch`), `Run /simplify`, `Run /security` (unless excepted), `Run /integrate`, `Run /document`, `Run /archive`, `Run /memory-flush`, `Wait for /grant-commit` (`needs_user`), `Run /commit`. **On non-git projects the swarm branch SHALL NOT be seeded** — only `Run /tdd` goes in the list, regardless of expected component count. Swarm-vs-solo is a Phase-6 main-context decision (per CLAUDE.md Article V) only on git projects; non-git workflows resolve to solo at triage time because `swarm-plan`, `approve-swarm`, and `swarm-dispatch` are already in `exceptions`.
46
51
 
47
52
  For every task: `subject` is imperative ("Run /scout for <slug>" / "Wait for /approve-spec <path>"); `description` names the phase + the slug; `metadata.phase` carries the phase name; consent-gate tasks set `metadata.needs_user: true`. Wire `addBlockedBy` so each task blocks until its predecessor completes — this surfaces the workflow's true dependency graph and prevents `/harness` from racing past a gate.
48
53
 
@@ -44,7 +44,7 @@ On every new session, before any work, you SHALL:
44
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
45
  3. **If `configured: true`** — read `docs/init/seed.md` §16 if present so you know what was added. Tell the user:
46
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.
47
+ 4. **Memory check.** The `memory_session_start` hook injects a memory index into your additional context. The hook emits a **debt-mode nag** only when `_pending.md` has unflushed candidates AND no active workflow on disk (i.e., `.claude/state/workflow.json` is absent) those candidates are debt from a prior workflow that didn't end-flush. During an active workflow, **Phase 10.6** (memory-flush, between archive and grant-commit) handles flushing automatically; the session-start nag stays silent. You SHALL run `/memory-flush` when the debt-mode nag fires, before starting new work.
48
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
49
  6. Once per session is sufficient. You SHALL NOT repeat the greeting on every prompt.
50
50
 
@@ -68,6 +68,7 @@ The 11-phase workflow is the only sanctioned path from request to commit. Phase
68
68
  | 9 | Integrate | `/integrate` | binding verify verdict |
69
69
  | 10 | Document | `/document` | docs |
70
70
  | 10.5 | Archive | `/archive` | bundle at `docs/archive/<date>/<slug>/` |
71
+ | 10.6 | Memory flush | `/memory-flush` | curated canonical memory + reset `_pending.md` |
71
72
  | 11 | **Grant commit** (gate C) + commit | user runs **`/grant-commit`**, then `/commit` (skill) | commit |
72
73
 
73
74
  **Mandatory rules:**
@@ -77,7 +78,7 @@ The 11-phase workflow is the only sanctioned path from request to commit. Phase
77
78
  - The only mechanism to bypass a phase is the `exceptions` array in `.claude/state/workflow.json`, written by `/triage`.
78
79
  - **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
80
  - 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
+ - **How the gates are structurally enforced.** Each consent command (`/approve-spec`, `/approve-swarm`, `/grant-commit`, `/grant-push`) 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. `/grant-push` is **not** a workflow-phase gate — it is a Bash-time consent for push to a protected branch (see Article VII). 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
82
  - **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
 
83
84
  **Entry points** (`/triage` writes `workflow.json` with `entry_phase` and `exceptions`):
@@ -105,7 +106,7 @@ When `/harness` is invoked, you SHALL:
105
106
 
106
107
  **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
 
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
+ **Resume after yield (auto).** After yielding at a consent gate, the harness skill writes `state: yielded` and removes `.harness_active`. The user runs the consent slash command in their next prompt; `consent_gate_grant` writes the gate marker (outside Claude's tool boundary), the command body writes the consent token, and the `harness_continuation` Stop hook detects fresh consent (rung 4: `workflow.json` present + `state=yielded` + a consent-token mtime newer than `harness_state`). The hook emits `{decision:"block"}`, and `Skill(harness)` is re-invoked in the same turn. The next invocation re-enters preflight, finds the gate token on disk, marks the gate task `completed`, and re-enters the loop. The user does not type `/harness` to resume.
109
110
 
110
111
  **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
 
@@ -157,21 +158,25 @@ The following bind every code change.
157
158
 
158
159
  **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
 
160
- You SHALL run `git add <named paths>` and `git commit` only when **both** hold:
161
+ **Branch-aware consent policy.** Consent enforcement for `git commit` and `git push` is driven by two `project.json` knobs:
161
162
 
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`).
163
+ - `git.protected_branches` glob list. `null` (default) means every branch is protected. Set e.g. `["main", "release/*"]` to limit consent enforcement to those branches.
164
+ - `git.branch_pattern` regex. `null` (default) means no naming check. Set e.g. `"^(feat|fix|chore|docs)/[a-z0-9-]+$"` to require conformant branch names on commit.
164
165
 
165
- `git_commit_guard` (Art. VIII) enforces both conditions.
166
+ On a **protected branch**, commits require a fresh `commit_consent` token (written by `/grant-commit`, 5-min TTL) and pushes require a fresh `push_consent` token (written by `/grant-push`, 5-min TTL) — both gated by the user having explicitly asked for the operation in their current request. On a non-protected branch, commits and pushes proceed without consent. `git_commit_guard` (Art. VIII) is the enforcer.
166
167
 
167
- You SHALL NEVER, unless the user names the exact operation in their current request:
168
+ **Detached HEAD.** When the current branch resolves to the literal string `HEAD` (detached state), the guard denies both commit and push with an explicit message. Check out a named branch before attempting either — branch-aware policy needs a named branch to evaluate `git.protected_branches` and `git.branch_pattern`.
168
169
 
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
170
+ **Hard-blocks regardless of consent, branch, or user request.** These operations rewrite history, skip safety, or sweep paths; `git_commit_guard`'s `FORBIDDEN_RE` blocks them flat-out:
171
+
172
+ - `git commit --amend` always create a new commit.
173
+ - `--no-verify`, `--no-gpg-sign`, or any flag that skips hooks/signing.
174
+ - `git reset --hard`, `git clean -f`, `git checkout --`, `git branch -D`.
175
+ - `git config` changes.
176
+ - `git rebase -i`, `git add -i` (interactive).
177
+ - `git add -A`, `git add .` — name the paths.
178
+
179
+ `git push` is no longer in this set — it is governed by the branch-aware policy above. `git push --force` and `--force-with-lease` are still forbidden unless the user names the exact operation in their current request, AND additionally subject to the branch-aware policy (force-push to a protected branch requires fresh `push_consent` plus the user-named carve-out).
175
180
 
176
181
  ## Article VIII — Hooks (the enforcement layer)
177
182
 
@@ -181,7 +186,7 @@ The 22 hooks in `.claude/hooks/` are the structural enforcement of this constitu
181
186
  |---|---|---|---|
182
187
  | `setup_guard` | PreToolUse / Edit\|Write\|MultiEdit | Art. III | Advisory reminder when `configured: false` (rate-limited 10 min). Does **not** block. |
183
188
  | `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 |
189
+ | `git_commit_guard` | PreToolUse / Bash + Edit\|Write\|MultiEdit | Art. IV gate C, Art. VII | Bash: enforce branch-aware policy `git commit` on a protected branch requires fresh `commit_consent`; `git push` on a protected branch requires fresh `push_consent`; both proceed without consent on non-protected branches; off-`branch_pattern` branches deny commits; detached HEAD denies both. Hard-block remaining forbidden flags (--amend, --no-verify, reset --hard, etc.). Write: gate writes to `.claude/state/{commit,push}_consent` and the matching `.{commit,push}_consent_grant` markers. |
185
190
  | `env_guard` | PreToolUse / Edit\|Write\|MultiEdit\|NotebookEdit | Art. VII | Block writes to `.env*` (allows `.env.example`) |
186
191
  | `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
192
  | `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 |
@@ -200,13 +205,13 @@ The 22 hooks in `.claude/hooks/` are the structural enforcement of this constitu
200
205
  | `memory_stop` | Stop | Art. IX | Auto-extract memory candidates each turn-end |
201
206
  | `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
207
  | `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 |
208
+ | `consent_gate_grant` | UserPromptSubmit | Art. IV gates A/B/C, Art. VII | Detect `/approve-spec`/`/approve-swarm`/`/grant-commit`/`/grant-push` in user input and write the gate-specific consent marker — runs OUTSIDE Claude's tool boundary so Claude cannot forge it |
204
209
 
205
210
  ## Article IX — Project memory
206
211
 
207
212
  The memory system at `.claude/memory/` accumulates project facts across sessions. You SHALL:
208
213
 
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`.
214
+ 1. Treat the seven canonical files (`landmarks.md`, `libraries.md`, `decisions.md`, `landmines.md`, `conventions.md`, `pending-questions.md`, `backlog.md`) as long-term project memory. Each entry has a stable key per the schema in `.claude/memory/README.md`.
210
215
  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
216
  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
217
  4. Treat `_resume.md` as the cross-session continuity snapshot (refreshed every turn-end and before compaction). It is **session memory**, not project memory.
@@ -257,7 +262,7 @@ Every UI design task that originates inside a workflow phase SHALL route through
257
262
  | 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
263
  | `/tdd` Step 6 SHALL invoke `Skill(design-ui, task_brief)` once per `## Design calls` row before Step 7 (verify). | `tdd` skill SOP. |
259
264
  | `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`. |
265
+ | `design-ui` SHALL classify incoming intents at Stage 0 (design / development / copy). A misrouted intent returns one of two terminal states: `final_state: "not_a_design_task"` (single-lane misroute) with `correct_lane`, OR `final_state: "mixed_brief"` (multi-lane misroute) with a structured `lane_split` array. Neither writes code. | `design-ui` Stage 0 + `references/design-vs-development.md`. |
261
266
  | 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
267
  | Multi-step impeccable recipes SHALL ask the user before proceeding. Single-step recipes SHALL auto-execute. | `references/intent-table.md` `mode` column. |
263
268
 
@@ -267,15 +272,15 @@ The vendored `impeccable` skill stays untouched (Article IX). `design-ui` is the
267
272
 
268
273
  ## Article XI — Skill provenance and the baseline manifest
269
274
 
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.
275
+ A skill at `.claude/skills/<slug>/SKILL.md` is **baseline-owned** iff its YAML frontmatter declares `owner: baseline`. Every other skill on disk — those without an `owner:` field, or those declaring `owner: user` — is user/third-party and out-of-scope of baseline audit checks. Absence-of-`owner` is the deliberate default so a project with pre-existing skills can install the baseline without annotating any of its own files. 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
276
 
272
277
  You SHALL:
273
278
 
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>`.
279
+ 1. **Declare baseline ownership only.** A SKILL.md that ships in the baseline SHALL declare `owner: baseline` in its frontmatter directly after `name:`. Authoring a user/third-party skill does NOT require any `owner:` annotation absence is the default. Explicit `owner: user` is permitted but never required. The only frontmatter-related FAIL the audit emits is `invalid owner=<value>` (a present-but-malformed `owner:` field, e.g. typo). Missing-`owner:` is silently skipped.
275
280
  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
281
  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
282
  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.
283
+ 5. **Out-of-scope skills don't break the audit.** Any skill on disk that doesn't declare `owner: baseline` is out-of-scope: excluded from the baseline count, the names-match check, and the hash-drift check. Installing the baseline into a project that already has its own skills is zero-friction — no per-file annotation required. Maintenance of those skills is the user's responsibility.
279
284
 
280
285
  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
286
 
@@ -288,11 +293,11 @@ Cryptographic supply-chain attestation, signed lock files, and per-skill aggrega
288
293
  | `.claude/hooks/` | 22 hook scripts (17 write/run-boundary + 4 lifecycle + 1 input-boundary). Bash + python3, no jq. |
289
294
  | `.claude/agents/` | 1 baseline subagent: `swarm-worker` (rendered from `src/agents/swarm-worker.template.md`) |
290
295
  | `.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` |
296
+ | `.claude/commands/` | 5 consent/bootstrap gates: `approve-spec`, `approve-swarm`, `grant-commit`, `grant-push`, `init-project` |
297
+ | `.claude/memory/` | 7 canonical knowledge files + `_pending.md` (staging) + `_resume.md` (continuity snapshot) + `README.md` |
293
298
  | `.claude/project.json` | per-project config (test/lint cmd, TDD globs, destructive patterns, swarm config, additions). Populated by `/init-project`. |
294
299
  | `.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` |
300
+ | `.claude/state/` | runtime: `workflow.json`, `commit_consent`, `push_consent`, `spec_approvals/`, `swarm_approvals/`, `swarm/`, `harness/<slug>.log`, `last_test_result` |
296
301
  | `.mcp.json` | three baseline MCP servers: `context7`, `plantuml`, `playwright` |
297
302
  | `src/` | pristine ship-time templates for every file `/init-project` modifies (overlay source for `npx @friedbotstudio/create-baseline`) |
298
303
  | `docs/init/seed.md` | genesis prompt — governing specification of the baseline |
@@ -317,8 +322,14 @@ Cryptographic supply-chain attestation, signed lock files, and per-skill aggrega
317
322
  **Memory (1)**:
318
323
  - `memory-flush`
319
324
 
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`
325
+ **Shared globals (7)** — one written for this baseline, six vendored from external sources with their upstream licenses preserved in `LICENSE` + `NOTICE` alongside each skill:
326
+ - `claude-automation-recommender` vendored from Anthropic's `claude-code-setup` plugin, Apache 2.0.
327
+ - `code-structure` — written for this baseline (Friedbot Studio). Mandatory on every code-generation step.
328
+ - `humanizer` — vendored from [`blader/humanizer`](https://github.com/blader/humanizer), MIT.
329
+ - `documentation` — vendored from Anthropic's `claude-code-setup` plugin, Apache 2.0.
330
+ - `technical-tutorials` — vendored from [`jonathimer/devmarketing-skills`](https://github.com/jonathimer/devmarketing-skills), MIT.
331
+ - `copywriting` — vendored from [`coreyhaines31/marketingskills`](https://github.com/coreyhaines31/marketingskills), MIT.
332
+ - `impeccable` — vendored from [`pbakaus/impeccable`](https://github.com/pbakaus/impeccable), Apache 2.0.
322
333
 
323
334
  **Audit (1)**:
324
335
  - `audit-baseline` — drift check between this constitution + seed.md and the implementation