@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,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
|
+
---
|