@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,277 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# install-class: dual
|
|
4
|
+
#
|
|
5
|
+
# lib/source-graph-walker.sh — walks source-graph closure from a seed hook
|
|
6
|
+
#
|
|
7
|
+
# @pattern patterns/code/gof/composite.md
|
|
8
|
+
# Traverses a tree of file references (source + dot-source + glob-source).
|
|
9
|
+
#
|
|
10
|
+
# @pattern patterns/code/ousterhout/deep-module.md
|
|
11
|
+
# Narrow interface — walk_source_dependents(hook_path) hides ref extraction +
|
|
12
|
+
# path resolution + fixed-point iteration + glob expansion inside the module.
|
|
13
|
+
#
|
|
14
|
+
# Contract (Hoare):
|
|
15
|
+
# - Precondition: hook_path exists and is readable
|
|
16
|
+
# - Postcondition (success): stdout is newline-separated list of ABSENT
|
|
17
|
+
# dependents (empty means all dependents resolve) + exit 0
|
|
18
|
+
# - Postcondition (failure): non-zero exit + stderr names the reason
|
|
19
|
+
# - Silent-fail per ADR-050 R7 on file-read errors
|
|
20
|
+
#
|
|
21
|
+
# @luminary vaughn-vernon (anticorruption layer between wired hook set
|
|
22
|
+
# and actual dependency graph)
|
|
23
|
+
#
|
|
24
|
+
# Per docs/decompositions/2026-09-15-install-class-dispatch.md
|
|
25
|
+
# Per goal docs/iteration-bets/2026-09-14c-install-class-dispatch-plus-walker-runtime.md
|
|
26
|
+
#
|
|
27
|
+
# NOTE: This IS the single walker implementation. `scripts/build-adopter-tree.sh`
|
|
28
|
+
# sources this lib at build time (retired its copy at goal 2026-09-14c Step 5.0
|
|
29
|
+
# per #1663 + ADR-058 c5). `lib/hook-installer.sh` sources it at install time
|
|
30
|
+
# via `install_by_class`. One implementation, three callers (build script,
|
|
31
|
+
# install-time lib, tests). See architecture/reviews/2026-09-15.md F2.
|
|
32
|
+
|
|
33
|
+
set -euo pipefail
|
|
34
|
+
|
|
35
|
+
# REPO_ROOT — inferred from lib/ location if unset
|
|
36
|
+
if [ -z "${REPO_ROOT:-}" ]; then
|
|
37
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Per-process walker cache — O-F2 cure (2026-09-15c architect-review).
|
|
41
|
+
# Ousterhout ch. 8 (Pull Complexity Downward) — callers stay simple; the
|
|
42
|
+
# lib absorbs the "run once per hook per process" decision. First call
|
|
43
|
+
# for a hook path runs the real walker; later calls return cached
|
|
44
|
+
# result. Cache holds OK paths only — failed walks re-run each time (rare
|
|
45
|
+
# case; not worth caching). Cache file is per-process; trap EXIT cleans up.
|
|
46
|
+
_SGW_CACHE=""
|
|
47
|
+
|
|
48
|
+
_sgw_init_cache() {
|
|
49
|
+
if [ -z "${_SGW_CACHE:-}" ]; then
|
|
50
|
+
_SGW_CACHE=$(mktemp -t bassclef-sgw.XXXXXX 2>/dev/null || echo "")
|
|
51
|
+
if [ -n "$_SGW_CACHE" ]; then
|
|
52
|
+
# shellcheck disable=SC2064 # expand $_SGW_CACHE at trap-set time
|
|
53
|
+
trap "[ -f '$_SGW_CACHE' ] && rm -f '$_SGW_CACHE'" EXIT
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Extract every .sh literal ref from a shell file — the walker's resolve
|
|
59
|
+
# step filters to only paths that map to real files, so false-positive
|
|
60
|
+
# extractions are cheap.
|
|
61
|
+
_sgw_extract_all_refs() {
|
|
62
|
+
local file="$1"
|
|
63
|
+
|
|
64
|
+
# 1. Every .sh literal in the file (quoted or path-shaped), from non-comment lines
|
|
65
|
+
grep -vE '^[[:space:]]*#' "$file" 2>/dev/null | \
|
|
66
|
+
grep -oE '"[^"]+\.sh"|'"'"'[^'"'"']+\.sh'"'"'|\$\{[^}]+\}/[^"'"'"'[:space:]]+\.sh|[$][A-Za-z_][A-Za-z0-9_]*/[^"'"'"'[:space:]]+\.sh|(\./|\.\./|/)[^"'"'"'[:space:]$]+\.sh' 2>/dev/null | \
|
|
67
|
+
tr -d '"'"'"'"' | \
|
|
68
|
+
sort -u
|
|
69
|
+
|
|
70
|
+
# 2. Glob-source patterns — for loops iterating dir/*.sh
|
|
71
|
+
grep -oE 'for[[:space:]]+[[:alnum:]_]+[[:space:]]+in[[:space:]]+[^;$]+/\*\.sh' "$file" 2>/dev/null | \
|
|
72
|
+
sed -E 's/.*[[:space:]]+in[[:space:]]+([^*]+)\*\.sh/\1__GLOB__/' 2>/dev/null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# Resolve a raw ref to an absolute repo path. Empty on unresolvable OR
|
|
76
|
+
# when the resolved path does not exist. Substitutes common bassclef vars.
|
|
77
|
+
_sgw_resolve_ref_in_repo() {
|
|
78
|
+
local src_file="$1"
|
|
79
|
+
local ref="$2"
|
|
80
|
+
|
|
81
|
+
local src_dir
|
|
82
|
+
src_dir="$(dirname "$src_file")"
|
|
83
|
+
|
|
84
|
+
local resolved="$ref"
|
|
85
|
+
resolved="${resolved//\$SCRIPT_DIR/$src_dir}"
|
|
86
|
+
resolved="${resolved//\$\{SCRIPT_DIR\}/$src_dir}"
|
|
87
|
+
resolved="${resolved//\$\{SCRIPT_DIR:-.\}/$src_dir}"
|
|
88
|
+
resolved="${resolved//\$CWD/$REPO_ROOT}"
|
|
89
|
+
resolved="${resolved//\$\{CWD\}/$REPO_ROOT}"
|
|
90
|
+
resolved="${resolved//\$BASSCLEF_DIR/$REPO_ROOT}"
|
|
91
|
+
resolved="${resolved//\$\{BASSCLEF_DIR\}/$REPO_ROOT}"
|
|
92
|
+
resolved="${resolved//\$\{BASSCLEF_DIR:-\}/$REPO_ROOT}"
|
|
93
|
+
resolved="${resolved//\$\{BASSCLEF_DIR:-.\}/$REPO_ROOT}"
|
|
94
|
+
resolved="${resolved//\$REPO_ROOT/$REPO_ROOT}"
|
|
95
|
+
resolved="${resolved//\$\{REPO_ROOT\}/$REPO_ROOT}"
|
|
96
|
+
resolved="${resolved//\$HOME/$REPO_ROOT}"
|
|
97
|
+
resolved="${resolved//\$\{HOME\}/$REPO_ROOT}"
|
|
98
|
+
resolved="${resolved//\$\{HOME:-/\}/$REPO_ROOT}"
|
|
99
|
+
resolved="${resolved//\$\{HOME_OVERRIDE:-\$\{HOME:-/\}\}/$REPO_ROOT}"
|
|
100
|
+
|
|
101
|
+
# Handle __GLOB__ marker (dir with trailing slash) BEFORE the $-check
|
|
102
|
+
if echo "$resolved" | grep -q '__GLOB__$'; then
|
|
103
|
+
local dir="${resolved%__GLOB__}"
|
|
104
|
+
dir="${dir%/}"
|
|
105
|
+
local normalized_dir
|
|
106
|
+
normalized_dir="$(cd "$dir" 2>/dev/null && pwd)" || {
|
|
107
|
+
echo ""
|
|
108
|
+
return 0
|
|
109
|
+
}
|
|
110
|
+
echo "${normalized_dir}/__GLOB__"
|
|
111
|
+
return 0
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# If still has unresolved variables, fall back to suffix extraction
|
|
115
|
+
if echo "$resolved" | grep -qE '\$'; then
|
|
116
|
+
local suffix
|
|
117
|
+
suffix="$(echo "$resolved" | grep -oE '(/lib/|/hooks/(_lib/)?)[[:alnum:]_-]+\.sh$' | head -1)"
|
|
118
|
+
if [ -n "$suffix" ]; then
|
|
119
|
+
resolved="${REPO_ROOT}${suffix}"
|
|
120
|
+
else
|
|
121
|
+
echo ""
|
|
122
|
+
return 0
|
|
123
|
+
fi
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
if [ "${resolved:0:1}" != "/" ]; then
|
|
127
|
+
resolved="${REPO_ROOT}/${resolved}"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Normalize the path; only if the file exists
|
|
131
|
+
local normalized
|
|
132
|
+
normalized="$(cd "$(dirname "$resolved")" 2>/dev/null && pwd)/$(basename "$resolved")" || {
|
|
133
|
+
echo ""
|
|
134
|
+
return 0
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if [ ! -f "$normalized" ]; then
|
|
138
|
+
echo ""
|
|
139
|
+
return 0
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
echo "$normalized"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
# Walk the source-graph closure from a seed file set. Returns every file
|
|
146
|
+
# reachable from the seeds via source/dot-source/bash-invoke/glob-source.
|
|
147
|
+
# Fixed-point iteration using a temp file for O(1) seen-lookup.
|
|
148
|
+
# Explicit cleanup at every return path (no RETURN trap — bad interaction
|
|
149
|
+
# with subshell + set -e).
|
|
150
|
+
_sgw_walk_source_closure() {
|
|
151
|
+
local seen_file
|
|
152
|
+
seen_file="$(mktemp -t bassclef-sgw-seen.XXXXXX)"
|
|
153
|
+
|
|
154
|
+
local -a queue
|
|
155
|
+
# Guard against empty $@ under set -u (bash 3.2)
|
|
156
|
+
if [ $# -gt 0 ]; then
|
|
157
|
+
queue=("$@")
|
|
158
|
+
else
|
|
159
|
+
queue=()
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
while [ "${#queue[@]}" -gt 0 ]; do
|
|
163
|
+
local current="${queue[0]}"
|
|
164
|
+
# Shift front — safe under bash 3.2
|
|
165
|
+
if [ "${#queue[@]}" -gt 1 ]; then
|
|
166
|
+
queue=("${queue[@]:1}")
|
|
167
|
+
else
|
|
168
|
+
queue=()
|
|
169
|
+
fi
|
|
170
|
+
[ -z "$current" ] && continue
|
|
171
|
+
|
|
172
|
+
# Skip if already seen
|
|
173
|
+
if grep -qFx "$current" "$seen_file" 2>/dev/null; then
|
|
174
|
+
continue
|
|
175
|
+
fi
|
|
176
|
+
echo "$current" >> "$seen_file"
|
|
177
|
+
|
|
178
|
+
# If __GLOB__ marker — expand to all *.sh in dir and enqueue each
|
|
179
|
+
if [ "${current: -8}" = "__GLOB__" ]; then
|
|
180
|
+
local dir="${current%__GLOB__}"
|
|
181
|
+
dir="${dir%/}"
|
|
182
|
+
if [ -d "$dir" ]; then
|
|
183
|
+
while IFS= read -r f; do
|
|
184
|
+
queue+=("$f")
|
|
185
|
+
done < <(find "$dir" -maxdepth 1 -name '*.sh' -type f)
|
|
186
|
+
fi
|
|
187
|
+
continue
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
[ ! -f "$current" ] && continue
|
|
191
|
+
|
|
192
|
+
while IFS= read -r ref; do
|
|
193
|
+
[ -z "$ref" ] && continue
|
|
194
|
+
local resolved
|
|
195
|
+
resolved="$(_sgw_resolve_ref_in_repo "$current" "$ref")"
|
|
196
|
+
if [ -n "$resolved" ] && ! grep -qFx "$resolved" "$seen_file" 2>/dev/null; then
|
|
197
|
+
queue+=("$resolved")
|
|
198
|
+
fi
|
|
199
|
+
done < <(_sgw_extract_all_refs "$current")
|
|
200
|
+
done
|
|
201
|
+
|
|
202
|
+
# Emit seen paths (real files; skip glob markers)
|
|
203
|
+
grep -v '__GLOB__$' "$seen_file" 2>/dev/null | sort -u
|
|
204
|
+
|
|
205
|
+
# Explicit cleanup (no RETURN trap)
|
|
206
|
+
rm -f "$seen_file"
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# Public: walk_source_dependents(hook_path)
|
|
210
|
+
#
|
|
211
|
+
# Returns newline-separated list of MISSING dependents (files the hook
|
|
212
|
+
# references via source/bash-invoke that don't exist on disk). Empty
|
|
213
|
+
# output means all dependents resolve. Non-zero exit means the hook
|
|
214
|
+
# itself is unreadable OR the graph traversal errored.
|
|
215
|
+
walk_source_dependents() {
|
|
216
|
+
local hook_path="$1"
|
|
217
|
+
|
|
218
|
+
if [ ! -f "$hook_path" ] || [ ! -r "$hook_path" ]; then
|
|
219
|
+
echo "walk_source_dependents: hook_path not readable: $hook_path" >&2
|
|
220
|
+
return 1
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
# Cache check — O-F2 cure. Return cached OK result without re-scanning.
|
|
224
|
+
_sgw_init_cache
|
|
225
|
+
if [ -n "$_SGW_CACHE" ] && grep -qFx "$hook_path" "$_SGW_CACHE" 2>/dev/null; then
|
|
226
|
+
return 0
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# Scan direct references from the hook file (non-recursive; check each
|
|
230
|
+
# direct dependent's existence). Full closure walk is available via
|
|
231
|
+
# _sgw_walk_source_closure for callers that need it (e.g., build script).
|
|
232
|
+
local missing=()
|
|
233
|
+
local ref resolved
|
|
234
|
+
while IFS= read -r ref; do
|
|
235
|
+
[ -z "$ref" ] && continue
|
|
236
|
+
resolved="$(_sgw_resolve_ref_in_repo "$hook_path" "$ref")"
|
|
237
|
+
if [ -z "$resolved" ]; then
|
|
238
|
+
# Try to extract the raw ref path for the missing report
|
|
239
|
+
local raw_path
|
|
240
|
+
raw_path=$(echo "$ref" | tr -d '"'"'"'"')
|
|
241
|
+
# Skip refs with unresolvable vars (runtime-fetched paths per ADR-050)
|
|
242
|
+
if echo "$raw_path" | grep -qE '\$'; then
|
|
243
|
+
continue
|
|
244
|
+
fi
|
|
245
|
+
# Skip glob markers
|
|
246
|
+
if echo "$raw_path" | grep -q '__GLOB__$'; then
|
|
247
|
+
continue
|
|
248
|
+
fi
|
|
249
|
+
# Skip refs that map to non-repo absolute paths (runtime env only)
|
|
250
|
+
if [ "${raw_path:0:1}" = "/" ] && [ ! -f "$raw_path" ]; then
|
|
251
|
+
# Ref that starts with / but doesn't exist — this IS a missing dependent
|
|
252
|
+
missing+=("$raw_path")
|
|
253
|
+
fi
|
|
254
|
+
fi
|
|
255
|
+
done < <(_sgw_extract_all_refs "$hook_path")
|
|
256
|
+
|
|
257
|
+
if [ ${#missing[@]} -gt 0 ]; then
|
|
258
|
+
printf '%s\n' "${missing[@]}"
|
|
259
|
+
return 1
|
|
260
|
+
fi
|
|
261
|
+
|
|
262
|
+
# Cache write — store OK path so later calls return fast.
|
|
263
|
+
if [ -n "$_SGW_CACHE" ]; then
|
|
264
|
+
echo "$hook_path" >> "$_SGW_CACHE" 2>/dev/null || true
|
|
265
|
+
fi
|
|
266
|
+
return 0
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# Public: walk_source_closure(seed_files...) — full transitive closure
|
|
270
|
+
# Callers that need the transitive dependency set (build script) use this.
|
|
271
|
+
walk_source_closure() {
|
|
272
|
+
_sgw_walk_source_closure "$@"
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# Export for callers
|
|
276
|
+
export -f walk_source_dependents 2>/dev/null || true
|
|
277
|
+
export -f walk_source_closure 2>/dev/null || true
|