create-ccc-tutor 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/README.md +41 -0
- package/bin/cli.js +76 -0
- package/package.json +28 -0
- package/template/.claude/commands/abandon.md +7 -0
- package/template/.claude/commands/add-anti-flag.md +7 -0
- package/template/.claude/commands/add-constitution-clause.md +7 -0
- package/template/.claude/commands/audit-spec.md +7 -0
- package/template/.claude/commands/commit.md +7 -0
- package/template/.claude/commands/constitution-edit.md +7 -0
- package/template/.claude/commands/db-schema.md +7 -0
- package/template/.claude/commands/exam.md +66 -0
- package/template/.claude/commands/execution-plan.md +7 -0
- package/template/.claude/commands/feature-draft.md +7 -0
- package/template/.claude/commands/handoff.md +7 -0
- package/template/.claude/commands/implement.md +7 -0
- package/template/.claude/commands/init.md +7 -0
- package/template/.claude/commands/next.md +7 -0
- package/template/.claude/commands/offload.md +7 -0
- package/template/.claude/commands/pickup.md +7 -0
- package/template/.claude/commands/recall.md +7 -0
- package/template/.claude/commands/remember.md +7 -0
- package/template/.claude/commands/slide.md +87 -0
- package/template/.claude/commands/spec-finalize.md +7 -0
- package/template/.claude/commands/test-fix.md +7 -0
- package/template/.claude/commands/uninstall.md +7 -0
- package/template/.claude/settings.json +161 -0
- package/template/.claude-plugin/plugin.json +41 -0
- package/template/.codex/config.toml +24 -0
- package/template/.codex/hooks.json +4 -0
- package/template/.codex/install-skills.sh +18 -0
- package/template/.codex/skills/exam/SKILL.md +61 -0
- package/template/.codex/skills/slide/SKILL.md +69 -0
- package/template/.harness/agents/README.md +70 -0
- package/template/.harness/agents/_template/junior-agent-template.md +116 -0
- package/template/.harness/agents/backend-reviewer.md +153 -0
- package/template/.harness/agents/frontend-reviewer.md +158 -0
- package/template/.harness/agents/security-reviewer.md +148 -0
- package/template/.harness/agents/test-fixer.md +147 -0
- package/template/.harness/docs/doc-sync.md +29 -0
- package/template/.harness/docs/git-hygiene.md +56 -0
- package/template/.harness/docs/spec-model.md +47 -0
- package/template/.harness/docs/tool-map.md +120 -0
- package/template/.harness/docs/workflow.md +59 -0
- package/template/.harness/scripts/README.md +70 -0
- package/template/.harness/scripts/auditor-gate.sh +388 -0
- package/template/.harness/scripts/bootstrap-check.sh +103 -0
- package/template/.harness/scripts/budget-monitor.sh +223 -0
- package/template/.harness/scripts/check-prereqs.sh +165 -0
- package/template/.harness/scripts/checkpoint-recall.sh +136 -0
- package/template/.harness/scripts/checkpoint-write.sh +281 -0
- package/template/.harness/scripts/decision-log-append.sh +90 -0
- package/template/.harness/scripts/env-check.sh +286 -0
- package/template/.harness/scripts/format-edit.sh +80 -0
- package/template/.harness/scripts/lint-bans.sh +110 -0
- package/template/.harness/scripts/memory-archive.sh +129 -0
- package/template/.harness/scripts/memory-recall.sh +197 -0
- package/template/.harness/scripts/memory-snapshot.sh +124 -0
- package/template/.harness/scripts/post-migration.sh +58 -0
- package/template/.harness/scripts/precommit-cycles.sh +74 -0
- package/template/.harness/scripts/precommit-typecheck.sh +69 -0
- package/template/.harness/scripts/scratchpad-recall.sh +83 -0
- package/template/.harness/scripts/scratchpad-update.sh +39 -0
- package/template/.harness/scripts/standalone-bootstrap.md +443 -0
- package/template/.harness/skills/abandon/SKILL.md +157 -0
- package/template/.harness/skills/add-anti-flag/SKILL.md +205 -0
- package/template/.harness/skills/add-constitution-clause/SKILL.md +244 -0
- package/template/.harness/skills/audit-spec/SKILL.md +395 -0
- package/template/.harness/skills/commit/SKILL.md +270 -0
- package/template/.harness/skills/constitution-edit/SKILL.md +292 -0
- package/template/.harness/skills/db-schema/SKILL.md +145 -0
- package/template/.harness/skills/db-schema/references/methodology.md +202 -0
- package/template/.harness/skills/execution-plan/SKILL.md +346 -0
- package/template/.harness/skills/feature-draft/SKILL.md +426 -0
- package/template/.harness/skills/handoff/SKILL.md +211 -0
- package/template/.harness/skills/implement/SKILL.md +355 -0
- package/template/.harness/skills/init/SKILL.md +805 -0
- package/template/.harness/skills/next/SKILL.md +245 -0
- package/template/.harness/skills/offload/SKILL.md +134 -0
- package/template/.harness/skills/pickup/SKILL.md +213 -0
- package/template/.harness/skills/recall/SKILL.md +159 -0
- package/template/.harness/skills/remember/SKILL.md +205 -0
- package/template/.harness/skills/spec-finalize/SKILL.md +196 -0
- package/template/.harness/skills/test-fix/SKILL.md +363 -0
- package/template/.harness/skills/uninstall/SKILL.md +370 -0
- package/template/.harness/state/install.json +83 -0
- package/template/AGENTS.md +262 -0
- package/template/CCC_MAGI_LICENSE +201 -0
- package/template/CCC_MAGI_README.md +986 -0
- package/template/CLAUDE.md +658 -0
- package/template/codex.md +39 -0
- package/template/constitution.md +164 -0
- package/template/course/README.md +15 -0
- package/template/course/course_code(example)/exam/README.md +2 -0
- package/template/course/course_code(example)/slide/slide_example-1.pdf +40 -0
- package/template/course/course_code(example)/slide/slide_example-2.pdf +40 -0
- package/template/docs/features/slide-query-implementation.md +79 -0
- package/template/docs/features/slide-query.md +211 -0
- package/template/docs-harness/README.md +42 -0
- package/template/docs-harness/adoption-playbook.md +373 -0
- package/template/docs-harness/ccc-step1-driver-template.md +288 -0
- package/template/docs-harness/cli-configs-README.md +78 -0
- package/template/docs-harness/context-architecture-v2.md +249 -0
- package/template/docs-harness/design-spec.md +437 -0
- package/template/docs-harness/memory-layer.md +135 -0
- package/template/docs-harness/retrospective-notes.md +204 -0
- package/template/gitignore +106 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# post-migration.sh — backend-specific steps after a schema migration is applied locally.
|
|
3
|
+
#
|
|
4
|
+
# Called manually by the user (or invoked from /db-schema's Step 10).
|
|
5
|
+
# Only relevant if backend_db_type is configured. Projects without a backend
|
|
6
|
+
# don't have this script (or it just exits 0).
|
|
7
|
+
#
|
|
8
|
+
# Typical responsibilities:
|
|
9
|
+
# 1. Refresh backend caches that don't auto-reload on `migration up`
|
|
10
|
+
# (e.g., PostgREST schema cache in some local stacks)
|
|
11
|
+
# 2. Regenerate typed bindings (so the typecheck doesn't fail on stale types)
|
|
12
|
+
# 3. Notify the live backend (managed Postgres / Supabase / etc.) if needed
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
# Ensure brew-installed tools (jq, etc.) are on PATH even in non-interactive
|
|
17
|
+
# shells where ~/.zprofile isn't loaded. macOS Apple Silicon path comes first.
|
|
18
|
+
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
19
|
+
|
|
20
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
21
|
+
# CUSTOMIZE: per-backend post-migration steps
|
|
22
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
# Example 1 — Supabase (local Docker stack):
|
|
25
|
+
# docker compose -f supabase/docker-compose.yml restart postgrest \
|
|
26
|
+
# || echo "warning: PostgREST restart failed; new RPCs may not appear in schema cache"
|
|
27
|
+
# supabase gen types typescript --local > src/lib/supabase/types.ts \
|
|
28
|
+
# || echo "warning: type regeneration failed"
|
|
29
|
+
|
|
30
|
+
# Example 2 — Prisma:
|
|
31
|
+
# npx prisma migrate dev --skip-seed
|
|
32
|
+
# npx prisma generate
|
|
33
|
+
|
|
34
|
+
# Example 3 — Drizzle:
|
|
35
|
+
# npx drizzle-kit push
|
|
36
|
+
# # types regen happens automatically with drizzle-kit
|
|
37
|
+
|
|
38
|
+
# Example 4 — Raw Postgres + pgtyped:
|
|
39
|
+
# psql "$DATABASE_URL" -f "$(ls -t supabase/migrations/*.sql | head -1)"
|
|
40
|
+
# npx pgtyped -c pgtyped.config.json
|
|
41
|
+
|
|
42
|
+
# Example 5 — Django:
|
|
43
|
+
# python manage.py migrate
|
|
44
|
+
# python manage.py inspectdb > types.py # if using inspectdb workflow
|
|
45
|
+
|
|
46
|
+
# Example 6 — None (no backend / no codegen step):
|
|
47
|
+
# exit 0
|
|
48
|
+
|
|
49
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
50
|
+
# Run
|
|
51
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
52
|
+
echo "ℹ️ post-migration.sh has no commands configured."
|
|
53
|
+
echo " Edit .harness/scripts/post-migration.sh to add your backend's"
|
|
54
|
+
echo " cache-refresh + typed-bindings-regenerate steps."
|
|
55
|
+
echo ""
|
|
56
|
+
echo " Without this, Stage 4 (/execution-plan) may operate on stale types."
|
|
57
|
+
|
|
58
|
+
exit 0
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Pre-commit dependency-cycle check.
|
|
3
|
+
#
|
|
4
|
+
# Only meaningful if the project has declared a dependency_flow (e.g.,
|
|
5
|
+
# `shared → ui → features → app`). If dependency_flow is empty, this script
|
|
6
|
+
# should exit 0 silently — /init removes the hook entry in that case.
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
# Ensure brew-installed tools (jq, etc.) are on PATH even in non-interactive
|
|
11
|
+
# shells where ~/.zprofile isn't loaded. macOS Apple Silicon path comes first.
|
|
12
|
+
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
13
|
+
|
|
14
|
+
# Filter: only fire on `git commit` invocations. The PreToolUse hook contract
|
|
15
|
+
# passes the tool call payload via stdin; we parse it and silently exit if
|
|
16
|
+
# the Bash command isn't a git commit.
|
|
17
|
+
#
|
|
18
|
+
# (We do this filtering here instead of relying on settings.json's `if`
|
|
19
|
+
# clause because that clause was found NOT to be honored consistently —
|
|
20
|
+
# see harness-testing-2026-05-25.md § P0.Z.)
|
|
21
|
+
|
|
22
|
+
# Read stdin (Claude Code passes JSON with tool_input.command for Bash hooks)
|
|
23
|
+
HOOK_INPUT="$(cat 2>/dev/null || true)"
|
|
24
|
+
if [ -n "$HOOK_INPUT" ]; then
|
|
25
|
+
# Try to extract the Bash command. If jq is available, use it. Otherwise
|
|
26
|
+
# fall back to grep (best-effort).
|
|
27
|
+
if command -v jq >/dev/null 2>&1; then
|
|
28
|
+
BASH_CMD="$(printf '%s' "$HOOK_INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")"
|
|
29
|
+
else
|
|
30
|
+
# Best-effort fallback: extract "command":"..." substring via grep
|
|
31
|
+
BASH_CMD="$(printf '%s' "$HOOK_INPUT" | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed -E 's/.*"command"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/' || echo "")"
|
|
32
|
+
fi
|
|
33
|
+
# Silent exit unless this is a git commit invocation
|
|
34
|
+
case "$BASH_CMD" in
|
|
35
|
+
git\ commit*|*\ git\ commit*)
|
|
36
|
+
# proceed
|
|
37
|
+
;;
|
|
38
|
+
*)
|
|
39
|
+
exit 0
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# === Original hook logic continues below ===
|
|
45
|
+
|
|
46
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
47
|
+
# CUSTOMIZE: pick your stack's cycle-detection command
|
|
48
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
49
|
+
# JS/TS (madge): COMMAND=(npx madge --circular src/)
|
|
50
|
+
# JS/TS (dpdm): COMMAND=(npx dpdm --no-warning src/)
|
|
51
|
+
# Python: COMMAND=(pylint --disable=all --enable=cyclic-import .)
|
|
52
|
+
# Go: COMMAND=(go vet ./...) # detects import cycles
|
|
53
|
+
# Rust: # rustc detects cycles natively
|
|
54
|
+
# None / skip: exit 0
|
|
55
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
COMMAND=(npx madge --circular src/)
|
|
58
|
+
|
|
59
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
60
|
+
# Run
|
|
61
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
62
|
+
if ! command -v "${COMMAND[0]}" >/dev/null 2>&1; then
|
|
63
|
+
echo "warning: ${COMMAND[0]} not found; skipping cycle check" >&2
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if ! "${COMMAND[@]}"; then
|
|
68
|
+
echo ""
|
|
69
|
+
echo "❌ Dependency cycle detected."
|
|
70
|
+
echo "If this is a deliberate exception, document the cycle in your"
|
|
71
|
+
echo "commit body with reasoning, then bypass with --no-verify (per"
|
|
72
|
+
echo "AGENTS.md § Anti-flag rules), but expect the auditor to question it."
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Pre-commit typecheck. Blocks commit if type/syntax check fails.
|
|
3
|
+
#
|
|
4
|
+
# Called from .claude/settings.json + .codex/hooks.json on `git commit:*`.
|
|
5
|
+
# Constitution § 5 (Spec and reality stay in sync) — typecheck is one of the
|
|
6
|
+
# mechanical gates that catch reality drift at the syntax level.
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
# Ensure brew-installed tools (jq, etc.) are on PATH even in non-interactive
|
|
11
|
+
# shells where ~/.zprofile isn't loaded. macOS Apple Silicon path comes first.
|
|
12
|
+
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
13
|
+
|
|
14
|
+
# Filter: only fire on `git commit` invocations. The PreToolUse hook contract
|
|
15
|
+
# passes the tool call payload via stdin; we parse it and silently exit if
|
|
16
|
+
# the Bash command isn't a git commit.
|
|
17
|
+
#
|
|
18
|
+
# (We do this filtering here instead of relying on settings.json's `if`
|
|
19
|
+
# clause because that clause was found NOT to be honored consistently —
|
|
20
|
+
# see harness-testing-2026-05-25.md § P0.Z.)
|
|
21
|
+
|
|
22
|
+
# Read stdin (Claude Code passes JSON with tool_input.command for Bash hooks)
|
|
23
|
+
HOOK_INPUT="$(cat 2>/dev/null || true)"
|
|
24
|
+
if [ -n "$HOOK_INPUT" ]; then
|
|
25
|
+
# Try to extract the Bash command. If jq is available, use it. Otherwise
|
|
26
|
+
# fall back to grep (best-effort).
|
|
27
|
+
if command -v jq >/dev/null 2>&1; then
|
|
28
|
+
BASH_CMD="$(printf '%s' "$HOOK_INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")"
|
|
29
|
+
else
|
|
30
|
+
# Best-effort fallback: extract "command":"..." substring via grep
|
|
31
|
+
BASH_CMD="$(printf '%s' "$HOOK_INPUT" | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed -E 's/.*"command"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/' || echo "")"
|
|
32
|
+
fi
|
|
33
|
+
# Silent exit unless this is a git commit invocation
|
|
34
|
+
case "$BASH_CMD" in
|
|
35
|
+
git\ commit*|*\ git\ commit*)
|
|
36
|
+
# proceed
|
|
37
|
+
;;
|
|
38
|
+
*)
|
|
39
|
+
exit 0
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# === Original hook logic continues below ===
|
|
45
|
+
|
|
46
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
47
|
+
# CUSTOMIZE: pick your stack's typecheck command
|
|
48
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
49
|
+
# TypeScript: COMMAND=(npx tsc --noEmit)
|
|
50
|
+
# TypeScript+pnpm: COMMAND=(pnpm exec tsc --noEmit)
|
|
51
|
+
# Python+mypy: COMMAND=(mypy .)
|
|
52
|
+
# Python+pyright: COMMAND=(pyright)
|
|
53
|
+
# Go: COMMAND=(go vet ./...)
|
|
54
|
+
# Rust: COMMAND=(cargo check --all-targets)
|
|
55
|
+
# Swift: COMMAND=(swift build --build-tests)
|
|
56
|
+
# None / skip: exit 0
|
|
57
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
COMMAND=(npx tsc --noEmit)
|
|
60
|
+
|
|
61
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
62
|
+
# Run
|
|
63
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
64
|
+
if ! command -v "${COMMAND[0]}" >/dev/null 2>&1; then
|
|
65
|
+
echo "warning: ${COMMAND[0]} not found; skipping typecheck" >&2
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
"${COMMAND[@]}"
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scratchpad-recall.sh — SessionStart hook for v2 working memory (Tier 1).
|
|
3
|
+
#
|
|
4
|
+
# Reads .harness/state/scratchpad.md and emits it as additionalContext so the
|
|
5
|
+
# AI starts the session aware of:
|
|
6
|
+
# - Current objective (carried from prior session, if any)
|
|
7
|
+
# - Last step taken
|
|
8
|
+
# - Next step planned
|
|
9
|
+
# - Open blockers
|
|
10
|
+
#
|
|
11
|
+
# If the file doesn't exist (fresh project), copies from template. If empty,
|
|
12
|
+
# emits a brief "no carryover" notice.
|
|
13
|
+
|
|
14
|
+
set -eu
|
|
15
|
+
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
16
|
+
|
|
17
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
18
|
+
SCRATCHPAD="$PROJECT_DIR/.harness/state/scratchpad.md"
|
|
19
|
+
TEMPLATE="$PROJECT_DIR/.harness/state/scratchpad.md.template"
|
|
20
|
+
|
|
21
|
+
# Drain stdin
|
|
22
|
+
cat >/dev/null 2>&1 || true
|
|
23
|
+
|
|
24
|
+
# Bootstrap from template if missing
|
|
25
|
+
if [ ! -f "$SCRATCHPAD" ] && [ -f "$TEMPLATE" ]; then
|
|
26
|
+
cp "$TEMPLATE" "$SCRATCHPAD" 2>/dev/null || true
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# If still missing or empty, emit a brief notice
|
|
30
|
+
if [ ! -f "$SCRATCHPAD" ] || [ ! -s "$SCRATCHPAD" ]; then
|
|
31
|
+
if command -v jq >/dev/null 2>&1; then
|
|
32
|
+
jq -n '{
|
|
33
|
+
hookSpecificOutput: {
|
|
34
|
+
hookEventName: "SessionStart",
|
|
35
|
+
additionalContext: "📋 Working scratchpad (.harness/state/scratchpad.md) is empty — fresh start. Per CLAUDE.md § Working Scratchpad, you will rewrite it at end of your first turn."
|
|
36
|
+
}
|
|
37
|
+
}'
|
|
38
|
+
fi
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Cap: read at most 500 lines (defensive against runaway files)
|
|
43
|
+
CONTENT=$(head -500 "$SCRATCHPAD")
|
|
44
|
+
|
|
45
|
+
# Char cap: ~2000 chars (~500 tokens). If oversized, truncate and warn.
|
|
46
|
+
if [ "${#CONTENT}" -gt 2000 ]; then
|
|
47
|
+
CONTENT=$(printf '%s' "$CONTENT" | head -c 2000)
|
|
48
|
+
CONTENT="$CONTENT
|
|
49
|
+
|
|
50
|
+
⚠️ (scratchpad exceeded 500-token cap; truncated. Rewrite leaner this turn.)"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Build additionalContext: prepend header explaining what this is and how AI should treat it
|
|
54
|
+
HEADER='## Working Scratchpad (Tier 1 memory — read at SessionStart)
|
|
55
|
+
|
|
56
|
+
The file below is the AI working scratchpad: the agent-managed core memory for this project. It survives compaction and `/clear` because it lives on disk. Per `CLAUDE.md § Working Scratchpad`:
|
|
57
|
+
|
|
58
|
+
- **Trust it**: it reflects state at end of last AI turn
|
|
59
|
+
- **Update it**: at the end of THIS turn, the Stop hook will instruct you to rewrite it with the current objective, last step, next step, and blockers
|
|
60
|
+
- **Keep it lean**: ≤500 tokens (~2000 chars). If you find yourself needing more, it belongs in `/remember` or `/handoff`, not the scratchpad
|
|
61
|
+
|
|
62
|
+
Current contents:
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
'
|
|
66
|
+
|
|
67
|
+
FOOTER='
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---'
|
|
71
|
+
|
|
72
|
+
FULL="${HEADER}${CONTENT}${FOOTER}"
|
|
73
|
+
|
|
74
|
+
if command -v jq >/dev/null 2>&1; then
|
|
75
|
+
printf '%s' "$FULL" | jq -Rs '{
|
|
76
|
+
hookSpecificOutput: {
|
|
77
|
+
hookEventName: "SessionStart",
|
|
78
|
+
additionalContext: .
|
|
79
|
+
}
|
|
80
|
+
}'
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
exit 0
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scratchpad-update.sh — Stop hook for v2 working memory (Tier 1).
|
|
3
|
+
#
|
|
4
|
+
# DESIGN NOTE (v2.1 — 2026-05-31):
|
|
5
|
+
# Claude Code's Stop hook schema does NOT support `hookSpecificOutput.additionalContext`
|
|
6
|
+
# (only PreToolUse / UserPromptSubmit / PostToolUse / PostToolBatch do). So this hook
|
|
7
|
+
# CANNOT inject text instructions back to the AI.
|
|
8
|
+
#
|
|
9
|
+
# Instead, the scratchpad rewrite rule lives in CLAUDE.md § Working Scratchpad, which the
|
|
10
|
+
# AI reads at SessionStart. The AI rewrites the scratchpad as the final act of each turn
|
|
11
|
+
# because the CLAUDE.md rule tells it to — no hook nudge required.
|
|
12
|
+
#
|
|
13
|
+
# This hook's job is now just to:
|
|
14
|
+
# 1. Ensure the scratchpad file + parent dir exist (defensive)
|
|
15
|
+
# 2. Stay silent (suppressOutput=true) so it never spams the user's screen
|
|
16
|
+
#
|
|
17
|
+
# Returning `{}` would also work, but `{"suppressOutput": true}` is the explicit
|
|
18
|
+
# "I have nothing to say" signal.
|
|
19
|
+
|
|
20
|
+
set -eu
|
|
21
|
+
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
22
|
+
|
|
23
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
24
|
+
SCRATCHPAD="$PROJECT_DIR/.harness/state/scratchpad.md"
|
|
25
|
+
TEMPLATE="$PROJECT_DIR/.harness/state/scratchpad.md.template"
|
|
26
|
+
|
|
27
|
+
# Drain stdin
|
|
28
|
+
cat >/dev/null 2>&1 || true
|
|
29
|
+
|
|
30
|
+
# Ensure dir + file exist (so next SessionStart's scratchpad-recall finds something)
|
|
31
|
+
mkdir -p "$(dirname "$SCRATCHPAD")" 2>/dev/null || true
|
|
32
|
+
if [ ! -f "$SCRATCHPAD" ] && [ -f "$TEMPLATE" ]; then
|
|
33
|
+
cp "$TEMPLATE" "$SCRATCHPAD" 2>/dev/null || true
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Emit a valid Stop schema response: suppress any output
|
|
37
|
+
printf '{"suppressOutput": true}\n'
|
|
38
|
+
|
|
39
|
+
exit 0
|