@thebassclef/lite 0.0.1 → 0.1.2
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 +85 -4
- package/dist/cli.cjs +1612 -0
- package/dist/cli.js +1589 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/package.json +51 -3
- package/substrate/.bassclef/lite-manifest.json +2701 -0
- package/substrate/.claude/agents/architect.md +70 -0
- package/substrate/.claude/agents/builder.md +114 -0
- package/substrate/.claude/agents/designer.md +156 -0
- package/substrate/.claude/agents/reviewer.md +88 -0
- package/substrate/.claude/hooks/artifact-ingestion-gate.sh +357 -0
- package/substrate/.claude/hooks/assert-verify-steering.sh +77 -0
- package/substrate/.claude/hooks/bassclef-source-config-validate.sh +215 -0
- package/substrate/.claude/hooks/bassclef-sync.sh +634 -0
- package/substrate/.claude/hooks/compound-noun-scrub.sh +292 -0
- package/substrate/.claude/hooks/kiss-expansion-inject.sh +69 -0
- package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
- package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +492 -0
- package/substrate/.claude/hooks/plain-english-steering.sh +156 -0
- package/substrate/.claude/hooks/post-skill-friction-check.sh +177 -0
- package/substrate/.claude/hooks/post-skill-telemetry.sh +62 -0
- package/substrate/.claude/hooks/pre-build-gate.sh +511 -0
- package/substrate/.claude/hooks/pre-commit-gate.sh +451 -0
- package/substrate/.claude/hooks/session-end.sh +433 -0
- package/substrate/.claude/hooks/session-reflection.sh +303 -0
- package/substrate/.claude/hooks/skill-body-grade-gate.sh +219 -0
- package/substrate/.claude/hooks/skill-body-intent-drift.sh +107 -0
- package/substrate/.claude/hooks/skill-step-list-check.sh +171 -0
- package/substrate/.claude/hooks/state-validate.sh +271 -0
- package/substrate/.claude/hooks/substrate-clarity-gate.sh +1110 -0
- package/substrate/.claude/hooks/temperance-gate.sh +147 -0
- package/substrate/.claude/hooks/testing-tier-enforce.sh +233 -0
- package/substrate/.claude/hooks/turn-prose-grade-measure.sh +219 -0
- package/substrate/.claude/hooks/turn-prose-kiss-check.sh +463 -0
- package/substrate/.claude/hooks/vocabulary-migration-check.sh +171 -0
- package/substrate/.claude/hooks/whereami-utc-gate.sh +142 -0
- package/substrate/.claude/luminaries/alan-cooper.md +170 -0
- package/substrate/.claude/luminaries/alistair-cockburn.md +140 -0
- package/substrate/.claude/luminaries/amazon-pr-faq.md +34 -0
- package/substrate/.claude/luminaries/ash-maurya.md +121 -0
- package/substrate/.claude/luminaries/bill-buxton.md +210 -0
- package/substrate/.claude/luminaries/charles-sanders-peirce.md +150 -0
- package/substrate/.claude/luminaries/david-ogilvy.md +192 -0
- package/substrate/.claude/luminaries/don-norman.md +173 -0
- package/substrate/.claude/luminaries/edward-tufte.md +179 -0
- package/substrate/.claude/luminaries/eric-evans.md +160 -0
- package/substrate/.claude/luminaries/frederick-brooks.md +50 -0
- package/substrate/.claude/luminaries/gang-of-four.md +157 -0
- package/substrate/.claude/luminaries/glenford-myers.md +230 -0
- package/substrate/.claude/luminaries/hunt-thomas.md +115 -0
- package/substrate/.claude/luminaries/hyrum-wright.md +94 -0
- package/substrate/.claude/luminaries/jason-fried-dhh.md +46 -0
- package/substrate/.claude/luminaries/jesse-james-garrett.md +154 -0
- package/substrate/.claude/luminaries/john-ousterhout.md +94 -0
- package/substrate/.claude/luminaries/karl-popper.md +132 -0
- package/substrate/.claude/luminaries/kent-beck.md +168 -0
- package/substrate/.claude/luminaries/linus-torvalds.md +218 -0
- package/substrate/.claude/luminaries/martin-fowler.md +164 -0
- package/substrate/.claude/luminaries/michael-feathers.md +125 -0
- package/substrate/.claude/luminaries/michael-nygard.md +118 -0
- package/substrate/.claude/luminaries/robert-c-martin.md +164 -0
- package/substrate/.claude/luminaries/saltzer-schroeder.md +194 -0
- package/substrate/.claude/luminaries/sophia-prater.md +193 -0
- package/substrate/.claude/luminaries/stephen-toulmin.md +131 -0
- package/substrate/.claude/luminaries/tony-hoare.md +170 -0
- package/substrate/.claude/luminaries/vaughn-vernon.md +50 -0
- package/substrate/.claude/luminaries/w-edwards-deming.md +158 -0
- package/substrate/.claude/rules/accessor-library-discipline.md +138 -0
- package/substrate/.claude/rules/adr-discipline.md +120 -0
- package/substrate/.claude/rules/api-conventions.md +125 -0
- package/substrate/.claude/rules/artifact-ingestion.md +179 -0
- package/substrate/.claude/rules/assert-only-after-verify.md +137 -0
- package/substrate/.claude/rules/blocked-items.md +146 -0
- package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
- package/substrate/.claude/rules/branching.md +28 -0
- package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
- package/substrate/.claude/rules/commit-conventions.md +22 -0
- package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/context-engineering.md +202 -0
- package/substrate/.claude/rules/context-management.md +85 -0
- package/substrate/.claude/rules/defensive-bash.md +68 -0
- package/substrate/.claude/rules/deferred-actions.md +233 -0
- package/substrate/.claude/rules/destructive-operations.md +69 -0
- package/substrate/.claude/rules/diagnosis.md +38 -0
- package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
- package/substrate/.claude/rules/guardrails.md +73 -0
- package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
- package/substrate/.claude/rules/identifier-leak-prevention.md +104 -0
- package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
- package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +98 -0
- package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +89 -0
- package/substrate/.claude/rules/loop-discipline.md +81 -0
- package/substrate/.claude/rules/manual-prod-approval.md +100 -0
- package/substrate/.claude/rules/marker-enrichment-discipline.md +99 -0
- package/substrate/.claude/rules/mobile-ephemeral-session.md +109 -0
- package/substrate/.claude/rules/new-dependency-check.md +51 -0
- package/substrate/.claude/rules/oo-ad-entry-point.md +117 -0
- package/substrate/.claude/rules/operator-facing-prose.md +196 -0
- package/substrate/.claude/rules/option-label-discipline.md +108 -0
- package/substrate/.claude/rules/pattern-annotation.md +100 -0
- package/substrate/.claude/rules/plain-english-discipline.md +156 -0
- package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
- package/substrate/.claude/rules/pr-body-shape.md +317 -0
- package/substrate/.claude/rules/pr-strategy.md +167 -0
- package/substrate/.claude/rules/pr-title-shape.md +161 -0
- package/substrate/.claude/rules/prototype-workflow.md +65 -0
- package/substrate/.claude/rules/reserved-skill-names.md +123 -0
- package/substrate/.claude/rules/schema-management.md +49 -0
- package/substrate/.claude/rules/sdlc-gates.md +149 -0
- package/substrate/.claude/rules/security.md +37 -0
- package/substrate/.claude/rules/session-artifacts.md +236 -0
- package/substrate/.claude/rules/skill-composition-declarations.md +124 -0
- package/substrate/.claude/rules/skill-description-clarity.md +247 -0
- package/substrate/.claude/rules/skill-procedure-step-list.md +137 -0
- package/substrate/.claude/rules/state-schema-validation.md +162 -0
- package/substrate/.claude/rules/stuck-signal-diagnostic.md +140 -0
- package/substrate/.claude/rules/substrate-config-schema.md +98 -0
- package/substrate/.claude/rules/test-list-discipline.md +175 -0
- package/substrate/.claude/rules/test-sufficiency.md +210 -0
- package/substrate/.claude/rules/testing-tier-config.md +145 -0
- package/substrate/.claude/rules/testing.md +38 -0
- package/substrate/.claude/rules/turn-estimate-grounding.md +134 -0
- package/substrate/.claude/rules/visual-hierarchy.md +437 -0
- package/substrate/.claude/rules/we-dont-break-adopters.md +126 -0
- package/substrate/.claude/rules/whereami-load-bearing.md +202 -0
- package/substrate/.claude/rules/writing-craft-discipline.md +92 -0
- package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
- package/substrate/.claude/skills/build/SKILL.md +640 -0
- package/substrate/.claude/skills/chronicle/SKILL.md +55 -0
- package/substrate/.claude/skills/clean-artifacts/SKILL.md +249 -0
- package/substrate/.claude/skills/decompose/SKILL.md +280 -0
- package/substrate/.claude/skills/diagnose/SKILL.md +297 -0
- package/substrate/.claude/skills/feynman/SKILL.md +90 -0
- package/substrate/.claude/skills/howdoi/SKILL.md +105 -0
- package/substrate/.claude/skills/ia-model/SKILL.md +108 -0
- package/substrate/.claude/skills/interaction-design/SKILL.md +112 -0
- package/substrate/.claude/skills/interpret-input/SKILL.md +180 -0
- package/substrate/.claude/skills/journal/SKILL.md +209 -0
- package/substrate/.claude/skills/kiss/SKILL.md +449 -0
- package/substrate/.claude/skills/launch/SKILL.md +915 -0
- package/substrate/.claude/skills/lean-canvas/SKILL.md +332 -0
- package/substrate/.claude/skills/longrun/SKILL.md +463 -0
- package/substrate/.claude/skills/luminary/SKILL.md +481 -0
- package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
- package/substrate/.claude/skills/onboard-repo/SKILL.md +1624 -0
- package/substrate/.claude/skills/pattern-review/SKILL.md +99 -0
- package/substrate/.claude/skills/personas/SKILL.md +207 -0
- package/substrate/.claude/skills/promote/SKILL.md +283 -0
- package/substrate/.claude/skills/requirement/SKILL.md +98 -0
- package/substrate/.claude/skills/retro/SKILL.md +117 -0
- package/substrate/.claude/skills/riff/SKILL.md +114 -0
- package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
- package/substrate/.claude/skills/session-end/SKILL.md +309 -0
- package/substrate/.claude/skills/session-log/SKILL.md +299 -0
- package/substrate/.claude/skills/skills/SKILL.md +228 -0
- package/substrate/.claude/skills/spec/SKILL.md +105 -0
- package/substrate/.claude/skills/sprint/SKILL.md +392 -0
- package/substrate/.claude/skills/stage/SKILL.md +384 -0
- package/substrate/.claude/skills/state-a-problem/SKILL.md +185 -0
- package/substrate/.claude/skills/temperance/SKILL.md +108 -0
- package/substrate/.claude/skills/use-case/SKILL.md +417 -0
- package/substrate/.claude/skills/user-stories/SKILL.md +268 -0
- package/substrate/.claude/skills/value-prop/SKILL.md +251 -0
- package/substrate/.claude/skills/verify/SKILL.md +160 -0
- package/substrate/.claude/skills/visual-review/SKILL.md +503 -0
- package/substrate/.claude/skills/whats-the-plan/SKILL.md +202 -0
- package/substrate/.claude/skills/whereami/SKILL.md +307 -0
- package/substrate/AGENTS.md +79 -0
- package/substrate/CLAUDE-lite.md +85 -0
- package/substrate/CODE_OF_CONDUCT.md +28 -0
- package/substrate/CONTRIBUTING.md +177 -0
- package/substrate/README.md +173 -0
- package/substrate/SECURITY.md +19 -0
- package/substrate/architecture/decisions/ADR-029-release-pipeline.md +79 -0
- package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
- package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
- package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
- package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
- package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
- package/substrate/lib/clean-artifacts-sweep.sh +112 -0
- package/substrate/lib/code-comment-discipline.sh +144 -0
- package/substrate/lib/composer-preflight.sh +459 -0
- package/substrate/lib/hook-inject.sh +255 -0
- package/substrate/lib/luminary-pick.sh +96 -0
- package/substrate/lib/output-discipline.sh +143 -0
- package/substrate/lib/prose-scan-boundary.sh +171 -0
- package/substrate/lib/rewrite-check.sh +214 -0
- package/substrate/lib/state.sh +1372 -0
- package/substrate/lib/telemetry.sh +205 -0
- package/substrate/lib/tier-check.sh +187 -0
- package/substrate/lib/tier-dependency-audit.sh +1088 -0
- package/substrate/presence/install/bassclef-hook-connect.sh +178 -0
- package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
- package/substrate/presence/install/bassclef-sync.template.sh +2076 -0
- package/substrate/presence/install/schedule-auto-save.cron.sh +88 -0
- package/substrate/presence/install/schedule-auto-save.taskscheduler.md +122 -0
- package/substrate/scripts/aggregate-telemetry.sh +217 -0
- package/substrate/scripts/analyze-tier-dependencies.sh +239 -0
- package/substrate/scripts/generate-lite-manifest.sh +505 -0
- package/substrate/scripts/generate-tier-manifest.sh +28 -0
- package/substrate/scripts/intent-drift-check.sh +456 -0
- package/substrate/scripts/lite-manifest-drift-check.sh +146 -0
- package/substrate/scripts/render-lite-manifest-doc.sh +150 -0
- package/substrate/standards/adr-template.md +86 -0
- package/substrate/standards/api-conventions/nextjs.md +84 -0
- package/substrate/standards/artifact-composition.md +209 -0
- package/substrate/standards/bash-hook-safety.md +246 -0
- package/substrate/standards/bassclef-configs-schema.md +232 -0
- package/substrate/standards/bassclef-evolution.md +143 -0
- package/substrate/standards/bassclef-internal-jargon.md +244 -0
- package/substrate/standards/bassclef-managed-sentinel.md +96 -0
- package/substrate/standards/bassclef-source-config.md +228 -0
- package/substrate/standards/branch-stacking.md +408 -0
- package/substrate/standards/code-safety-principles.md +176 -0
- package/substrate/standards/composer-prerequisites.md +155 -0
- package/substrate/standards/deferred-actions-schema.md +204 -0
- package/substrate/standards/dependency-discipline/cargo.md +39 -0
- package/substrate/standards/dependency-discipline/gem.md +43 -0
- package/substrate/standards/dependency-discipline/go-mod.md +41 -0
- package/substrate/standards/dependency-discipline/npm.md +42 -0
- package/substrate/standards/dependency-discipline/pip.md +42 -0
- package/substrate/standards/deployment-topology/ec2-tailscale.md +225 -0
- package/substrate/standards/deployment-topology.md +69 -0
- package/substrate/standards/docs-sync-allowlist.md +76 -0
- package/substrate/standards/domain-and-dns.md +145 -0
- package/substrate/standards/frontend-stack.md +67 -0
- package/substrate/standards/frontmatter-schema.md +154 -0
- package/substrate/standards/graceful-exit.md +227 -0
- package/substrate/standards/hook-idempotency.md +102 -0
- package/substrate/standards/hook-injection-discipline.md +202 -0
- package/substrate/standards/hook-install-class.md +215 -0
- package/substrate/standards/input-handler-interface.md +152 -0
- package/substrate/standards/lite-manifest-schema-changes.md +135 -0
- package/substrate/standards/luminary-matching.md +105 -0
- package/substrate/standards/luminary-problem-patterns.md +481 -0
- package/substrate/standards/migration-discipline/active-record.md +50 -0
- package/substrate/standards/migration-discipline/alembic.md +43 -0
- package/substrate/standards/migration-discipline/gorm.md +50 -0
- package/substrate/standards/migration-discipline/prisma.md +53 -0
- package/substrate/standards/migration-discipline/sqlalchemy.md +51 -0
- package/substrate/standards/mobile-ephemeral-session.md +167 -0
- package/substrate/standards/model-routing-discipline.md +160 -0
- package/substrate/standards/ogilvy-writing-rules.md +225 -0
- package/substrate/standards/opener-discipline.md +96 -0
- package/substrate/standards/operator-facing-prose-discipline.md +201 -0
- package/substrate/standards/persona-schema.md +229 -0
- package/substrate/standards/pluggable-luminaries.md +323 -0
- package/substrate/standards/pr-body-discipline.md +115 -0
- package/substrate/standards/preview-state-schema.md +189 -0
- package/substrate/standards/project-directory-layout.md +276 -0
- package/substrate/standards/release-tagging.md +137 -0
- package/substrate/standards/reserved-skill-names.md +120 -0
- package/substrate/standards/scannable-multi-option-output.md +261 -0
- package/substrate/standards/sdlc-compliance.md +286 -0
- package/substrate/standards/sdlc-gates/typescript.md +57 -0
- package/substrate/standards/secrets-lifecycle.md +210 -0
- package/substrate/standards/security-scanner-adapter.md +145 -0
- package/substrate/standards/session-board.md +256 -0
- package/substrate/standards/skill-output-discipline.md +90 -0
- package/substrate/standards/state-spine-contract.md +255 -0
- package/substrate/standards/state-spine.md +511 -0
- package/substrate/standards/steering-hints/kiss-words.md +11 -0
- package/substrate/standards/substrate-config-schema.md +267 -0
- package/substrate/standards/tech-stack-config.md +109 -0
- package/substrate/standards/tier-dependency-analysis.md +167 -0
- package/substrate/standards/tier-runtime-deps/lite.md +57 -0
- package/substrate/standards/tier-tag-schema.md +155 -0
- package/substrate/standards/two-layer-config.md +99 -0
- package/substrate/standards/use-case-format.md +292 -0
- package/substrate/standards/user-story-invest.md +268 -0
- package/substrate/standards/velocity-and-appetite.md +229 -0
- package/substrate/standards/voice-input-pattern.md +119 -0
- package/substrate/standards/whereami-schema.md +301 -0
- package/substrate/standards/worktree-management.md +211 -0
- package/substrate/standards/writing-guide.md +213 -0
- package/substrate/templates/chronicle-template.md +75 -0
- package/substrate/templates/deferred-action-template.md +45 -0
- package/substrate/templates/memory-proposal-template.md +77 -0
- package/substrate/templates/persona-template.md +200 -0
- package/substrate/templates/pr-faq.md +45 -0
- package/substrate/templates/secret-rotation-template.md +162 -0
- package/substrate/templates/spec-template.md +131 -0
- package/substrate/templates/use-case-template.md +194 -0
- package/substrate/templates/user-story-template.md +107 -0
- package/substrate/templates/whereami-template.md +101 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# install-class: project
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
# Observable failure trap — closes bassclef-upstream#1075 (silent-stderr class).
|
|
7
|
+
# Under `set -e`, any command failure exits the shell without printing.
|
|
8
|
+
# The harness reports "No stderr output" and the agent cannot self-diagnose.
|
|
9
|
+
# This trap emits filename + line + exit code + failing command to stderr
|
|
10
|
+
# BEFORE the shell exits, so the failure is observable.
|
|
11
|
+
# Per .claude/rules/defensive-bash.md discipline 4 (extended for observable failure).
|
|
12
|
+
trap '_ec=$?; if [ "$_ec" -ne 0 ]; then echo "pre-commit-gate.sh: FAIL at line $LINENO: exit $_ec (command: $BASH_COMMAND)" >&2; fi' ERR
|
|
13
|
+
|
|
14
|
+
# Pre-Commit Gate — fires on Bash PreToolUse for git commit commands.
|
|
15
|
+
# Requires visible verification evidence before committing.
|
|
16
|
+
# Checks: feature branch, source files without tests, UI usability.
|
|
17
|
+
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
# Malformed JSON → jq exits non-zero; fail-soft to empty COMMAND so the
|
|
20
|
+
# next branch (non-commit skip) fires. Hardened under WU-2a per
|
|
21
|
+
# bassclef#1101 + bassclef#1098 sufficiency rubric criterion 6
|
|
22
|
+
# (stdin contract). Previously crashed harness commit calls on malformed
|
|
23
|
+
# stdin (exit 5 from jq).
|
|
24
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null || echo "")
|
|
25
|
+
|
|
26
|
+
# Only fire on git commit commands
|
|
27
|
+
if ! echo "$COMMAND" | grep -q 'git commit'; then
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Trace log
|
|
32
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
33
|
+
source "$SCRIPT_DIR/trace-helper.sh"
|
|
34
|
+
trace_log "pre-commit" "git commit"
|
|
35
|
+
|
|
36
|
+
# --- CCF-3 operator-path guard (bassclef#740) ---
|
|
37
|
+
# Reject commits adding absolute paths matching /Users/<name> or /home/<name>
|
|
38
|
+
# in non-exempt locations. Operator-specific paths must live in
|
|
39
|
+
# .claude/settings.local.json (gitignored), not in shared substrate.
|
|
40
|
+
# Per handoff spec from 2026-05-23 cold-adopter run (PR #735, F70).
|
|
41
|
+
# Exempt: rules/hooks/skills/standards/docs/strategy/chronicle/scripts/tests
|
|
42
|
+
# (places where the policy itself is documented or test fixtures live).
|
|
43
|
+
# Override: SKIP_OPERATOR_PATHS=1 git commit (logged via trace-helper)
|
|
44
|
+
if [ "${SKIP_OPERATOR_PATHS:-0}" != "1" ]; then
|
|
45
|
+
STAGED_NONEXEMPT=$(git diff --cached --name-only --diff-filter=AM 2>/dev/null | \
|
|
46
|
+
grep -vE '^\.claude/(rules|hooks|skills|luminaries|agents)/' | \
|
|
47
|
+
grep -vE '^standards/' | \
|
|
48
|
+
grep -vE '^architecture/' | \
|
|
49
|
+
grep -vE '^design/' | \
|
|
50
|
+
grep -vE '^docs/' | \
|
|
51
|
+
grep -vE '^chronicle/' | \
|
|
52
|
+
grep -vE '^strategy/' | \
|
|
53
|
+
grep -vE '^scripts/tests/' || true)
|
|
54
|
+
if [ -n "$STAGED_NONEXEMPT" ]; then
|
|
55
|
+
LEAKED=""
|
|
56
|
+
while IFS= read -r f; do
|
|
57
|
+
[ -z "$f" ] && continue
|
|
58
|
+
[ ! -f "$f" ] && continue
|
|
59
|
+
MATCHES=$(grep -nE '/Users/[A-Za-z0-9_.-]+|/home/[A-Za-z0-9_.-]+' "$f" 2>/dev/null || true)
|
|
60
|
+
if [ -n "$MATCHES" ]; then
|
|
61
|
+
LEAKED="${LEAKED}
|
|
62
|
+
${f}:
|
|
63
|
+
${MATCHES}
|
|
64
|
+
"
|
|
65
|
+
fi
|
|
66
|
+
done <<< "$STAGED_NONEXEMPT"
|
|
67
|
+
if [ -n "$LEAKED" ]; then
|
|
68
|
+
# Wrapped in { ...; } >&2 per bassclef-upstream#1229 cure so BLOCK
|
|
69
|
+
# message reaches the agent via Claude Code's PreToolUse error path.
|
|
70
|
+
# Matches sibling scrub-hook convention (pre-gh-pseudonym-scrub.sh
|
|
71
|
+
# L204-225, pre-gh-sibling-repo-scrub.sh L212-233).
|
|
72
|
+
{
|
|
73
|
+
echo ""
|
|
74
|
+
echo "============================================"
|
|
75
|
+
echo "BLOCKED: operator path in committed file (CCF-3)"
|
|
76
|
+
echo "============================================"
|
|
77
|
+
echo "$LEAKED"
|
|
78
|
+
echo ""
|
|
79
|
+
echo "Operator-specific paths (/Users/<name>, /home/<name>) must NOT ship"
|
|
80
|
+
echo "in shared substrate. Move to .claude/settings.local.json (gitignored)."
|
|
81
|
+
echo "Policy: standards/two-layer-config.md (bassclef#740)"
|
|
82
|
+
echo ""
|
|
83
|
+
echo "Override: SKIP_OPERATOR_PATHS=1 git commit (logged, use sparingly)"
|
|
84
|
+
echo "Silence is not deferral — see .claude/rules/blocked-items.md"
|
|
85
|
+
echo "============================================"
|
|
86
|
+
} >&2
|
|
87
|
+
exit 2
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# --- Testing-tier enforcement (bassclef#1037) ---
|
|
93
|
+
# Per-path tier check: Tier 0 BLOCKs when sibling test mtime did not advance
|
|
94
|
+
# with the source. Tier 1 WARNs. Tier 2/3 silent. Allowlist grace baseline
|
|
95
|
+
# at .claude/hooks/testing-tier-enforce-allowlist.txt covers existing untested
|
|
96
|
+
# bassclef surfaces for 60d. Override: SKIP_TESTING_TIER_ENFORCE=1.
|
|
97
|
+
if [ -x "$SCRIPT_DIR/testing-tier-enforce.sh" ]; then
|
|
98
|
+
if ! "$SCRIPT_DIR/testing-tier-enforce.sh"; then
|
|
99
|
+
# Hook BLOCKed with structured stderr message. Propagate exit.
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# --- Cold-adopter harness fast-path (bassclef-upstream#350, bet 25h WU-2) ---
|
|
105
|
+
# When staged changes touch substrate-affecting paths per
|
|
106
|
+
# .claude/rules/cold-adopter-harness-discipline.md § "When this rule fires",
|
|
107
|
+
# run the cold-adopter harness in fast mode (structural-only) to catch
|
|
108
|
+
# adopter-observable regressions at commit time. The PR-CI job (bet 25g WU-2)
|
|
109
|
+
# remains the required PR-time enforcement; this hook is the operator-side
|
|
110
|
+
# fast-fail layer per Saltzer-Schroeder complete mediation.
|
|
111
|
+
#
|
|
112
|
+
# Override: SKIP_COLD_ADOPTER_HARNESS=1 git commit (logged via trace-helper)
|
|
113
|
+
if [ "${SKIP_COLD_ADOPTER_HARNESS:-0}" != "1" ]; then
|
|
114
|
+
# The 12-pattern matcher mirrors .claude/rules/cold-adopter-harness-discipline.md
|
|
115
|
+
# § "When this rule fires". Keep these patterns in sync; a future WU may
|
|
116
|
+
# centralize the list via a sourced library function.
|
|
117
|
+
STAGED_SUBSTRATE=$(git diff --cached --name-only --diff-filter=AM 2>/dev/null | grep -E \
|
|
118
|
+
-e '^\.claude/hooks/[^/]+\.sh$' \
|
|
119
|
+
-e '^\.claude/skills/[^/]+/SKILL\.md$' \
|
|
120
|
+
-e '^\.claude/rules/[^/]+\.md$' \
|
|
121
|
+
-e '^\.claude/agents/[^/]+\.md$' \
|
|
122
|
+
-e '^\.claude/luminaries/[^/]+\.md$' \
|
|
123
|
+
-e '^lib/[^/]+\.sh$' \
|
|
124
|
+
-e '^standards/[^/]+\.md$' \
|
|
125
|
+
-e '^standards/state-spine/schemas/[^/]+\.json$' \
|
|
126
|
+
-e '^presence/install/bassclef-sync\..*\.sh$' \
|
|
127
|
+
-e '^architecture/decisions/ADR-.*\.md$' \
|
|
128
|
+
-e '^\.github/workflows/bassclef-.*\.yml$' \
|
|
129
|
+
-e '^scripts/[^/]+\.sh$' \
|
|
130
|
+
|| true)
|
|
131
|
+
if [ -n "$STAGED_SUBSTRATE" ]; then
|
|
132
|
+
# Default to scripts/cold-adopter-harness-sync.sh relative to this hook's
|
|
133
|
+
# location; tests override via BASSCLEF_HARNESS_PATH env var.
|
|
134
|
+
HARNESS_PATH="${BASSCLEF_HARNESS_PATH:-$SCRIPT_DIR/../../scripts/cold-adopter-harness-sync.sh}"
|
|
135
|
+
if [ -x "$HARNESS_PATH" ]; then
|
|
136
|
+
trace_log "pre-commit" "cold-adopter harness fast-path firing"
|
|
137
|
+
HARNESS_RC=0
|
|
138
|
+
bash "$HARNESS_PATH" --mode structural --target . >/dev/null 2>&1 || HARNESS_RC=$?
|
|
139
|
+
if [ "$HARNESS_RC" != "0" ]; then
|
|
140
|
+
# Wrapped in { ...; } >&2 per bassclef-upstream#1229 cure so BLOCK
|
|
141
|
+
# message reaches the agent via Claude Code's PreToolUse error path.
|
|
142
|
+
{
|
|
143
|
+
echo ""
|
|
144
|
+
echo "============================================"
|
|
145
|
+
echo "BLOCKED: cold-adopter harness fast-path"
|
|
146
|
+
echo "============================================"
|
|
147
|
+
echo "Substrate-affecting paths staged:"
|
|
148
|
+
echo "$STAGED_SUBSTRATE" | sed 's/^/ /'
|
|
149
|
+
echo ""
|
|
150
|
+
echo "Cold-adopter harness exited with code $HARNESS_RC."
|
|
151
|
+
echo ""
|
|
152
|
+
echo "Run for diagnostic output:"
|
|
153
|
+
echo " bash scripts/cold-adopter-harness-sync.sh --mode structural --target ."
|
|
154
|
+
echo ""
|
|
155
|
+
echo "Override (logged via trace-helper):"
|
|
156
|
+
echo " SKIP_COLD_ADOPTER_HARNESS=1 git commit"
|
|
157
|
+
echo ""
|
|
158
|
+
echo "Discipline: .claude/rules/cold-adopter-harness-discipline.md"
|
|
159
|
+
echo "Standard: \`standards/cold-adopter-harness.md\` (standard tier)"
|
|
160
|
+
echo "Silence is not deferral (see .claude/rules/blocked-items.md)."
|
|
161
|
+
echo "============================================"
|
|
162
|
+
} >&2
|
|
163
|
+
exit 2
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
fi
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
# --- Lead-lens sign-off 3-marker gate (bet 24a Step 2b; closes #836) ---
|
|
170
|
+
# Substrate-affecting paths staged? Require three markers before commit:
|
|
171
|
+
# state/markers/pre-mortem/<branch-slug>.marker
|
|
172
|
+
# state/markers/luminary/<branch-slug>.marker (with 'lead:' field)
|
|
173
|
+
# state/markers/lead-lens-signoff/<branch-slug>.marker
|
|
174
|
+
# Discipline lives in .claude/rules/loop-discipline.md Step 0.5 + 2a + 5.5.
|
|
175
|
+
# Override: SKIP_LEAD_LENS_SIGNOFF=1 git commit (logged via trace-helper)
|
|
176
|
+
if [ "${SKIP_LEAD_LENS_SIGNOFF:-0}" != "1" ]; then
|
|
177
|
+
# Reuse the substrate-affecting matcher shape from cold-adopter fast-path.
|
|
178
|
+
STAGED_SUBSTRATE_LL=$(git diff --cached --name-only --diff-filter=AM 2>/dev/null | grep -E \
|
|
179
|
+
-e '^\.claude/hooks/[^/]+\.sh$' \
|
|
180
|
+
-e '^\.claude/skills/[^/]+/SKILL\.md$' \
|
|
181
|
+
-e '^\.claude/rules/[^/]+\.md$' \
|
|
182
|
+
-e '^\.claude/agents/[^/]+\.md$' \
|
|
183
|
+
-e '^\.claude/luminaries/[^/]+\.md$' \
|
|
184
|
+
-e '^lib/[^/]+\.sh$' \
|
|
185
|
+
-e '^standards/[^/]+\.md$' \
|
|
186
|
+
-e '^standards/state-spine/schemas/[^/]+\.json$' \
|
|
187
|
+
-e '^presence/install/bassclef-sync\..*\.sh$' \
|
|
188
|
+
-e '^architecture/decisions/ADR-.*\.md$' \
|
|
189
|
+
-e '^\.github/workflows/bassclef-.*\.yml$' \
|
|
190
|
+
-e '^scripts/[^/]+\.sh$' \
|
|
191
|
+
|| true)
|
|
192
|
+
if [ -n "$STAGED_SUBSTRATE_LL" ]; then
|
|
193
|
+
LL_BRANCH_SLUG=$(git branch --show-current 2>/dev/null | tr '/' '-')
|
|
194
|
+
PREM_M="state/markers/pre-mortem/${LL_BRANCH_SLUG}.marker"
|
|
195
|
+
LUM_M="state/markers/luminary/${LL_BRANCH_SLUG}.marker"
|
|
196
|
+
SIGN_M="state/markers/lead-lens-signoff/${LL_BRANCH_SLUG}.marker"
|
|
197
|
+
|
|
198
|
+
LL_MISSING=""
|
|
199
|
+
if [ ! -f "$PREM_M" ]; then
|
|
200
|
+
LL_MISSING="${LL_MISSING} - pre-mortem marker missing at $PREM_M\n"
|
|
201
|
+
fi
|
|
202
|
+
if [ ! -f "$LUM_M" ]; then
|
|
203
|
+
LL_MISSING="${LL_MISSING} - luminary marker missing at $LUM_M\n"
|
|
204
|
+
elif ! grep -qE '^[[:space:]]*-[[:space:]]*lead[^a-zA-Z0-9_]' "$LUM_M"; then
|
|
205
|
+
# Accept: "- lead:", "- lead (goal-level):", "- lead luminary:", "- lead-luminary:"
|
|
206
|
+
# Reject: "- leader:" (word-boundary check), "- date:", any line without "lead" after dash
|
|
207
|
+
LL_MISSING="${LL_MISSING} - luminary marker at $LUM_M missing lead field (expected line starting with dash lead followed by colon or modifier)\n"
|
|
208
|
+
fi
|
|
209
|
+
if [ ! -f "$SIGN_M" ]; then
|
|
210
|
+
LL_MISSING="${LL_MISSING} - lead-lens sign-off marker missing at $SIGN_M\n"
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
if [ -n "$LL_MISSING" ]; then
|
|
214
|
+
trace_log "pre-commit" "lead-lens 3-marker gate BLOCKED"
|
|
215
|
+
# Wrapped in { ...; } >&2 per bassclef-upstream#1229 cure so BLOCK
|
|
216
|
+
# message reaches the agent via Claude Code's PreToolUse error path.
|
|
217
|
+
# Prior to cure: this exact block fired 3 times in ~1 week (08-12a,
|
|
218
|
+
# 08-12d, 08-15c); agent saw "No stderr output" and bypassed via
|
|
219
|
+
# python subprocess, masking the actual discipline miss.
|
|
220
|
+
{
|
|
221
|
+
echo ""
|
|
222
|
+
echo "============================================"
|
|
223
|
+
echo "BLOCKED: lead-lens sign-off 3-marker gate (bet 24a / #836)"
|
|
224
|
+
echo "============================================"
|
|
225
|
+
echo "Substrate-affecting paths staged:"
|
|
226
|
+
echo "$STAGED_SUBSTRATE_LL" | sed 's/^/ /'
|
|
227
|
+
echo ""
|
|
228
|
+
echo "Missing:"
|
|
229
|
+
echo -e "$LL_MISSING"
|
|
230
|
+
echo "Discipline: .claude/rules/loop-discipline.md Step 0.5 + Step 2a + Step 5.5"
|
|
231
|
+
echo ""
|
|
232
|
+
echo "Cure — touch each missing marker with body content per marker-enrichment-discipline:"
|
|
233
|
+
echo " mkdir -p state/markers/pre-mortem state/markers/luminary state/markers/lead-lens-signoff"
|
|
234
|
+
echo " # write body content per rule Step 0.5 + 2a + 5.5"
|
|
235
|
+
echo ""
|
|
236
|
+
echo "Override (logged via trace-helper):"
|
|
237
|
+
echo " SKIP_LEAD_LENS_SIGNOFF=1 git commit"
|
|
238
|
+
echo ""
|
|
239
|
+
echo "Silence is not deferral — see .claude/rules/blocked-items.md"
|
|
240
|
+
echo "============================================"
|
|
241
|
+
} >&2
|
|
242
|
+
exit 2
|
|
243
|
+
fi
|
|
244
|
+
fi
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# --- Feature branch enforcement ---
|
|
248
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
|
|
249
|
+
WARNINGS=""
|
|
250
|
+
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
|
|
251
|
+
WARNINGS="${WARNINGS}COMMITTING DIRECTLY TO MAIN — use a feature branch and PR instead.\n"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
# --- Check staged source files for matching test files ---
|
|
255
|
+
STAGED_SOURCE_FILES=$(git diff --cached --name-only --diff-filter=AM -- 'src/lib/*.ts' 'src/agents/*.ts' 'src/app/api/**/*.ts' 2>/dev/null || true)
|
|
256
|
+
if [ -n "$STAGED_SOURCE_FILES" ]; then
|
|
257
|
+
while IFS= read -r srcfile; do
|
|
258
|
+
basename=$(basename "$srcfile" .ts)
|
|
259
|
+
case "$basename" in
|
|
260
|
+
prisma|redis|queue|auth|langfuse|secrets|index) continue ;;
|
|
261
|
+
esac
|
|
262
|
+
if echo "$srcfile" | grep -q 'src/app/api/'; then
|
|
263
|
+
if [ ! -f "src/__tests__/api-routes.test.ts" ] && [ ! -f "src/__tests__/${basename}.test.ts" ]; then
|
|
264
|
+
WARNINGS="${WARNINGS}API ROUTE WITHOUT TEST: ${srcfile}\n"
|
|
265
|
+
fi
|
|
266
|
+
elif [ ! -f "src/__tests__/${basename}.test.ts" ]; then
|
|
267
|
+
WARNINGS="${WARNINGS}SOURCE FILE WITHOUT TEST: ${srcfile} → expected src/__tests__/${basename}.test.ts\n"
|
|
268
|
+
fi
|
|
269
|
+
done <<< "$STAGED_SOURCE_FILES"
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
# --- /verify evidence check (MUST gate) ---
|
|
273
|
+
# Emit BLOCKED: /verify when source files are staged without verify evidence.
|
|
274
|
+
# Checks both /tmp (desktop) and state/markers/verify/ (ephemeral-safe).
|
|
275
|
+
# Per bassclef#342: markers relocated from .claude/verify-markers/ to
|
|
276
|
+
# state/markers/verify/ (rulebook-vs-log drawer separation).
|
|
277
|
+
# blocked-items.md rule requires resolve-or-explicit-defer.
|
|
278
|
+
STAGED_SOURCE=$(git diff --cached --name-only --diff-filter=AM -- 'src/**/*.ts' 'src/**/*.tsx' 'src/**/*.js' 'scripts/**/*.ts' 2>/dev/null | head -5)
|
|
279
|
+
if [ -n "$STAGED_SOURCE" ]; then
|
|
280
|
+
BRANCH_SLUG=$(git branch --show-current 2>/dev/null | tr '/' '-')
|
|
281
|
+
VERIFY_MARKER_TMP="/tmp/claude-verify-${BRANCH_SLUG}"
|
|
282
|
+
VERIFY_MARKER_GIT="state/markers/verify/${BRANCH_SLUG}.marker"
|
|
283
|
+
VERIFY_RECENT=0
|
|
284
|
+
NOW=$(date +%s)
|
|
285
|
+
|
|
286
|
+
# Check desktop marker
|
|
287
|
+
if [ -f "$VERIFY_MARKER_TMP" ]; then
|
|
288
|
+
AGE=$(( NOW - $(stat -f %m "$VERIFY_MARKER_TMP" 2>/dev/null || stat -c %Y "$VERIFY_MARKER_TMP" 2>/dev/null || echo 0) ))
|
|
289
|
+
[ "$AGE" -lt 300 ] && VERIFY_RECENT=1
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
# Check ephemeral-safe (git-tracked) marker
|
|
293
|
+
if [ "$VERIFY_RECENT" -eq 0 ] && [ -f "$VERIFY_MARKER_GIT" ]; then
|
|
294
|
+
AGE=$(( NOW - $(stat -f %m "$VERIFY_MARKER_GIT" 2>/dev/null || stat -c %Y "$VERIFY_MARKER_GIT" 2>/dev/null || echo 0) ))
|
|
295
|
+
[ "$AGE" -lt 300 ] && VERIFY_RECENT=1
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
if [ "$VERIFY_RECENT" -eq 0 ]; then
|
|
299
|
+
WARNINGS="${WARNINGS}BLOCKED: /verify — source files staged without recent verify evidence.\n"
|
|
300
|
+
WARNINGS="${WARNINGS} Run /verify BEFORE committing, or explicitly defer with rationale.\n"
|
|
301
|
+
WARNINGS="${WARNINGS} Silence is not deferral (see .claude/rules/blocked-items.md).\n"
|
|
302
|
+
WARNINGS="${WARNINGS} Checked: $VERIFY_MARKER_TMP and $VERIFY_MARKER_GIT (5-min freshness).\n"
|
|
303
|
+
fi
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
# --- Reserved skill names check (collision with Claude Code built-ins) ---
|
|
307
|
+
# See .claude/rules/reserved-skill-names.md + standards/reserved-skill-names.md
|
|
308
|
+
if [ "${SKIP_RESERVED_NAMES:-0}" != "1" ]; then
|
|
309
|
+
STAGED_NEW_SKILLS=$(git diff --cached --name-only --diff-filter=A -- '.claude/skills/*/SKILL.md' 2>/dev/null || true)
|
|
310
|
+
if [ -n "$STAGED_NEW_SKILLS" ]; then
|
|
311
|
+
# Extract reserved names from the standards table (Name column values inside backticks)
|
|
312
|
+
RESERVED_LIST=""
|
|
313
|
+
if [ -f "standards/reserved-skill-names.md" ]; then
|
|
314
|
+
RESERVED_LIST=$(grep -oE '`[a-z][a-z0-9-]+`' standards/reserved-skill-names.md | tr -d '`' | sort -u)
|
|
315
|
+
fi
|
|
316
|
+
if [ -n "$RESERVED_LIST" ]; then
|
|
317
|
+
while IFS= read -r skill_path; do
|
|
318
|
+
skill_name=$(echo "$skill_path" | sed -n 's|\.claude/skills/\([^/]*\)/SKILL\.md|\1|p')
|
|
319
|
+
if [ -n "$skill_name" ] && echo "$RESERVED_LIST" | grep -qx "$skill_name"; then
|
|
320
|
+
WARNINGS="${WARNINGS}BLOCKED: reserved skill name — \`$skill_name\` collides with a Claude Code built-in.\n"
|
|
321
|
+
WARNINGS="${WARNINGS} See standards/reserved-skill-names.md for the list.\n"
|
|
322
|
+
WARNINGS="${WARNINGS} Rename the skill directory, OR override with SKIP_RESERVED_NAMES=1 git commit.\n"
|
|
323
|
+
WARNINGS="${WARNINGS} Silence is not deferral (see .claude/rules/blocked-items.md).\n"
|
|
324
|
+
fi
|
|
325
|
+
done <<< "$STAGED_NEW_SKILLS"
|
|
326
|
+
fi
|
|
327
|
+
fi
|
|
328
|
+
fi
|
|
329
|
+
|
|
330
|
+
# --- Bassclef evolution check: methodology/config changes being committed ---
|
|
331
|
+
# Catches .claude/ changes AND settings/config changes that may be global
|
|
332
|
+
STAGED_CLAUDE=$(git diff --cached --name-only -- '.claude/skills/*' '.claude/rules/*' '.claude/hooks/*' '.claude/agents/*' 2>/dev/null | grep -v 'SESSION_LOCK\|LAST_SAVE' | head -5)
|
|
333
|
+
STAGED_CONFIG=$(git diff --cached --name-only -- 'settings.json' '.claude/settings.json' '*/settings.json' 'package.json' '.eslintrc*' 'tsconfig*.json' '.prettierrc*' '.env.example' 2>/dev/null | head -5)
|
|
334
|
+
|
|
335
|
+
if [ -n "$STAGED_CLAUDE" ] || [ -n "$STAGED_CONFIG" ]; then
|
|
336
|
+
ALL_METHOD_FILES="${STAGED_CLAUDE}${STAGED_CONFIG}"
|
|
337
|
+
WARNINGS="${WARNINGS}BASSCLEF EVOLUTION CHECK — is this local or global?\n"
|
|
338
|
+
if [ -n "$STAGED_CLAUDE" ]; then
|
|
339
|
+
WARNINGS="${WARNINGS} Substrate: $(echo "$STAGED_CLAUDE" | tr '\n' ', ')\n"
|
|
340
|
+
fi
|
|
341
|
+
if [ -n "$STAGED_CONFIG" ]; then
|
|
342
|
+
WARNINGS="${WARNINGS} Config: $(echo "$STAGED_CONFIG" | tr '\n' ', ')\n"
|
|
343
|
+
fi
|
|
344
|
+
WARNINGS="${WARNINGS} If this applies to ANY project → run /promote before committing.\n"
|
|
345
|
+
WARNINGS="${WARNINGS} If app-specific → proceed. If unsure → promote (cheaper to reject later).\n"
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
# --- Chronicle Gate Evidence enforcement (MUST gate, bassclef#298) ---
|
|
349
|
+
# Chronicles are the authoritative input for the 5-session gate-compliance
|
|
350
|
+
# counter. A chronicle without "## Gate Evidence" reads as "no data" in the
|
|
351
|
+
# counter, silencing the compliance signal (the failure mode that motivated
|
|
352
|
+
# this gate). Block commits to chronicle/*.md or docs/chronicle/*.md that
|
|
353
|
+
# lack the section. Override: SKIP_CHRONICLE_GATE_EVIDENCE=1 git commit.
|
|
354
|
+
if [ "${SKIP_CHRONICLE_GATE_EVIDENCE:-0}" != "1" ]; then
|
|
355
|
+
STAGED_CHRONICLES=$(git diff --cached --name-only --diff-filter=AM -- 'chronicle/*.md' 'docs/chronicle/*.md' 2>/dev/null || true)
|
|
356
|
+
# Source spine accessor library when available — preferred frontmatter
|
|
357
|
+
# check route per state-spine-contract.md. Graceful fallback for repos
|
|
358
|
+
# pre-spine-v0.
|
|
359
|
+
if [ -f "lib/state.sh" ]; then
|
|
360
|
+
# shellcheck source=/dev/null
|
|
361
|
+
source "lib/state.sh" 2>/dev/null || true
|
|
362
|
+
fi
|
|
363
|
+
if [ -n "$STAGED_CHRONICLES" ]; then
|
|
364
|
+
while IFS= read -r chronicle_path; do
|
|
365
|
+
[ -z "$chronicle_path" ] && continue
|
|
366
|
+
[ ! -f "$chronicle_path" ] && continue
|
|
367
|
+
# Two acceptance paths (transitional during bassclef#298 schema rollout):
|
|
368
|
+
# 1. Frontmatter `gates_fired` populated (future-default; spine schema)
|
|
369
|
+
# 2. Markdown body section `## Gate Evidence` (legacy; current chronicles)
|
|
370
|
+
HAS_EVIDENCE=0
|
|
371
|
+
if command -v state_chronicle_gate_evidence >/dev/null 2>&1; then
|
|
372
|
+
chronicle_id=$(basename "$chronicle_path" .md)
|
|
373
|
+
gates_json=$(state_chronicle_gate_evidence "$chronicle_id" 2>/dev/null || echo "[]")
|
|
374
|
+
if [ -n "$gates_json" ] && [ "$gates_json" != "[]" ] && [ "$gates_json" != "null" ]; then
|
|
375
|
+
HAS_EVIDENCE=1
|
|
376
|
+
fi
|
|
377
|
+
fi
|
|
378
|
+
# Accept either "## Gate Evidence" or "## Gate evidence" (both forms exist historically)
|
|
379
|
+
if [ "$HAS_EVIDENCE" = "0" ] && grep -qiE "^## Gate (E|e)vidence" "$chronicle_path"; then
|
|
380
|
+
HAS_EVIDENCE=1
|
|
381
|
+
fi
|
|
382
|
+
if [ "$HAS_EVIDENCE" = "0" ]; then
|
|
383
|
+
WARNINGS="${WARNINGS}BLOCKED: chronicle missing Gate Evidence — \`${chronicle_path}\`\n"
|
|
384
|
+
WARNINGS="${WARNINGS} Required: frontmatter \`gates_fired\` array OR \"## Gate Evidence\" body section.\n"
|
|
385
|
+
WARNINGS="${WARNINGS} Template: templates/chronicle-template.md\n"
|
|
386
|
+
WARNINGS="${WARNINGS} Standard: standards/sdlc-compliance.md §\"Gate Evidence Format\"\n"
|
|
387
|
+
WARNINGS="${WARNINGS} Override: SKIP_CHRONICLE_GATE_EVIDENCE=1 git commit (logged).\n"
|
|
388
|
+
WARNINGS="${WARNINGS} Silence is not deferral (see .claude/rules/blocked-items.md).\n"
|
|
389
|
+
fi
|
|
390
|
+
done <<< "$STAGED_CHRONICLES"
|
|
391
|
+
fi
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
# --- UI visual review enforcement (MUST gate) ---
|
|
395
|
+
STAGED_UI=$(git diff --cached --name-only -- 'src/app/**/page.tsx' 'src/components/**/*.tsx' '*.css' '*.scss' 2>/dev/null | head -5)
|
|
396
|
+
if [ -n "$STAGED_UI" ]; then
|
|
397
|
+
# Check for visual review evidence
|
|
398
|
+
TODAY=$(date +%Y-%m-%d)
|
|
399
|
+
VISUAL_REVIEWS=$(git diff --cached --name-only -- 'docs/visual-reviews/*.md' 2>/dev/null || true)
|
|
400
|
+
RECENT_REVIEWS=$(find docs/visual-reviews/ -name "${TODAY}*" -type f 2>/dev/null | head -1)
|
|
401
|
+
if [ -z "$VISUAL_REVIEWS" ] && [ -z "$RECENT_REVIEWS" ]; then
|
|
402
|
+
WARNINGS="${WARNINGS}VISUAL REVIEW REQUIRED — UI change detected but no visual review report found.\n"
|
|
403
|
+
WARNINGS="${WARNINGS} Run /visual-review on every page touched BEFORE committing.\n"
|
|
404
|
+
WARNINGS="${WARNINGS} Report goes to: docs/visual-reviews/${TODAY}-{page-name}.md\n"
|
|
405
|
+
WARNINGS="${WARNINGS} This is a MUST gate for UI changes. See /verify.\n"
|
|
406
|
+
fi
|
|
407
|
+
WARNINGS="${WARNINGS}UI CHANGE — usability checklist:\n"
|
|
408
|
+
WARNINGS="${WARNINGS} Role check | Scanning distance | Jargon | Attribution | Accessibility\n"
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
# --- Output warnings if any ---
|
|
412
|
+
if [ -n "$WARNINGS" ]; then
|
|
413
|
+
echo ""
|
|
414
|
+
echo "============================================"
|
|
415
|
+
echo "TESTING CHECKS"
|
|
416
|
+
echo "============================================"
|
|
417
|
+
echo -e "$WARNINGS"
|
|
418
|
+
echo "These are WARNINGs — address before merging."
|
|
419
|
+
echo "============================================"
|
|
420
|
+
echo ""
|
|
421
|
+
fi
|
|
422
|
+
|
|
423
|
+
cat <<'GATE'
|
|
424
|
+
============================================
|
|
425
|
+
PRE-COMMIT GATE — MANDATORY BEFORE COMMITTING
|
|
426
|
+
============================================
|
|
427
|
+
|
|
428
|
+
STOP. Your response MUST contain a visible verification section.
|
|
429
|
+
|
|
430
|
+
## Post-Build Verification (EACH task, not batched)
|
|
431
|
+
- Change type: [which row applies]
|
|
432
|
+
- Verification performed: [exact command(s) and output summary]
|
|
433
|
+
- Tests: [file + count, or "no testable logic"]
|
|
434
|
+
- Build: [passes / fails]
|
|
435
|
+
- Result: [pass/fail — if fail, do not commit]
|
|
436
|
+
|
|
437
|
+
| Change type | Minimum verification |
|
|
438
|
+
|------------------------------------|----------------------------------------------------|
|
|
439
|
+
| Pure function (scoring, parsing) | Unit test passes for that function |
|
|
440
|
+
| Worker / agent / queue | Boot the worker + process at least one real job |
|
|
441
|
+
| API route | Hit the endpoint, verify response |
|
|
442
|
+
| Schema migration | Verify column exists, Prisma client regenerated |
|
|
443
|
+
| Middleware / auth | Protected routes AND existing routes still work |
|
|
444
|
+
| Docs / config only | N/A — state "docs/config only" |
|
|
445
|
+
|
|
446
|
+
New pure function or utility? → Write test BEFORE committing.
|
|
447
|
+
"Will add tests later" is never acceptable.
|
|
448
|
+
============================================
|
|
449
|
+
GATE
|
|
450
|
+
|
|
451
|
+
exit 0
|