@thebassclef/lite 1.0.4 → 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.
Files changed (275) hide show
  1. package/dist/cli.cjs +65 -0
  2. package/dist/cli.js +65 -0
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/lite/.claude/agents/architect.md +70 -0
  7. package/dist/lite/.claude/agents/builder.md +114 -0
  8. package/dist/lite/.claude/agents/designer.md +156 -0
  9. package/dist/lite/.claude/agents/reviewer.md +88 -0
  10. package/dist/lite/.claude/hooks/bassclef-sync.sh +85 -27
  11. package/dist/lite/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
  12. package/dist/lite/.claude/hooks/longrun-prep-render-check.sh +236 -0
  13. package/dist/lite/.claude/hooks/persona-name-scrub-check.sh +105 -0
  14. package/dist/lite/.claude/hooks/skill-step-list-check.sh +171 -0
  15. package/dist/lite/.claude/luminaries/alan-cooper.md +170 -0
  16. package/dist/lite/.claude/luminaries/alistair-cockburn.md +140 -0
  17. package/dist/lite/.claude/luminaries/amazon-pr-faq.md +34 -0
  18. package/dist/lite/.claude/luminaries/andreas-zeller.md +74 -0
  19. package/dist/lite/.claude/luminaries/ash-maurya.md +121 -0
  20. package/dist/lite/.claude/luminaries/bill-buxton.md +210 -0
  21. package/dist/lite/.claude/luminaries/charles-sanders-peirce.md +150 -0
  22. package/dist/lite/.claude/luminaries/david-ogilvy.md +192 -0
  23. package/dist/lite/.claude/luminaries/don-norman.md +173 -0
  24. package/dist/lite/.claude/luminaries/edward-tufte.md +179 -0
  25. package/dist/lite/.claude/luminaries/eric-evans.md +160 -0
  26. package/dist/lite/.claude/luminaries/frederick-brooks.md +50 -0
  27. package/dist/lite/.claude/luminaries/gang-of-four.md +157 -0
  28. package/dist/lite/.claude/luminaries/glenford-myers.md +230 -0
  29. package/dist/lite/.claude/luminaries/hunt-thomas.md +115 -0
  30. package/dist/lite/.claude/luminaries/hyrum-wright.md +94 -0
  31. package/dist/lite/.claude/luminaries/jason-fried-dhh.md +46 -0
  32. package/dist/lite/.claude/luminaries/jesse-james-garrett.md +154 -0
  33. package/dist/lite/.claude/luminaries/john-ousterhout.md +94 -0
  34. package/dist/lite/.claude/luminaries/karl-popper.md +132 -0
  35. package/dist/lite/.claude/luminaries/kent-beck.md +168 -0
  36. package/dist/lite/.claude/luminaries/linus-torvalds.md +218 -0
  37. package/dist/lite/.claude/luminaries/martin-fowler.md +164 -0
  38. package/dist/lite/.claude/luminaries/michael-feathers.md +125 -0
  39. package/dist/lite/.claude/luminaries/michael-nygard.md +118 -0
  40. package/dist/lite/.claude/luminaries/robert-c-martin.md +164 -0
  41. package/dist/lite/.claude/luminaries/saltzer-schroeder.md +194 -0
  42. package/dist/lite/.claude/luminaries/sophia-prater.md +193 -0
  43. package/dist/lite/.claude/luminaries/stephen-toulmin.md +131 -0
  44. package/dist/lite/.claude/luminaries/tony-hoare.md +170 -0
  45. package/dist/lite/.claude/luminaries/vaughn-vernon.md +50 -0
  46. package/dist/lite/.claude/luminaries/w-edwards-deming.md +158 -0
  47. package/dist/lite/.claude/rules/accessor-library-discipline.md +110 -0
  48. package/dist/lite/.claude/rules/adr-discipline.md +96 -0
  49. package/dist/lite/.claude/rules/api-conventions.md +115 -0
  50. package/dist/lite/.claude/rules/artifact-ingestion.md +137 -0
  51. package/dist/lite/.claude/rules/assert-only-after-verify.md +111 -0
  52. package/dist/lite/.claude/rules/blocked-items.md +139 -0
  53. package/dist/lite/.claude/rules/bootstrap-pair-discipline.md +106 -0
  54. package/dist/lite/.claude/rules/branching.md +28 -0
  55. package/dist/lite/.claude/rules/cold-adopter-harness-discipline.md +93 -0
  56. package/dist/lite/.claude/rules/commit-conventions.md +22 -0
  57. package/dist/lite/.claude/rules/compounding-axis-fresh-analysis.md +173 -0
  58. package/dist/lite/.claude/rules/compounding-sequence-fresh-analysis.md +173 -0
  59. package/dist/lite/.claude/rules/context-engineering.md +155 -0
  60. package/dist/lite/.claude/rules/context-management.md +85 -0
  61. package/dist/lite/.claude/rules/defensive-bash.md +52 -0
  62. package/dist/lite/.claude/rules/deferred-actions.md +233 -0
  63. package/dist/lite/.claude/rules/destructive-operations.md +69 -0
  64. package/dist/lite/.claude/rules/diagnosis.md +38 -0
  65. package/dist/lite/.claude/rules/github-issue-flash-tweet.md +114 -0
  66. package/dist/lite/.claude/rules/guardrails.md +73 -0
  67. package/dist/lite/.claude/rules/hook-wire-on-author.md +77 -0
  68. package/dist/lite/.claude/rules/identifier-leak-prevention.md +73 -0
  69. package/dist/lite/.claude/rules/iteration-bet-brief-completeness.md +43 -0
  70. package/dist/lite/.claude/rules/lite-manifest-schema-change-discipline.md +79 -0
  71. package/dist/lite/.claude/rules/longrun-prep-plan-doc-compression.md +77 -0
  72. package/dist/lite/.claude/rules/loop-discipline.md +71 -0
  73. package/dist/lite/.claude/rules/manual-prod-approval.md +100 -0
  74. package/dist/lite/.claude/rules/marker-enrichment-discipline.md +72 -0
  75. package/dist/lite/.claude/rules/mobile-ephemeral-session.md +109 -0
  76. package/dist/lite/.claude/rules/new-dependency-check.md +44 -0
  77. package/dist/lite/.claude/rules/oo-ad-entry-point.md +95 -0
  78. package/dist/lite/.claude/rules/operator-facing-prose.md +177 -0
  79. package/dist/lite/.claude/rules/option-label-discipline.md +82 -0
  80. package/dist/lite/.claude/rules/pattern-annotation.md +83 -0
  81. package/dist/lite/.claude/rules/persona-name-leak-scrub.md +90 -0
  82. package/dist/lite/.claude/rules/plain-english-discipline.md +132 -0
  83. package/dist/lite/.claude/rules/plan-enumeration-needs-value-props.md +177 -0
  84. package/dist/lite/.claude/rules/pr-body-shape.md +195 -0
  85. package/dist/lite/.claude/rules/pr-strategy.md +142 -0
  86. package/dist/lite/.claude/rules/pr-title-shape.md +90 -0
  87. package/dist/lite/.claude/rules/prototype-workflow.md +53 -0
  88. package/dist/lite/.claude/rules/reserved-skill-names.md +103 -0
  89. package/dist/lite/.claude/rules/schema-management.md +42 -0
  90. package/dist/lite/.claude/rules/sdlc-gates.md +149 -0
  91. package/dist/lite/.claude/rules/security.md +37 -0
  92. package/dist/lite/.claude/rules/session-artifacts.md +236 -0
  93. package/dist/lite/.claude/rules/skill-composition-declarations.md +105 -0
  94. package/dist/lite/.claude/rules/skill-description-clarity.md +196 -0
  95. package/dist/lite/.claude/rules/skill-procedure-step-list.md +119 -0
  96. package/dist/lite/.claude/rules/sprint-prep-preset-picker.md +76 -0
  97. package/dist/lite/.claude/rules/state-schema-validation.md +156 -0
  98. package/dist/lite/.claude/rules/stuck-signal-diagnostic.md +111 -0
  99. package/dist/lite/.claude/rules/substrate-config-schema.md +85 -0
  100. package/dist/lite/.claude/rules/test-list-discipline.md +129 -0
  101. package/dist/lite/.claude/rules/test-sufficiency.md +186 -0
  102. package/dist/lite/.claude/rules/testing-tier-config.md +125 -0
  103. package/dist/lite/.claude/rules/testing.md +38 -0
  104. package/dist/lite/.claude/rules/turn-estimate-grounding.md +82 -0
  105. package/dist/lite/.claude/rules/visual-hierarchy.md +427 -0
  106. package/dist/lite/.claude/rules/we-dont-break-adopters.md +103 -0
  107. package/dist/lite/.claude/rules/whereami-load-bearing.md +184 -0
  108. package/dist/lite/.claude/rules/writing-craft-discipline.md +72 -0
  109. package/dist/lite/.claude/rules/wu-sequencing-compounds.md +119 -0
  110. package/dist/lite/.claude/skills/build/SKILL.md +640 -0
  111. package/dist/lite/.claude/skills/chronicle/SKILL.md +55 -0
  112. package/dist/lite/.claude/skills/clean-artifacts/SKILL.md +249 -0
  113. package/dist/lite/.claude/skills/decompose/SKILL.md +280 -0
  114. package/dist/lite/.claude/skills/diagnose/SKILL.md +297 -0
  115. package/dist/lite/.claude/skills/feynman/SKILL.md +90 -0
  116. package/dist/lite/.claude/skills/howdoi/SKILL.md +105 -0
  117. package/dist/lite/.claude/skills/ia-model/SKILL.md +108 -0
  118. package/dist/lite/.claude/skills/interaction-design/SKILL.md +112 -0
  119. package/dist/lite/.claude/skills/interpret-input/SKILL.md +180 -0
  120. package/dist/lite/.claude/skills/journal/SKILL.md +209 -0
  121. package/dist/lite/.claude/skills/kiss/SKILL.md +449 -0
  122. package/dist/lite/.claude/skills/launch/SKILL.md +915 -0
  123. package/dist/lite/.claude/skills/lean-canvas/SKILL.md +332 -0
  124. package/dist/lite/.claude/skills/longrun/SKILL.md +512 -0
  125. package/dist/lite/.claude/skills/luminary/SKILL.md +481 -0
  126. package/dist/lite/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
  127. package/dist/lite/.claude/skills/onboard-repo/SKILL.md +1640 -0
  128. package/dist/lite/.claude/skills/pattern-review/SKILL.md +99 -0
  129. package/dist/lite/.claude/skills/personas/SKILL.md +207 -0
  130. package/dist/lite/.claude/skills/promote/SKILL.md +283 -0
  131. package/dist/lite/.claude/skills/requirement/SKILL.md +98 -0
  132. package/dist/lite/.claude/skills/retro/SKILL.md +117 -0
  133. package/dist/lite/.claude/skills/riff/SKILL.md +114 -0
  134. package/dist/lite/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
  135. package/dist/lite/.claude/skills/session-end/SKILL.md +309 -0
  136. package/dist/lite/.claude/skills/session-log/SKILL.md +299 -0
  137. package/dist/lite/.claude/skills/skills/SKILL.md +228 -0
  138. package/dist/lite/.claude/skills/spec/SKILL.md +105 -0
  139. package/dist/lite/.claude/skills/sprint/SKILL.md +418 -0
  140. package/dist/lite/.claude/skills/stage/SKILL.md +384 -0
  141. package/dist/lite/.claude/skills/state-a-problem/SKILL.md +185 -0
  142. package/dist/lite/.claude/skills/temperance/SKILL.md +108 -0
  143. package/dist/lite/.claude/skills/use-case/SKILL.md +417 -0
  144. package/dist/lite/.claude/skills/user-stories/SKILL.md +268 -0
  145. package/dist/lite/.claude/skills/value-prop/SKILL.md +251 -0
  146. package/dist/lite/.claude/skills/verify/SKILL.md +160 -0
  147. package/dist/lite/.claude/skills/visual-review/SKILL.md +503 -0
  148. package/dist/lite/.claude/skills/whats-the-plan/SKILL.md +202 -0
  149. package/dist/lite/.claude/skills/whereami/SKILL.md +307 -0
  150. package/dist/lite/AGENTS.md +79 -0
  151. package/dist/lite/CLAUDE-lite.md +85 -0
  152. package/dist/lite/CODE_OF_CONDUCT.md +28 -0
  153. package/dist/lite/CONTRIBUTING.md +177 -0
  154. package/dist/lite/README.md +173 -0
  155. package/dist/lite/SECURITY.md +19 -0
  156. package/dist/lite/architecture/decisions/ADR-029-release-pipeline.md +79 -0
  157. package/dist/lite/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
  158. package/dist/lite/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
  159. package/dist/lite/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
  160. package/dist/lite/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
  161. package/dist/lite/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
  162. package/dist/lite/lib/clean-artifacts-sweep.sh +112 -0
  163. package/dist/lite/lib/code-comment-discipline.sh +144 -0
  164. package/dist/lite/lib/composer-preflight.sh +459 -0
  165. package/dist/lite/lib/deferred-actions.sh +146 -0
  166. package/dist/lite/lib/hook-header-parser.sh +61 -0
  167. package/dist/lite/lib/hook-heartbeat.sh +152 -0
  168. package/dist/lite/lib/hook-inject.sh +255 -0
  169. package/dist/lite/lib/hook-installer.sh +195 -0
  170. package/dist/lite/lib/luminary-pick.sh +96 -0
  171. package/dist/lite/lib/output-discipline.sh +143 -0
  172. package/dist/lite/lib/prose-scan-boundary.sh +171 -0
  173. package/dist/lite/lib/rewrite-check.sh +214 -0
  174. package/dist/lite/lib/session-rescue.sh +151 -0
  175. package/dist/lite/lib/source-graph-walker.sh +277 -0
  176. package/dist/lite/lib/state.sh +1372 -0
  177. package/dist/lite/lib/telemetry.sh +205 -0
  178. package/dist/lite/lib/tier-check.sh +187 -0
  179. package/dist/lite/lib/tier-dependency-audit.sh +1088 -0
  180. package/dist/lite/presence/install/bassclef-hook-connect.sh +178 -0
  181. package/dist/lite/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
  182. package/dist/lite/presence/install/bassclef-sync.template.sh +2278 -0
  183. package/dist/lite/presence/install/schedule-auto-save.cron.sh +88 -0
  184. package/dist/lite/presence/install/schedule-auto-save.taskscheduler.md +122 -0
  185. package/dist/lite/scripts/aggregate-telemetry.sh +217 -0
  186. package/dist/lite/scripts/analyze-tier-dependencies.sh +239 -0
  187. package/dist/lite/scripts/generate-lite-manifest.sh +505 -0
  188. package/dist/lite/scripts/generate-tier-manifest.sh +28 -0
  189. package/dist/lite/scripts/intent-drift-check.sh +456 -0
  190. package/dist/lite/scripts/lite-manifest-drift-check.sh +146 -0
  191. package/dist/lite/scripts/render-lite-manifest-doc.sh +150 -0
  192. package/dist/lite/standards/adr-template.md +86 -0
  193. package/dist/lite/standards/api-conventions/nextjs.md +84 -0
  194. package/dist/lite/standards/artifact-composition.md +209 -0
  195. package/dist/lite/standards/bash-hook-safety.md +246 -0
  196. package/dist/lite/standards/bassclef-configs-schema.md +232 -0
  197. package/dist/lite/standards/bassclef-evolution.md +143 -0
  198. package/dist/lite/standards/bassclef-internal-jargon.md +244 -0
  199. package/dist/lite/standards/bassclef-managed-sentinel.md +96 -0
  200. package/dist/lite/standards/bassclef-source-config.md +228 -0
  201. package/dist/lite/standards/branch-stacking.md +408 -0
  202. package/dist/lite/standards/code-safety-principles.md +176 -0
  203. package/dist/lite/standards/composer-prerequisites.md +155 -0
  204. package/dist/lite/standards/deferred-actions-schema.md +204 -0
  205. package/dist/lite/standards/dependency-discipline/cargo.md +39 -0
  206. package/dist/lite/standards/dependency-discipline/gem.md +43 -0
  207. package/dist/lite/standards/dependency-discipline/go-mod.md +41 -0
  208. package/dist/lite/standards/dependency-discipline/npm.md +42 -0
  209. package/dist/lite/standards/dependency-discipline/pip.md +42 -0
  210. package/dist/lite/standards/deployment-topology/ec2-tailscale.md +225 -0
  211. package/dist/lite/standards/deployment-topology.md +69 -0
  212. package/dist/lite/standards/docs-sync-allowlist.md +76 -0
  213. package/dist/lite/standards/domain-and-dns.md +145 -0
  214. package/dist/lite/standards/frontend-stack.md +67 -0
  215. package/dist/lite/standards/frontmatter-schema.md +154 -0
  216. package/dist/lite/standards/graceful-exit.md +227 -0
  217. package/dist/lite/standards/hook-idempotency.md +102 -0
  218. package/dist/lite/standards/hook-injection-discipline.md +202 -0
  219. package/dist/lite/standards/hook-install-class.md +215 -0
  220. package/dist/lite/standards/input-handler-interface.md +152 -0
  221. package/dist/lite/standards/lite-manifest-schema-changes.md +180 -0
  222. package/dist/lite/standards/lite-manifest.json +2797 -0
  223. package/dist/lite/standards/luminary-matching.md +105 -0
  224. package/dist/lite/standards/luminary-problem-patterns.md +481 -0
  225. package/dist/lite/standards/migration-discipline/active-record.md +50 -0
  226. package/dist/lite/standards/migration-discipline/alembic.md +43 -0
  227. package/dist/lite/standards/migration-discipline/gorm.md +50 -0
  228. package/dist/lite/standards/migration-discipline/prisma.md +53 -0
  229. package/dist/lite/standards/migration-discipline/sqlalchemy.md +51 -0
  230. package/dist/lite/standards/mobile-ephemeral-session.md +167 -0
  231. package/dist/lite/standards/model-routing-discipline.md +160 -0
  232. package/dist/lite/standards/ogilvy-writing-rules.md +225 -0
  233. package/dist/lite/standards/opener-discipline.md +96 -0
  234. package/dist/lite/standards/operator-facing-prose-discipline.md +201 -0
  235. package/dist/lite/standards/persona-schema.md +229 -0
  236. package/dist/lite/standards/pluggable-luminaries.md +323 -0
  237. package/dist/lite/standards/pr-body-discipline.md +115 -0
  238. package/dist/lite/standards/preview-state-schema.md +189 -0
  239. package/dist/lite/standards/project-directory-layout.md +276 -0
  240. package/dist/lite/standards/release-tagging.md +137 -0
  241. package/dist/lite/standards/reserved-skill-names.md +120 -0
  242. package/dist/lite/standards/scannable-multi-option-output.md +265 -0
  243. package/dist/lite/standards/sdlc-compliance.md +286 -0
  244. package/dist/lite/standards/sdlc-gates/typescript.md +57 -0
  245. package/dist/lite/standards/secrets-lifecycle.md +210 -0
  246. package/dist/lite/standards/security-scanner-adapter.md +145 -0
  247. package/dist/lite/standards/session-board.md +256 -0
  248. package/dist/lite/standards/skill-output-discipline.md +121 -0
  249. package/dist/lite/standards/state-spine-contract.md +255 -0
  250. package/dist/lite/standards/state-spine.md +511 -0
  251. package/dist/lite/standards/steering-hints/kiss-words.md +11 -0
  252. package/dist/lite/standards/substrate-config-schema.md +267 -0
  253. package/dist/lite/standards/tech-stack-config.md +109 -0
  254. package/dist/lite/standards/tier-dependency-analysis.md +167 -0
  255. package/dist/lite/standards/tier-runtime-deps/lite.md +57 -0
  256. package/dist/lite/standards/tier-tag-schema.md +155 -0
  257. package/dist/lite/standards/two-layer-config.md +99 -0
  258. package/dist/lite/standards/use-case-format.md +292 -0
  259. package/dist/lite/standards/user-story-invest.md +268 -0
  260. package/dist/lite/standards/velocity-and-appetite.md +229 -0
  261. package/dist/lite/standards/voice-input-pattern.md +119 -0
  262. package/dist/lite/standards/whereami-schema.md +301 -0
  263. package/dist/lite/standards/worktree-management.md +211 -0
  264. package/dist/lite/standards/writing-guide.md +213 -0
  265. package/dist/lite/templates/chronicle-template.md +75 -0
  266. package/dist/lite/templates/deferred-action-template.md +45 -0
  267. package/dist/lite/templates/memory-proposal-template.md +77 -0
  268. package/dist/lite/templates/persona-template.md +200 -0
  269. package/dist/lite/templates/pr-faq.md +45 -0
  270. package/dist/lite/templates/secret-rotation-template.md +162 -0
  271. package/dist/lite/templates/spec-template.md +131 -0
  272. package/dist/lite/templates/use-case-template.md +194 -0
  273. package/dist/lite/templates/user-story-template.md +107 -0
  274. package/dist/lite/templates/whereami-template.md +101 -0
  275. 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