@thebassclef/lite 1.4.0 → 1.5.1
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/.bassclef-source.json +2 -2
- package/dist/lite/.claude/hooks/_lib/wirings.sh +237 -0
- package/dist/lite/.claude/hooks/pre-commit-manifest-autoregen.sh +212 -0
- package/dist/lite/.claude/hooks/session-reflection.d/08-settings-drift.sh +66 -6
- package/dist/lite/.claude/hooks/session-reflection.d/20-artifact-staleness.sh +25 -5
- package/dist/lite/.claude/hooks/session-reflection.d/30-metrics-staleness.sh +11 -0
- package/dist/lite/.claude/hooks/session-reflection.d/60-deferred-actions.sh +2 -1
- package/dist/lite/.claude/hooks/session-reflection.d/80-hook-heartbeat-check.sh +20 -0
- package/dist/lite/.claude/hooks/session-reflection.d/tests/20-artifact-staleness.test.sh +89 -0
- package/dist/lite/.claude/hooks/session-reflection.sh +12 -1
- package/dist/lite/.claude/luminaries/david-farley.md +115 -0
- package/dist/lite/.claude/luminaries/jez-humble.md +124 -0
- package/dist/lite/.claude/luminaries/martin-fowler.md +18 -0
- package/dist/lite/.claude/skills/longrun/SKILL.md +51 -0
- package/dist/lite/.claude/skills/onboard-repo/SKILL.md +39 -11
- package/dist/lite/.claude/skills/provision-deploy-host/SKILL.md +2 -2
- package/dist/lite/lib/ancestor-claude-check.sh +101 -0
- package/dist/lite/lib/fixture-builder.sh +324 -0
- package/dist/lite/lib/mechanism-fidelity.sh +14 -0
- package/dist/lite/lib/workflow-metrics.sh +166 -0
- package/dist/lite/presence/install/bassclef-configs.template.jsonc +76 -0
- package/dist/lite/presence/install/bassclef-sync.template.sh +7 -4
- package/dist/lite/scripts/generate-lite-manifest.sh +151 -1
- package/dist/lite/scripts/workflow-metrics-query.sh +57 -0
- package/dist/lite/standards/lite-manifest-schema-changes.md +24 -0
- package/dist/lite/standards/lite-manifest.json +82 -71
- package/dist/lite/standards/mechanism-fidelity.md +1 -0
- package/dist/lite/standards/substrate-config-schema.md +2 -2
- package/package.json +1 -1
- package/dist/lite/.claude/skills/journal-export/SKILL.md +0 -293
- package/dist/lite/.claude/skills/release/SKILL.md +0 -311
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{ "tier": "lite",
|
|
2
|
+
// Adopter-facing default for `.claude/bassclef-configs.jsonc`.
|
|
3
|
+
// Ships via lite manifest per bassclef-cli#104. `bassclef init` copies this
|
|
4
|
+
// file to `.claude/bassclef-configs.jsonc` on first-run. Adopters edit it
|
|
5
|
+
// to tune per-repo behavior.
|
|
6
|
+
//
|
|
7
|
+
// Full field catalog + validation: standards/state-spine/schemas/bassclef-configs.schema.json
|
|
8
|
+
// Field reference doc: standards/bassclef-configs-schema.md
|
|
9
|
+
//
|
|
10
|
+
// Every field below is optional. Absent fields fall back to substrate defaults.
|
|
11
|
+
// ----- tech stack -----
|
|
12
|
+
// Declares your primary framework so per-stack skills (SDLC gates,
|
|
13
|
+
// dependency check, migration discipline) load the right sibling docs.
|
|
14
|
+
// Common values: "nextjs", "vite-react", "remix", "fastapi", "rails",
|
|
15
|
+
// "express", "go-http", or omit for framework-agnostic.
|
|
16
|
+
//
|
|
17
|
+
// "tech_stack": {
|
|
18
|
+
// "frontend": "nextjs",
|
|
19
|
+
// "pkg_manager": "pnpm",
|
|
20
|
+
// "orm": "prisma",
|
|
21
|
+
// "lang": "typescript"
|
|
22
|
+
// },
|
|
23
|
+
|
|
24
|
+
// ----- prose discipline -----
|
|
25
|
+
// Controls the /kiss words Stop hook. Values:
|
|
26
|
+
// true — advisory (default; findings to stderr, session continues)
|
|
27
|
+
// "strict" — blocks the stop on jargon findings, forces a rewrite turn
|
|
28
|
+
// false — disabled
|
|
29
|
+
//
|
|
30
|
+
// "prose_discipline": {
|
|
31
|
+
// "kiss_words_turn_prose": true
|
|
32
|
+
// },
|
|
33
|
+
|
|
34
|
+
// ----- testing tier per path -----
|
|
35
|
+
// Extends .claude/rules/testing-tier-config.md with per-repo path matchers.
|
|
36
|
+
// Tier 0 = strict TDD (test mtime <= source mtime, BLOCK at pre-commit)
|
|
37
|
+
// Tier 1 = test-with (WARN at pre-commit if new source has no matching test)
|
|
38
|
+
// Tier 2 = smoke (advisory)
|
|
39
|
+
// Tier 3 = manual verify (silent)
|
|
40
|
+
//
|
|
41
|
+
// "testing": {
|
|
42
|
+
// "global_floor": 1,
|
|
43
|
+
// "path_matchers": [
|
|
44
|
+
// { "match": "src/middleware.ts", "tier": 0 },
|
|
45
|
+
// { "match": "src/lib/auth/**", "tier": 0 },
|
|
46
|
+
// { "match": "src/app/**", "tier": 2 }
|
|
47
|
+
// ]
|
|
48
|
+
// },
|
|
49
|
+
|
|
50
|
+
// ----- /promote target -----
|
|
51
|
+
// Where /promote sends substrate proposals. Two shapes:
|
|
52
|
+
// "<owner>/<repo>" — gh issue create --repo <value>
|
|
53
|
+
// "email:<address>" — mailto: URL printed for you to send
|
|
54
|
+
// Absent — /promote falls back to current-repo filing.
|
|
55
|
+
//
|
|
56
|
+
// "promote_target": "your-org/your-substrate-fork",
|
|
57
|
+
|
|
58
|
+
// ----- longrun orchestrator merge mode -----
|
|
59
|
+
// Controls how /longrun handles PR merges within its bet scope.
|
|
60
|
+
// "operator-gated" — every PR pauses for your review (default)
|
|
61
|
+
// "agent-merges-within-scope" — orchestrator merges autonomously within
|
|
62
|
+
// bet scope; hard_ceilings stay blocking
|
|
63
|
+
//
|
|
64
|
+
// "longrun": {
|
|
65
|
+
// "orchestrator_merge": {
|
|
66
|
+
// "mode": "operator-gated",
|
|
67
|
+
// "hard_ceilings": ["auth", "schema", "security", "prod-deploy", "blast-radius-floor"]
|
|
68
|
+
// }
|
|
69
|
+
// },
|
|
70
|
+
|
|
71
|
+
// ----- adopter defaults -----
|
|
72
|
+
// Per-adopter tunings. See standards/bassclef-configs-schema.md
|
|
73
|
+
// for the full field list.
|
|
74
|
+
//
|
|
75
|
+
// "adopter_defaults": {}
|
|
76
|
+
}
|
|
@@ -2178,10 +2178,13 @@ echo ""
|
|
|
2178
2178
|
# === 6. Boot check — only report what's missing ===
|
|
2179
2179
|
MISSING=""
|
|
2180
2180
|
|
|
2181
|
-
# Google service account (needed for
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2181
|
+
# Google service account (needed for journal → Google Docs)
|
|
2182
|
+
# Ship 1 (#1816): env var lookup; unset = feature disabled.
|
|
2183
|
+
# Operator sets BASSCLEF_GCLOUD_KEY in their shell profile pointing at their
|
|
2184
|
+
# service-account JSON. Adopters without a Google Docs pipeline leave it unset.
|
|
2185
|
+
SA_KEY="${BASSCLEF_GCLOUD_KEY:-}"
|
|
2186
|
+
if [ -n "$SA_KEY" ] && [ ! -f "$SA_KEY" ]; then
|
|
2187
|
+
MISSING="${MISSING}\n- Google Docs service account key missing at \$BASSCLEF_GCLOUD_KEY (needed for /journal → Google Doc push)"
|
|
2185
2188
|
fi
|
|
2186
2189
|
|
|
2187
2190
|
# gh CLI auth (needed for /promote, issue creation)
|
|
@@ -30,7 +30,11 @@
|
|
|
30
30
|
|
|
31
31
|
set -euo pipefail
|
|
32
32
|
|
|
33
|
-
MANIFEST_VERSION
|
|
33
|
+
# Bug 2 fix (#1829): MANIFEST_VERSION was hardcoded here; dry-run always
|
|
34
|
+
# emitted the compile-time value regardless of on-disk manifest state,
|
|
35
|
+
# so the pre-commit auto-regen hook saw phantom version drift on every
|
|
36
|
+
# commit and bumped needlessly. Now resolved dynamically from the on-disk
|
|
37
|
+
# manifest AFTER OUTPUT_PATH is set (see below).
|
|
34
38
|
|
|
35
39
|
# --- arg parse ---
|
|
36
40
|
DRY_RUN=0
|
|
@@ -94,6 +98,16 @@ if [[ -z "$OUTPUT_PATH" ]]; then
|
|
|
94
98
|
OUTPUT_PATH="${REPO_ROOT}/${TARGET_TIER}-manifest.json"
|
|
95
99
|
fi
|
|
96
100
|
|
|
101
|
+
# --- resolve MANIFEST_VERSION dynamically (Bug 2 fix per #1829) ---
|
|
102
|
+
# Read from on-disk manifest so dry-run + write emit the SAME version.
|
|
103
|
+
# Callers that need to bump the version (pre-commit auto-regen hook)
|
|
104
|
+
# apply the bump AFTER regen via jq. Default 0.0.0 when no manifest exists.
|
|
105
|
+
if [[ -f "$OUTPUT_PATH" ]]; then
|
|
106
|
+
MANIFEST_VERSION=$(jq -r '.manifest_version // "0.0.0"' "$OUTPUT_PATH" 2>/dev/null || echo "0.0.0")
|
|
107
|
+
else
|
|
108
|
+
MANIFEST_VERSION="0.0.0"
|
|
109
|
+
fi
|
|
110
|
+
|
|
97
111
|
# --- generation metadata ---
|
|
98
112
|
GENERATED_AT="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
|
|
99
113
|
UPSTREAM_COMMIT="$(cd "$REPO_ROOT" && git rev-parse HEAD 2>/dev/null || echo '0000000000000000000000000000000000000000')"
|
|
@@ -140,6 +154,49 @@ count_hook_tier_declarations() {
|
|
|
140
154
|
|| true
|
|
141
155
|
}
|
|
142
156
|
|
|
157
|
+
# Extract install-class from bash hook file # install-class: header.
|
|
158
|
+
# Ship 1 (#1825): the install-class boundary Gate B reads this per hook
|
|
159
|
+
# to filter operator-scope files from adopter bundles. Values per
|
|
160
|
+
# standards/hook-install-class.md — operator | project | dual.
|
|
161
|
+
# Missing header — grace-window default is "dual" per docs/risk-ledgers/
|
|
162
|
+
# 2026-09-20-ship-1-install-class-boundary.md pre-mortem N2.
|
|
163
|
+
extract_hook_install_class() {
|
|
164
|
+
local val
|
|
165
|
+
val=$(grep -m1 -E '^#[[:space:]]*install-class:[[:space:]]' "$1" 2>/dev/null \
|
|
166
|
+
| sed -E 's/^#[[:space:]]*install-class:[[:space:]]*//' \
|
|
167
|
+
| sed -E 's/[[:space:]]*$//' \
|
|
168
|
+
|| true)
|
|
169
|
+
# Grace-window default per pre-mortem N2 fold — missing header treated as dual.
|
|
170
|
+
echo "${val:-dual}"
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# Gate B — install-class admission check.
|
|
174
|
+
# Returns 0 (admit) when the file belongs in the current TARGET_TIER's bundle
|
|
175
|
+
# based on install-class alone. Returns 1 (reject) when operator-scope in an
|
|
176
|
+
# adopter target. Ship 1 (#1825, #1827, #1828) closes the boundary here.
|
|
177
|
+
check_install_class_admission() {
|
|
178
|
+
local install_class="$1"
|
|
179
|
+
local surface_type="$2"
|
|
180
|
+
# Only enforce on hook + script + presence-template + lib surfaces —
|
|
181
|
+
# skill + rule + luminary + agent + standard + adr do not carry
|
|
182
|
+
# install-class semantics (they are content, not wiring).
|
|
183
|
+
case "$surface_type" in
|
|
184
|
+
hook|script|lib|presence-template) ;;
|
|
185
|
+
*) return 0 ;;
|
|
186
|
+
esac
|
|
187
|
+
# Operator-class always excluded from adopter bundles.
|
|
188
|
+
# Ship 1 grace window (through 2026-10-31 per ADR-031) — allow override
|
|
189
|
+
# for legacy files during rollout via SKIP_INSTALL_CLASS_FILTER.
|
|
190
|
+
if [ "${SKIP_INSTALL_CLASS_FILTER:-0}" = "1" ]; then
|
|
191
|
+
return 0
|
|
192
|
+
fi
|
|
193
|
+
case "$install_class" in
|
|
194
|
+
operator) return 1 ;;
|
|
195
|
+
project|dual) return 0 ;;
|
|
196
|
+
*) return 0 ;;
|
|
197
|
+
esac
|
|
198
|
+
}
|
|
199
|
+
|
|
143
200
|
# Normalize `—` YAML escape to literal em-dash character. Closes
|
|
144
201
|
# bassclef-upstream#1548 — YAML frontmatter with double-quoted strings can
|
|
145
202
|
# carry `—` as a 6-char literal; jq preserves it as `\\u2014` in JSON
|
|
@@ -313,6 +370,21 @@ emit_entries() {
|
|
|
313
370
|
*) continue ;;
|
|
314
371
|
esac
|
|
315
372
|
|
|
373
|
+
# Ship 1 (#1825) Gate B — install-class filter.
|
|
374
|
+
# Excludes operator-scope files from adopter bundles.
|
|
375
|
+
# Only fires on wiring-carrying surface types (hook, script, lib,
|
|
376
|
+
# presence-template). Content surfaces (skill, rule, luminary, agent,
|
|
377
|
+
# standard, adr) pass through.
|
|
378
|
+
case "$surface_type" in
|
|
379
|
+
hook|script|lib|presence-template)
|
|
380
|
+
local install_class
|
|
381
|
+
install_class=$(extract_hook_install_class "$f" || echo "dual")
|
|
382
|
+
if ! check_install_class_admission "$install_class" "$surface_type"; then
|
|
383
|
+
continue
|
|
384
|
+
fi
|
|
385
|
+
;;
|
|
386
|
+
esac
|
|
387
|
+
|
|
316
388
|
case "$slug_from" in
|
|
317
389
|
dirname)
|
|
318
390
|
slug=$(basename "$(dirname "$f")")
|
|
@@ -441,6 +513,13 @@ while IFS= read -r f; do
|
|
|
441
513
|
PRESENCE_TEMPLATE_MD_FILES+=("$f")
|
|
442
514
|
done < <(find "$REPO_ROOT/presence/install" -maxdepth 1 -type f -name '*.md' 2>/dev/null | sort)
|
|
443
515
|
|
|
516
|
+
# Presence templates (jsonc) — Ship 1 (bassclef-cli#104) — configs template
|
|
517
|
+
# ships so `bassclef init` can copy it to adopter's `.claude/bassclef-configs.jsonc`.
|
|
518
|
+
PRESENCE_TEMPLATE_JSONC_FILES=()
|
|
519
|
+
while IFS= read -r f; do
|
|
520
|
+
PRESENCE_TEMPLATE_JSONC_FILES+=("$f")
|
|
521
|
+
done < <(find "$REPO_ROOT/presence/install" -maxdepth 1 -type f -name '*.jsonc' 2>/dev/null | sort)
|
|
522
|
+
|
|
444
523
|
# Templates (md) — per #1392 Shape 3; chronicle-template + iteration-goal etc adopters copy
|
|
445
524
|
TEMPLATE_FILES=()
|
|
446
525
|
while IFS= read -r f; do
|
|
@@ -556,6 +635,9 @@ ENTRIES_JSON=$(
|
|
|
556
635
|
if [[ ${#PRESENCE_TEMPLATE_MD_FILES[@]} -gt 0 ]]; then
|
|
557
636
|
emit_entries "presence-template" extract_yaml_tier extract_yaml_description basename "${PRESENCE_TEMPLATE_MD_FILES[@]}"
|
|
558
637
|
fi
|
|
638
|
+
if [[ ${#PRESENCE_TEMPLATE_JSONC_FILES[@]} -gt 0 ]]; then
|
|
639
|
+
emit_entries "presence-template" extract_json_tier extract_json_description basename "${PRESENCE_TEMPLATE_JSONC_FILES[@]}"
|
|
640
|
+
fi
|
|
559
641
|
if [[ ${#TEMPLATE_FILES[@]} -gt 0 ]]; then
|
|
560
642
|
emit_entries "template" extract_yaml_tier extract_yaml_description basename "${TEMPLATE_FILES[@]}"
|
|
561
643
|
fi
|
|
@@ -644,3 +726,71 @@ else
|
|
|
644
726
|
echo "$MANIFEST_JSON" > "$OUTPUT_PATH"
|
|
645
727
|
echo "Wrote $OUTPUT_PATH ($ENTRY_COUNT entries; commit ${UPSTREAM_COMMIT:0:7})" >&2
|
|
646
728
|
fi
|
|
729
|
+
|
|
730
|
+
# =============================================================
|
|
731
|
+
# Ship 1 (#1827) — Gate C: wiring/file symmetry check
|
|
732
|
+
# =============================================================
|
|
733
|
+
# Post-emit — cross-reference hooks wired in the adopter settings template
|
|
734
|
+
# against hooks emitted in the manifest. Any wiring entry without a
|
|
735
|
+
# matching file entry is a "dead-wired hook" (per #1827). Emits WARNING
|
|
736
|
+
# in V1 (ADVISORY per ADR-031 grace window); flips to BLOCK in V2 after
|
|
737
|
+
# one calibration cycle.
|
|
738
|
+
#
|
|
739
|
+
# Per @luminary linus-torvalds — adopter contract at the boundary.
|
|
740
|
+
# Per @luminary saltzer-schroeder — complete mediation.
|
|
741
|
+
# Per @luminary michael-nygard — stability pattern (fail-visible not fail-silent).
|
|
742
|
+
#
|
|
743
|
+
# Only fires for TARGET_TIER=lite. Other tiers have their own settings templates
|
|
744
|
+
# tracked in follow-on work. Skips when settings template absent (adopter has
|
|
745
|
+
# not published it yet — early Ship 1 dev state).
|
|
746
|
+
if [ "$TARGET_TIER" = "lite" ] && [ "${SKIP_MANIFEST_SYMMETRY:-0}" != "1" ]; then
|
|
747
|
+
SETTINGS_TEMPLATE="$REPO_ROOT/presence/install/public-bassclef-settings.template.json"
|
|
748
|
+
ALLOWLIST="$REPO_ROOT/scripts/generate-lite-manifest-symmetry-allowlist.txt"
|
|
749
|
+
if [ -f "$SETTINGS_TEMPLATE" ] && command -v jq >/dev/null 2>&1; then
|
|
750
|
+
# Extract hook basenames wired in settings template.
|
|
751
|
+
WIRED_TMP=$(mktemp -t bassclef-wired.XXXXXX)
|
|
752
|
+
MANIFEST_HOOKS_TMP=$(mktemp -t bassclef-manifest-hooks.XXXXXX)
|
|
753
|
+
ALLOWLIST_TMP=$(mktemp -t bassclef-allowlist.XXXXXX)
|
|
754
|
+
trap 'rm -f "$WIRED_TMP" "$MANIFEST_HOOKS_TMP" "$ALLOWLIST_TMP"' EXIT
|
|
755
|
+
|
|
756
|
+
jq -r '.hooks | to_entries[] | .value[] | .hooks[] | .command' "$SETTINGS_TEMPLATE" 2>/dev/null \
|
|
757
|
+
| grep -oE '[a-zA-Z0-9_-]+\.sh' | sort -u > "$WIRED_TMP"
|
|
758
|
+
|
|
759
|
+
# Extract hook slugs from the manifest we just emitted.
|
|
760
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
761
|
+
echo "$MANIFEST_JSON" | jq -r '.entries[] | select(.type=="hook") | .slug + ".sh"' 2>/dev/null | sort -u > "$MANIFEST_HOOKS_TMP"
|
|
762
|
+
else
|
|
763
|
+
jq -r '.entries[] | select(.type=="hook") | .slug + ".sh"' "$OUTPUT_PATH" 2>/dev/null | sort -u > "$MANIFEST_HOOKS_TMP"
|
|
764
|
+
fi
|
|
765
|
+
|
|
766
|
+
# Load allowlist (empty file OK — grep -v exits 1 when all lines match; guard for set -e).
|
|
767
|
+
if [ -f "$ALLOWLIST" ]; then
|
|
768
|
+
grep -vE '^\s*#|^\s*$' "$ALLOWLIST" 2>/dev/null > "$ALLOWLIST_TMP" || : > "$ALLOWLIST_TMP"
|
|
769
|
+
sort -u "$ALLOWLIST_TMP" -o "$ALLOWLIST_TMP" 2>/dev/null || true
|
|
770
|
+
else
|
|
771
|
+
: > "$ALLOWLIST_TMP"
|
|
772
|
+
fi
|
|
773
|
+
|
|
774
|
+
# Wired minus manifest, minus allowlist.
|
|
775
|
+
DEAD_WIRED=$(comm -23 "$WIRED_TMP" "$MANIFEST_HOOKS_TMP" | comm -23 - "$ALLOWLIST_TMP" || true)
|
|
776
|
+
if [ -z "$DEAD_WIRED" ]; then
|
|
777
|
+
DEAD_COUNT=0
|
|
778
|
+
else
|
|
779
|
+
DEAD_COUNT=$(echo "$DEAD_WIRED" | wc -l | tr -d ' ')
|
|
780
|
+
fi
|
|
781
|
+
|
|
782
|
+
if [ "$DEAD_COUNT" -gt 0 ]; then
|
|
783
|
+
echo "" >&2
|
|
784
|
+
echo "generate-lite-manifest: SYMMETRY WARNING — $DEAD_COUNT hook(s) wired in settings template but absent from manifest:" >&2
|
|
785
|
+
echo "$DEAD_WIRED" | sed 's/^/ - /' >&2
|
|
786
|
+
echo "" >&2
|
|
787
|
+
echo "Resolution paths:" >&2
|
|
788
|
+
echo " 1. Retag source hook so it enters lite (tier: lite + install-class: project or dual)" >&2
|
|
789
|
+
echo " 2. Remove the wiring entry from $SETTINGS_TEMPLATE" >&2
|
|
790
|
+
echo " 3. Add the hook basename to $ALLOWLIST (grace window through 2026-10-31)" >&2
|
|
791
|
+
echo "" >&2
|
|
792
|
+
echo "Per .claude/rules/we-dont-break-adopters.md (ADR-031). SKIP_MANIFEST_SYMMETRY=1 bypasses one call." >&2
|
|
793
|
+
# V1 ADVISORY — exit 0 with warning. V2 flips to exit 4 (BLOCK).
|
|
794
|
+
fi
|
|
795
|
+
fi
|
|
796
|
+
fi
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tier: lite
|
|
3
|
+
# CLI wrapper for lib/workflow-metrics.sh — Module B4 query helper.
|
|
4
|
+
#
|
|
5
|
+
# Used at Phase checkpoints per canvas activity diagram to sample the
|
|
6
|
+
# median bassclef-pr-ci run duration over the last N days.
|
|
7
|
+
#
|
|
8
|
+
# Closes sunj-labs/bassclef-upstream#1307 (parent epic #1750).
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# scripts/workflow-metrics-query.sh # list all entries
|
|
12
|
+
# scripts/workflow-metrics-query.sh --workflow <name> # filter by workflow
|
|
13
|
+
# scripts/workflow-metrics-query.sh --median # emit median
|
|
14
|
+
# scripts/workflow-metrics-query.sh --workflow <name> --median # median for one workflow
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
WORKFLOW=""
|
|
19
|
+
MEDIAN=0
|
|
20
|
+
STORE_DIR=""
|
|
21
|
+
|
|
22
|
+
while [[ $# -gt 0 ]]; do
|
|
23
|
+
case "$1" in
|
|
24
|
+
--workflow) WORKFLOW="${2:-}"; shift 2 ;;
|
|
25
|
+
--median) MEDIAN=1; shift ;;
|
|
26
|
+
--store-dir) STORE_DIR="${2:-}"; shift 2 ;;
|
|
27
|
+
-h|--help)
|
|
28
|
+
grep -E '^# ' "$0" | sed 's/^# \?//'
|
|
29
|
+
exit 0
|
|
30
|
+
;;
|
|
31
|
+
*)
|
|
32
|
+
echo "unknown arg: $1" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
;;
|
|
35
|
+
esac
|
|
36
|
+
done
|
|
37
|
+
|
|
38
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")
|
|
39
|
+
LIB="$REPO_ROOT/lib/workflow-metrics.sh"
|
|
40
|
+
|
|
41
|
+
if [ ! -f "$LIB" ]; then
|
|
42
|
+
echo "workflow-metrics-query: lib not found at $LIB" >&2
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# shellcheck source=/dev/null
|
|
47
|
+
source "$LIB"
|
|
48
|
+
|
|
49
|
+
if [ -z "$STORE_DIR" ]; then
|
|
50
|
+
STORE_DIR=$(_workflow_metrics_default_store)
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if [ "$MEDIAN" = "1" ]; then
|
|
54
|
+
compute_median "$STORE_DIR" "$WORKFLOW"
|
|
55
|
+
else
|
|
56
|
+
query_metrics "$STORE_DIR" "$WORKFLOW"
|
|
57
|
+
fi
|
|
@@ -34,6 +34,30 @@ 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
|
+
### Ship 1 — install-class boundary + retag rollout (v1.8.7 → v1.9.0, 2026-09-20)
|
|
38
|
+
|
|
39
|
+
- **Change type:** entry-removal (3 entries drop) + entry-add (1 template ships) + policy-change (Gate B install-class filter + Gate C wiring/file symmetry check added to generator)
|
|
40
|
+
- **Fields:** none changed at manifest schema layer. Emission behavior extends.
|
|
41
|
+
- **Version bump:** v1.8.7 → v1.9.0 (MINOR; entries removed + new emission surface + generator behavior extended).
|
|
42
|
+
- **Rationale:** bassclef-upstream#1825 + #1827 + #1824 + #1816 + #1828 + #1728. Five sisters from the cli 1.2.1 smoke and one coordinator from the cli 1.1.1 smoke. Generator gains three gates — tier filter, install-class filter, wiring/file symmetry. Adopters at cli 1.2.x stop seeing PreToolUse errors on every bash tool call once cli picks up.
|
|
43
|
+
- **Retagged out of lite (drop from adopter bundle):**
|
|
44
|
+
- the `/release` skill (substrate concern; operator-only)
|
|
45
|
+
- the `/journal-export` skill (substrate concern; operator-only)
|
|
46
|
+
- the operator sync hook (`install-class: operator`; adopters use the dispatcher)
|
|
47
|
+
- **Added to lite (new adopter file):**
|
|
48
|
+
- `presence/install/bassclef-configs.template.jsonc` — `bassclef init` copies to `.claude/bassclef-configs.jsonc`
|
|
49
|
+
- **Wiring cleanup:** 33 dead-wired hook entries pruned from `presence/install/public-bassclef-settings.template.json`. Each named a hook whose source did not ship in the lite bundle (mostly `tier: standard` hooks). PreToolUse errors on every bash tool call resolve.
|
|
50
|
+
- **Path sanitization:** 27 hardcoded `~/src/sunj-labs/bassclef` occurrences in 2 skill bodies replaced with `${BASSCLEF_DIR:-$CLAUDE_PROJECT_DIR}` pattern. 3 `sunjay-google-ops` gcloud path leaks replaced with `${BASSCLEF_GCLOUD_KEY:-}` env var lookup.
|
|
51
|
+
- **New generator gates:**
|
|
52
|
+
- Gate A — tier filter (strict; upstream/archive/unknown never enter lite)
|
|
53
|
+
- Gate B — install-class filter (operator scope excluded from adopter bundles)
|
|
54
|
+
- Gate C — wiring/file symmetry (ADVISORY V1 per ADR-031 grace window; flip to BLOCK V2)
|
|
55
|
+
- Allowlist file `scripts/generate-lite-manifest-symmetry-allowlist.txt` grants grace exceptions during rollout
|
|
56
|
+
- Overrides: `SKIP_INSTALL_CLASS_FILTER=1`, `SKIP_MANIFEST_SYMMETRY=1`
|
|
57
|
+
- **Downstream cure:** bassclef-cli picks up on next 1.2.x publish. Fresh `bassclef init` on cli 1.2.x sees zero PreToolUse errors, gets a copy of `bassclef-configs.template.jsonc` at `.claude/bassclef-configs.jsonc`, and has `/onboard-repo` with the new top-up path.
|
|
58
|
+
- **Old shape retired:** dead-wired hook entries in the adopter settings template. Adopters who ran cli 1.2.1 still have those entries in their `.claude/settings.json` locally; the sync run picks up the pruned template.
|
|
59
|
+
- **Closes:** #1825, #1827, #1824, #1816, #1828, #1728 upstream; delivers bassclef-cli#101, #104 (new); rides delivery of cli#105, #106, #108, #102, #107 (already cured upstream). cli#103 stays cli-side per cli#96.
|
|
60
|
+
|
|
37
61
|
### Goal 2026-09-17c — one tier declaration per file (v1.8.1 → v1.8.2, 2026-09-17)
|
|
38
62
|
|
|
39
63
|
- **Change type:** content-change (27 content hashes; no entries added or removed)
|