@thebassclef/lite 1.0.3 → 1.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/dist/cli.cjs +92 -6
- package/dist/cli.js +92 -6
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lite/.claude/agents/architect.md +70 -0
- package/dist/lite/.claude/agents/builder.md +114 -0
- package/dist/lite/.claude/agents/designer.md +156 -0
- package/dist/lite/.claude/agents/reviewer.md +88 -0
- package/dist/lite/.claude/hooks/bassclef-sync.sh +85 -27
- package/dist/lite/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
- package/dist/lite/.claude/hooks/longrun-prep-render-check.sh +236 -0
- package/dist/lite/.claude/hooks/persona-name-scrub-check.sh +105 -0
- package/dist/lite/.claude/hooks/skill-step-list-check.sh +171 -0
- package/dist/lite/.claude/luminaries/alan-cooper.md +170 -0
- package/dist/lite/.claude/luminaries/alistair-cockburn.md +140 -0
- package/dist/lite/.claude/luminaries/amazon-pr-faq.md +34 -0
- package/dist/lite/.claude/luminaries/andreas-zeller.md +74 -0
- package/dist/lite/.claude/luminaries/ash-maurya.md +121 -0
- package/dist/lite/.claude/luminaries/bill-buxton.md +210 -0
- package/dist/lite/.claude/luminaries/charles-sanders-peirce.md +150 -0
- package/dist/lite/.claude/luminaries/david-ogilvy.md +192 -0
- package/dist/lite/.claude/luminaries/don-norman.md +173 -0
- package/dist/lite/.claude/luminaries/edward-tufte.md +179 -0
- package/dist/lite/.claude/luminaries/eric-evans.md +160 -0
- package/dist/lite/.claude/luminaries/frederick-brooks.md +50 -0
- package/dist/lite/.claude/luminaries/gang-of-four.md +157 -0
- package/dist/lite/.claude/luminaries/glenford-myers.md +230 -0
- package/dist/lite/.claude/luminaries/hunt-thomas.md +115 -0
- package/dist/lite/.claude/luminaries/hyrum-wright.md +94 -0
- package/dist/lite/.claude/luminaries/jason-fried-dhh.md +46 -0
- package/dist/lite/.claude/luminaries/jesse-james-garrett.md +154 -0
- package/dist/lite/.claude/luminaries/john-ousterhout.md +94 -0
- package/dist/lite/.claude/luminaries/karl-popper.md +132 -0
- package/dist/lite/.claude/luminaries/kent-beck.md +168 -0
- package/dist/lite/.claude/luminaries/linus-torvalds.md +218 -0
- package/dist/lite/.claude/luminaries/martin-fowler.md +164 -0
- package/dist/lite/.claude/luminaries/michael-feathers.md +125 -0
- package/dist/lite/.claude/luminaries/michael-nygard.md +118 -0
- package/dist/lite/.claude/luminaries/robert-c-martin.md +164 -0
- package/dist/lite/.claude/luminaries/saltzer-schroeder.md +194 -0
- package/dist/lite/.claude/luminaries/sophia-prater.md +193 -0
- package/dist/lite/.claude/luminaries/stephen-toulmin.md +131 -0
- package/dist/lite/.claude/luminaries/tony-hoare.md +170 -0
- package/dist/lite/.claude/luminaries/vaughn-vernon.md +50 -0
- package/dist/lite/.claude/luminaries/w-edwards-deming.md +158 -0
- package/dist/lite/.claude/rules/accessor-library-discipline.md +110 -0
- package/dist/lite/.claude/rules/adr-discipline.md +96 -0
- package/dist/lite/.claude/rules/api-conventions.md +115 -0
- package/dist/lite/.claude/rules/artifact-ingestion.md +137 -0
- package/dist/lite/.claude/rules/assert-only-after-verify.md +111 -0
- package/dist/lite/.claude/rules/blocked-items.md +139 -0
- package/dist/lite/.claude/rules/bootstrap-pair-discipline.md +106 -0
- package/dist/lite/.claude/rules/branching.md +28 -0
- package/dist/lite/.claude/rules/cold-adopter-harness-discipline.md +93 -0
- package/dist/lite/.claude/rules/commit-conventions.md +22 -0
- package/dist/lite/.claude/rules/compounding-axis-fresh-analysis.md +173 -0
- package/dist/lite/.claude/rules/compounding-sequence-fresh-analysis.md +173 -0
- package/dist/lite/.claude/rules/context-engineering.md +155 -0
- package/dist/lite/.claude/rules/context-management.md +85 -0
- package/dist/lite/.claude/rules/defensive-bash.md +52 -0
- package/dist/lite/.claude/rules/deferred-actions.md +233 -0
- package/dist/lite/.claude/rules/destructive-operations.md +69 -0
- package/dist/lite/.claude/rules/diagnosis.md +38 -0
- package/dist/lite/.claude/rules/github-issue-flash-tweet.md +114 -0
- package/dist/lite/.claude/rules/guardrails.md +73 -0
- package/dist/lite/.claude/rules/hook-wire-on-author.md +77 -0
- package/dist/lite/.claude/rules/identifier-leak-prevention.md +73 -0
- package/dist/lite/.claude/rules/iteration-bet-brief-completeness.md +43 -0
- package/dist/lite/.claude/rules/lite-manifest-schema-change-discipline.md +79 -0
- package/dist/lite/.claude/rules/longrun-prep-plan-doc-compression.md +77 -0
- package/dist/lite/.claude/rules/loop-discipline.md +71 -0
- package/dist/lite/.claude/rules/manual-prod-approval.md +100 -0
- package/dist/lite/.claude/rules/marker-enrichment-discipline.md +72 -0
- package/dist/lite/.claude/rules/mobile-ephemeral-session.md +109 -0
- package/dist/lite/.claude/rules/new-dependency-check.md +44 -0
- package/dist/lite/.claude/rules/oo-ad-entry-point.md +95 -0
- package/dist/lite/.claude/rules/operator-facing-prose.md +177 -0
- package/dist/lite/.claude/rules/option-label-discipline.md +82 -0
- package/dist/lite/.claude/rules/pattern-annotation.md +83 -0
- package/dist/lite/.claude/rules/persona-name-leak-scrub.md +90 -0
- package/dist/lite/.claude/rules/plain-english-discipline.md +132 -0
- package/dist/lite/.claude/rules/plan-enumeration-needs-value-props.md +177 -0
- package/dist/lite/.claude/rules/pr-body-shape.md +195 -0
- package/dist/lite/.claude/rules/pr-strategy.md +142 -0
- package/dist/lite/.claude/rules/pr-title-shape.md +90 -0
- package/dist/lite/.claude/rules/prototype-workflow.md +53 -0
- package/dist/lite/.claude/rules/reserved-skill-names.md +103 -0
- package/dist/lite/.claude/rules/schema-management.md +42 -0
- package/dist/lite/.claude/rules/sdlc-gates.md +149 -0
- package/dist/lite/.claude/rules/security.md +37 -0
- package/dist/lite/.claude/rules/session-artifacts.md +236 -0
- package/dist/lite/.claude/rules/skill-composition-declarations.md +105 -0
- package/dist/lite/.claude/rules/skill-description-clarity.md +196 -0
- package/dist/lite/.claude/rules/skill-procedure-step-list.md +119 -0
- package/dist/lite/.claude/rules/sprint-prep-preset-picker.md +76 -0
- package/dist/lite/.claude/rules/state-schema-validation.md +156 -0
- package/dist/lite/.claude/rules/stuck-signal-diagnostic.md +111 -0
- package/dist/lite/.claude/rules/substrate-config-schema.md +85 -0
- package/dist/lite/.claude/rules/test-list-discipline.md +129 -0
- package/dist/lite/.claude/rules/test-sufficiency.md +186 -0
- package/dist/lite/.claude/rules/testing-tier-config.md +125 -0
- package/dist/lite/.claude/rules/testing.md +38 -0
- package/dist/lite/.claude/rules/turn-estimate-grounding.md +82 -0
- package/dist/lite/.claude/rules/visual-hierarchy.md +427 -0
- package/dist/lite/.claude/rules/we-dont-break-adopters.md +103 -0
- package/dist/lite/.claude/rules/whereami-load-bearing.md +184 -0
- package/dist/lite/.claude/rules/writing-craft-discipline.md +72 -0
- package/dist/lite/.claude/rules/wu-sequencing-compounds.md +119 -0
- package/dist/lite/.claude/skills/build/SKILL.md +640 -0
- package/dist/lite/.claude/skills/chronicle/SKILL.md +55 -0
- package/dist/lite/.claude/skills/clean-artifacts/SKILL.md +249 -0
- package/dist/lite/.claude/skills/decompose/SKILL.md +280 -0
- package/dist/lite/.claude/skills/diagnose/SKILL.md +297 -0
- package/dist/lite/.claude/skills/feynman/SKILL.md +90 -0
- package/dist/lite/.claude/skills/howdoi/SKILL.md +105 -0
- package/dist/lite/.claude/skills/ia-model/SKILL.md +108 -0
- package/dist/lite/.claude/skills/interaction-design/SKILL.md +112 -0
- package/dist/lite/.claude/skills/interpret-input/SKILL.md +180 -0
- package/dist/lite/.claude/skills/journal/SKILL.md +209 -0
- package/dist/lite/.claude/skills/kiss/SKILL.md +449 -0
- package/dist/lite/.claude/skills/launch/SKILL.md +915 -0
- package/dist/lite/.claude/skills/lean-canvas/SKILL.md +332 -0
- package/dist/lite/.claude/skills/longrun/SKILL.md +512 -0
- package/dist/lite/.claude/skills/luminary/SKILL.md +481 -0
- package/dist/lite/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
- package/dist/lite/.claude/skills/onboard-repo/SKILL.md +1640 -0
- package/dist/lite/.claude/skills/pattern-review/SKILL.md +99 -0
- package/dist/lite/.claude/skills/personas/SKILL.md +207 -0
- package/dist/lite/.claude/skills/promote/SKILL.md +283 -0
- package/dist/lite/.claude/skills/requirement/SKILL.md +98 -0
- package/dist/lite/.claude/skills/retro/SKILL.md +117 -0
- package/dist/lite/.claude/skills/riff/SKILL.md +114 -0
- package/dist/lite/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
- package/dist/lite/.claude/skills/session-end/SKILL.md +309 -0
- package/dist/lite/.claude/skills/session-log/SKILL.md +299 -0
- package/dist/lite/.claude/skills/skills/SKILL.md +228 -0
- package/dist/lite/.claude/skills/spec/SKILL.md +105 -0
- package/dist/lite/.claude/skills/sprint/SKILL.md +418 -0
- package/dist/lite/.claude/skills/stage/SKILL.md +384 -0
- package/dist/lite/.claude/skills/state-a-problem/SKILL.md +185 -0
- package/dist/lite/.claude/skills/temperance/SKILL.md +108 -0
- package/dist/lite/.claude/skills/use-case/SKILL.md +417 -0
- package/dist/lite/.claude/skills/user-stories/SKILL.md +268 -0
- package/dist/lite/.claude/skills/value-prop/SKILL.md +251 -0
- package/dist/lite/.claude/skills/verify/SKILL.md +160 -0
- package/dist/lite/.claude/skills/visual-review/SKILL.md +503 -0
- package/dist/lite/.claude/skills/whats-the-plan/SKILL.md +202 -0
- package/dist/lite/.claude/skills/whereami/SKILL.md +307 -0
- package/dist/lite/AGENTS.md +79 -0
- package/dist/lite/CLAUDE-lite.md +85 -0
- package/dist/lite/CODE_OF_CONDUCT.md +28 -0
- package/dist/lite/CONTRIBUTING.md +177 -0
- package/dist/lite/README.md +173 -0
- package/dist/lite/SECURITY.md +19 -0
- package/dist/lite/architecture/decisions/ADR-029-release-pipeline.md +79 -0
- package/dist/lite/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
- package/dist/lite/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
- package/dist/lite/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
- package/dist/lite/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
- package/dist/lite/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
- package/dist/lite/lib/clean-artifacts-sweep.sh +112 -0
- package/dist/lite/lib/code-comment-discipline.sh +144 -0
- package/dist/lite/lib/composer-preflight.sh +459 -0
- package/dist/lite/lib/deferred-actions.sh +146 -0
- package/dist/lite/lib/hook-header-parser.sh +61 -0
- package/dist/lite/lib/hook-heartbeat.sh +152 -0
- package/dist/lite/lib/hook-inject.sh +255 -0
- package/dist/lite/lib/hook-installer.sh +195 -0
- package/dist/lite/lib/luminary-pick.sh +96 -0
- package/dist/lite/lib/output-discipline.sh +143 -0
- package/dist/lite/lib/prose-scan-boundary.sh +171 -0
- package/dist/lite/lib/rewrite-check.sh +214 -0
- package/dist/lite/lib/session-rescue.sh +151 -0
- package/dist/lite/lib/source-graph-walker.sh +277 -0
- package/dist/lite/lib/state.sh +1372 -0
- package/dist/lite/lib/telemetry.sh +205 -0
- package/dist/lite/lib/tier-check.sh +187 -0
- package/dist/lite/lib/tier-dependency-audit.sh +1088 -0
- package/dist/lite/presence/install/bassclef-hook-connect.sh +178 -0
- package/dist/lite/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
- package/dist/lite/presence/install/bassclef-sync.template.sh +2278 -0
- package/dist/lite/presence/install/schedule-auto-save.cron.sh +88 -0
- package/dist/lite/presence/install/schedule-auto-save.taskscheduler.md +122 -0
- package/dist/lite/scripts/aggregate-telemetry.sh +217 -0
- package/dist/lite/scripts/analyze-tier-dependencies.sh +239 -0
- package/dist/lite/scripts/generate-lite-manifest.sh +505 -0
- package/dist/lite/scripts/generate-tier-manifest.sh +28 -0
- package/dist/lite/scripts/intent-drift-check.sh +456 -0
- package/dist/lite/scripts/lite-manifest-drift-check.sh +146 -0
- package/dist/lite/scripts/render-lite-manifest-doc.sh +150 -0
- package/dist/lite/standards/adr-template.md +86 -0
- package/dist/lite/standards/api-conventions/nextjs.md +84 -0
- package/dist/lite/standards/artifact-composition.md +209 -0
- package/dist/lite/standards/bash-hook-safety.md +246 -0
- package/dist/lite/standards/bassclef-configs-schema.md +232 -0
- package/dist/lite/standards/bassclef-evolution.md +143 -0
- package/dist/lite/standards/bassclef-internal-jargon.md +244 -0
- package/dist/lite/standards/bassclef-managed-sentinel.md +96 -0
- package/dist/lite/standards/bassclef-source-config.md +228 -0
- package/dist/lite/standards/branch-stacking.md +408 -0
- package/dist/lite/standards/code-safety-principles.md +176 -0
- package/dist/lite/standards/composer-prerequisites.md +155 -0
- package/dist/lite/standards/deferred-actions-schema.md +204 -0
- package/dist/lite/standards/dependency-discipline/cargo.md +39 -0
- package/dist/lite/standards/dependency-discipline/gem.md +43 -0
- package/dist/lite/standards/dependency-discipline/go-mod.md +41 -0
- package/dist/lite/standards/dependency-discipline/npm.md +42 -0
- package/dist/lite/standards/dependency-discipline/pip.md +42 -0
- package/dist/lite/standards/deployment-topology/ec2-tailscale.md +225 -0
- package/dist/lite/standards/deployment-topology.md +69 -0
- package/dist/lite/standards/docs-sync-allowlist.md +76 -0
- package/dist/lite/standards/domain-and-dns.md +145 -0
- package/dist/lite/standards/frontend-stack.md +67 -0
- package/dist/lite/standards/frontmatter-schema.md +154 -0
- package/dist/lite/standards/graceful-exit.md +227 -0
- package/dist/lite/standards/hook-idempotency.md +102 -0
- package/dist/lite/standards/hook-injection-discipline.md +202 -0
- package/dist/lite/standards/hook-install-class.md +215 -0
- package/dist/lite/standards/input-handler-interface.md +152 -0
- package/dist/lite/standards/lite-manifest-schema-changes.md +180 -0
- package/dist/lite/standards/lite-manifest.json +2797 -0
- package/dist/lite/standards/luminary-matching.md +105 -0
- package/dist/lite/standards/luminary-problem-patterns.md +481 -0
- package/dist/lite/standards/migration-discipline/active-record.md +50 -0
- package/dist/lite/standards/migration-discipline/alembic.md +43 -0
- package/dist/lite/standards/migration-discipline/gorm.md +50 -0
- package/dist/lite/standards/migration-discipline/prisma.md +53 -0
- package/dist/lite/standards/migration-discipline/sqlalchemy.md +51 -0
- package/dist/lite/standards/mobile-ephemeral-session.md +167 -0
- package/dist/lite/standards/model-routing-discipline.md +160 -0
- package/dist/lite/standards/ogilvy-writing-rules.md +225 -0
- package/dist/lite/standards/opener-discipline.md +96 -0
- package/dist/lite/standards/operator-facing-prose-discipline.md +201 -0
- package/dist/lite/standards/persona-schema.md +229 -0
- package/dist/lite/standards/pluggable-luminaries.md +323 -0
- package/dist/lite/standards/pr-body-discipline.md +115 -0
- package/dist/lite/standards/preview-state-schema.md +189 -0
- package/dist/lite/standards/project-directory-layout.md +276 -0
- package/dist/lite/standards/release-tagging.md +137 -0
- package/dist/lite/standards/reserved-skill-names.md +120 -0
- package/dist/lite/standards/scannable-multi-option-output.md +265 -0
- package/dist/lite/standards/sdlc-compliance.md +286 -0
- package/dist/lite/standards/sdlc-gates/typescript.md +57 -0
- package/dist/lite/standards/secrets-lifecycle.md +210 -0
- package/dist/lite/standards/security-scanner-adapter.md +145 -0
- package/dist/lite/standards/session-board.md +256 -0
- package/dist/lite/standards/skill-output-discipline.md +121 -0
- package/dist/lite/standards/state-spine-contract.md +255 -0
- package/dist/lite/standards/state-spine.md +511 -0
- package/dist/lite/standards/steering-hints/kiss-words.md +11 -0
- package/dist/lite/standards/substrate-config-schema.md +267 -0
- package/dist/lite/standards/tech-stack-config.md +109 -0
- package/dist/lite/standards/tier-dependency-analysis.md +167 -0
- package/dist/lite/standards/tier-runtime-deps/lite.md +57 -0
- package/dist/lite/standards/tier-tag-schema.md +155 -0
- package/dist/lite/standards/two-layer-config.md +99 -0
- package/dist/lite/standards/use-case-format.md +292 -0
- package/dist/lite/standards/user-story-invest.md +268 -0
- package/dist/lite/standards/velocity-and-appetite.md +229 -0
- package/dist/lite/standards/voice-input-pattern.md +119 -0
- package/dist/lite/standards/whereami-schema.md +301 -0
- package/dist/lite/standards/worktree-management.md +211 -0
- package/dist/lite/standards/writing-guide.md +213 -0
- package/dist/lite/templates/chronicle-template.md +75 -0
- package/dist/lite/templates/deferred-action-template.md +45 -0
- package/dist/lite/templates/memory-proposal-template.md +77 -0
- package/dist/lite/templates/persona-template.md +200 -0
- package/dist/lite/templates/pr-faq.md +45 -0
- package/dist/lite/templates/secret-rotation-template.md +162 -0
- package/dist/lite/templates/spec-template.md +131 -0
- package/dist/lite/templates/use-case-template.md +194 -0
- package/dist/lite/templates/user-story-template.md +107 -0
- package/dist/lite/templates/whereami-template.md +101 -0
- package/package.json +1 -1
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# install-class: dual
|
|
4
|
+
# PostToolUse: Stop
|
|
5
|
+
#
|
|
6
|
+
# /longrun prep render check — closes ticket #1632.
|
|
7
|
+
#
|
|
8
|
+
# Fires four render-shape checks against the latest assistant message
|
|
9
|
+
# when the message carries a /longrun prep proposal:
|
|
10
|
+
#
|
|
11
|
+
# Symptom 1 — path label repetition. Every axis section repeating
|
|
12
|
+
# "Path A / Path B / Path C" as row prefixes = pure chart-junk per
|
|
13
|
+
# Tufte. Threshold: option labels appearing > 3 * option_count
|
|
14
|
+
# outside table header rows triggers BLOCK.
|
|
15
|
+
#
|
|
16
|
+
# Symptom 2 — no progressive disclosure. Recommend line declares
|
|
17
|
+
# Option X but multiple options carry full 6-axis blocks. Per
|
|
18
|
+
# Norman progressive disclosure + ADR-055 D3 recommended-only
|
|
19
|
+
# shape. Trigger: 2+ #### Option X sections beneath a
|
|
20
|
+
# "### Compounding value — recommended only" anchor when a
|
|
21
|
+
# Recommend line is present.
|
|
22
|
+
#
|
|
23
|
+
# Symptom 3 — TUI-unsafe table cells. Cells holding apostrophes,
|
|
24
|
+
# parens, or em-dashes fracture at Claude Code TUI render. Per
|
|
25
|
+
# .claude/rules/visual-hierarchy.md §12. Trigger: any markdown
|
|
26
|
+
# table row (starts and ends with |) carries [']()—] inside a cell
|
|
27
|
+
# (excluding header separator rows).
|
|
28
|
+
#
|
|
29
|
+
# Symptom 4 — "(Via /SKILL)" placeholder leak. Template placeholder
|
|
30
|
+
# text should be substituted with the dispatched skill name.
|
|
31
|
+
# Trigger: literal "(Via /SKILL)" appears in the message.
|
|
32
|
+
#
|
|
33
|
+
# Anchor luminaries:
|
|
34
|
+
# @luminary don-norman — progressive disclosure, signifier
|
|
35
|
+
# @luminary edward-tufte — data-ink ratio, chart-junk
|
|
36
|
+
# @luminary michael-feathers — characterization tests
|
|
37
|
+
# @luminary kent-beck — Tier 0 strict-TDD
|
|
38
|
+
#
|
|
39
|
+
# Toggle (default advisory; flip strict after calibration cycle):
|
|
40
|
+
# LONGRUN_PREP_RENDER_CHECK_TOGGLE=strict → exit 2 on any finding
|
|
41
|
+
# LONGRUN_PREP_RENDER_CHECK_TOGGLE=advisory → exit 0, findings to stderr (default)
|
|
42
|
+
# LONGRUN_PREP_RENDER_CHECK_TOGGLE=silent → exit 0, no output
|
|
43
|
+
#
|
|
44
|
+
# Override per-call:
|
|
45
|
+
# SKIP_LONGRUN_PREP_RENDER_CHECK=1
|
|
46
|
+
|
|
47
|
+
set -uo pipefail
|
|
48
|
+
|
|
49
|
+
# Override — skip and log
|
|
50
|
+
if [ "${SKIP_LONGRUN_PREP_RENDER_CHECK:-0}" = "1" ]; then
|
|
51
|
+
echo "[longrun-prep-render-check: SKIPPED via SKIP_LONGRUN_PREP_RENDER_CHECK=1]" >&2
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
TOGGLE="${LONGRUN_PREP_RENDER_CHECK_TOGGLE:-advisory}"
|
|
56
|
+
|
|
57
|
+
# Silent mode — exit clean
|
|
58
|
+
if [ "$TOGGLE" = "silent" ]; then
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Fixture-mode override (tests) — checked FIRST so fixture content is
|
|
63
|
+
# the source of truth when the env var is set. Skips the transcript
|
|
64
|
+
# extraction entirely.
|
|
65
|
+
if [ -n "${LONGRUN_PREP_RENDER_FIXTURE:-}" ] && [ -f "${LONGRUN_PREP_RENDER_FIXTURE}" ]; then
|
|
66
|
+
MESSAGE_TEXT="$(cat "${LONGRUN_PREP_RENDER_FIXTURE}")"
|
|
67
|
+
else
|
|
68
|
+
# Normal runtime path — read stdin JSON + extract latest assistant message
|
|
69
|
+
STDIN_JSON="$(cat 2>/dev/null || echo '{}')"
|
|
70
|
+
TRANSCRIPT_PATH="$(echo "$STDIN_JSON" | jq -r '.transcript_path // empty' 2>/dev/null || echo "")"
|
|
71
|
+
|
|
72
|
+
if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then
|
|
73
|
+
exit 0
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
MESSAGE_TEXT="$(jq -r '
|
|
77
|
+
select(.type == "assistant")
|
|
78
|
+
| .message.content[]?
|
|
79
|
+
| select(.type == "text")
|
|
80
|
+
| .text
|
|
81
|
+
' "$TRANSCRIPT_PATH" 2>/dev/null | tail -c 32000)"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if [ -z "$MESSAGE_TEXT" ]; then
|
|
85
|
+
exit 0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Only fire on messages that look like /longrun prep proposals.
|
|
89
|
+
# Anchor patterns per SKILL body Step 1.5-1.7:
|
|
90
|
+
# - "### Compare options" — the scan-table anchor
|
|
91
|
+
# - "### Compounding value" — the axis block anchor
|
|
92
|
+
# - "**Recommend:**" — the recommendation opener
|
|
93
|
+
# If none of these appear, this is not a prep proposal; skip.
|
|
94
|
+
if ! echo "$MESSAGE_TEXT" | grep -qE '(### Compare options|### Compounding value|\*\*Recommend:\*\*)'; then
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
FINDINGS=""
|
|
99
|
+
FINDING_COUNT=0
|
|
100
|
+
|
|
101
|
+
# =========================================================================
|
|
102
|
+
# Symptom 1 — Path label repetition (Tufte chart-junk)
|
|
103
|
+
# =========================================================================
|
|
104
|
+
#
|
|
105
|
+
# Count occurrences of "Option [a-z]" or "Path [A-Z]" or "Shape [a-c]" in
|
|
106
|
+
# non-comment / non-fenced-code lines. Deduct one occurrence per option
|
|
107
|
+
# for the header row + one for the Recommend line + one for the card
|
|
108
|
+
# section header. If remaining count > 0, we have per-option axis
|
|
109
|
+
# repetition — the chart-junk pattern.
|
|
110
|
+
#
|
|
111
|
+
# Threshold: per-option axis repetition means 6+ extra label rows per
|
|
112
|
+
# option. If the total residual count is > 3, the anti-pattern is present.
|
|
113
|
+
LABEL_TOTAL=$(echo "$MESSAGE_TEXT" | \
|
|
114
|
+
grep -vE '^[[:space:]]*```' | \
|
|
115
|
+
grep -oE '\b(Option [a-z]|Path [A-Z]|Shape [a-c])\b' | wc -l | tr -d ' ')
|
|
116
|
+
OPTION_COUNT=$(echo "$MESSAGE_TEXT" | \
|
|
117
|
+
grep -vE '^[[:space:]]*```' | \
|
|
118
|
+
grep -oE '\b(Option [a-z]|Path [A-Z]|Shape [a-c])\b' | sort -u | wc -l | tr -d ' ')
|
|
119
|
+
|
|
120
|
+
# Baseline: header row + card section + recommend line + one summary sentence.
|
|
121
|
+
# Estimate ~4 legitimate uses per option label.
|
|
122
|
+
BASELINE=$((OPTION_COUNT * 4))
|
|
123
|
+
|
|
124
|
+
if [ "$LABEL_TOTAL" -gt "$BASELINE" ] && [ "$OPTION_COUNT" -ge 2 ]; then
|
|
125
|
+
EXCESS=$((LABEL_TOTAL - BASELINE))
|
|
126
|
+
FINDINGS="${FINDINGS}
|
|
127
|
+
Symptom 1 — path label repetition (Tufte chart-junk):
|
|
128
|
+
${LABEL_TOTAL} option-label mentions across ${OPTION_COUNT} options
|
|
129
|
+
(baseline ~${BASELINE}; excess ~${EXCESS})
|
|
130
|
+
Cure — collapse per-axis 'Option A / B / C' rows into ONE header naming
|
|
131
|
+
options once, then rows carry values without re-labeling."
|
|
132
|
+
FINDING_COUNT=$((FINDING_COUNT + 1))
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# =========================================================================
|
|
136
|
+
# Symptom 2 — no progressive disclosure (Norman)
|
|
137
|
+
# =========================================================================
|
|
138
|
+
#
|
|
139
|
+
# Fires when Recommend line declares Option X AND non-recommended options
|
|
140
|
+
# ALSO carry full 6-axis "#### Option Y" cards beneath the
|
|
141
|
+
# "### Compounding value — recommended only" anchor. Per bassclef-upstream
|
|
142
|
+
# #1376 + ADR-055 D3, only the recommended option gets a full card.
|
|
143
|
+
RECOMMENDED=$(echo "$MESSAGE_TEXT" | \
|
|
144
|
+
grep -oE '\*\*Recommend[^*]*\*\*[[:space:]]*(Option [a-z]|Path [A-Z]|Shape [a-c])' | \
|
|
145
|
+
head -1 | grep -oE '(Option [a-z]|Path [A-Z]|Shape [a-c])' | head -1)
|
|
146
|
+
|
|
147
|
+
if [ -n "$RECOMMENDED" ]; then
|
|
148
|
+
# Count #### Option X headers under the recommended-only anchor
|
|
149
|
+
CARD_HEADERS_UNDER_ANCHOR=$(echo "$MESSAGE_TEXT" | awk '
|
|
150
|
+
/^### Compounding value/ { in_anchor=1; next }
|
|
151
|
+
/^### / && in_anchor { in_anchor=0 }
|
|
152
|
+
in_anchor && /^#### (Option [a-z]|Path [A-Z]|Shape [a-c])/ { print }
|
|
153
|
+
' | wc -l | tr -d ' ')
|
|
154
|
+
|
|
155
|
+
if [ "$CARD_HEADERS_UNDER_ANCHOR" -ge 2 ]; then
|
|
156
|
+
FINDINGS="${FINDINGS}
|
|
157
|
+
Symptom 2 — no progressive disclosure (Norman):
|
|
158
|
+
Recommend declared '${RECOMMENDED}' but ${CARD_HEADERS_UNDER_ANCHOR}
|
|
159
|
+
#### Option cards appear under '### Compounding value — recommended only'
|
|
160
|
+
Cure — render ONE card for the recommended option only. Non-recommended
|
|
161
|
+
options carry axes as one-liner cells in the scan-table row above.
|
|
162
|
+
See .claude/rules/compounding-sequence-fresh-analysis.md postcondition."
|
|
163
|
+
FINDING_COUNT=$((FINDING_COUNT + 1))
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# =========================================================================
|
|
168
|
+
# Symptom 3 — TUI-unsafe table cells (visual-hierarchy §12)
|
|
169
|
+
# =========================================================================
|
|
170
|
+
#
|
|
171
|
+
# Detect markdown table rows (start and end with |, not separator rows)
|
|
172
|
+
# that carry apostrophes, parens, or em-dashes inside cell text.
|
|
173
|
+
# Per .claude/rules/visual-hierarchy.md §12 — card format is the cure.
|
|
174
|
+
UNSAFE_CELL_LINES=$(echo "$MESSAGE_TEXT" | \
|
|
175
|
+
grep -E '^\|.*\|[[:space:]]*$' | \
|
|
176
|
+
grep -vE '^\|[[:space:]:-]+\|' | \
|
|
177
|
+
grep -E "['()—]" | head -3)
|
|
178
|
+
|
|
179
|
+
if [ -n "$UNSAFE_CELL_LINES" ]; then
|
|
180
|
+
UNSAFE_COUNT=$(echo "$UNSAFE_CELL_LINES" | wc -l | tr -d ' ')
|
|
181
|
+
FINDINGS="${FINDINGS}
|
|
182
|
+
Symptom 3 — TUI-unsafe table cells (visual-hierarchy §12):
|
|
183
|
+
${UNSAFE_COUNT} table row(s) carry apostrophes / parens / em-dashes
|
|
184
|
+
in cell text. First offending row:
|
|
185
|
+
$(echo "$UNSAFE_CELL_LINES" | head -1 | cut -c1-120)
|
|
186
|
+
Cure — move affected content to card format (bullets under a heading)
|
|
187
|
+
or replace ' with U+2019, replace () with plain prose, replace — with
|
|
188
|
+
HTML entity or backticks."
|
|
189
|
+
FINDING_COUNT=$((FINDING_COUNT + 1))
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
# =========================================================================
|
|
193
|
+
# Symptom 4 — "(Via /SKILL)" placeholder leak
|
|
194
|
+
# =========================================================================
|
|
195
|
+
#
|
|
196
|
+
# Detect literal "(Via /SKILL)" or "(via /SKILL)" or "(/SKILL)" in the
|
|
197
|
+
# message. These are template placeholders that should have been
|
|
198
|
+
# substituted with the actual dispatched skill name.
|
|
199
|
+
LEAK_COUNT=$(echo "$MESSAGE_TEXT" | grep -cE '\((Via|via) /SKILL\)|\(/SKILL\)' 2>/dev/null | tr -d '[:space:]' || echo 0)
|
|
200
|
+
LEAK_COUNT="${LEAK_COUNT:-0}"
|
|
201
|
+
|
|
202
|
+
if [ "$LEAK_COUNT" -gt 0 ]; then
|
|
203
|
+
FINDINGS="${FINDINGS}
|
|
204
|
+
Symptom 4 — '(Via /SKILL)' placeholder leak:
|
|
205
|
+
${LEAK_COUNT} literal placeholder(s) in message. Should be substituted
|
|
206
|
+
with the dispatched skill name (e.g., 'via /state-a-problem brief').
|
|
207
|
+
Cure — replace each '(Via /SKILL)' with 'via /<actual-skill>' or drop
|
|
208
|
+
the citation if no skill fired."
|
|
209
|
+
FINDING_COUNT=$((FINDING_COUNT + 1))
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
# =========================================================================
|
|
213
|
+
# Emit + exit per toggle
|
|
214
|
+
# =========================================================================
|
|
215
|
+
|
|
216
|
+
if [ "$FINDING_COUNT" -eq 0 ]; then
|
|
217
|
+
exit 0
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
case "$TOGGLE" in
|
|
221
|
+
strict)
|
|
222
|
+
echo "🛑 LONGRUN-PREP-RENDER — BLOCKED (${FINDING_COUNT} finding(s); ticket #1632)" >&2
|
|
223
|
+
echo "$FINDINGS" >&2
|
|
224
|
+
echo "" >&2
|
|
225
|
+
echo "Override: SKIP_LONGRUN_PREP_RENDER_CHECK=1" >&2
|
|
226
|
+
exit 2
|
|
227
|
+
;;
|
|
228
|
+
*)
|
|
229
|
+
# Default: advisory
|
|
230
|
+
echo "⚠ LONGRUN-PREP-RENDER — ADVISORY (${FINDING_COUNT} finding(s); ticket #1632)" >&2
|
|
231
|
+
echo "$FINDINGS" >&2
|
|
232
|
+
echo "" >&2
|
|
233
|
+
echo "Flip to strict via LONGRUN_PREP_RENDER_CHECK_TOGGLE=strict" >&2
|
|
234
|
+
exit 0
|
|
235
|
+
;;
|
|
236
|
+
esac
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# install-class: dual
|
|
4
|
+
# persona-name-scrub-check — PreToolUse hook that scans SKILL descriptions,
|
|
5
|
+
# SKILL bodies, rule bodies, luminary bodies, and adopter-facing docs
|
|
6
|
+
# (docs/**/*.md, docs-site/content/**/*.{md,mdx}) for bassclef persona
|
|
7
|
+
# proper nouns (Sam, Louis, Jamie, Morgan).
|
|
8
|
+
#
|
|
9
|
+
# V1 (bassclef-web#327): description-only scope.
|
|
10
|
+
# V2 (bassclef-web#339): body scope + adopter-facing docs paths.
|
|
11
|
+
#
|
|
12
|
+
# Per .claude/rules/persona-name-leak-scrub.md.
|
|
13
|
+
# V1+V2 ADVISORY per ADR-031 grace window. Exit 0 with stderr finding.
|
|
14
|
+
# V3 BLOCK deferred pending calibration cycle.
|
|
15
|
+
#
|
|
16
|
+
# Exit codes:
|
|
17
|
+
# 0 — allow (non-matching path, non-Edit/Write, clean content, or override)
|
|
18
|
+
#
|
|
19
|
+
# Override: SKIP_PERSONA_NAME_SCRUB=1
|
|
20
|
+
|
|
21
|
+
set +e
|
|
22
|
+
|
|
23
|
+
INPUT=$(cat 2>/dev/null)
|
|
24
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
|
|
25
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""' 2>/dev/null)
|
|
26
|
+
|
|
27
|
+
# Only fire on Edit or Write or MultiEdit
|
|
28
|
+
case "$TOOL_NAME" in
|
|
29
|
+
Edit|Write|MultiEdit) ;;
|
|
30
|
+
*) exit 0 ;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
# Override path
|
|
34
|
+
if [ "${SKIP_PERSONA_NAME_SCRUB:-}" = "1" ]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Path scope decision — V2 broadened per bassclef-web#339
|
|
39
|
+
# Order matters: skip docs/personas/*.md BEFORE the docs/*.md general match
|
|
40
|
+
case "$FILE_PATH" in
|
|
41
|
+
*/docs/personas/*.md)
|
|
42
|
+
exit 0 ;;
|
|
43
|
+
*/.claude/skills/*/SKILL.md) ;;
|
|
44
|
+
*/.claude/rules/*.md) ;;
|
|
45
|
+
*/.claude/luminaries/*.md) ;;
|
|
46
|
+
*/docs-site/content/*.md|*/docs-site/content/*.mdx) ;;
|
|
47
|
+
*/docs/*.md) ;;
|
|
48
|
+
*) exit 0 ;;
|
|
49
|
+
esac
|
|
50
|
+
|
|
51
|
+
# Extract content — Write → content; Edit → new_string; MultiEdit → concat edits[].new_string
|
|
52
|
+
CONTENT=""
|
|
53
|
+
if [ "$TOOL_NAME" = "Write" ]; then
|
|
54
|
+
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""' 2>/dev/null)
|
|
55
|
+
elif [ "$TOOL_NAME" = "MultiEdit" ]; then
|
|
56
|
+
CONTENT=$(echo "$INPUT" | jq -r '[.tool_input.edits[]? | .new_string] | join("\n")' 2>/dev/null)
|
|
57
|
+
else
|
|
58
|
+
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""' 2>/dev/null)
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
[ -z "$CONTENT" ] && exit 0
|
|
62
|
+
|
|
63
|
+
# Strip false-positive sources BEFORE regex scan (R4 + R12 mitigations):
|
|
64
|
+
# 1. Fenced code blocks (``` ... ```)
|
|
65
|
+
# 2. Inline backtick spans (`...`)
|
|
66
|
+
# awk + sed pipeline. Order: fenced first (multi-line), then inline (single-line).
|
|
67
|
+
STRIPPED=$(echo "$CONTENT" | awk '
|
|
68
|
+
BEGIN { in_block = 0 }
|
|
69
|
+
/^```/ { in_block = !in_block; next }
|
|
70
|
+
{ if (!in_block) print }
|
|
71
|
+
' | sed 's/`[^`]*`//g')
|
|
72
|
+
|
|
73
|
+
# Word-boundary case-sensitive regex for persona proper nouns.
|
|
74
|
+
# grep -E for extended regex, -o extracts matches for the ADVISORY report.
|
|
75
|
+
MATCHES=$(echo "$STRIPPED" | grep -oE '\b(Sam|Louis|Jamie|Morgan)\b' 2>/dev/null | sort -u | tr '\n' ' ')
|
|
76
|
+
|
|
77
|
+
if [ -n "$MATCHES" ]; then
|
|
78
|
+
# Determine scope label for the ADVISORY (description vs body vs docs)
|
|
79
|
+
SCOPE_LABEL="body"
|
|
80
|
+
if echo "$STRIPPED" | grep -qE '^description:.*\b(Sam|Louis|Jamie|Morgan)\b'; then
|
|
81
|
+
SCOPE_LABEL="description"
|
|
82
|
+
fi
|
|
83
|
+
case "$FILE_PATH" in
|
|
84
|
+
*/docs/*|*/docs-site/*) SCOPE_LABEL="adopter-facing content" ;;
|
|
85
|
+
esac
|
|
86
|
+
|
|
87
|
+
cat >&2 <<EOF
|
|
88
|
+
⚠ PERSONA-NAME-SCRUB — ADVISORY (V2)
|
|
89
|
+
|
|
90
|
+
File: $FILE_PATH
|
|
91
|
+
Scope: $SCOPE_LABEL
|
|
92
|
+
Match: $MATCHES
|
|
93
|
+
|
|
94
|
+
Adopters read SKILL bodies + rules + luminaries + docs. They have
|
|
95
|
+
no context on bassclef persona names. Substitute role words —
|
|
96
|
+
writer, picker, reviewer, operator, adopter.
|
|
97
|
+
|
|
98
|
+
Or backtick the name if it names a variable / quoted external ref.
|
|
99
|
+
|
|
100
|
+
Per .claude/rules/persona-name-leak-scrub.md
|
|
101
|
+
Override (logged): SKIP_PERSONA_NAME_SCRUB=1
|
|
102
|
+
EOF
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
exit 0
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# install-class: dual
|
|
4
|
+
# Skill-step-list check — Stop hook that scans the transcript for a Skill tool
|
|
5
|
+
# dispatch followed by an assistant response without a step-list block.
|
|
6
|
+
#
|
|
7
|
+
# Per sunj-labs/bassclef-upstream#1119: closes the SKILL-step-skip class caught
|
|
8
|
+
# in session 2026-08-05a. Rule at .claude/rules/skill-procedure-step-list.md.
|
|
9
|
+
# Ships as pair per bootstrap-pair-discipline.md.
|
|
10
|
+
#
|
|
11
|
+
# Sibling pattern: .claude/hooks/turn-prose-kiss-check.sh (Stop hook + transcript scan).
|
|
12
|
+
#
|
|
13
|
+
# Input (stdin): JSON with transcript_path + session_id
|
|
14
|
+
# {"transcript_path": "/path/to/transcript.jsonl", "session_id": "..."}
|
|
15
|
+
#
|
|
16
|
+
# Toggle (env or .claude/bassclef-configs.jsonc):
|
|
17
|
+
# SKILL_STEP_LIST_TOGGLE=true — advisory (exit 0, findings to stderr) [DEFAULT]
|
|
18
|
+
# SKILL_STEP_LIST_TOGGLE=strict — strict (exit 2, blocks stop, forces rewrite)
|
|
19
|
+
# SKILL_STEP_LIST_TOGGLE=false — silent (exit 0, no scan)
|
|
20
|
+
#
|
|
21
|
+
# Override per-call:
|
|
22
|
+
# SKIP_SKILL_STEP_LIST=1 — skip scan, exit 0
|
|
23
|
+
#
|
|
24
|
+
# Exit codes:
|
|
25
|
+
# 0 — pass (no findings, advisory mode, toggle off, override set, or no Skill dispatched)
|
|
26
|
+
# 2 — block stop (strict mode + Skill dispatched + no step-list in response)
|
|
27
|
+
#
|
|
28
|
+
# Reads:
|
|
29
|
+
# - $TRANSCRIPT_PATH (JSONL, one event per line)
|
|
30
|
+
# - .claude/bassclef-configs.jsonc (toggle when env not set)
|
|
31
|
+
|
|
32
|
+
set +e
|
|
33
|
+
|
|
34
|
+
# === Override path ===
|
|
35
|
+
if [ "${SKIP_SKILL_STEP_LIST:-0}" = "1" ]; then
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# === Source install-class resolver ===
|
|
40
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
41
|
+
|
|
42
|
+
# Hook liveness heartbeat (silent-fail)
|
|
43
|
+
{
|
|
44
|
+
for _hb_c in "${SCRIPT_DIR}/../../lib/hook-heartbeat.sh" "${HOME:-/}/lib/hook-heartbeat.sh"; do
|
|
45
|
+
[ -f "$_hb_c" ] && source "$_hb_c" && heartbeat_mark "skill-step-list-check" && break
|
|
46
|
+
done
|
|
47
|
+
unset _hb_c
|
|
48
|
+
} 2>/dev/null || true
|
|
49
|
+
|
|
50
|
+
for _candidate in \
|
|
51
|
+
"${SCRIPT_DIR}/../../lib/hook-inject.sh" \
|
|
52
|
+
"${HOME_OVERRIDE:-${HOME:-/}}/lib/hook-inject.sh"; do
|
|
53
|
+
if [ -f "$_candidate" ]; then
|
|
54
|
+
# shellcheck disable=SC1090
|
|
55
|
+
source "$_candidate"
|
|
56
|
+
break
|
|
57
|
+
fi
|
|
58
|
+
done
|
|
59
|
+
unset _candidate
|
|
60
|
+
|
|
61
|
+
# === Parse stdin JSON ===
|
|
62
|
+
STDIN_JSON=$(cat 2>/dev/null || echo '{}')
|
|
63
|
+
TRANSCRIPT_PATH=$(echo "$STDIN_JSON" | jq -r '.transcript_path // ""' 2>/dev/null)
|
|
64
|
+
|
|
65
|
+
# Graceful skip if no transcript path
|
|
66
|
+
if [ -z "$TRANSCRIPT_PATH" ]; then
|
|
67
|
+
exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Graceful skip if transcript file missing
|
|
71
|
+
if [ ! -f "$TRANSCRIPT_PATH" ]; then
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# === Resolve config file ===
|
|
76
|
+
if declare -f resolve_config_path >/dev/null 2>&1; then
|
|
77
|
+
CONFIG_FILE=$(resolve_config_path 2>/dev/null) || CONFIG_FILE=""
|
|
78
|
+
else
|
|
79
|
+
CONFIG_FILE="${SCRIPT_DIR}/../bassclef-configs.jsonc"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# === Resolve toggle ===
|
|
83
|
+
TOGGLE="${SKILL_STEP_LIST_TOGGLE:-}"
|
|
84
|
+
if [ -z "$TOGGLE" ]; then
|
|
85
|
+
if [ -n "$CONFIG_FILE" ] && [ -f "$CONFIG_FILE" ]; then
|
|
86
|
+
TOGGLE=$(sed 's|//.*||g' "$CONFIG_FILE" 2>/dev/null \
|
|
87
|
+
| jq -r '.skill_step_list.toggle // "true"' 2>/dev/null)
|
|
88
|
+
fi
|
|
89
|
+
TOGGLE="${TOGGLE:-true}"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
case "$TOGGLE" in
|
|
93
|
+
true|"true") MODE="advisory" ;;
|
|
94
|
+
strict|"strict") MODE="strict" ;;
|
|
95
|
+
false|"false") exit 0 ;;
|
|
96
|
+
*) MODE="advisory" ;;
|
|
97
|
+
esac
|
|
98
|
+
|
|
99
|
+
# === Scan transcript for a Skill tool_use ===
|
|
100
|
+
# We scan the last 200 lines to keep the hook fast.
|
|
101
|
+
LAST_LINES=$(tail -200 "$TRANSCRIPT_PATH" 2>/dev/null)
|
|
102
|
+
|
|
103
|
+
# Find lines with Skill tool_use
|
|
104
|
+
SKILL_LINE_NUM=$(echo "$LAST_LINES" | grep -n '"type":"tool_use"' 2>/dev/null | grep '"name":"Skill"' | tail -1 | cut -d: -f1)
|
|
105
|
+
|
|
106
|
+
if [ -z "$SKILL_LINE_NUM" ]; then
|
|
107
|
+
# No Skill dispatched in recent transcript — silent pass
|
|
108
|
+
exit 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# === Find the assistant text_content event AFTER the Skill line ===
|
|
112
|
+
# The response we care about is the one after the Skill tool_result comes back.
|
|
113
|
+
AFTER_SKILL=$(echo "$LAST_LINES" | tail -n +"$((SKILL_LINE_NUM + 1))" 2>/dev/null)
|
|
114
|
+
|
|
115
|
+
# Get the latest assistant text_content in that portion
|
|
116
|
+
LAST_ASSISTANT_AFTER=$(echo "$AFTER_SKILL" | grep '"type":"assistant"' | tail -1)
|
|
117
|
+
|
|
118
|
+
if [ -z "$LAST_ASSISTANT_AFTER" ]; then
|
|
119
|
+
# Skill dispatched but no response yet — silent pass
|
|
120
|
+
exit 0
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Extract text content from the assistant message
|
|
124
|
+
MESSAGE_TEXT=$(echo "$LAST_ASSISTANT_AFTER" \
|
|
125
|
+
| jq -r '.message.content[]? |
|
|
126
|
+
if .type == "text" then
|
|
127
|
+
.text
|
|
128
|
+
else
|
|
129
|
+
empty
|
|
130
|
+
end' 2>/dev/null)
|
|
131
|
+
|
|
132
|
+
if [ -z "$MESSAGE_TEXT" ]; then
|
|
133
|
+
# Assistant message had no text content (tool_use only) — silent pass
|
|
134
|
+
exit 0
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# === Check for step-list pattern ===
|
|
138
|
+
# Pattern: two markers must both appear:
|
|
139
|
+
# 1. A "Step N" reference (Step + digit)
|
|
140
|
+
# 2. At least one "[x]" or "[~]" bracket status marker
|
|
141
|
+
HAS_STEP=$(echo "$MESSAGE_TEXT" | grep -cE 'Step[[:space:]]+[0-9]+' 2>/dev/null)
|
|
142
|
+
HAS_MARKER=$(echo "$MESSAGE_TEXT" | grep -cE '\[[x~]\]' 2>/dev/null)
|
|
143
|
+
|
|
144
|
+
if [ "$HAS_STEP" -gt 0 ] && [ "$HAS_MARKER" -gt 0 ]; then
|
|
145
|
+
# Step-list present — silent pass
|
|
146
|
+
exit 0
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# === Missing step-list — emit finding ===
|
|
150
|
+
NOTICE="SKILL step-list check: recent Skill dispatch response lacks a step-list block."
|
|
151
|
+
NOTICE="$NOTICE Per .claude/rules/skill-procedure-step-list.md,"
|
|
152
|
+
NOTICE="$NOTICE write each SKILL procedure step with [x] done+source OR [~] deferred+reason."
|
|
153
|
+
|
|
154
|
+
# Trace log if trace-helper available
|
|
155
|
+
if [ -f "${SCRIPT_DIR}/../../lib/trace-helper.sh" ]; then
|
|
156
|
+
source "${SCRIPT_DIR}/../../lib/trace-helper.sh" 2>/dev/null
|
|
157
|
+
if declare -f trace_record >/dev/null 2>&1; then
|
|
158
|
+
trace_record "skill-step-list-check" "advisory-fired" "$NOTICE" 2>/dev/null
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if [ "$MODE" = "strict" ]; then
|
|
163
|
+
echo "🛑 BLOCKED: $NOTICE" >&2
|
|
164
|
+
echo "" >&2
|
|
165
|
+
echo "To resolve: rewrite the response with a step list at the top." >&2
|
|
166
|
+
echo "Override: SKIP_SKILL_STEP_LIST=1 <command> (logged)" >&2
|
|
167
|
+
exit 2
|
|
168
|
+
else
|
|
169
|
+
echo "⚠ ADVISORY: $NOTICE" >&2
|
|
170
|
+
exit 0
|
|
171
|
+
fi
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: Alan Cooper
|
|
4
|
+
slug: alan-cooper
|
|
5
|
+
claimed_by: [designer]
|
|
6
|
+
referenced_by_skills: [ia-model, jtbd-tasks, task-scenarios]
|
|
7
|
+
primary_domain: ux
|
|
8
|
+
depth: full
|
|
9
|
+
sources:
|
|
10
|
+
- type: book
|
|
11
|
+
title: "About Face: The Essentials of Interaction Design (4th edition)"
|
|
12
|
+
authors: ["Alan Cooper", "Robert Reimann", "David Cronin", "Christopher Noessel"]
|
|
13
|
+
year: 2014
|
|
14
|
+
url: "https://www.wiley.com/en-us/About+Face%3A+The+Essentials+of+Interaction+Design%2C+4th+Edition-p-9781118766576"
|
|
15
|
+
isbn: "9781118766576"
|
|
16
|
+
methodology_covered:
|
|
17
|
+
- "Goal-Directed Design — design starts from user goals, not features or tasks"
|
|
18
|
+
- "Personas as design tools — composite archetypes derived from user research"
|
|
19
|
+
- "Scenarios — narrative descriptions of personas using the product to achieve goals"
|
|
20
|
+
- "Three categories of users: novice + intermediate + expert; design for the perpetual intermediate"
|
|
21
|
+
- type: book
|
|
22
|
+
title: "The Inmates Are Running the Asylum: Why High-Tech Products Drive Us Crazy and How to Restore the Sanity"
|
|
23
|
+
authors: ["Alan Cooper"]
|
|
24
|
+
year: 1999
|
|
25
|
+
url: "https://www.pearson.com/en-us/subject-catalog/p/inmates-are-running-the-asylum-the-why-high-tech-products-drive-us-crazy-and-how-to-restore-the-sanity/P200000009296"
|
|
26
|
+
isbn: "9780672326141"
|
|
27
|
+
methodology_covered:
|
|
28
|
+
- "Programmer-driven design produces hostile interfaces"
|
|
29
|
+
- "Interaction designers as a distinct discipline, separate from engineering"
|
|
30
|
+
- "Persona origin — Cooper's first published articulation of the persona methodology"
|
|
31
|
+
verification_status: verified
|
|
32
|
+
solves_problems_brownfield:
|
|
33
|
+
- "Existing UI exposes the system's structure when users want their workflow"
|
|
34
|
+
- "Power users keep retracing the same multi-step path through the current UI"
|
|
35
|
+
- "Persona research surfaces a goal but the existing UI optimizes for novice exploration"
|
|
36
|
+
- "App is feature-rich but each user wants only one slice for their job"
|
|
37
|
+
solves_problems_greenfield:
|
|
38
|
+
- "Designing a workflow-heavy app for returning users with named goals"
|
|
39
|
+
- "Building a product where personas + scenarios should drive the UI before any screen sketch"
|
|
40
|
+
- "Planning a tool for power users who need their job-specific slice surfaced from day one"
|
|
41
|
+
- "Mid-complexity product where personas keep early design decisions grounded in real users"
|
|
42
|
+
anti_patterns:
|
|
43
|
+
- "Truly simple consumer apps — Cooper overweights workflow modeling"
|
|
44
|
+
- "First-launch novelty experiences — goal-directed assumes a returning user"
|
|
45
|
+
- "Pure marketing or storytelling surfaces"
|
|
46
|
+
description: "\"Personas are precision tools — each one a research-grounded behavioral archetype, not a fictional user."
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# Alan Cooper
|
|
50
|
+
|
|
51
|
+
## Signature
|
|
52
|
+
|
|
53
|
+
*"Personas are precision tools — each one a research-grounded behavioral archetype, not a fictional user. Start with user goals and let personas carry you there."*
|
|
54
|
+
|
|
55
|
+
"Father of Visual Basic"; founder of Cooper (the consultancy); author of
|
|
56
|
+
**About Face** and **The Inmates Are Running the Asylum**. The bassclef
|
|
57
|
+
voice on **Goal-Directed Design** and the proper use of personas as
|
|
58
|
+
research artifacts.
|
|
59
|
+
|
|
60
|
+
## Core methods
|
|
61
|
+
|
|
62
|
+
- **Goal-Directed Design** — Start with user goals (what they want to
|
|
63
|
+
accomplish, at life/experience/end levels), then derive tasks, then
|
|
64
|
+
derive interface. Feature-first design inverts this and produces
|
|
65
|
+
feature-dense, goal-incoherent products.
|
|
66
|
+
- **Personas as behavioral archetypes** — Built from interview pattern
|
|
67
|
+
analysis, not invented. Each persona represents a distinct goal set +
|
|
68
|
+
mental model + behavior pattern. A good product serves a primary
|
|
69
|
+
persona ruthlessly; secondary personas are served if it doesn't
|
|
70
|
+
compromise the primary.
|
|
71
|
+
- **Three levels of goals** — Life goals (long-term aspirations),
|
|
72
|
+
experience goals (how the interaction should feel), end goals (what
|
|
73
|
+
they want to accomplish in this session). Life goals shape brand;
|
|
74
|
+
experience goals shape interaction; end goals shape task flow.
|
|
75
|
+
- **Scenarios over requirements** — Describe the user in their context
|
|
76
|
+
pursuing their goal. A list of requirements decomposes; a scenario
|
|
77
|
+
holds the context that makes requirements make sense.
|
|
78
|
+
- **Dancing bear anti-pattern** — When something is remarkable *that it
|
|
79
|
+
works at all*, we accept it despite being difficult to use. Enterprise
|
|
80
|
+
software especially. Cooper's insight: don't accept the dancing bear.
|
|
81
|
+
|
|
82
|
+
## When to channel this luminary
|
|
83
|
+
|
|
84
|
+
When the biggest risk is building the wrong thing for the wrong person.
|
|
85
|
+
Cooper dominates when you have a target user population with distinct
|
|
86
|
+
behavior patterns, when goals (not features) should drive the product,
|
|
87
|
+
and when the risk of serving-everyone-badly is real. Think: operator
|
|
88
|
+
tools where the primary user does this job all day, specialist tools
|
|
89
|
+
where casual users will never be the target, B2B products with clear
|
|
90
|
+
user roles.
|
|
91
|
+
|
|
92
|
+
Do NOT channel Cooper as primary for: consumer products with vague
|
|
93
|
+
personas, rapid prototyping where persona rigor is premature, projects
|
|
94
|
+
where research budget doesn't support proper persona development (use
|
|
95
|
+
lightweight JTBD instead).
|
|
96
|
+
|
|
97
|
+
## Stack translation
|
|
98
|
+
|
|
99
|
+
In a Next.js + Prisma operator tool:
|
|
100
|
+
|
|
101
|
+
- **User goals → top-level nav** — If the primary persona's goal is
|
|
102
|
+
"move deals through pipeline efficiently," nav centers on deal flow,
|
|
103
|
+
not on feature taxonomy.
|
|
104
|
+
- **Personas → role-based access + UI variants** — Actual personas
|
|
105
|
+
often map to auth roles (Operator vs Broker vs Viewer). Each role
|
|
106
|
+
gets a goal-optimized surface, not a feature-subset of a generic UI.
|
|
107
|
+
- **Scenarios → key path tests** — Each scenario becomes an end-to-end
|
|
108
|
+
test that walks through the persona's goal. If the scenario breaks,
|
|
109
|
+
the product breaks for that persona.
|
|
110
|
+
- **Primary persona dominance** — When Primary Persona and Secondary
|
|
111
|
+
Persona needs conflict, Primary wins. Tailwind variants, conditional
|
|
112
|
+
rendering, feature flags — all serve this.
|
|
113
|
+
|
|
114
|
+
## Anti-patterns it prevents
|
|
115
|
+
|
|
116
|
+
- **Self-referential design** — designing for ourselves because we're
|
|
117
|
+
easy to imagine. Cooper's rigor demands research-grounded personas.
|
|
118
|
+
- **Generic "the user"** — vague singular user that's really an
|
|
119
|
+
amalgam of all users. Produces features for all, good-fit for none.
|
|
120
|
+
- **Feature-driven roadmap** — building because the feature was
|
|
121
|
+
requested, not because it serves a persona's goal. Accumulates
|
|
122
|
+
feature bloat without coherent direction.
|
|
123
|
+
- **Persona gallery** — fictional marketing personas dressed as UX
|
|
124
|
+
personas. Names, photos, and hobbies without behavioral grounding.
|
|
125
|
+
Useless for design decisions.
|
|
126
|
+
- **Goal conflation** — treating "user wants to export to CSV" as a
|
|
127
|
+
goal. That's a task. The goal is "report to their manager." The task
|
|
128
|
+
could be replaced by a better path to the goal.
|
|
129
|
+
|
|
130
|
+
## Worked example
|
|
131
|
+
|
|
132
|
+
For POA's deal pipeline, Cooper's approach starts with:
|
|
133
|
+
|
|
134
|
+
**Primary persona**: "Operator" — the person whose full-time job is
|
|
135
|
+
managing deal flow. Life goal: become a successful PE operator.
|
|
136
|
+
Experience goal: feel in control of their pipeline at a glance. End
|
|
137
|
+
goals per session: advance stuck deals, respond to broker inbound, log
|
|
138
|
+
new conversations, identify stalled opportunities.
|
|
139
|
+
|
|
140
|
+
**Secondary persona**: "Broker" — external contact. Life goal: maximize
|
|
141
|
+
commissions. Experience goal: trust the platform. End goals per session:
|
|
142
|
+
submit new listings, see status on submitted deals, communicate with
|
|
143
|
+
Operator.
|
|
144
|
+
|
|
145
|
+
**Primary wins**: the main surface is optimized for Operator. Broker
|
|
146
|
+
access is a narrow, focused interface (not the Operator UI with fewer
|
|
147
|
+
permissions). Dashboards emphasize stuck/stalled deals (end-goal
|
|
148
|
+
triggers) over total-deals-count (vanity metric).
|
|
149
|
+
|
|
150
|
+
What Cooper would NOT produce: a generic "deal management platform"
|
|
151
|
+
designed for "users." A feature-grid home page. A Broker UI that's
|
|
152
|
+
just Operator UI with most nav items hidden.
|
|
153
|
+
|
|
154
|
+
## Sources
|
|
155
|
+
|
|
156
|
+
- *About Face: The Essentials of Interaction Design* — Cooper,
|
|
157
|
+
Reimann, Cronin, Noessel, Wiley (4th ed 2014) — the foundational text
|
|
158
|
+
- *The Inmates Are Running the Asylum* — Cooper (1999, rev. 2004)
|
|
159
|
+
- cooper.com — Cooper consultancy (now part of Designit)
|
|
160
|
+
|
|
161
|
+
## Related luminaries
|
|
162
|
+
|
|
163
|
+
- **Kim Goodwin** — Goodwin provides the operational method for
|
|
164
|
+
Cooper's Goal-Directed Design; pair them always.
|
|
165
|
+
- **Sophia Prater** — OOUX starts with objects; Cooper with goals. Both
|
|
166
|
+
reject feature-first. Complementary at different layers.
|
|
167
|
+
- **Teresa Torres** — Continuous Discovery updates Cooper's research
|
|
168
|
+
rigor for weekly cadence.
|
|
169
|
+
- **Indi Young** — Mental models research at the thinking layer below
|
|
170
|
+
Cooper's behavioral archetypes.
|