@thebassclef/lite 1.9.9 → 1.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lite/.claude/hooks/artifact-ingestion-gate.sh +9 -3
- package/dist/lite/.claude/hooks/pre-commit-gate.sh +31 -0
- package/dist/lite/.claude/hooks/pre-commit-identifier-leak-scrub.sh +58 -2
- package/dist/lite/.claude/hooks/save-state.sh +6 -1
- package/dist/lite/.claude/hooks/session-reflection.d/83-install-written-paths-rebuild.sh +111 -0
- package/dist/lite/.claude/hooks/session-reflection.d/97-last-block-count.sh +53 -0
- package/dist/lite/.claude/hooks/session-reflection.d/tests/97-last-block-count.test.sh +131 -0
- package/dist/lite/.claude/hooks/session-reflection.sh +22 -0
- package/dist/lite/.claude/hooks/state-validate.sh +8 -0
- package/dist/lite/.claude/rules/install-written-paths-mediation.md +74 -0
- package/dist/lite/.claude/rules/last-block-marker.md +79 -0
- package/dist/lite/.claude/skills/autonomous/SKILL.md +53 -7
- package/dist/lite/.claude/skills/build/SKILL.md +41 -5
- package/dist/lite/.claude/skills/deploy-prod/SKILL.md +10 -0
- package/dist/lite/.claude/skills/ia-model/SKILL.md +8 -0
- package/dist/lite/.claude/skills/interaction-design/SKILL.md +8 -0
- package/dist/lite/.claude/skills/jtbd-tasks/SKILL.md +9 -1
- package/dist/lite/.claude/skills/last-block/SKILL.md +99 -0
- package/dist/lite/.claude/skills/launch/SKILL.md +44 -12
- package/dist/lite/.claude/skills/objectory-decompose/SKILL.md +5 -17
- package/dist/lite/.claude/skills/onboard-repo/SKILL.md +18 -18
- package/dist/lite/.claude/skills/personas/SKILL.md +1 -1
- package/dist/lite/.claude/skills/use-case/SKILL.md +5 -4
- package/dist/lite/bassclef-version.json +5 -5
- package/dist/lite/lib/capability-probe.sh +39 -1
- package/dist/lite/lib/composer-preflight.sh +20 -4
- package/dist/lite/lib/install-written-paths.sh +369 -0
- package/dist/lite/lib/last-block.sh +153 -0
- package/dist/lite/lib/luminary-pick.sh +35 -13
- package/dist/lite/lib/state.sh +82 -11
- package/dist/lite/scripts/interpret-input.sh +19 -4
- package/dist/lite/standards/lite-manifest-schema-changes.md +115 -0
- package/dist/lite/standards/lite-manifest.json +80 -26
- package/dist/lite/standards/state-spine.md +1 -0
- package/package.json +2 -2
package/dist/lite/lib/state.sh
CHANGED
|
@@ -40,8 +40,9 @@ __state_check_binary_deps() {
|
|
|
40
40
|
if [ "${__STATE_DEPS_CHECKED:-}" = "1" ]; then
|
|
41
41
|
return 0
|
|
42
42
|
fi
|
|
43
|
+
# Baseline deps — awk + jq required unconditionally
|
|
43
44
|
local missing=""
|
|
44
|
-
for bin in awk
|
|
45
|
+
for bin in awk jq; do
|
|
45
46
|
command -v "$bin" >/dev/null 2>&1 || missing="$missing $bin"
|
|
46
47
|
done
|
|
47
48
|
if [ -n "$missing" ]; then
|
|
@@ -49,21 +50,63 @@ __state_check_binary_deps() {
|
|
|
49
50
|
STATE ACCESSOR FAILURE
|
|
50
51
|
Required binary missing from PATH:$missing
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
YAML frontmatter extraction + JSON tooling).
|
|
53
|
+
awk + jq are load-bearing for lib/state.sh accessors.
|
|
54
54
|
|
|
55
55
|
Resolution:
|
|
56
|
-
macOS: brew install gawk
|
|
57
|
-
Debian: sudo apt-get install gawk
|
|
58
|
-
|
|
59
|
-
Closes the bassclef#598 silent-failure class.
|
|
56
|
+
macOS: brew install gawk jq
|
|
57
|
+
Debian: sudo apt-get install gawk jq
|
|
60
58
|
EOF
|
|
61
59
|
return 4
|
|
62
60
|
fi
|
|
61
|
+
|
|
62
|
+
# Per cli#308: YAML parser needs EITHER yq OR python3+PyYAML.
|
|
63
|
+
# Stock macOS has python3 but not PyYAML. Pre-cli#308, that mismatch
|
|
64
|
+
# caused silent failures where __state_check_binary_deps passed but
|
|
65
|
+
# the actual yaml parse failed with ModuleNotFoundError. Now we check
|
|
66
|
+
# that at least one working parser exists.
|
|
67
|
+
__state_check_yaml_parser || return 6
|
|
63
68
|
export __STATE_DEPS_CHECKED=1
|
|
64
69
|
return 0
|
|
65
70
|
}
|
|
66
71
|
|
|
72
|
+
# YAML parser check (per cli#308). Returns 0 if yq available OR
|
|
73
|
+
# python3+yaml-module importable. Returns 6 if neither.
|
|
74
|
+
__state_check_yaml_parser() {
|
|
75
|
+
# Cache the result per shell process.
|
|
76
|
+
if [ "${__STATE_YAML_PARSER:-}" = "yq" ] || [ "${__STATE_YAML_PARSER:-}" = "python3" ]; then
|
|
77
|
+
return 0
|
|
78
|
+
fi
|
|
79
|
+
# Prefer yq (faster + simpler contract).
|
|
80
|
+
if command -v yq >/dev/null 2>&1; then
|
|
81
|
+
export __STATE_YAML_PARSER=yq
|
|
82
|
+
return 0
|
|
83
|
+
fi
|
|
84
|
+
# Fall back to python3+PyYAML.
|
|
85
|
+
if command -v python3 >/dev/null 2>&1 && python3 -c "import yaml" >/dev/null 2>&1; then
|
|
86
|
+
export __STATE_YAML_PARSER=python3
|
|
87
|
+
return 0
|
|
88
|
+
fi
|
|
89
|
+
cat >&2 <<EOF
|
|
90
|
+
STATE ACCESSOR FAILURE — no YAML parser available (per cli#308)
|
|
91
|
+
|
|
92
|
+
lib/state.sh needs ONE of:
|
|
93
|
+
- yq (preferred — faster, no Python module needed)
|
|
94
|
+
- python3 + PyYAML module
|
|
95
|
+
|
|
96
|
+
Both are missing on this machine.
|
|
97
|
+
|
|
98
|
+
Resolution:
|
|
99
|
+
macOS (preferred): brew install yq
|
|
100
|
+
macOS (alt): python3 -m pip install pyyaml
|
|
101
|
+
Debian: sudo apt-get install yq OR python3 -m pip install pyyaml
|
|
102
|
+
|
|
103
|
+
Per cli#308 — this check closes the silent-failure class where
|
|
104
|
+
python3 existed but PyYAML did not, and callers reported "goal not
|
|
105
|
+
found" (wrong diagnosis).
|
|
106
|
+
EOF
|
|
107
|
+
return 6
|
|
108
|
+
}
|
|
109
|
+
|
|
67
110
|
# yq2json — extract YAML frontmatter from markdown file, emit JSON.
|
|
68
111
|
# Used by Shape B (markdown + YAML frontmatter + body) entity accessors.
|
|
69
112
|
#
|
|
@@ -86,7 +129,7 @@ EOF
|
|
|
86
129
|
# on invalid input) + @luminary michael-feathers (characterization
|
|
87
130
|
# tests RED-first via fixtures/2026-09-06-silent-empty/).
|
|
88
131
|
__state_yq2json() {
|
|
89
|
-
__state_check_binary_deps || return
|
|
132
|
+
__state_check_binary_deps || return $?
|
|
90
133
|
local file="$1"
|
|
91
134
|
if [ ! -f "$file" ]; then
|
|
92
135
|
return 1
|
|
@@ -127,7 +170,23 @@ __state_yq2json() {
|
|
|
127
170
|
|
|
128
171
|
local out
|
|
129
172
|
local ec
|
|
130
|
-
|
|
173
|
+
# Per cli#308 — prefer yq when available, fall back to python3+PyYAML.
|
|
174
|
+
# __state_check_binary_deps (called at top of this function via return 4
|
|
175
|
+
# path) already resolved __STATE_YAML_PARSER to one of the two.
|
|
176
|
+
if [ "${__STATE_YAML_PARSER:-}" = "yq" ]; then
|
|
177
|
+
out=$(awk '/^---$/{c++; next} c==1' "$file" | yq -o=json '.' 2>&1)
|
|
178
|
+
ec=$?
|
|
179
|
+
if [ "$ec" -ne 0 ]; then
|
|
180
|
+
printf 'yaml parse failed (yq): %s\n' "$out" >&2
|
|
181
|
+
return 3
|
|
182
|
+
fi
|
|
183
|
+
# yq returns `null` for empty input; coerce to `{}` for consistency
|
|
184
|
+
# with python3 path.
|
|
185
|
+
if [ "$out" = "null" ]; then
|
|
186
|
+
out="{}"
|
|
187
|
+
fi
|
|
188
|
+
else
|
|
189
|
+
out=$(awk '/^---$/{c++; next} c==1' "$file" | python3 -c "
|
|
131
190
|
import sys, yaml, json
|
|
132
191
|
try:
|
|
133
192
|
data = yaml.safe_load(sys.stdin) or {}
|
|
@@ -136,7 +195,8 @@ except Exception as e:
|
|
|
136
195
|
print(f'yaml parse failed: {e}', file=sys.stderr)
|
|
137
196
|
sys.exit(3)
|
|
138
197
|
")
|
|
139
|
-
|
|
198
|
+
ec=$?
|
|
199
|
+
fi
|
|
140
200
|
# Instrument real-parse count for #1519 tests + observability.
|
|
141
201
|
__STATE_YQ2JSON_PARSE_COUNT=$(( ${__STATE_YQ2JSON_PARSE_COUNT:-0} + 1 ))
|
|
142
202
|
if [ "$ec" -ne 0 ]; then
|
|
@@ -185,7 +245,7 @@ __state_atomic_write() {
|
|
|
185
245
|
# output) + @luminary michael-nygard (silent-fail wrap; write does not
|
|
186
246
|
# crash caller).
|
|
187
247
|
__state_yaml_write() {
|
|
188
|
-
__state_check_binary_deps || return
|
|
248
|
+
__state_check_binary_deps || return $?
|
|
189
249
|
# Finding #6 (#2036): `local path` is a zsh-magic variable name — ties to
|
|
190
250
|
# $PATH when sourced from zsh. Renamed to `local p` throughout this file.
|
|
191
251
|
local p="$1"
|
|
@@ -1030,6 +1090,17 @@ state_reference_get() {
|
|
|
1030
1090
|
marker)
|
|
1031
1091
|
state_marker_get "$id"
|
|
1032
1092
|
;;
|
|
1093
|
+
input-artifact)
|
|
1094
|
+
# InputArtifact — Shape C (pure JSON) per state-spine.md L262.
|
|
1095
|
+
# Added per sunj-labs/bassclef-cli#315: /objectory-decompose Step 1
|
|
1096
|
+
# reads input-artifact via this accessor; without a case the call
|
|
1097
|
+
# exited 5 and the SKILL could not read the artifact in lite.
|
|
1098
|
+
if [ -f "docs/input-artifacts/${id}.json" ]; then
|
|
1099
|
+
cat "docs/input-artifacts/${id}.json"
|
|
1100
|
+
else
|
|
1101
|
+
return 1
|
|
1102
|
+
fi
|
|
1103
|
+
;;
|
|
1033
1104
|
gate)
|
|
1034
1105
|
# Gates derive from Markers; not addressable directly in v0
|
|
1035
1106
|
echo "state_reference_get: gate type derives from Marker; not directly addressable in v0" >&2
|
|
@@ -52,12 +52,14 @@ SOURCE=""
|
|
|
52
52
|
TYPE="auto"
|
|
53
53
|
PERSIST=0
|
|
54
54
|
SLUG=""
|
|
55
|
+
INTENT="" # cli#319 cure — operator intent text; defaults to SOURCE in text mode
|
|
55
56
|
|
|
56
57
|
while [ $# -gt 0 ]; do
|
|
57
58
|
case "$1" in
|
|
58
59
|
--type=*) TYPE="${1#--type=}"; shift ;;
|
|
59
60
|
--persist) PERSIST=1; shift ;;
|
|
60
61
|
--slug=*) SLUG="${1#--slug=}"; shift ;;
|
|
62
|
+
--intent=*) INTENT="${1#--intent=}"; shift ;; # cli#319
|
|
61
63
|
--help|-h) usage; exit 0 ;;
|
|
62
64
|
--*) echo "interpret-input: unknown flag '$1'" >&2; usage >&2; exit 2 ;;
|
|
63
65
|
*)
|
|
@@ -117,7 +119,15 @@ fi
|
|
|
117
119
|
|
|
118
120
|
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
# cli#319 cure — default INTENT to SOURCE in text mode; empty otherwise.
|
|
123
|
+
# /pick-luminaries matches intent against the luminary catalog; an empty
|
|
124
|
+
# intent is explicitly valid (adopters may inject it later), but text input
|
|
125
|
+
# carries operator intent in SOURCE already — reuse it as a safe default.
|
|
126
|
+
if [ -z "$INTENT" ] && [ "$TYPE" = "text" ]; then
|
|
127
|
+
INTENT="$SOURCE"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
STRUCTURAL_HINTS='{"verb_goal_pairs": []}'
|
|
121
131
|
|
|
122
132
|
case "$TYPE" in
|
|
123
133
|
text)
|
|
@@ -149,7 +159,7 @@ case "$TYPE" in
|
|
|
149
159
|
if [ -z "$REPO_LOCAL" ]; then
|
|
150
160
|
# Source can't be resolved; return Phase B-style stub (still valid InputArtifact)
|
|
151
161
|
EXTRACTED_TEXT="deferred to Phase C"
|
|
152
|
-
STRUCTURAL_HINTS='{}'
|
|
162
|
+
STRUCTURAL_HINTS='{"verb_goal_pairs": []}'
|
|
153
163
|
else
|
|
154
164
|
EXTRACT_OUT=$(bash "$REPO_ROOT/scripts/interpret-input/extract-repo.sh" "$REPO_LOCAL" 2>/dev/null)
|
|
155
165
|
EXTRACT_RC=$?
|
|
@@ -160,10 +170,13 @@ case "$TYPE" in
|
|
|
160
170
|
|
|
161
171
|
if [ "$EXTRACT_RC" != "0" ] || [ -z "$EXTRACT_OUT" ]; then
|
|
162
172
|
EXTRACTED_TEXT="repo extraction returned no signal for $SOURCE"
|
|
163
|
-
STRUCTURAL_HINTS='{}'
|
|
173
|
+
STRUCTURAL_HINTS='{"verb_goal_pairs": []}'
|
|
164
174
|
else
|
|
165
175
|
EXTRACTED_TEXT=$(echo "$EXTRACT_OUT" | jq -r '.extracted_text')
|
|
166
|
-
|
|
176
|
+
# cli#312 cure — merge default verb_goal_pairs: [] so downstream readers
|
|
177
|
+
# (/build, /launch templates) always find the key even when extract
|
|
178
|
+
# doesn't produce it. Extract wins on any key it does emit.
|
|
179
|
+
STRUCTURAL_HINTS=$(echo "$EXTRACT_OUT" | jq -c '{verb_goal_pairs: []} + .structural_hints')
|
|
167
180
|
fi
|
|
168
181
|
fi
|
|
169
182
|
EXTERNAL_URLS='[]'
|
|
@@ -179,6 +192,7 @@ ARTIFACT=$(jq -n \
|
|
|
179
192
|
--arg type "$TYPE" \
|
|
180
193
|
--arg source "$SOURCE" \
|
|
181
194
|
--arg extracted_text "$EXTRACTED_TEXT" \
|
|
195
|
+
--arg intent "$INTENT" \
|
|
182
196
|
--arg created_at "$NOW" \
|
|
183
197
|
--argjson external_urls "$EXTERNAL_URLS" \
|
|
184
198
|
--argjson structural_hints "$STRUCTURAL_HINTS" \
|
|
@@ -187,6 +201,7 @@ ARTIFACT=$(jq -n \
|
|
|
187
201
|
type: $type,
|
|
188
202
|
source: $source,
|
|
189
203
|
extracted_text: $extracted_text,
|
|
204
|
+
intent: $intent,
|
|
190
205
|
structural_hints: $structural_hints,
|
|
191
206
|
external_urls: $external_urls,
|
|
192
207
|
created_at: $created_at
|
|
@@ -34,6 +34,121 @@ Every entry stays in this file for the life of the manifest. Never pruned. When
|
|
|
34
34
|
|
|
35
35
|
## Entries (newest first)
|
|
36
36
|
|
|
37
|
+
### cli#319 — interpret-input writes intent field (v1.16.9 → v1.16.10, 2026-10-07)
|
|
38
|
+
|
|
39
|
+
- **Change type:** content-change (1 file: `scripts/interpret-input.sh`). Script now emits `intent` field in input-artifact JSON. Prior shape omitted it.
|
|
40
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `interpret-input` script slug.
|
|
41
|
+
- **Version bump:** v1.16.9 → v1.16.10 (patch — content-only change on 1 slug; rides on top of cli#312 v1.16.9 bump).
|
|
42
|
+
- **Rationale:** bassclef-cli#319 — Kunal cold-adopter smoke caught downstream readers (`/launch`, `/build`) needing the intent field + missing on artifact JSON. Per PR #2105.
|
|
43
|
+
- **Downstream cure:** no action for adopters at exact-pin. Downstream readers now get a stable intent key.
|
|
44
|
+
- **Old shape retired:** nothing retired. Additive key.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### cli#312 — interpret-input emits verb_goal_pairs default (v1.16.8 → v1.16.9, 2026-10-07)
|
|
48
|
+
|
|
49
|
+
- **Change type:** content-change (1 file: `scripts/interpret-input.sh`). Script now writes `structural_hints.verb_goal_pairs` as an empty array when no pairs detected. Prior code omitted the key.
|
|
50
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `interpret-input` script slug.
|
|
51
|
+
- **Version bump:** v1.16.8 → v1.16.9 (patch — content-only change on 1 slug; rides on top of cli#324 v1.16.8 bump).
|
|
52
|
+
- **Rationale:** bassclef-cli#312 — Kunal cold-adopter smoke caught downstream readers tripping on missing key. Default-empty-array is defensive. Per PR #2104.
|
|
53
|
+
- **Downstream cure:** no action for adopters at exact-pin. Downstream readers of `structural_hints.verb_goal_pairs` get a consistent array shape.
|
|
54
|
+
- **Old shape retired:** nothing retired. Behavior is additive — the key always exists now; readers that handled missing-key still work.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### cli#324 — /launch Phase 11 greenfield partial vs redesign full (v1.16.7 → v1.16.8, 2026-10-07)
|
|
58
|
+
|
|
59
|
+
- **Change type:** content-change (1 file: `.claude/skills/launch/SKILL.md`). Phase 11 now distinguishes greenfield partial-fit from redesign full-fit. Prior behavior conflated both cases.
|
|
60
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `launch` skill slug.
|
|
61
|
+
- **Version bump:** v1.16.7 → v1.16.8 (patch — content-only change on 1 slug; rides on top of cli#322 v1.16.7 bump).
|
|
62
|
+
- **Rationale:** bassclef-cli#324 — Kunal cold-adopter smoke caught `/launch` Phase 11 misreading greenfield intents as redesign full-reshape. Partial-fit path missing. Per PR #2103.
|
|
63
|
+
- **Downstream cure:** no action for adopters at exact-pin. Phase 11 now reads adopter intent + routes to partial OR full. Prior sessions that hit full-reshape see no regression (full stays as-is).
|
|
64
|
+
- **Old shape retired:** nothing retired. Phase 11 branch is additive.
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### cli#322 — /launch Phase 14 jargon gate (v1.16.6 → v1.16.7, 2026-10-07)
|
|
68
|
+
|
|
69
|
+
- **Change type:** content-change (1 file: `.claude/skills/launch/SKILL.md`). Phase 14 template now runs a jargon gate on the output before writing. Prior behavior shipped jargon through.
|
|
70
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `launch` skill slug.
|
|
71
|
+
- **Version bump:** v1.16.6 → v1.16.7 (patch — content-only change on 1 slug; rides on top of cli#309 v1.16.6 bump).
|
|
72
|
+
- **Rationale:** bassclef-cli#322 — Kunal cold-adopter smoke caught `/launch` Phase 14 shipping bassclef-internal jargon into adopter-facing output. Per PR #2100.
|
|
73
|
+
- **Downstream cure:** no action for adopters at exact-pin. Phase 14 now surfaces jargon via gate before write.
|
|
74
|
+
- **Old shape retired:** nothing retired. Gate is additive.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### cli#309 — /build hosting_platform=none warns (v1.16.5 → v1.16.6, 2026-10-07)
|
|
78
|
+
|
|
79
|
+
- **Change type:** content-change (1 file: `lib/composer-preflight.sh`). Helper now warns + continues when hosting_platform=none instead of refusing. Prior code refused unconditionally.
|
|
80
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `composer-preflight` lib slug.
|
|
81
|
+
- **Version bump:** v1.16.5 → v1.16.6 (patch — content-only change on 1 slug; rides on top of cli#311 v1.16.5 bump).
|
|
82
|
+
- **Rationale:** bassclef-cli#309 — Kunal cold-adopter smoke caught `/build` refusing when adopter opted out of hosting. Local-only builds are a valid shape. Per PR #2101.
|
|
83
|
+
- **Downstream cure:** no action for adopters at exact-pin. Local-only builds (hosting_platform=none) now warn + proceed.
|
|
84
|
+
- **Old shape retired:** nothing retired. Behavior is additive — refuse stays for other invalid states.
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### cli#311 — artifact-ingestion-gate skip when parent_bet is null (v1.16.4 → v1.16.5, 2026-10-07)
|
|
88
|
+
|
|
89
|
+
- **Change type:** content-change (1 file: `.claude/hooks/artifact-ingestion-gate.sh`). Hook now skips the goal-doc parent-walk when the active goal declares `parent_bet: null` in frontmatter. Prior behavior treated null as missing + fired BLOCK on orientation-gate.
|
|
90
|
+
- **Fields:** 448 entries (unchanged). Content hash shifts on the `artifact-ingestion-gate` hook slug.
|
|
91
|
+
- **Version bump:** v1.16.4 → v1.16.5 (patch — content-only change on 1 slug; no entry count change).
|
|
92
|
+
- **Rationale:** bassclef-cli#311 — Kunal cold-adopter smoke caught the orientation-gate firing BLOCK on root-level goals (no parent). Null parent_bet is valid state for arc-root goals; the gate was treating it as unresolved reference. Per PR #2102.
|
|
93
|
+
- **Downstream cure:** no action for adopters at exact-pin. Root goals with `parent_bet: null` stop firing BLOCK at session-start; existing goals with non-null parents still get the walk.
|
|
94
|
+
- **Old shape retired:** nothing retired. Null-parent-bet branch is additive on top of existing walk logic.
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
### #2036 Finding #10 — /last-block skill + marker format (v1.15.5 → v1.16.0, 2026-10-06)
|
|
98
|
+
|
|
99
|
+
- **Change type:** content-add (4 new files: `.claude/skills/last-block/SKILL.md`, `lib/last-block.sh`, `.claude/rules/last-block-marker.md`, `.claude/hooks/session-reflection.d/97-last-block-count.sh`). New skill that prints the exact text of a BLOCK or guardrail banner from this session or prior. New marker format at `state/last-block/<slug>.md`.
|
|
100
|
+
- **Fields:** 448 entries (+4 from 444). Four new slugs — skill `last-block`, lib `last-block`, rule `last-block-marker`, hook `97-last-block-count`.
|
|
101
|
+
- **Version bump:** v1.15.5 → v1.16.0 (minor — content-add of 4 new lite slugs). Rides on top of Finding #7 which landed first (v1.15.4 → v1.15.5).
|
|
102
|
+
- **Rationale:** Kunal v1.6.4 adopter run — "I saw a BLOCK banner scroll off the top of the terminal. No way to read it again." Finding #10 adds `/last-block` for recall + a hook that counts markers at session-reflection time. Per bassclef-upstream#2036 Finding #10 + PR #2061.
|
|
103
|
+
- **Downstream cure:** no action for adopters at exact-pin. Four new files land on next sync — all `tier: lite` so every tier picks them up. No shape change on existing slugs.
|
|
104
|
+
- **Old shape retired:** nothing retired (content-add only).
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
### cli#305 — identifier-leak scrub self-exclude + commit author check (v1.15.3 → v1.15.4, 2026-10-04)
|
|
108
|
+
|
|
109
|
+
- **Change type:** content-change (1 file: `.claude/hooks/pre-commit-identifier-leak-scrub.sh`). Check 2 now filters out hunks from the hook's own files, its test, the rule, and the pattern source. Check 3 added — scans `git var GIT_AUTHOR_IDENT` for the pattern set plus the `.local` suffix. BLOCK banner adds a resolution path pointing at the GitHub no-reply address.
|
|
110
|
+
- **Fields:** 444 entries (unchanged). Content hash shifts on the `pre-commit-identifier-leak-scrub` hook slug.
|
|
111
|
+
- **Version bump:** v1.15.3 → v1.15.4 (patch — content-only change on 1 slug; no entry count change). Rides on top of the Finding #7 bump (v1.15.3) when PRs land in order.
|
|
112
|
+
- **Rationale:** Kunal cli#305 — first commit after `bassclef init` blocked on the check's own files; author identity leaked silently when `user.email` was unset on Mac. Class A identity leak sister to cli#313 + cli#320 shipped in v1.15.2. Per PR #2062 (planned).
|
|
113
|
+
- **Downstream cure:** no action for adopters at exact-pin. Self-exclude paths are PATH-scoped, not pattern-scoped — leaks moved into non-self files still block. Author check is additive; adopters with clean emails see no change. Adopters whose git author ends in `.local` or carries a hostname pattern see the new BLOCK with a recipe pointing at `<username>@users.noreply.github.com`.
|
|
114
|
+
- **Old shape retired:** nothing retired. Check 1 (message) + Check 2 (staged content, now filtered) + Check 3 (author) chain is additive.
|
|
115
|
+
|
|
116
|
+
### #2036 Finding #7 — Playwright probe file-based fallback (v1.15.4 → v1.15.5, 2026-10-05)
|
|
117
|
+
|
|
118
|
+
- **Change type:** content-change (1 file: `lib/capability-probe.sh`). `probe_mcp_playwright()` extended with four MCP config file fallback paths after the `CLAUDE_MCP_PLAYWRIGHT` env-var fast path. Fail-soft on missing `jq` + malformed JSON.
|
|
119
|
+
- **Fields:** 444 entries (unchanged). Content hash shifts on the `capability-probe` lib slug.
|
|
120
|
+
- **Version bump:** v1.15.4 → v1.15.5 (patch — content-change on existing lib slug per policy). Rebased on top of cli#305 which landed first.
|
|
121
|
+
- **Rationale:** Kunal v1.6.4 adopter run installed Playwright MCP but did not set `CLAUDE_MCP_PLAYWRIGHT`; probe returned 1; `/riff` + `/build` skipped screenshots. Fallback now reads `.mcp.json`, project + user `.claude/settings.json`, and `~/.claude.json`. Per bassclef-upstream#2036 Finding #7 + PR #2060.
|
|
122
|
+
- **Downstream cure:** nothing — byte-for-byte unchanged when `CLAUDE_MCP_PLAYWRIGHT` is set (fast path first). Adopters without the env var set gain file-based detection on the fly.
|
|
123
|
+
- **Old shape retired:** immediately (new behavior is additive).
|
|
124
|
+
|
|
125
|
+
### cli#313 + cli#320 — identity-leak sweep in luminary-pick + personas (v1.15.1 → v1.15.2, 2026-10-04)
|
|
126
|
+
|
|
127
|
+
- **Change type:** content-change (2 files: `lib/luminary-pick.sh` + `.claude/skills/personas/SKILL.md`). luminary-pick basedir fallback moves from `$HOME/src/sunj-labs/bassclef` to `$CLAUDE_PROJECT_DIR` → `git rev-parse` → `pwd` chain, plus adds `.claude/luminaries/*.md` catalog fallback for lite tier. personas SKILL default slug changes from email-derived (`operator-[local-part]`) to plain `operator` (never from email).
|
|
128
|
+
- **Fields:** 444 entries (unchanged). Content hash shifts on the `luminary-pick` lib slug + `personas` skill slug.
|
|
129
|
+
- **Version bump:** v1.15.1 → v1.15.2 (patch; content-only on 2 slugs; no schema shape shift; no entry count change).
|
|
130
|
+
- **Rationale:** bassclef-cli#313 (luminary-pick hardcoded eng path; adopters hit "catalog dir missing" every /launch Phase 3.5) + bassclef-cli#320 (operator slug derived from git email leaked GitHub account ID into committed docs). Kunal cold-adopter smoke caught both; shared class is "engineering assumption in cold paths" (per plan doc Slot 3).
|
|
131
|
+
- **Downstream cure:** no action for adopters at exact-pin. Both changes are additive — lite tier adopters now get a working picker catalog; email-derived slugs never fire again. Operators wanting a display name beyond `operator` get an in-turn prompt instead.
|
|
132
|
+
- **Old shape retired:** nothing retired. Both old shapes stay viable (BASSCLEF_DIR env var still honored first; manual slug entry still allowed via operator reply).
|
|
133
|
+
|
|
134
|
+
### cli#307 — /build Phase 0 awk matches Step-N + WU-N (v1.15.0 → v1.15.1, 2026-10-04)
|
|
135
|
+
|
|
136
|
+
- **Change type:** content-change (1 file: `.claude/skills/build/SKILL.md`). Phase 0 safety floor awk pattern + prose at L276 updated to recognize both `### Step-N` (new vocab per ADR-040 D1) and `### WU-N` (legacy).
|
|
137
|
+
- **Fields:** 444 entries (unchanged). Content hash shifts on the `build` skill slug.
|
|
138
|
+
- **Version bump:** v1.15.0 → v1.15.1 (patch; content-only change on 1 slug; no schema shape shift; no entry count change).
|
|
139
|
+
- **Rationale:** bassclef-cli#307 — Kunal cold-adopter smoke caught the Phase 0 awk reading zero acceptance lines on Step-format specs. Partial-rename regression from ADR-040 D1 (Phase 1 grep got the rename, Phase 0 awk was missed).
|
|
140
|
+
- **Downstream cure:** no action for adopters at exact-pin — the fix is additive (both heading forms match). Step-format specs now trigger the floor as designed. WU-format specs continue to work (characterization).
|
|
141
|
+
- **Old shape retired:** nothing retired. The WU-only pattern leaves. The `(Step|WU)-` pattern stays indefinitely.
|
|
142
|
+
|
|
143
|
+
### #2036 — install-written-paths manifest + lib + rule (v1.14.4 → v1.15.0, 2026-10-03)
|
|
144
|
+
|
|
145
|
+
- **Change type:** content-add (3 new entries: `lib/install-written-paths.sh`, `.claude/rules/install-written-paths-mediation.md`, `.claude/hooks/session-reflection.d/83-install-written-paths-rebuild.sh`); content-change on `.claude/hooks/pre-commit-gate.sh` (filter block added for Kunal Finding #8 cure).
|
|
146
|
+
- **Fields:** 441 entries → 444 entries (3 adds, 1 content_hash shift).
|
|
147
|
+
- **Version bump:** v1.14.4 → v1.15.0 (content-add MINOR per discipline policy).
|
|
148
|
+
- **Rationale:** bassclef-upstream#2036 Finding #8 structural cure. See `architecture/reviews/2026-10-03.md` + plan doc `docs/next-session-plan-2026-10-04-kunal-slots-5-6.md` Slot 5.
|
|
149
|
+
- **Downstream cure:** no action for adopters at exact-pin — the new entries are additive and the lib's accessor API is new. Adopters pulling at `@thebassclef/lite@^1.15.0` get the cure automatically; the session-start fragment regenerates the install-written-paths manifest on first fresh-install session.
|
|
150
|
+
- **Old shape retired:** nothing retired. All existing entries preserved.
|
|
151
|
+
|
|
37
152
|
### #1777 — friction hook pattern adds stage|launch new skill vocabulary (v1.14.2 → v1.14.3, 2026-10-01)
|
|
38
153
|
|
|
39
154
|
- **Change type:** content-change (1 file: `post-skill-friction-check` hook)
|