@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.
Files changed (197) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +222 -0
  3. package/bin/cli.js +247 -0
  4. package/obj/template/.claude/agents/swarm-worker.md +52 -0
  5. package/obj/template/.claude/bin/LICENSE +201 -0
  6. package/obj/template/.claude/bin/NOTICE +48 -0
  7. package/obj/template/.claude/commands/approve-spec.md +29 -0
  8. package/obj/template/.claude/commands/approve-swarm.md +27 -0
  9. package/obj/template/.claude/commands/grant-commit.md +19 -0
  10. package/obj/template/.claude/commands/init-project.md +191 -0
  11. package/obj/template/.claude/hooks/artifact_template_guard.sh +141 -0
  12. package/obj/template/.claude/hooks/consent_gate_grant.sh +89 -0
  13. package/obj/template/.claude/hooks/destructive_cmd_guard.sh +42 -0
  14. package/obj/template/.claude/hooks/env_guard.sh +36 -0
  15. package/obj/template/.claude/hooks/git_commit_guard.sh +93 -0
  16. package/obj/template/.claude/hooks/harness_continuation.sh +121 -0
  17. package/obj/template/.claude/hooks/lib/__pycache__/resume_writer.cpython-314.pyc +0 -0
  18. package/obj/template/.claude/hooks/lib/common.sh +328 -0
  19. package/obj/template/.claude/hooks/lib/resume_writer.py +341 -0
  20. package/obj/template/.claude/hooks/lint_runner.sh +55 -0
  21. package/obj/template/.claude/hooks/memory_pre_compact.sh +36 -0
  22. package/obj/template/.claude/hooks/memory_session_start.sh +244 -0
  23. package/obj/template/.claude/hooks/memory_stop.sh +173 -0
  24. package/obj/template/.claude/hooks/plantuml_syntax_guard.sh +161 -0
  25. package/obj/template/.claude/hooks/process_lifecycle_guard.sh +89 -0
  26. package/obj/template/.claude/hooks/setup_guard.sh +50 -0
  27. package/obj/template/.claude/hooks/spec_approval_guard.sh +81 -0
  28. package/obj/template/.claude/hooks/spec_design_calls_guard.sh +183 -0
  29. package/obj/template/.claude/hooks/spec_diagram_presence_guard.sh +141 -0
  30. package/obj/template/.claude/hooks/swarm_approval_guard.sh +39 -0
  31. package/obj/template/.claude/hooks/swarm_boundary_guard.sh +136 -0
  32. package/obj/template/.claude/hooks/tdd_order_guard.sh +176 -0
  33. package/obj/template/.claude/hooks/test_runner.sh +75 -0
  34. package/obj/template/.claude/hooks/tests/fixtures/ac008_byte_equal_reference.txt +12 -0
  35. package/obj/template/.claude/hooks/tests/memory_session_start_test.sh +285 -0
  36. package/obj/template/.claude/hooks/track_guard.sh +127 -0
  37. package/obj/template/.claude/hooks/verify_pass_guard.sh +88 -0
  38. package/obj/template/.claude/memory/README.md +108 -0
  39. package/obj/template/.claude/memory/_pending.md +15 -0
  40. package/obj/template/.claude/memory/_resume.md +12 -0
  41. package/obj/template/.claude/memory/conventions.md +26 -0
  42. package/obj/template/.claude/memory/decisions.md +29 -0
  43. package/obj/template/.claude/memory/landmarks.md +26 -0
  44. package/obj/template/.claude/memory/landmines.md +27 -0
  45. package/obj/template/.claude/memory/libraries.md +27 -0
  46. package/obj/template/.claude/memory/pending-questions.md +28 -0
  47. package/obj/template/.claude/project.json +221 -0
  48. package/obj/template/.claude/settings.json +110 -0
  49. package/obj/template/.claude/skills/archive/SKILL.md +48 -0
  50. package/obj/template/.claude/skills/archive/archive.sh +145 -0
  51. package/obj/template/.claude/skills/audit-baseline/SKILL.md +80 -0
  52. package/obj/template/.claude/skills/audit-baseline/audit.sh +919 -0
  53. package/obj/template/.claude/skills/brd/SKILL.md +44 -0
  54. package/obj/template/.claude/skills/brd/template.md +83 -0
  55. package/obj/template/.claude/skills/chore/SKILL.md +99 -0
  56. package/obj/template/.claude/skills/claude-automation-recommender/LICENSE +202 -0
  57. package/obj/template/.claude/skills/claude-automation-recommender/NOTICE +69 -0
  58. package/obj/template/.claude/skills/claude-automation-recommender/SKILL.md +358 -0
  59. package/obj/template/.claude/skills/claude-automation-recommender/references/hooks-patterns.md +226 -0
  60. package/obj/template/.claude/skills/claude-automation-recommender/references/mcp-servers.md +263 -0
  61. package/obj/template/.claude/skills/claude-automation-recommender/references/plugins-reference.md +98 -0
  62. package/obj/template/.claude/skills/claude-automation-recommender/references/skills-reference.md +408 -0
  63. package/obj/template/.claude/skills/claude-automation-recommender/references/subagent-templates.md +181 -0
  64. package/obj/template/.claude/skills/code-structure/SKILL.md +204 -0
  65. package/obj/template/.claude/skills/commit/SKILL.md +21 -0
  66. package/obj/template/.claude/skills/copywriting/SKILL.md +252 -0
  67. package/obj/template/.claude/skills/copywriting/evals/evals.json +111 -0
  68. package/obj/template/.claude/skills/copywriting/references/ai-writing-detection.md +200 -0
  69. package/obj/template/.claude/skills/copywriting/references/copy-frameworks.md +344 -0
  70. package/obj/template/.claude/skills/copywriting/references/natural-transitions.md +272 -0
  71. package/obj/template/.claude/skills/design-ui/SKILL.md +175 -0
  72. package/obj/template/.claude/skills/design-ui/references/design-vs-development.md +89 -0
  73. package/obj/template/.claude/skills/design-ui/references/intent-table.md +64 -0
  74. package/obj/template/.claude/skills/design-ui/references/orchestration.md +121 -0
  75. package/obj/template/.claude/skills/design-ui/references/state-machine.md +125 -0
  76. package/obj/template/.claude/skills/document/SKILL.md +66 -0
  77. package/obj/template/.claude/skills/documentation/SKILL.md +50 -0
  78. package/obj/template/.claude/skills/harness/SKILL.md +169 -0
  79. package/obj/template/.claude/skills/humanizer/SKILL.md +489 -0
  80. package/obj/template/.claude/skills/humanizer/references/ai-writing-detection.md +208 -0
  81. package/obj/template/.claude/skills/impeccable/PROJECT_NOTES.md +22 -0
  82. package/obj/template/.claude/skills/impeccable/SKILL.md +153 -0
  83. package/obj/template/.claude/skills/impeccable/agents/openai.yaml +4 -0
  84. package/obj/template/.claude/skills/impeccable/reference/adapt.md +190 -0
  85. package/obj/template/.claude/skills/impeccable/reference/animate.md +173 -0
  86. package/obj/template/.claude/skills/impeccable/reference/audit.md +134 -0
  87. package/obj/template/.claude/skills/impeccable/reference/bolder.md +113 -0
  88. package/obj/template/.claude/skills/impeccable/reference/brand.md +104 -0
  89. package/obj/template/.claude/skills/impeccable/reference/clarify.md +174 -0
  90. package/obj/template/.claude/skills/impeccable/reference/cognitive-load.md +106 -0
  91. package/obj/template/.claude/skills/impeccable/reference/color-and-contrast.md +105 -0
  92. package/obj/template/.claude/skills/impeccable/reference/colorize.md +154 -0
  93. package/obj/template/.claude/skills/impeccable/reference/craft.md +138 -0
  94. package/obj/template/.claude/skills/impeccable/reference/critique.md +213 -0
  95. package/obj/template/.claude/skills/impeccable/reference/delight.md +302 -0
  96. package/obj/template/.claude/skills/impeccable/reference/distill.md +111 -0
  97. package/obj/template/.claude/skills/impeccable/reference/document.md +427 -0
  98. package/obj/template/.claude/skills/impeccable/reference/extract.md +70 -0
  99. package/obj/template/.claude/skills/impeccable/reference/harden.md +347 -0
  100. package/obj/template/.claude/skills/impeccable/reference/heuristics-scoring.md +234 -0
  101. package/obj/template/.claude/skills/impeccable/reference/interaction-design.md +195 -0
  102. package/obj/template/.claude/skills/impeccable/reference/layout.md +141 -0
  103. package/obj/template/.claude/skills/impeccable/reference/live.md +513 -0
  104. package/obj/template/.claude/skills/impeccable/reference/motion-design.md +99 -0
  105. package/obj/template/.claude/skills/impeccable/reference/onboard.md +234 -0
  106. package/obj/template/.claude/skills/impeccable/reference/optimize.md +258 -0
  107. package/obj/template/.claude/skills/impeccable/reference/overdrive.md +130 -0
  108. package/obj/template/.claude/skills/impeccable/reference/personas.md +178 -0
  109. package/obj/template/.claude/skills/impeccable/reference/polish.md +232 -0
  110. package/obj/template/.claude/skills/impeccable/reference/product.md +62 -0
  111. package/obj/template/.claude/skills/impeccable/reference/quieter.md +99 -0
  112. package/obj/template/.claude/skills/impeccable/reference/responsive-design.md +114 -0
  113. package/obj/template/.claude/skills/impeccable/reference/shape.md +136 -0
  114. package/obj/template/.claude/skills/impeccable/reference/spatial-design.md +100 -0
  115. package/obj/template/.claude/skills/impeccable/reference/teach.md +137 -0
  116. package/obj/template/.claude/skills/impeccable/reference/typeset.md +124 -0
  117. package/obj/template/.claude/skills/impeccable/reference/typography.md +159 -0
  118. package/obj/template/.claude/skills/impeccable/reference/ux-writing.md +107 -0
  119. package/obj/template/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  120. package/obj/template/.claude/skills/impeccable/scripts/command-metadata.json +94 -0
  121. package/obj/template/.claude/skills/impeccable/scripts/design-parser.mjs +820 -0
  122. package/obj/template/.claude/skills/impeccable/scripts/detect-csp.mjs +198 -0
  123. package/obj/template/.claude/skills/impeccable/scripts/is-generated.mjs +69 -0
  124. package/obj/template/.claude/skills/impeccable/scripts/live-accept.mjs +465 -0
  125. package/obj/template/.claude/skills/impeccable/scripts/live-browser.js +4684 -0
  126. package/obj/template/.claude/skills/impeccable/scripts/live-inject.mjs +436 -0
  127. package/obj/template/.claude/skills/impeccable/scripts/live-poll.mjs +187 -0
  128. package/obj/template/.claude/skills/impeccable/scripts/live-server.mjs +679 -0
  129. package/obj/template/.claude/skills/impeccable/scripts/live-wrap.mjs +395 -0
  130. package/obj/template/.claude/skills/impeccable/scripts/live.mjs +247 -0
  131. package/obj/template/.claude/skills/impeccable/scripts/load-context.mjs +93 -0
  132. package/obj/template/.claude/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  133. package/obj/template/.claude/skills/impeccable/scripts/pin.mjs +214 -0
  134. package/obj/template/.claude/skills/implement/SKILL.md +83 -0
  135. package/obj/template/.claude/skills/intake/SKILL.md +46 -0
  136. package/obj/template/.claude/skills/intake/template.md +61 -0
  137. package/obj/template/.claude/skills/integrate/SKILL.md +62 -0
  138. package/obj/template/.claude/skills/memory-flush/SKILL.md +172 -0
  139. package/obj/template/.claude/skills/memory-flush/sweep.py +286 -0
  140. package/obj/template/.claude/skills/memory-flush/tests/run.sh +327 -0
  141. package/obj/template/.claude/skills/prose/SKILL.md +119 -0
  142. package/obj/template/.claude/skills/rca/SKILL.md +42 -0
  143. package/obj/template/.claude/skills/rca/template.md +83 -0
  144. package/obj/template/.claude/skills/research/SKILL.md +75 -0
  145. package/obj/template/.claude/skills/scenario/SKILL.md +64 -0
  146. package/obj/template/.claude/skills/scout/SKILL.md +72 -0
  147. package/obj/template/.claude/skills/security/SKILL.md +75 -0
  148. package/obj/template/.claude/skills/simplify/SKILL.md +67 -0
  149. package/obj/template/.claude/skills/spec/SKILL.md +69 -0
  150. package/obj/template/.claude/skills/spec/template.md +274 -0
  151. package/obj/template/.claude/skills/spec-diagram-review/SKILL.md +81 -0
  152. package/obj/template/.claude/skills/spec-lint/SKILL.md +55 -0
  153. package/obj/template/.claude/skills/spec-lint/lint.sh +218 -0
  154. package/obj/template/.claude/skills/spec-render/SKILL.md +45 -0
  155. package/obj/template/.claude/skills/spec-render/render.sh +109 -0
  156. package/obj/template/.claude/skills/spec-traceability-review/SKILL.md +72 -0
  157. package/obj/template/.claude/skills/swarm-dispatch/SKILL.md +212 -0
  158. package/obj/template/.claude/skills/swarm-dispatch/swarm_merge.sh +154 -0
  159. package/obj/template/.claude/skills/swarm-plan/SKILL.md +90 -0
  160. package/obj/template/.claude/skills/swarm-plan/validate.sh +181 -0
  161. package/obj/template/.claude/skills/tdd/SKILL.md +100 -0
  162. package/obj/template/.claude/skills/technical-tutorials/SKILL.md +569 -0
  163. package/obj/template/.claude/skills/technical-tutorials/references/audience-context-README.md +53 -0
  164. package/obj/template/.claude/skills/technical-tutorials/references/audience-context.md +246 -0
  165. package/obj/template/.claude/skills/technical-tutorials/references/audience-example.md +175 -0
  166. package/obj/template/.claude/skills/technical-tutorials/references/audience-template.md +152 -0
  167. package/obj/template/.claude/skills/triage/SKILL.md +55 -0
  168. package/obj/template/.claude/skills/verify/SKILL.md +74 -0
  169. package/obj/template/.mcp.json +24 -0
  170. package/obj/template/CLAUDE.md +327 -0
  171. package/obj/template/docs/init/seed.md +585 -0
  172. package/obj/template/manifest.json +214 -0
  173. package/package.json +48 -0
  174. package/src/.mcp.template.json +24 -0
  175. package/src/.npmrc.template +2 -0
  176. package/src/CLAUDE.template.md +327 -0
  177. package/src/agents/swarm-worker.template.md +51 -0
  178. package/src/cli/conflict.js +31 -0
  179. package/src/cli/doctor.js +152 -0
  180. package/src/cli/install.js +93 -0
  181. package/src/cli/io.js +27 -0
  182. package/src/cli/manifest.js +38 -0
  183. package/src/cli/mcp.js +54 -0
  184. package/src/cli/merge.js +107 -0
  185. package/src/cli/plantuml.js +121 -0
  186. package/src/cli/util.js +10 -0
  187. package/src/memory/_pending.template.md +15 -0
  188. package/src/memory/_resume.template.md +12 -0
  189. package/src/memory/conventions.template.md +26 -0
  190. package/src/memory/decisions.template.md +29 -0
  191. package/src/memory/landmarks.template.md +26 -0
  192. package/src/memory/landmines.template.md +27 -0
  193. package/src/memory/libraries.template.md +27 -0
  194. package/src/memory/pending-questions.template.md +28 -0
  195. package/src/project.template.json +221 -0
  196. package/src/seed.template.md +585 -0
  197. package/src/settings.template.json +110 -0
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env bash
2
+ # Track Guard — PreToolUse(Write|Edit|MultiEdit)
3
+ #
4
+ # Enforces workflow phase ordering at the Write boundary. Reads the active
5
+ # workflow from .claude/state/workflow.json (written by /triage). When Claude
6
+ # tries to create/edit an artifact for phase N, all prior phases up to N-1
7
+ # must either (a) have their artifact present or (b) be listed in the
8
+ # triage `exceptions` array.
9
+ #
10
+ # Phase order + artifact globs come from .workflow.phases / .workflow.artifacts
11
+ # in .claude/project.json.
12
+
13
+ # shellcheck source=./lib/common.sh
14
+ . "${BASH_SOURCE[0]%/*}/lib/common.sh"
15
+ read_payload
16
+
17
+ TOOL="$(payload_get .tool_name)"
18
+ case "$TOOL" in
19
+ Write|Edit|MultiEdit) ;;
20
+ *) emit_allow ;;
21
+ esac
22
+
23
+ FILE="$(payload_get .tool_input.file_path)"
24
+ [ -n "$FILE" ] || emit_allow
25
+ rel="${FILE#$CLAUDE_PROJECT_ROOT/}"
26
+
27
+ WORKFLOW_STATE="$STATE_DIR/workflow.json"
28
+ # If no active workflow, nothing to enforce — triage hasn't run yet, which
29
+ # is fine for quickfix / ad-hoc work.
30
+ [ -f "$WORKFLOW_STATE" ] || emit_allow
31
+
32
+ # Delegate phase ordering logic to python for clarity.
33
+ python3 - "$rel" "$WORKFLOW_STATE" "$PROJECT_JSON" <<'PY'
34
+ import json, sys, os, fnmatch, re
35
+ rel, workflow_state, project_json = sys.argv[1], sys.argv[2], sys.argv[3]
36
+
37
+ def glob_match(path, pat):
38
+ if fnmatch.fnmatchcase(path, pat):
39
+ return True
40
+ if '**' in pat:
41
+ rx = re.escape(pat).replace(r'\*\*', '.*').replace(r'\*', '[^/]*').replace(r'\?', '.')
42
+ return bool(re.fullmatch(rx, path))
43
+ return False
44
+
45
+ try:
46
+ ws = json.load(open(workflow_state))
47
+ except Exception:
48
+ sys.exit(0) # malformed → don't block
49
+ try:
50
+ pj = json.load(open(project_json))
51
+ except Exception:
52
+ sys.exit(0)
53
+
54
+ phases = pj.get("workflow", {}).get("phases") or []
55
+ artifacts = pj.get("workflow", {}).get("artifacts") or {}
56
+ exceptions = set(ws.get("exceptions") or [])
57
+ entry = ws.get("entry_phase")
58
+
59
+ # Find which phase this file belongs to.
60
+ file_phase = None
61
+ for ph in phases:
62
+ pat = artifacts.get(ph)
63
+ if pat and glob_match(rel, pat):
64
+ file_phase = ph
65
+ break
66
+
67
+ if file_phase is None:
68
+ sys.exit(0) # file is not a workflow artifact → allow
69
+
70
+ # Find index of file_phase and entry_phase.
71
+ try:
72
+ file_idx = phases.index(file_phase)
73
+ except ValueError:
74
+ sys.exit(0)
75
+ entry_idx = phases.index(entry) if entry in phases else 0
76
+
77
+ # Only enforce ordering from the entry phase onward.
78
+ missing = []
79
+ project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(workflow_state))))
80
+ # project_root = repo root (workflow_state is .claude/state/workflow.json)
81
+ for i in range(entry_idx, file_idx):
82
+ ph = phases[i]
83
+ if ph in exceptions:
84
+ continue
85
+ pat = artifacts.get(ph)
86
+ if not pat:
87
+ # phase has no artifact (e.g. tdd/simplify) — consider it satisfied
88
+ # only if workflow_state.completed includes it.
89
+ if ph in (ws.get("completed") or []):
90
+ continue
91
+ missing.append(ph)
92
+ continue
93
+ # Look for any file matching the artifact glob under project_root.
94
+ found = False
95
+ for root, _dirs, files in os.walk(project_root):
96
+ # skip heavy dirs
97
+ parts = root.replace(project_root, '', 1).lstrip('/').split('/')
98
+ if parts and parts[0] in ('.git', 'node_modules', '.config', '.claude'):
99
+ if ph != 'review': # review artifacts live under .claude/state/
100
+ continue
101
+ for f in files:
102
+ candidate = os.path.relpath(os.path.join(root, f), project_root)
103
+ if glob_match(candidate, pat):
104
+ found = True
105
+ break
106
+ if found:
107
+ break
108
+ if not found:
109
+ missing.append(ph)
110
+
111
+ if missing:
112
+ msg = (
113
+ f"Track Guard: cannot write '{rel}' (phase '{file_phase}') — "
114
+ f"prior phases not completed: {', '.join(missing)}. "
115
+ f"Either produce those artifacts first, or inject exceptions via /triage."
116
+ )
117
+ print(json.dumps({
118
+ "hookSpecificOutput": {
119
+ "hookEventName": "PreToolUse",
120
+ "permissionDecision": "deny",
121
+ "permissionDecisionReason": msg,
122
+ }
123
+ }))
124
+ PY
125
+
126
+ # If python printed a block decision, exit 0 (decision is in stdout).
127
+ exit 0
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # Verify Pass Guard — PreToolUse(Write|Edit|MultiEdit)
3
+ #
4
+ # Belt-and-braces backstop for the `verify` skill. Operates at the Write tool
5
+ # boundary: even if the skill's verdict is bypassed, Claude physically cannot
6
+ # persist a "PASS" line to a verification artifact when the most recent test
7
+ # output contradicts it.
8
+ #
9
+ # Triggers only when the target file is a verification artifact (paths under
10
+ # docs/verify/** or filename matches *verify* / *verification*), and the
11
+ # content being written contains a PASS line (VERIFY: PASS, STATUS: PASS,
12
+ # RESULT: PASS, or a line that is just "PASS").
13
+ #
14
+ # Truth source: .claude/state/last_test_result (written by test_runner.sh
15
+ # and the `verify` skill). Contains one line: PASS|FAIL.
16
+
17
+ # shellcheck source=./lib/common.sh
18
+ . "${BASH_SOURCE[0]%/*}/lib/common.sh"
19
+ read_payload
20
+
21
+ TOOL="$(payload_get .tool_name)"
22
+ case "$TOOL" in
23
+ Write|Edit|MultiEdit) ;;
24
+ *) emit_allow ;;
25
+ esac
26
+
27
+ FILE="$(payload_get .tool_input.file_path)"
28
+ [ -n "$FILE" ] || emit_allow
29
+ rel="${FILE#$CLAUDE_PROJECT_ROOT/}"
30
+
31
+ # Is this a verification artifact?
32
+ is_verify=0
33
+ case "$rel" in
34
+ docs/verify/*|docs/verification/*) is_verify=1 ;;
35
+ esac
36
+ base="$(basename "$rel")"
37
+ case "$base" in
38
+ *verify*|*verification*|*VERIFY*) is_verify=1 ;;
39
+ esac
40
+ [ "$is_verify" -eq 1 ] || emit_allow
41
+
42
+ # Collect proposed content: Write.content, Edit.new_string, MultiEdit.edits[].new_string.
43
+ content=""
44
+ case "$TOOL" in
45
+ Write) content="$(payload_get .tool_input.content)" ;;
46
+ Edit) content="$(payload_get .tool_input.new_string)" ;;
47
+ MultiEdit)
48
+ content="$(python3 -c '
49
+ import json, os
50
+ raw = os.environ.get("HOOK_PAYLOAD","")
51
+ d = json.loads(raw) if raw else {}
52
+ edits = (d.get("tool_input") or {}).get("edits") or []
53
+ print("\n".join(e.get("new_string","") for e in edits))
54
+ ')"
55
+ ;;
56
+ esac
57
+
58
+ # Look for a PASS claim in the proposed content.
59
+ if ! python3 -c "
60
+ import re,sys
61
+ c = sys.argv[1]
62
+ lines = c.splitlines()
63
+ for ln in lines:
64
+ s = ln.strip()
65
+ if re.fullmatch(r'PASS', s):
66
+ sys.exit(0)
67
+ if re.match(r'(VERIFY|STATUS|RESULT|VERDICT)\s*[:=]\s*PASS\b', s, re.I):
68
+ sys.exit(0)
69
+ sys.exit(1)
70
+ " "$content"; then
71
+ emit_allow
72
+ fi
73
+
74
+ # A PASS claim is being written. Check the truth source.
75
+ TRUTH="$STATE_DIR/last_test_result"
76
+ if [ ! -f "$TRUTH" ]; then
77
+ log_line verify_pass_guard "BLOCKED no truth source for PASS claim in $rel"
78
+ emit_block "Verify Pass Guard: cannot persist a PASS line — no test evidence exists at .claude/state/last_test_result. Run the tests (or invoke the \`verify\` skill) to produce a verdict before claiming PASS."
79
+ fi
80
+
81
+ verdict="$(head -1 "$TRUTH" | tr -d '[:space:]')"
82
+ if [ "$verdict" != "PASS" ]; then
83
+ log_line verify_pass_guard "BLOCKED verdict=$verdict claim=PASS file=$rel"
84
+ emit_block "Verify Pass Guard: cannot persist a PASS line — the latest test verdict is '$verdict' (see .claude/state/last_test_result). Fix the failing tests first; do not edit the verification artifact to claim PASS."
85
+ fi
86
+
87
+ log_line verify_pass_guard "ALLOWED verdict=PASS file=$rel"
88
+ emit_allow
@@ -0,0 +1,108 @@
1
+ # Project memory
2
+
3
+ Persistent project knowledge that travels with the repo. Loaded into Claude's context at session start (via the `memory_session_start.sh` hook) and updated as a byproduct of phase skills doing their normal work, plus auto-extracted candidates from the `memory_stop.sh` hook (curated via `/memory-flush`).
4
+
5
+ ## Files
6
+
7
+ | File | Owners | Holds |
8
+ |---|---|---|
9
+ | `landmarks.md` | `scout` | Where things live: `path:line — role` |
10
+ | `libraries.md` | `research` | Validated library APIs by `<lib>@<version>` |
11
+ | `decisions.md` | `spec`, `rca` | Architectural choices with rationale; rejected approaches |
12
+ | `landmines.md` | `security`, `integrate`, `scout` | Gotchas: "do not edit X without also editing Y" |
13
+ | `conventions.md` | `scenario`, `implement` | Repo-specific test/code idioms (fixture patterns, naming, layout) |
14
+ | `pending-questions.md` | any phase | Open questions the current session couldn't resolve |
15
+ | `_pending.md` | `memory_stop.sh` (writes), `/memory-flush` (clears) | Auto-extracted candidates awaiting curation. **Content gitignored**; the file structure is committed. |
16
+ | `_resume.md` | `memory_pre_compact.sh` + `memory_stop.sh` (write), `memory_session_start.sh` (reads), `harness` (reads) | **Continuity** snapshot — last completed phase, next phase due, in-flight files, recent user prompts. Refreshed every turn-end and again before compaction. Re-injected at every session start (compact / clear / resume / startup). **Gitignored** — pure session state, not project knowledge. |
17
+
18
+ ## Source provenance (mandatory for feedback-derived entries)
19
+
20
+ Every entry MUST carry a `source:` field declaring how the rule was learned. Allowed values:
21
+
22
+ | `source:` | Meaning | `verbatim:` requirement |
23
+ |---|---|---|
24
+ | `user-instruction` | The user stated a rule or directive in conversation | **Required** |
25
+ | `user-feedback` | The user corrected behavior or affirmed a non-obvious approach | **Required** |
26
+ | `incident` | Recovered from an actual failure or near-miss in this session | Recommended (incident-report quote) |
27
+ | `inferred-from-code` | Derived by reading the codebase | Not applicable |
28
+ | `library-pinned` | Came from a `context7` lookup | Not applicable (cited URL/version is the source) |
29
+ | `unrecorded` | Pre-schema-bump entry whose source was lost | Quality flag — curator must clear at next touch |
30
+
31
+ For `source: user-instruction` and `source: user-feedback`, the entry MUST include a `verbatim:` blockquote of the user's actual words. The verbatim is the canonical truth; the body of the entry is Claude's interpretation. **When verbatim and interpretation conflict, verbatim wins** — `CLAUDE.md` Article IX clause 6.
32
+
33
+ The verbatim is not a summary, not a paraphrase, and not in Claude's voice. It is the user's words. If the original turn is no longer available, the entry's source is `unrecorded` and the curator MUST flag it for the user to confirm or restate at the next opportunity.
34
+
35
+ `/memory-flush` SHALL reject any candidate promotion to a canonical file when `source` is `user-instruction` or `user-feedback` and `verbatim:` is missing or empty.
36
+
37
+ ## Per-entry shape (canonical files)
38
+
39
+ ```markdown
40
+ ## <stable key>
41
+
42
+ > verbatim (user, <ISO date>):
43
+ > <user's exact words, attributed — required when source ∈ {user-instruction, user-feedback}>
44
+
45
+ - source: <user-instruction|user-feedback|incident|inferred-from-code|library-pinned|unrecorded>
46
+ - <field>: <value>
47
+ - verified-at: <commit SHA short>
48
+ - last-touched: <ISO date>
49
+ - caveat: <optional>
50
+ ```
51
+
52
+ The **stable key** is the entry's primary key for deduplication. New entries with the same key replace; different keys append. The verbatim block is intentionally a markdown blockquote (`> ...`) so it survives plain-text grep and renders distinctly when the file is read.
53
+
54
+ Multiple verbatim blocks are allowed (and encouraged) when the user clarifies or refines an instruction across turns — each new clarification gets its own `> verbatim (user, <ISO date>):` block; older blocks are kept for provenance.
55
+
56
+ | File | Stable key |
57
+ |---|---|
58
+ | `landmarks.md` | `path:line` |
59
+ | `libraries.md` | `<lib>@<version>` |
60
+ | `decisions.md` | short slug (e.g., `auth-jwt-vs-session`) |
61
+ | `landmines.md` | `path:line` or short description slug |
62
+ | `conventions.md` | short slug |
63
+ | `pending-questions.md` | auto-numbered `Q-NNN` |
64
+
65
+ ## Self-healing rules
66
+
67
+ **Memory accelerates triage; it never authorizes a skip.** Every skill that *cites* a memory entry must first re-verify it (file exists, symbol still at named line, library version still pinned). On verification failure, the skill **corrects or deletes the entry in the same run** before proceeding. Drift self-heals because every read is also a check.
68
+
69
+ ## Bounding rules
70
+
71
+ - Each canonical file has `size-cap: <N>` in frontmatter (default 500 lines). When a skill writes and exceeds, it must prune the oldest unverified entries in the same write. Working-set discipline.
72
+ - Decay: entries unverified for ≥30 commits (git) OR ≥30 days since `last-touched:` (non-git fallback) are marked `stale`. The next phase that touches them either re-verifies or deletes.
73
+
74
+ ## Closure fields
75
+
76
+ Two optional, register-specific closure fields cause `/memory-flush` Step 0 to delete the entry block on its next run:
77
+
78
+ | File | Field | Semantics |
79
+ |---|---|---|
80
+ | `pending-questions.md` | `resolved-at: <ISO date>` | The question has been answered; entry is closed. |
81
+ | `landmarks.md`, `libraries.md`, `decisions.md`, `landmines.md`, `conventions.md` | `superseded-at: <ISO date>` | The fact is no longer true; entry is closed. |
82
+
83
+ **Per-file invariant**: on `pending-questions.md`, `superseded-at:` MUST NOT appear; on the other five canonical files, `resolved-at:` MUST NOT appear. Mutually exclusive at the file level. Not enforced by audit — documented invariant only. The `/memory-flush` Step 0a sweep flags violations in its report rather than deleting.
84
+
85
+ **Body-prose signals.** Three regexes, case-insensitive, line-anchored:
86
+
87
+ - R1: `^(\s*-\s*)?\*\*?Resolution\s+(path\s+taken|by|date)\b`
88
+ - R2: `^Superseded\s+(by|at|on)\b`
89
+ - R3: `^Resolved\s+(by|on|at)\b`
90
+
91
+ A match without a corresponding structured closure field causes `/memory-flush` Step 0b to surface a once-per-entry `Close <key> from <file>? (y / n / skip)` prompt.
92
+
93
+ **Closure short-circuits decay (AC-005).** `memory_session_start.sh` excludes any entry carrying a closure field from the stale count. `stale` ≠ `closed`: a stale entry is *unverified*; closure is a separate, deliberate signal that the entry is no longer load-bearing.
94
+
95
+ ## How memory gets updated
96
+
97
+ Two paths:
98
+
99
+ 1. **Phase skills, as a byproduct.** Each skill that produces a workflow artifact also writes any new entries for its owned file. No separate "update memory" task — the same tool call as the artifact write.
100
+ 2. **Stop hook auto-extraction.** `memory_stop.sh` reads the just-completed turn's transcript, extracts touched paths / cited library APIs / verbalized decisions, and appends candidates to `_pending.md`. Claude reviews via `/memory-flush` and commits keepers to canonical files.
101
+
102
+ ## Read order on session start
103
+
104
+ `memory_session_start.sh` hook prints a compact index (number of entries per file, count of stale entries, count of pending candidates), then appends the body of `_resume.md` if a recent snapshot exists, with a framing line that depends on the session source (`compact` / `clear` / `resume` / `startup`). Canonical files load on first relevant skill invocation.
105
+
106
+ ## Continuity vs knowledge
107
+
108
+ Six canonical files plus `_pending.md` hold **project knowledge** — facts about the codebase that survive multiple sessions and get re-verified on every cite. `_resume.md` is different: it's a **continuity snapshot** describing the *current session* — what we just touched, what the user just asked, what phase we're on. It's overwritten each turn and gitignored. The split keeps long-term knowledge clean of session-state noise.
@@ -0,0 +1,15 @@
1
+ ---
2
+ owners: [memory_stop.sh writes; /memory-flush clears]
3
+ category: auto-extracted candidates awaiting curation
4
+ verifies-against: none
5
+ ---
6
+
7
+ # Pending memory candidates
8
+
9
+ Auto-extracted by `memory_stop.sh` at end of each turn. Run `/memory-flush` to review and commit keepers to the canonical files.
10
+
11
+ **Content of this file is gitignored.** The file itself (with this header) is committed; everything below the `---` separator below is per-session and not staged.
12
+
13
+ ---
14
+
15
+ <!-- candidates appended below this line -->
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: resume
3
+ type: continuity
4
+ last-updated: never
5
+ trigger: stop
6
+ ---
7
+
8
+ # Resume snapshot
9
+
10
+ ## No prior session
11
+
12
+ This file is overwritten by `memory_stop.sh` at end of each turn and by `memory_pre_compact.sh` before context compaction. The SessionStart hook reads it on the next session start.
@@ -0,0 +1,26 @@
1
+ ---
2
+ owners: [scenario, implement]
3
+ category: repo-specific test and code conventions
4
+ size-cap: 500
5
+ key: short slug
6
+ verifies-against: codebase
7
+ ---
8
+
9
+ # Conventions
10
+
11
+ Repo-specific patterns the `scenario` and `implement` skills should match. Fixture locations, helper idioms, naming, file layout quirks. Not generic best practices — specific facts about *this* codebase.
12
+
13
+ Each entry's stable key is a short slug.
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## <short-slug>
19
+
20
+ - Convention: <pattern, rule, or idiom this repo follows>
21
+ - Why: <reason — historical, tooling-driven, performance, etc.>
22
+ - Verified-at: <commit SHA short>
23
+ - Last-touched: <ISO date>
24
+ ```
25
+
26
+ ---
@@ -0,0 +1,29 @@
1
+ ---
2
+ owners: [spec, rca]
3
+ category: architectural decisions
4
+ size-cap: 500
5
+ key: short slug
6
+ verifies-against: spec/rca artifact
7
+ ---
8
+
9
+ # Architectural decisions
10
+
11
+ Why this repo took the path it took. Includes rejected alternatives so a future session doesn't re-litigate.
12
+
13
+ Each entry's stable key is a short slug (e.g., `auth-jwt-vs-session`, `worktree-isolation`).
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## <short-slug>
19
+
20
+ - Decision: <what was chosen>
21
+ - Rationale: <why — the constraint or evidence that decided it>
22
+ - Rejected alternatives:
23
+ - <alt 1> → <why rejected>
24
+ - <alt 2> → <why rejected>
25
+ - Source: <spec slug / rca slug / conversation>
26
+ - Verified-at: <commit SHA short>
27
+ ```
28
+
29
+ ---
@@ -0,0 +1,26 @@
1
+ ---
2
+ owners: [scout]
3
+ category: codebase landmarks
4
+ size-cap: 500
5
+ key: path:line
6
+ verifies-against: git
7
+ ---
8
+
9
+ # Codebase landmarks
10
+
11
+ Where things live in this repo. The `scout` skill cites these and re-verifies before use; failed verifications are corrected or deleted in the same run.
12
+
13
+ Each entry's stable key is `path:line`.
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## <path:line>
19
+
20
+ - Role: <what lives here, why it matters>
21
+ - Verified-at: <commit SHA short>
22
+ - Last-touched: <ISO date>
23
+ - Caveat: <optional — gotcha, neighbour file that must change with this one, etc.>
24
+ ```
25
+
26
+ ---
@@ -0,0 +1,27 @@
1
+ ---
2
+ owners: [security, integrate, scout]
3
+ category: gotchas and recurring true positives
4
+ size-cap: 500
5
+ key: path:line or short slug
6
+ verifies-against: git
7
+ ---
8
+
9
+ # Landmines
10
+
11
+ Things that have bitten before and will bite again. "Editing X without also editing Y breaks Z." Recurring true positives from security review. Version skew traps.
12
+
13
+ Each entry's stable key is `path:line` or a short slug.
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## <path:line or slug>
19
+
20
+ - Path: <file/symbol involved>
21
+ - Trap: <what goes wrong, plain language>
22
+ - Mitigation: <what to check / do instead>
23
+ - Verified-at: <commit SHA short>
24
+ - Last-touched: <ISO date>
25
+ ```
26
+
27
+ ---
@@ -0,0 +1,27 @@
1
+ ---
2
+ owners: [research]
3
+ category: validated library APIs
4
+ size-cap: 500
5
+ key: lib@version
6
+ verifies-against: lockfile + context7
7
+ ---
8
+
9
+ # Validated library APIs
10
+
11
+ Library APIs the team has confirmed via `context7` MCP against the version present in this repo's lockfile. Saves a context7 round-trip when a stable choice is referenced again.
12
+
13
+ Each entry's stable key is `<lib>@<version>`. If the lockfile bumps, re-verify and update the version.
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## <lib>@<version>
19
+
20
+ - Role: <what this lib is used for in this repo>
21
+ - API: <key symbols / canonical call shape>
22
+ - Verified-at: <commit SHA short>
23
+ - Last-touched: <ISO date>
24
+ - Caveat: <optional — version pin reason, breaking-change notes>
25
+ ```
26
+
27
+ ---
@@ -0,0 +1,28 @@
1
+ ---
2
+ owners: [any phase]
3
+ category: cross-session open questions
4
+ size-cap: 500
5
+ key: Q-NNN
6
+ verifies-against: none
7
+ ---
8
+
9
+ # Pending questions
10
+
11
+ Questions the current session couldn't resolve. Surfaced at next session start so context isn't lost across yields.
12
+
13
+ Each entry's stable key is auto-numbered `Q-NNN`.
14
+
15
+ Per-entry shape:
16
+
17
+ ```markdown
18
+ ## Q-NNN
19
+
20
+ - Question: <what's open>
21
+ - Raised in: <date / phase / conversation>
22
+ - Blocker for: <what work is gated on this>
23
+ - Options considered: <a> / <b> / <c>
24
+ - Verified-at: <commit SHA short>
25
+ - Last-touched: <ISO date>
26
+ ```
27
+
28
+ ---