@oneie/claude 0.8.0 → 0.10.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/.claude-plugin/plugin.json +1 -1
- package/agents/abm-strategist.md +67 -1
- package/agents/ads-meta.md +67 -1
- package/agents/analyst.md +67 -1
- package/agents/animator.md +108 -0
- package/agents/architect.md +269 -20
- package/agents/brand-guardian.md +67 -1
- package/agents/brand-strategist.md +67 -1
- package/agents/campaign-content.md +67 -1
- package/agents/campaign-email.md +67 -1
- package/agents/campaign-sms.md +67 -1
- package/agents/campaign-social.md +67 -1
- package/agents/cco.md +83 -2
- package/agents/ceo.md +108 -11
- package/agents/chairman.md +197 -0
- package/agents/cmo.md +82 -2
- package/agents/community-greeter.md +67 -1
- package/agents/community-moderator.md +67 -1
- package/agents/compliance.md +67 -1
- package/agents/copywriter.md +67 -1
- package/agents/creative-strategist.md +67 -1
- package/agents/cro.md +81 -1
- package/agents/cto.md +266 -28
- package/agents/customer-interviewer.md +67 -1
- package/agents/customer-researcher.md +67 -1
- package/agents/customer-success-manager.md +67 -1
- package/agents/customer-trainer.md +67 -1
- package/agents/cxo.md +82 -1
- package/agents/demand-creator.md +67 -1
- package/agents/demo-mover.md +67 -1
- package/agents/demo-specialist.md +67 -1
- package/agents/demo-thai-family-law.md +67 -1
- package/agents/designer.md +67 -1
- package/agents/discovery-caller.md +67 -1
- package/agents/doctor.md +269 -0
- package/agents/educate-coach.md +67 -1
- package/agents/elevate-tutor.md +67 -1
- package/agents/email-lifecycle-marketer.md +67 -1
- package/agents/engage-specialist.md +67 -1
- package/agents/events-coordinator.md +67 -1
- package/agents/foundation-builder.md +67 -1
- package/agents/funnel-architect.md +67 -1
- package/agents/gift-creator.md +67 -1
- package/agents/google-ads.md +67 -1
- package/agents/guide.md +67 -1
- package/agents/helpdesk-dispatcher.md +67 -1
- package/agents/hook-specialist.md +67 -1
- package/agents/identify-optimizer.md +67 -1
- package/agents/implementer.md +313 -45
- package/agents/incident-commander.md +67 -1
- package/agents/insights-lead.md +87 -1
- package/agents/journey-runner.md +67 -1
- package/agents/linkedin-ads.md +67 -1
- package/agents/live-sales-chat.md +67 -1
- package/agents/market-researcher.md +67 -1
- package/agents/media-buyer.md +67 -1
- package/agents/memory-keeper.md +195 -0
- package/agents/movers-customer-researcher.md +67 -1
- package/agents/movers-foundation-builder.md +67 -1
- package/agents/movers-market-researcher.md +67 -1
- package/agents/movers-pricing-strategist.md +67 -1
- package/agents/nurture-architect.md +67 -1
- package/agents/offer-architect.md +67 -1
- package/agents/onboarder.md +67 -1
- package/agents/onboarding-specialist.md +67 -1
- package/agents/operations-dashboard.md +87 -1
- package/agents/perf-engineer.md +333 -37
- package/agents/playbook-writer.md +67 -1
- package/agents/plg-strategist.md +67 -1
- package/agents/positioning-architect.md +67 -1
- package/agents/press-officer.md +67 -1
- package/agents/pricing-strategist.md +67 -1
- package/agents/privacy-officer.md +67 -1
- package/agents/referral-manager.md +67 -1
- package/agents/refine-analyst.md +67 -1
- package/agents/release-manager.md +446 -39
- package/agents/renewals-upsell-rep.md +67 -1
- package/agents/review-engineer.md +319 -45
- package/agents/rewards-steward.md +67 -1
- package/agents/sales-call-coach.md +67 -1
- package/agents/sales-closer.md +67 -1
- package/agents/security-auditor.md +343 -48
- package/agents/sell-closer.md +67 -1
- package/agents/share-amplifier.md +67 -1
- package/agents/social-media-manager.md +67 -1
- package/agents/storyteller.md +301 -0
- package/agents/strategist.md +67 -1
- package/agents/strategy-aligner.md +67 -1
- package/agents/support-agent.md +67 -1
- package/agents/tagger.md +327 -0
- package/agents/tech-writer.md +195 -22
- package/agents/test-engineer.md +398 -29
- package/agents/tiktok-ads.md +67 -1
- package/agents/tracking-engineer.md +67 -1
- package/agents/trailkeeper.md +181 -0
- package/agents/upsell-strategist.md +67 -1
- package/agents/voice.md +67 -1
- package/agents/w1-recon.md +1 -1
- package/agents/w2-decide.md +1 -1
- package/agents/w3-edit.md +8 -2
- package/agents/w4-verify.md +13 -0
- package/agents/workflow-optimiser.md +81 -1
- package/commands/close.md +916 -160
- package/commands/deploy.md +102 -724
- package/commands/do.md +58 -2
- package/commands/sweep.md +159 -0
- package/commands/tasks.md +222 -0
- package/hooks/scripts/dev-only.sh +135 -0
- package/hooks/scripts/git-add-guard.sh +37 -2
- package/hooks/scripts/session-start.sh +32 -4
- package/package.json +1 -1
- package/rules/scripts.md +85 -0
- package/scripts/CLAUDE.md +315 -0
- package/scripts/ad-copy-lint.sh +656 -0
- package/scripts/agent-actor-parity.sh +129 -0
- package/scripts/blocks-manifest-cached.sh +100 -0
- package/scripts/chat-context-check.sh +89 -0
- package/scripts/chrome.mjs +18 -0
- package/scripts/close-metrics.sh +587 -0
- package/scripts/close-owner.sh +326 -0
- package/scripts/db-sync-lock-check.sh +116 -0
- package/scripts/deploy-emit.sh +311 -0
- package/scripts/deploy-gate-check.sh +155 -0
- package/scripts/deploy-ready.sh +78 -0
- package/scripts/deploy-record.sh +605 -0
- package/scripts/deploy-schema-check.sh +58 -0
- package/scripts/deploy.sh +393 -243
- package/scripts/do-auto.sh +127 -26
- package/scripts/do-board.sh +429 -0
- package/scripts/do-close.sh +1184 -0
- package/scripts/do-consumer-sweep.sh +18 -1
- package/scripts/do-decide.sh +476 -0
- package/scripts/do-fleet.sh +8 -2
- package/scripts/do-plan-json.mjs +110 -12
- package/scripts/do-prove-selftest.sh +108 -0
- package/scripts/do-prove.sh +86 -10
- package/scripts/do-rank.py +200 -3
- package/scripts/do-reconcile.sh +73 -12
- package/scripts/do-signal.sh +101 -23
- package/scripts/do-smoke.sh +18 -1
- package/scripts/do-w4-gates.sh +11 -1
- package/scripts/do-world-check.sh +153 -0
- package/scripts/download-stats.sh +172 -0
- package/scripts/factory-brief-check.sh +330 -0
- package/scripts/factory-check.sh +18 -1
- package/scripts/factory-close-check.sh +257 -0
- package/scripts/factory-emit.sh +211 -0
- package/scripts/factory-executor-check.mjs +353 -0
- package/scripts/factory-peak.sh +301 -0
- package/scripts/factory-repo.sh +71 -0
- package/scripts/factory-review-check.mjs +61 -0
- package/scripts/factory-tasks-check.sh +18 -1
- package/scripts/fixtures/factory-brief-real.md +44 -0
- package/scripts/flywheel-outcome.sh +63 -0
- package/scripts/gate-reaper-check.sh +98 -0
- package/scripts/gate-reaper.sh +9 -0
- package/scripts/gate-watchdog.sh +619 -0
- package/scripts/gc-content-check.sh +142 -0
- package/scripts/gh-traffic-capture.sh +153 -0
- package/scripts/govern-order-check.sh +202 -0
- package/scripts/governor-doors-check.sh +86 -5
- package/scripts/health.sh +448 -0
- package/scripts/id-inventory.mjs +418 -0
- package/scripts/incident.sh +212 -0
- package/scripts/land.sh +755 -45
- package/scripts/lib/gc-finished.sh +77 -0
- package/scripts/livekit-ratchet.sh +18 -1
- package/scripts/machine-check.sh +1 -1
- package/scripts/memory-index-budget.sh +79 -0
- package/scripts/npm-downloads.sh +109 -0
- package/scripts/one-agents.mjs +204 -8
- package/scripts/one-resume.sh +31 -3
- package/scripts/pr-body.sh +335 -0
- package/scripts/preview-fd-check.sh +289 -0
- package/scripts/redirect-lint.sh +169 -0
- package/scripts/release.sh +40 -6
- package/scripts/resume-lost-sessions.sh +68 -0
- package/scripts/shoot-pages.mjs +140 -0
- package/scripts/signal-meta-backfill.ts +451 -0
- package/scripts/signal-watch.sh +63 -6
- package/scripts/speed-cache-check.sh +12 -2
- package/scripts/sweep.sh +426 -0
- package/scripts/task-titles-dump.ts +101 -0
- package/scripts/test-cached.sh +47 -10
- package/scripts/test-lanes.sh +14 -0
- package/scripts/thread-name-backfill.ts +215 -0
- package/scripts/triage-shape-check.sh +149 -0
- package/scripts/tsc-cached.sh +155 -8
- package/scripts/typedb-flake-check.sh +3 -1
- package/scripts/urls-lint.sh +8 -0
- package/scripts/verify-board-doors.sh +80 -0
- package/scripts/verify-fast.sh +159 -6
- package/scripts/worktree-up.sh +21 -3
- package/skills/astro/SKILL.md +9 -3
- package/skills/astro/optimize-performance.md +3 -2
- package/skills/cloudflare/SKILL.md +3 -2
- package/skills/cloudflare-security-audit/AI-AND-LLM.md +83 -0
- package/skills/cloudflare-security-audit/ATTACK-CLASSES.md +130 -0
- package/skills/cloudflare-security-audit/CLIENT-SIDE.md +83 -0
- package/skills/cloudflare-security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/skills/cloudflare-security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/skills/cloudflare-security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/skills/cloudflare-security-audit/HUNTING.md +251 -0
- package/skills/cloudflare-security-audit/LICENSE +21 -0
- package/skills/cloudflare-security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/skills/cloudflare-security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/skills/cloudflare-security-audit/PROVENANCE.md +78 -0
- package/skills/cloudflare-security-audit/RECONNAISSANCE.md +156 -0
- package/skills/cloudflare-security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/skills/cloudflare-security-audit/SKILL.md +192 -0
- package/skills/cloudflare-security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/skills/cloudflare-security-audit/VALIDATION-AND-REPORTING.md +186 -0
- package/skills/cloudflare-security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/skills/cloudflare-security-audit/report-schema.json +461 -0
- package/skills/cloudflare-security-audit/validate-coverage-ledger.cjs +872 -0
- package/skills/cloudflare-security-audit/validate-coverage-ledger.test.cjs +740 -0
- package/skills/cloudflare-security-audit/validate-findings.cjs +773 -0
- package/skills/cloudflare-security-audit/validate-findings.test.cjs +652 -0
- package/skills/deploy/REFERENCE.md +713 -0
- package/skills/deploy/SKILL.md +140 -0
- package/skills/fleet-audit/SKILL.md +58 -0
- package/skills/meeting/SKILL.md +220 -0
- package/skills/planning/SKILL.md +256 -0
- package/skills/shadcn/SKILL.md +1 -1
- package/skills/typedb/SKILL.md +7 -0
- package/skills/voice/SKILL.md +94 -6
- package/skills/voice/corpus-check.sh +87 -0
- package/templates/template-agent.md +7 -1
- package/templates/template-feature.md +9 -0
- package/templates/template-todo.md +29 -0
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# close-metrics.sh — mine every DETERMINISTIC number a close can report, in one
|
|
3
|
+
# bounded read-only pass.
|
|
4
|
+
#
|
|
5
|
+
# manifest: needs-env
|
|
6
|
+
# Only for the substrate reachability probe, which reads the same
|
|
7
|
+
# ONE_ENV_FILE ladder do-signal.sh and do-close.sh read. Every other row is
|
|
8
|
+
# local git / filesystem and needs nothing.
|
|
9
|
+
#
|
|
10
|
+
# WHY. `/close` reported six leg states and almost no numbers about the WORK.
|
|
11
|
+
# "closed=true pass=6" says the doors were knocked on; it does not say what
|
|
12
|
+
# changed, whether the tree is proven, whether the branch reached trunk, or why
|
|
13
|
+
# a gate could not run. Those numbers all exist — scattered across nine scripts,
|
|
14
|
+
# each of which a model was expected to remember to call. This is the one call.
|
|
15
|
+
#
|
|
16
|
+
# IT COMPOSES, IT DOES NOT RE-DERIVE. Every row below names an owner that
|
|
17
|
+
# already computes it (test-cached.sh for the receipt, machine-check.sh for
|
|
18
|
+
# pressure, deploy-record.sh for unlanded rows, rubric-weights.json for the
|
|
19
|
+
# weights). A number this script computed itself, that one of those also
|
|
20
|
+
# computes, is a second opinion — and a second opinion is drift with a delay on
|
|
21
|
+
# it. Where there is no owner, the row is git or the filesystem, directly.
|
|
22
|
+
#
|
|
23
|
+
# THE HONESTY LAW (verbatim from do-w4-gates.sh, and the reason this file is not
|
|
24
|
+
# a pile of `echo $(git ...)`): every row has FOUR states, never two —
|
|
25
|
+
# ok : measured, the number is real
|
|
26
|
+
# bad : measured, and the number is a problem
|
|
27
|
+
# unrun : COULD NOT BE MEASURED — the source was absent, empty, or too slow
|
|
28
|
+
# n/a : does not apply to this close, by rule
|
|
29
|
+
# A number with no state beside it is the failure this law exists to stop. In
|
|
30
|
+
# THIS session, `grep -c "error TS" <file>` returned `0` against an output file
|
|
31
|
+
# a queued gate had not written yet — "zero errors" and "never ran" are the same
|
|
32
|
+
# three characters. Every numeric row here carries its state, and `unrun` never
|
|
33
|
+
# prints a zero.
|
|
34
|
+
#
|
|
35
|
+
# IT NEVER RUNS A GATE. `/close` is a FULL-lane trigger and a fast pass is never
|
|
36
|
+
# reported as a full pass — so this asks `test-cached.sh` (TEST_CACHE_KEY_ONLY=1,
|
|
37
|
+
# ~1s, structurally cannot start vitest) whether the tree ALREADY carries a
|
|
38
|
+
# receipt, and reads `.w4-gates.json` if a cycle left one. It must never invoke
|
|
39
|
+
# `do-w4-gates.sh` bare: that runs `do-reconcile.sh types`, a tsc that queues
|
|
40
|
+
# minutes behind the governor, and a metrics row is not worth a gate slot.
|
|
41
|
+
#
|
|
42
|
+
# IT CANNOT FAIL A CLOSE. It has its own budget, every external call is bounded,
|
|
43
|
+
# and it exits 0 unless its own arguments are wrong. A miner that made the
|
|
44
|
+
# closer slower or redder would be removed within a week, and then the numbers
|
|
45
|
+
# would be gone along with it.
|
|
46
|
+
#
|
|
47
|
+
# USAGE
|
|
48
|
+
# close-metrics.sh [<slug>] every section, human-readable
|
|
49
|
+
# close-metrics.sh --json one object, for a caller
|
|
50
|
+
# close-metrics.sh --section work,tree only these
|
|
51
|
+
# close-metrics.sh --self-test fixtures + the unrun proofs
|
|
52
|
+
#
|
|
53
|
+
# OPTIONS
|
|
54
|
+
# --slug <slug> the plan/promise this close is for (enables promise rows)
|
|
55
|
+
# --composite <0.NN> the cycle composite, so the rubric section can gate it
|
|
56
|
+
# --dims k=v,... per-axis scores (security,stability,simplicity,speed,integration)
|
|
57
|
+
# --base <ref> trunk to measure against (default: origin/main)
|
|
58
|
+
# --section <a,b> work,tree,gates,rubric,close,machine,substrate (default: all)
|
|
59
|
+
# --budget <secs> whole-run wall clock (default: 20)
|
|
60
|
+
# --json machine-readable
|
|
61
|
+
# --json-out <file> ALSO write the JSON here — one measurement, two readers
|
|
62
|
+
#
|
|
63
|
+
# EXIT 0 always (2 on a usage error). A metric is never a verdict.
|
|
64
|
+
set -uo pipefail
|
|
65
|
+
|
|
66
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
67
|
+
S="$ROOT/.claude/scripts"
|
|
68
|
+
SLUG=""; COMPOSITE=""; DIMS=""; BASE_REF="${CLOSE_BASE_REF:-origin/main}"
|
|
69
|
+
SECTIONS="work,tree,gates,rubric,close,machine,substrate"
|
|
70
|
+
BUDGET="${CLOSE_METRICS_BUDGET:-20}"; JSON=0; SELFTEST=0
|
|
71
|
+
# ONE RUN, TWO CONSUMERS. The measured block costs ~17s of real work — git
|
|
72
|
+
# plumbing, a cache-key hash, a governor read. Running it once for the human and
|
|
73
|
+
# again for the machine would double that on the closer's critical path, and the
|
|
74
|
+
# two runs would measure different instants of a tree seven sessions are editing.
|
|
75
|
+
# --json-out writes the machine copy to a file while stdout stays the table, so
|
|
76
|
+
# the signal and the report are the SAME measurement, not two of them.
|
|
77
|
+
JSON_OUT=""
|
|
78
|
+
STARTED=$(date +%s)
|
|
79
|
+
|
|
80
|
+
while [ $# -gt 0 ]; do
|
|
81
|
+
case "$1" in
|
|
82
|
+
--slug) SLUG="${2:-}"; shift 2 ;;
|
|
83
|
+
--composite) COMPOSITE="${2:-}"; shift 2 ;;
|
|
84
|
+
--dims) DIMS="${2:-}"; shift 2 ;;
|
|
85
|
+
--base) BASE_REF="${2:-}"; shift 2 ;;
|
|
86
|
+
--section) SECTIONS="${2:-}"; shift 2 ;;
|
|
87
|
+
--budget) BUDGET="${2:-}"; shift 2 ;;
|
|
88
|
+
--json) JSON=1; shift ;;
|
|
89
|
+
--json-out) JSON_OUT="${2:-}"; shift 2 ;;
|
|
90
|
+
--self-test) SELFTEST=1; shift ;;
|
|
91
|
+
-h|--help) sed -n '/^# USAGE/,/^# EXIT/p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
|
92
|
+
--*) echo "close-metrics: unknown flag $1" >&2; exit 2 ;;
|
|
93
|
+
*) [ -z "$SLUG" ] && SLUG="$1" || { echo "close-metrics: unexpected arg $1" >&2; exit 2; }; shift ;;
|
|
94
|
+
esac
|
|
95
|
+
done
|
|
96
|
+
|
|
97
|
+
ROWS="$(mktemp)"; trap 'rm -f "$ROWS"' EXIT
|
|
98
|
+
|
|
99
|
+
# _row <section> <name> <value> <state> [note]
|
|
100
|
+
# The state is NOT optional and there is no default. A caller that forgets it
|
|
101
|
+
# gets `unrun`, because an unstated state is exactly the ambiguity this file
|
|
102
|
+
# exists to remove.
|
|
103
|
+
# US (0x1f) as the field separator, NOT a tab. Tab is IFS *whitespace*, and bash
|
|
104
|
+
# collapses runs of IFS whitespace — so a row with an empty value (`composite`
|
|
105
|
+
# before a score is passed) lost the field and every column after it shifted
|
|
106
|
+
# left, printing the STATE where the value belongs. A metrics file whose own
|
|
107
|
+
# report can mislabel a state is worse than no metrics file, and 0x1f is
|
|
108
|
+
# non-whitespace so `read` keeps every empty field exactly where it was written.
|
|
109
|
+
_ROW_FS=$'\037'
|
|
110
|
+
_row() {
|
|
111
|
+
# Every field is flattened: a value containing a newline would split one row
|
|
112
|
+
# into two and shift every column after it. That is not hypothetical — see the
|
|
113
|
+
# `grep -c || echo 0` note in the machine section.
|
|
114
|
+
local _1 _2 _3 _4 _5
|
|
115
|
+
_1=$(printf '%s' "$1" | tr -d '\n\037'); _2=$(printf '%s' "$2" | tr -d '\n\037')
|
|
116
|
+
_3=$(printf '%s' "${3:-}" | tr '\n' ' ' | tr -d '\037')
|
|
117
|
+
_4=$(printf '%s' "${4:-unrun}" | tr -d '\n\037')
|
|
118
|
+
_5=$(printf '%s' "${5:-}" | tr '\n' ' ' | tr -d '\037')
|
|
119
|
+
printf '%s%s%s%s%s%s%s%s%s\n' "$_1" "$_ROW_FS" "$_2" "$_ROW_FS" "$_3" "$_ROW_FS" "$_4" "$_ROW_FS" "$_5" >> "$ROWS"
|
|
120
|
+
}
|
|
121
|
+
_want() { case ",$SECTIONS," in *",$1,"*) return 0 ;; *) return 1 ;; esac; }
|
|
122
|
+
_has() { command -v "$1" >/dev/null 2>&1; }
|
|
123
|
+
_left() { echo $(( BUDGET - ( $(date +%s) - STARTED ) )); }
|
|
124
|
+
|
|
125
|
+
# Every external call goes through here. A source that hangs costs its own
|
|
126
|
+
# budget and reports `unrun`; it never costs the run.
|
|
127
|
+
_try() { # _try <secs> <cmd...> → stdout, rc
|
|
128
|
+
local secs="$1"; shift
|
|
129
|
+
local left; left=$(_left); [ "$left" -lt 1 ] && return 124
|
|
130
|
+
[ "$secs" -gt "$left" ] && secs="$left"
|
|
131
|
+
if [ -f "$S/lib/govern.sh" ]; then
|
|
132
|
+
# shellcheck disable=SC1090
|
|
133
|
+
( . "$S/lib/govern.sh" >/dev/null 2>&1; run_bounded "$secs" "$@" ) 2>/dev/null
|
|
134
|
+
else
|
|
135
|
+
"$@" 2>/dev/null
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# ── work — what actually changed ────────────────────────────────────────────
|
|
140
|
+
# Against the INDEX AND the worktree (`git diff HEAD`), because a close happens
|
|
141
|
+
# before a commit as often as after one, and a metric that only sees committed
|
|
142
|
+
# work reports an empty session for the most common case.
|
|
143
|
+
if _want work; then
|
|
144
|
+
if git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
|
145
|
+
numstat="$(git -C "$ROOT" diff HEAD --numstat 2>/dev/null)"
|
|
146
|
+
namest="$(git -C "$ROOT" diff HEAD --name-status 2>/dev/null)"
|
|
147
|
+
untracked="$(git -C "$ROOT" ls-files --others --exclude-standard 2>/dev/null | grep -c . || true)"; untracked="${untracked:-0}"
|
|
148
|
+
files=$(printf '%s' "$numstat" | grep -c . || true)
|
|
149
|
+
ins=$(printf '%s\n' "$numstat" | awk -F'\t' '$1!="-"{s+=$1}END{print s+0}')
|
|
150
|
+
del=$(printf '%s\n' "$numstat" | awk -F'\t' '$2!="-"{s+=$2}END{print s+0}')
|
|
151
|
+
added=$(printf '%s\n' "$namest" | awk '$1=="A"' | grep -c . || true)
|
|
152
|
+
removed=$(printf '%s\n' "$namest"| awk '$1=="D"' | grep -c . || true)
|
|
153
|
+
renamed=$(printf '%s\n' "$namest"| awk '$1 ~ /^R/' | grep -c . || true)
|
|
154
|
+
paths=$(printf '%s\n' "$numstat" | awk -F'\t' '{print $3}')
|
|
155
|
+
tests=$(printf '%s\n' "$paths" | grep -cE '(^|/)(tests?|__tests__)/|\.(test|spec)\.[tj]sx?$' || true)
|
|
156
|
+
docs=$(printf '%s\n' "$paths" | grep -cE '\.mdx?$' || true)
|
|
157
|
+
code=$(( files - tests - docs )); [ "$code" -lt 0 ] && code=0
|
|
158
|
+
|
|
159
|
+
# `files` is the only row here that can be legitimately 0 (a close with
|
|
160
|
+
# nothing uncommitted), so it is `ok` at zero. The derived rows follow it.
|
|
161
|
+
_row work files_changed "$files" ok "vs HEAD, index + worktree"
|
|
162
|
+
_row work lines_added "$ins" ok
|
|
163
|
+
_row work lines_removed "$del" ok
|
|
164
|
+
_row work files_new "$added" ok
|
|
165
|
+
_row work files_deleted "$removed" "$( [ "$removed" -gt 0 ] && echo bad || echo ok )" \
|
|
166
|
+
"$( [ "$removed" -gt 0 ] && echo 'a delete takes the FULL lane — vitest related cannot see a file that is gone' )"
|
|
167
|
+
_row work files_renamed "$renamed" "$( [ "$renamed" -gt 0 ] && echo bad || echo ok )" \
|
|
168
|
+
"$( [ "$renamed" -gt 0 ] && echo 'a rename takes the FULL lane' )"
|
|
169
|
+
_row work files_untracked "$untracked" ok "new files git has never seen"
|
|
170
|
+
_row work test_files "$tests" ok
|
|
171
|
+
_row work doc_files "$docs" ok
|
|
172
|
+
_row work code_files "$code" ok
|
|
173
|
+
# Not a quality score — a RATIO, reported without a threshold on purpose.
|
|
174
|
+
# `test-coverage` is an axis rubric-weights.json says is "scored by NOTHING
|
|
175
|
+
# today"; inventing a number for it would put a fake input into a real gate.
|
|
176
|
+
if [ "$code" -gt 0 ]; then
|
|
177
|
+
_row work tests_per_code_file "$(awk -v t="$tests" -v c="$code" 'BEGIN{printf "%.2f", t/c}')" ok "ratio only — NOT a coverage figure"
|
|
178
|
+
else
|
|
179
|
+
_row work tests_per_code_file "" n/a "no code files changed"
|
|
180
|
+
fi
|
|
181
|
+
biggest=$(printf '%s\n' "$numstat" | awk -F'\t' '$1!="-"{print $1+$2"\t"$3}' | sort -rn | head -1)
|
|
182
|
+
[ -n "$biggest" ] && _row work largest_file "$(printf '%s' "$biggest" | cut -f2) ($(printf '%s' "$biggest" | cut -f1) lines)" ok
|
|
183
|
+
else
|
|
184
|
+
_row work files_changed "" unrun "not a git repository"
|
|
185
|
+
fi
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# ── tree — where this work is, and whether it reached trunk ─────────────────
|
|
189
|
+
if _want tree; then
|
|
190
|
+
if git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
|
191
|
+
br="$(git -C "$ROOT" branch --show-current 2>/dev/null)"
|
|
192
|
+
_row tree branch "${br:-<detached>}" "$( [ -n "$br" ] && echo ok || echo bad )"
|
|
193
|
+
_row tree worktree "$ROOT" ok "$( [ -f "$ROOT/.git" ] && echo 'linked worktree' || echo 'primary tree' )"
|
|
194
|
+
dirty=$(git -C "$ROOT" status --porcelain 2>/dev/null | grep -c . || true)
|
|
195
|
+
# A dirty tree is not a fault — but it is the reason a receipt cannot bind,
|
|
196
|
+
# since the memo key hashes `git diff HEAD` by content.
|
|
197
|
+
_row tree dirty_paths "$dirty" "$( [ "$dirty" -gt 0 ] && echo bad || echo ok )" \
|
|
198
|
+
"$( [ "$dirty" -gt 0 ] && echo 'a receipt minted on a dirty tree describes a tree that never ships' )"
|
|
199
|
+
|
|
200
|
+
if git -C "$ROOT" rev-parse --verify --quiet "$BASE_REF" >/dev/null 2>&1; then
|
|
201
|
+
ahead=$(git -C "$ROOT" rev-list --count "$BASE_REF..HEAD" 2>/dev/null || echo)
|
|
202
|
+
behind=$(git -C "$ROOT" rev-list --count "HEAD..$BASE_REF" 2>/dev/null || echo)
|
|
203
|
+
_row tree commits_ahead "${ahead:-}" "$( [ -n "$ahead" ] && echo ok || echo unrun )" "vs $BASE_REF"
|
|
204
|
+
_row tree commits_behind "${behind:-}" "$( [ -n "$behind" ] && { [ "${behind:-0}" -gt 30 ] && echo bad || echo ok; } || echo unrun )" \
|
|
205
|
+
"$( [ "${behind:-0}" -gt 30 ] && echo 'trunk has moved far — a gate here measures a stale tree' )"
|
|
206
|
+
# LANDED IS AN ANCESTRY FACT, NOT A MERGE RESULT. `git merge` succeeding is
|
|
207
|
+
# a claim about an instant; being an ancestor of trunk is a fact about now.
|
|
208
|
+
# Three lands on 2026-09-05 printed "main fast-forwarded" while main never
|
|
209
|
+
# moved — this is the check that would have caught them.
|
|
210
|
+
if git -C "$ROOT" merge-base --is-ancestor HEAD "$BASE_REF" 2>/dev/null; then
|
|
211
|
+
_row tree landed yes ok "HEAD is an ancestor of $BASE_REF"
|
|
212
|
+
else
|
|
213
|
+
_row tree landed no ok "${ahead:-?} commit(s) not yet in $BASE_REF"
|
|
214
|
+
fi
|
|
215
|
+
else
|
|
216
|
+
_row tree commits_ahead "" unrun "$BASE_REF does not resolve — fetch, or pass --base"
|
|
217
|
+
_row tree landed "" unrun "no $BASE_REF to measure ancestry against"
|
|
218
|
+
fi
|
|
219
|
+
wt=$(git -C "$ROOT" worktree list 2>/dev/null | grep -c . || true)
|
|
220
|
+
_row tree worktrees "$wt" "$( [ "$wt" -gt 12 ] && echo bad || echo ok )" \
|
|
221
|
+
"$( [ "$wt" -gt 12 ] && echo 'each is ~120MB and one tsserver — bash .claude/scripts/do-auto.sh --gc' )"
|
|
222
|
+
else
|
|
223
|
+
_row tree branch "" unrun "not a git repository"
|
|
224
|
+
fi
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
# ── gates — what is PROVEN about this exact tree, never what could be run ────
|
|
228
|
+
if _want gates; then
|
|
229
|
+
# THE RECEIPT — is this exact tree already proven by a FULL suite?
|
|
230
|
+
#
|
|
231
|
+
# `test-full.sh` is THE one definition of the full suite, and it fans out to a
|
|
232
|
+
# `test-cached.sh` per lane. TEST_CACHE_KEY_ONLY=1 makes every one of them
|
|
233
|
+
# print its key and exit 0 WITHOUT starting vitest — ~1s, and it structurally
|
|
234
|
+
# cannot launch a suite. That last property is why this row is allowed to
|
|
235
|
+
# exist at all: `/close` is a FULL-lane trigger and a fast pass is never
|
|
236
|
+
# reported as a full pass, so the only honest question is "does a receipt
|
|
237
|
+
# already exist", never "let me go and make one".
|
|
238
|
+
#
|
|
239
|
+
# Calling `test-cached.sh` directly here was WRONG and read as `unrun` on a
|
|
240
|
+
# tree that may well have been proven: that script takes a `<folder>` and
|
|
241
|
+
# prints a usage line without one. do-close.sh's own gate leg already knew
|
|
242
|
+
# this. Composing the owner beats re-deriving it — the same rule as everywhere
|
|
243
|
+
# else in this file.
|
|
244
|
+
#
|
|
245
|
+
# The key is content-addressed, so a NEIGHBOUR'S suite on this same tree counts
|
|
246
|
+
# as yours. A memo HIT is free and it counts.
|
|
247
|
+
if [ -f "$S/test-full.sh" ]; then
|
|
248
|
+
keys="$(cd "$ROOT" && TEST_CACHE_KEY_ONLY=1 _try 12 bash .claude/scripts/test-full.sh | grep -Eo '^[0-9a-f]{64}$')"
|
|
249
|
+
# ${TMPDIR:-/tmp}/one-test-cache — the SAME default test-cached.sh:32 mints into
|
|
250
|
+
# and do-close.sh:110 reads. It used to be "$ROOT/.claude/.test-cache", a path no
|
|
251
|
+
# minter has ever written to, so `ls` found nothing and this row could only ever
|
|
252
|
+
# answer MISS. Measured 2026-09-15 on a tree whose two lanes were both stamped:
|
|
253
|
+
# the gate LEG read "pass — 2/2 lane(s), minted 09:16:44Z" and this row read
|
|
254
|
+
# "MISS 0/2", same tree, same second. A permanent false RED on the one row that
|
|
255
|
+
# gates the board write.
|
|
256
|
+
#
|
|
257
|
+
# This is the file's own Rule 1 broken — "it composes, it never re-derives". The
|
|
258
|
+
# row re-derived the cache PATH instead of taking the owner's, which is the same
|
|
259
|
+
# drift-with-a-delay that made it call test-cached.sh without a <folder>. Both
|
|
260
|
+
# halves of that lesson are now spent; the path is not to be re-derived either.
|
|
261
|
+
cache="${TEST_CACHE_DIR:-${TMPDIR:-/tmp}/one-test-cache}"
|
|
262
|
+
if [ -z "$keys" ]; then
|
|
263
|
+
_row gates full_suite_receipt "" unrun "test-full.sh printed no receipt key inside its budget"
|
|
264
|
+
else
|
|
265
|
+
n=0; hit=0
|
|
266
|
+
for k in $keys; do
|
|
267
|
+
n=$((n+1))
|
|
268
|
+
ls "$cache" 2>/dev/null | grep -q "$k" && hit=$((hit+1))
|
|
269
|
+
done
|
|
270
|
+
if [ "$hit" -eq "$n" ]; then
|
|
271
|
+
_row gates full_suite_receipt "HIT $hit/$n" ok "every lane of the FULL suite is stamped for THIS tree"
|
|
272
|
+
else
|
|
273
|
+
_row gates full_suite_receipt "MISS $hit/$n" bad "cd one.ie/web && FULL_VERIFY=1 bun run verify — an unstamped lane is an UNRUN lane, never a passed one"
|
|
274
|
+
fi
|
|
275
|
+
fi
|
|
276
|
+
else
|
|
277
|
+
_row gates full_suite_receipt "" unrun "test-full.sh not in this tree"
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
# A cycle's own gate pack, if one was left. NEVER regenerated here: running
|
|
281
|
+
# do-w4-gates.sh bare runs do-reconcile.sh types, a tsc that queues behind the
|
|
282
|
+
# governor, and no metrics row is worth a gate slot.
|
|
283
|
+
pack=""
|
|
284
|
+
for c in "$ROOT/.w4-gates.json" "$ROOT/.claude/.w4-gates.json"; do [ -f "$c" ] && pack="$c" && break; done
|
|
285
|
+
if [ -n "$pack" ] && _has jq; then
|
|
286
|
+
for st in pass fail unrun; do
|
|
287
|
+
_row gates "w4_$st" "$(jq -r "[.gates[]?|select(.status==\"$st\")]|length" "$pack" 2>/dev/null || echo)" \
|
|
288
|
+
"$( [ "$st" = "fail" ] && echo bad || echo ok )" "$(basename "$pack")"
|
|
289
|
+
done
|
|
290
|
+
_row gates w4_deterministic_pass "$(jq -r '.deterministic_pass//empty' "$pack" 2>/dev/null)" ok
|
|
291
|
+
else
|
|
292
|
+
_row gates w4_pack "" unrun "no .w4-gates.json — this close did not come from a /do cycle, or W4 never wrote one"
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
# delta_tsc is a HARD CONJUNCT of the cycle gate and it is a DELTA: it needs a
|
|
296
|
+
# baseline to subtract from. There is no baseline file in this repo today, so
|
|
297
|
+
# this row is honestly unrun rather than quietly 0. A 0 here would satisfy
|
|
298
|
+
# `delta_tsc <= 0` on evidence that does not exist.
|
|
299
|
+
base_tsc=""
|
|
300
|
+
for c in "$ROOT/.claude/.tsc-baseline" "$ROOT/.w0-baseline.json"; do [ -f "$c" ] && base_tsc="$c" && break; done
|
|
301
|
+
if [ -n "$base_tsc" ]; then
|
|
302
|
+
_row gates delta_tsc "" unrun "baseline at $base_tsc — compare after a measured tsc; this script never runs one"
|
|
303
|
+
else
|
|
304
|
+
_row gates delta_tsc "" unrun "no W0 baseline on disk — delta_tsc is unmeasurable, so the cycle gate cannot be scored green"
|
|
305
|
+
fi
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
# ── rubric — the verdict, gated against weights this file never restates ────
|
|
309
|
+
if _want rubric; then
|
|
310
|
+
W="$ROOT/.claude/scripts/rubric-weights.json"
|
|
311
|
+
if [ -f "$W" ] && _has jq; then
|
|
312
|
+
gate=$(jq -r '.gate' "$W"); gfgate=$(jq -r '.goalFitGate' "$W")
|
|
313
|
+
_row rubric gate_threshold "$gate" ok "composite must be >= this (rubric-weights.json)"
|
|
314
|
+
_row rubric goalfit_threshold "$gfgate" ok "goal-fit must be >= this — independent HARD gate"
|
|
315
|
+
else
|
|
316
|
+
_row rubric gate_threshold "" unrun "rubric-weights.json unreadable — the thresholds are NOT restated anywhere else"
|
|
317
|
+
fi
|
|
318
|
+
if [ -n "$COMPOSITE" ]; then
|
|
319
|
+
_row rubric composite "$COMPOSITE" \
|
|
320
|
+
"$(awk -v c="$COMPOSITE" -v g="${gate:-0.65}" 'BEGIN{print (c+0>=g+0)?"ok":"bad"}')" "cycle rubric"
|
|
321
|
+
else
|
|
322
|
+
_row rubric composite "" unrun "no --composite passed — a close with no score is not a scored close"
|
|
323
|
+
fi
|
|
324
|
+
if [ -n "$DIMS" ]; then
|
|
325
|
+
# `printf '%s'` with no trailing newline loses the LAST field: `read` returns
|
|
326
|
+
# non-zero on a final unterminated line and the loop body never runs for it.
|
|
327
|
+
# Measured — `--dims security=0.9,stability=0.8` reported security and
|
|
328
|
+
# silently dropped stability, which is a missing axis in a weighted gate.
|
|
329
|
+
printf '%s\n' "$DIMS" | tr ',' '\n' | while IFS='=' read -r k v; do
|
|
330
|
+
[ -z "$k" ] && continue
|
|
331
|
+
printf 'rubric%saxis_%s%s%s%s%s%s\n' "$_ROW_FS" "$k" "$_ROW_FS" "$v" "$_ROW_FS" \
|
|
332
|
+
"$(awk -v x="$v" 'BEGIN{print (x+0>=0.5)?"ok":"bad"}')" "$_ROW_FS" >> "$ROWS"
|
|
333
|
+
done
|
|
334
|
+
else
|
|
335
|
+
_row rubric axes "" unrun "no --dims passed"
|
|
336
|
+
fi
|
|
337
|
+
# VELOCITY — against the previous composite in text/learnings.md. Both
|
|
338
|
+
# separators are matched because the file genuinely carries both
|
|
339
|
+
# (`composite 0.88` and `composite=0.89`); a regex that matched one would
|
|
340
|
+
# report `+0.00`, which is indistinguishable from "no change" and is the worst
|
|
341
|
+
# failure mode a metric has.
|
|
342
|
+
L="$ROOT/text/learnings.md"
|
|
343
|
+
if [ -f "$L" ]; then
|
|
344
|
+
prev="$(grep -oE 'composite[ =:]+[0-9]*\.?[0-9]+' "$L" 2>/dev/null | tail -1 | grep -oE '[0-9]*\.?[0-9]+$')"
|
|
345
|
+
n="$(grep -cE 'composite[ =:]+[0-9]' "$L" 2>/dev/null || true)"; n="${n:-0}"
|
|
346
|
+
if [ -n "$prev" ] && [ -n "$COMPOSITE" ]; then
|
|
347
|
+
_row rubric velocity "$(awk -v a="$COMPOSITE" -v b="$prev" 'BEGIN{printf "%+.2f", a-b}')" ok "vs $prev, the last of $n recorded"
|
|
348
|
+
elif [ -n "$prev" ]; then
|
|
349
|
+
_row rubric velocity "" unrun "last recorded is $prev ($n rows) — pass --composite to get a delta"
|
|
350
|
+
else
|
|
351
|
+
_row rubric velocity "" unrun "no composite found in text/learnings.md"
|
|
352
|
+
fi
|
|
353
|
+
else
|
|
354
|
+
_row rubric velocity "" unrun "text/learnings.md absent"
|
|
355
|
+
fi
|
|
356
|
+
fi
|
|
357
|
+
|
|
358
|
+
# ── close — what this repo already knows is unclosed ────────────────────────
|
|
359
|
+
if _want close; then
|
|
360
|
+
LED="${CLOSE_LEDGER:-$ROOT/.claude/.close-pending.jsonl}"
|
|
361
|
+
if [ -f "$LED" ]; then
|
|
362
|
+
open=$(grep -c . "$LED" 2>/dev/null || true); open="${open:-0}"
|
|
363
|
+
_row close ledger_open "$open" "$( [ "$open" -gt 0 ] && echo bad || echo ok )" \
|
|
364
|
+
"$( [ "$open" -gt 0 ] && echo 'bash .claude/scripts/do-close.sh --pending' )"
|
|
365
|
+
else
|
|
366
|
+
_row close ledger_open 0 ok "no ledger yet — nothing has ever failed to close"
|
|
367
|
+
fi
|
|
368
|
+
if [ -f "$S/deploy-record.sh" ]; then
|
|
369
|
+
out="$(_try 8 bash "$S/deploy-record.sh" --pending)"; rc=$?
|
|
370
|
+
case "$rc" in
|
|
371
|
+
0) _row close deploy_rows_pending 0 ok "trunk carries every recorded run" ;;
|
|
372
|
+
6) _row close deploy_rows_pending "$(printf '%s' "$out" | grep -cE '^\s*\{|run' || echo '?')" bad \
|
|
373
|
+
"bash .claude/scripts/deploy-record.sh --land — from a worktree cut from trunk" ;;
|
|
374
|
+
124) _row close deploy_rows_pending "" unrun "deploy-record.sh --pending exceeded its budget" ;;
|
|
375
|
+
*) _row close deploy_rows_pending "" unrun "deploy-record.sh --pending exit=$rc" ;;
|
|
376
|
+
esac
|
|
377
|
+
else
|
|
378
|
+
_row close deploy_rows_pending "" unrun "deploy-record.sh not found"
|
|
379
|
+
fi
|
|
380
|
+
# The mirror. `packages/claude` is GENERATED from `.claude` by
|
|
381
|
+
# sync-claude-mirror.sh, and when it drifts the STALE copy is what a plugin
|
|
382
|
+
# user's `/close` loads — so the authority is edited and nothing changes.
|
|
383
|
+
if [ -f "$S/sync-claude-mirror.sh" ]; then
|
|
384
|
+
_try 10 bash "$S/sync-claude-mirror.sh" --check >/dev/null 2>&1; rc=$?
|
|
385
|
+
case "$rc" in
|
|
386
|
+
0) _row close claude_mirror in-sync ok ;;
|
|
387
|
+
124) _row close claude_mirror "" unrun "mirror check exceeded its budget" ;;
|
|
388
|
+
*) _row close claude_mirror DRIFT bad "packages/claude is behind .claude — the STALE copy is what a plugin's /close loads. bash .claude/scripts/sync-claude-mirror.sh" ;;
|
|
389
|
+
esac
|
|
390
|
+
else
|
|
391
|
+
_row close claude_mirror "" unrun "sync-claude-mirror.sh not found"
|
|
392
|
+
fi
|
|
393
|
+
if [ -n "$SLUG" ] && [ -f "$S/do-derives-check.sh" ]; then
|
|
394
|
+
_try 8 bash "$S/do-derives-check.sh" "$SLUG" >/dev/null 2>&1; rc=$?
|
|
395
|
+
case "$rc" in
|
|
396
|
+
0) _row close derives complete ok "every 'derives: true' artifact is on disk" ;;
|
|
397
|
+
124) _row close derives "" unrun "derives check exceeded its budget" ;;
|
|
398
|
+
*) _row close derives missing bad "bash .claude/scripts/do-derives-check.sh $SLUG" ;;
|
|
399
|
+
esac
|
|
400
|
+
else
|
|
401
|
+
_row close derives "" n/a "$( [ -z "$SLUG" ] && echo 'no slug — nothing to derive from' || echo 'do-derives-check.sh not found' )"
|
|
402
|
+
fi
|
|
403
|
+
fi
|
|
404
|
+
|
|
405
|
+
# ── machine — the context that turns "unrun" from a mystery into a reason ───
|
|
406
|
+
# This section exists because "tsc not measured, box saturated" once closed three
|
|
407
|
+
# cycles green. The pressure is not a metric about the work; it is the EVIDENCE
|
|
408
|
+
# for every unrun row above it.
|
|
409
|
+
if _want machine; then
|
|
410
|
+
cores="$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null)"
|
|
411
|
+
load="$(uptime 2>/dev/null | sed -E 's/.*load averages?: ([0-9.]+).*/\1/')"
|
|
412
|
+
if [ -n "$load" ] && [ -n "$cores" ]; then
|
|
413
|
+
_row machine load "$load / ${cores} cores" \
|
|
414
|
+
"$(awk -v l="$load" -v c="$cores" 'BEGIN{print (l+0 > 2*c)?"bad":"ok"}')" \
|
|
415
|
+
"$(awk -v l="$load" -v c="$cores" 'BEGIN{if(l+0>2*c) print "saturated — a queued gate is a WAIT, not a hang"}')"
|
|
416
|
+
else
|
|
417
|
+
_row machine load "" unrun "could not read load or core count"
|
|
418
|
+
fi
|
|
419
|
+
if _has vm_stat; then
|
|
420
|
+
free_mb=$(vm_stat 2>/dev/null | awk '/Pages free/{gsub(/\./,"",$3); print int($3*4096/1048576)}')
|
|
421
|
+
[ -n "$free_mb" ] && _row machine free_mb "$free_mb" "$( [ "${free_mb:-0}" -lt 512 ] && echo bad || echo ok )" \
|
|
422
|
+
"$( [ "${free_mb:-0}" -lt 512 ] && echo 'memory is the binding constraint on gate concurrency, not cores' )" \
|
|
423
|
+
|| _row machine free_mb "" unrun "vm_stat gave no page count"
|
|
424
|
+
else
|
|
425
|
+
_row machine free_mb "" unrun "vm_stat absent (not a mac)"
|
|
426
|
+
fi
|
|
427
|
+
gd="${GOVERN_DIR:-${TMPDIR:-/tmp}/one-govern}"
|
|
428
|
+
if [ -d "$gd" ]; then
|
|
429
|
+
# `grep -c` already prints 0 when it matches nothing — it just EXITS 1. So
|
|
430
|
+
# `grep -c … || echo 0` emits TWO lines ("0\n0"), and a multi-line value tore
|
|
431
|
+
# the row apart: the report printed the note where the state belongs.
|
|
432
|
+
# Measured by --self-test's stateless-row check, which is why that check
|
|
433
|
+
# asserts structure rather than trusting the writer.
|
|
434
|
+
slots=$(ls "$gd" 2>/dev/null | grep -c '^slot-' || true)
|
|
435
|
+
locks=$(ls "$gd" 2>/dev/null | grep -c '^lock-' || true)
|
|
436
|
+
_row machine gate_slots_held "$slots" ok "machine-wide; this is what a queueing gate is waiting for"
|
|
437
|
+
_row machine gate_locks "$locks" ok
|
|
438
|
+
else
|
|
439
|
+
_row machine gate_slots_held "" unrun "no governor dir at $gd — nothing has taken a slot yet"
|
|
440
|
+
fi
|
|
441
|
+
fi
|
|
442
|
+
|
|
443
|
+
# ── substrate — is there a door to close through at all ─────────────────────
|
|
444
|
+
if _want substrate; then
|
|
445
|
+
base="${ONE_API_URL:-}"
|
|
446
|
+
if [ -z "$base" ]; then
|
|
447
|
+
if _try 2 curl -fsS -m 1 -o /dev/null "http://localhost:4321/api/health"; then base="http://localhost:4321"; else base="https://one.ie"; fi
|
|
448
|
+
fi
|
|
449
|
+
code="$(_try 6 curl -s -o /dev/null -w '%{http_code}' -m 5 "$base/api/health")"
|
|
450
|
+
case "$code" in
|
|
451
|
+
200) _row substrate door "$base" ok "reachable — the close can write" ;;
|
|
452
|
+
"") _row substrate door "$base" unrun "no answer inside the budget — the close will FILE its legs, not drop them" ;;
|
|
453
|
+
*) _row substrate door "$base" bad "health returned $code — board writes will be filed to the ledger instead" ;;
|
|
454
|
+
esac
|
|
455
|
+
if [ -n "$SLUG" ]; then
|
|
456
|
+
P="$ROOT/text/$SLUG.md"
|
|
457
|
+
if [ -f "$P" ]; then
|
|
458
|
+
if grep -qE '^\s*proof:' "$P" 2>/dev/null; then
|
|
459
|
+
_row substrate promise "$SLUG" ok "text/$SLUG.md carries a proof: — settleable"
|
|
460
|
+
else
|
|
461
|
+
_row substrate promise "$SLUG" bad "text/$SLUG.md has no proof: — a promise with no observable settles DISSOLVED"
|
|
462
|
+
fi
|
|
463
|
+
else
|
|
464
|
+
_row substrate promise "" n/a "no text/$SLUG.md — this close has no promise"
|
|
465
|
+
fi
|
|
466
|
+
else
|
|
467
|
+
_row substrate promise "" n/a "no slug given"
|
|
468
|
+
fi
|
|
469
|
+
fi
|
|
470
|
+
|
|
471
|
+
# ── self-test ───────────────────────────────────────────────────────────────
|
|
472
|
+
if [ "$SELFTEST" -eq 1 ]; then
|
|
473
|
+
echo "── close-metrics.sh --self-test ──"; fails=0
|
|
474
|
+
ck() { if [ "$1" = 0 ]; then echo "ok: $2"; else echo "FAIL: $2"; fails=$((fails+1)); fi; }
|
|
475
|
+
|
|
476
|
+
out="$(bash "${BASH_SOURCE[0]}" --section work,tree 2>&1)"
|
|
477
|
+
printf '%s' "$out" | grep -q 'files_changed'; ck $? "work section reports files_changed"
|
|
478
|
+
printf '%s' "$out" | grep -q 'landed'; ck $? "tree section reports landed as an ANCESTRY fact"
|
|
479
|
+
|
|
480
|
+
# THE UNRUN PROOF, and it is the whole point of the file. Point a section at a
|
|
481
|
+
# source that does not exist and require the row to read `unrun` — never `0`.
|
|
482
|
+
# A miner that prints 0 for an absent source is the `grep -c` trap with a
|
|
483
|
+
# nicer font, and this repo has shipped that failure.
|
|
484
|
+
out="$(CLOSE_BASE_REF=refs/heads/definitely-not-a-branch bash "${BASH_SOURCE[0]}" --section tree 2>&1)"
|
|
485
|
+
printf '%s' "$out" | grep -E 'landed .*unrun' >/dev/null; ck $? "RED PROOF — an unresolvable base makes landed UNRUN, not 'no'"
|
|
486
|
+
# Anchored on the VALUE COLUMN, not the line: the unrun row's own note reads
|
|
487
|
+
# "no origin/main to measure ancestry against", and a bare /(yes|no)/ matched
|
|
488
|
+
# that word in the prose and reported a verdict the code never emitted. A
|
|
489
|
+
# checker that fails on its own note is noise, and noise is how a red proof
|
|
490
|
+
# stops being read.
|
|
491
|
+
CLOSE_BASE_REF=refs/heads/definitely-not-a-branch bash "${BASH_SOURCE[0]}" --section tree --json 2>/dev/null \
|
|
492
|
+
| tr ',' '\n' | grep -A1 '"name":"landed"' | grep -qE '"value":"(yes|no)"' \
|
|
493
|
+
&& { echo "FAIL: unresolvable base still asserted a landed verdict"; fails=$((fails+1)); }
|
|
494
|
+
|
|
495
|
+
out="$(TEST_CACHE_DIR=/definitely/not/here bash "${BASH_SOURCE[0]}" --section gates 2>&1)"
|
|
496
|
+
printf '%s' "$out" | grep -E 'full_suite_receipt .*(MISS|unrun)' >/dev/null
|
|
497
|
+
ck $? "RED PROOF — an absent receipt cache is MISS or unrun, never a green receipt"
|
|
498
|
+
|
|
499
|
+
# GREEN PROOF — and it is the half that was missing, which is how the row stayed
|
|
500
|
+
# broken. The red proof above passes just as happily when the row can ONLY answer
|
|
501
|
+
# red: for months `cache` defaulted to "$ROOT/.claude/.test-cache", a path no
|
|
502
|
+
# minter has ever written to, so MISS was the only reachable verdict and the one
|
|
503
|
+
# check guarding it was satisfied by the defect. Measured 2026-09-15: the gate LEG
|
|
504
|
+
# read "pass — 2/2 lane(s)" on a tree this row called "MISS 0/2", same second.
|
|
505
|
+
#
|
|
506
|
+
# A check that cannot go both ways is not a check. But note WHERE the fault was:
|
|
507
|
+
# in the DEFAULT. A proof that exports TEST_CACHE_DIR overrides that default and
|
|
508
|
+
# passes against the broken version too — verified, and it is why the first attempt
|
|
509
|
+
# at this check was worthless. So the proof reads the default EXPRESSION and
|
|
510
|
+
# requires it to be the same one the minter uses.
|
|
511
|
+
minter="$(grep -m1 '^CACHE_DIR=' "$ROOT/.claude/scripts/test-cached.sh" | sed 's/^CACHE_DIR=//')"
|
|
512
|
+
mine="$(grep -m1 '^[[:space:]]*cache=' "${BASH_SOURCE[0]}" | sed 's/^[[:space:]]*cache=//')"
|
|
513
|
+
[ -n "$minter" ] && [ "$minter" = "$mine" ]
|
|
514
|
+
ck $? "PARITY — the receipt cache default matches test-cached.sh's (minter: ${minter:-?} / reader: ${mine:-?})"
|
|
515
|
+
|
|
516
|
+
out="$(bash "${BASH_SOURCE[0]}" --section rubric 2>&1)"
|
|
517
|
+
printf '%s' "$out" | grep -q 'no --composite passed'
|
|
518
|
+
ck $? "RED PROOF — no --composite is UNRUN, never a zero score"
|
|
519
|
+
# delta_tsc lives in `gates`, not `rubric`. Asking the wrong section for it
|
|
520
|
+
# returned nothing and read as a failure — the check was wrong, not the code.
|
|
521
|
+
out="$(bash "${BASH_SOURCE[0]}" --section gates 2>&1)"
|
|
522
|
+
printf '%s' "$out" | grep 'delta_tsc' | grep -q unrun
|
|
523
|
+
ck $? "RED PROOF — delta_tsc with no baseline is UNRUN (a 0 would satisfy the gate on no evidence)"
|
|
524
|
+
|
|
525
|
+
# The budget is real: a run must not outlive it by more than a slack second.
|
|
526
|
+
t0=$(date +%s); bash "${BASH_SOURCE[0]}" --budget 3 >/dev/null 2>&1; t1=$(date +%s)
|
|
527
|
+
[ $(( t1 - t0 )) -le 12 ]; ck $? "the whole run respects its budget (took $(( t1 - t0 ))s)"
|
|
528
|
+
|
|
529
|
+
# Every row carries a state, always. This is the law the file is built on, so
|
|
530
|
+
# it is asserted structurally rather than trusted.
|
|
531
|
+
bad=$(bash "${BASH_SOURCE[0]}" --json 2>/dev/null | tr ',' '\n' | grep -c '"state":""' || true)
|
|
532
|
+
[ "${bad:-0}" -eq 0 ]; ck $? "every row carries one of the four states (stateless rows: ${bad:-?})"
|
|
533
|
+
|
|
534
|
+
echo "──"
|
|
535
|
+
[ "$fails" -eq 0 ] && { echo "close-metrics self-test: PASS"; exit 0; }
|
|
536
|
+
echo "close-metrics self-test: $fails FAILURE(S)"; exit 1
|
|
537
|
+
fi
|
|
538
|
+
|
|
539
|
+
# ── report ──────────────────────────────────────────────────────────────────
|
|
540
|
+
OK=$(awk -F'\037' '$4=="ok"' "$ROWS" | grep -c . || true)
|
|
541
|
+
BAD=$(awk -F'\037' '$4=="bad"' "$ROWS" | grep -c . || true)
|
|
542
|
+
UNRUN=$(awk -F'\037' '$4=="unrun"' "$ROWS" | grep -c . || true)
|
|
543
|
+
NA=$(awk -F'\037' '$4=="n/a"' "$ROWS" | grep -c . || true)
|
|
544
|
+
ELAPSED=$(( $(date +%s) - STARTED ))
|
|
545
|
+
|
|
546
|
+
_emit_json() {
|
|
547
|
+
printf '{"slug":"%s","elapsed_s":%d,"ok":%d,"bad":%d,"unrun":%d,"na":%d,"rows":[' \
|
|
548
|
+
"$SLUG" "$ELAPSED" "$OK" "$BAD" "$UNRUN" "$NA"
|
|
549
|
+
local first=1 sec name val state note
|
|
550
|
+
while IFS="$_ROW_FS" read -r sec name val state note; do
|
|
551
|
+
[ -n "$sec" ] || continue
|
|
552
|
+
[ "$first" -eq 1 ] || printf ','; first=0
|
|
553
|
+
esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr -d '\000-\037'; }
|
|
554
|
+
printf '{"section":"%s","name":"%s","value":"%s","state":"%s","note":"%s"}' \
|
|
555
|
+
"$(esc "$sec")" "$(esc "$name")" "$(esc "$val")" "$(esc "$state")" "$(esc "$note")"
|
|
556
|
+
done < "$ROWS"
|
|
557
|
+
printf ']}\n'
|
|
558
|
+
}
|
|
559
|
+
[ -n "$JSON_OUT" ] && _emit_json > "$JSON_OUT" 2>/dev/null
|
|
560
|
+
|
|
561
|
+
if [ "$JSON" -eq 1 ]; then
|
|
562
|
+
printf '{"slug":"%s","elapsed_s":%d,"ok":%d,"bad":%d,"unrun":%d,"na":%d,"rows":[' \
|
|
563
|
+
"$SLUG" "$ELAPSED" "$OK" "$BAD" "$UNRUN" "$NA"
|
|
564
|
+
first=1
|
|
565
|
+
while IFS="$_ROW_FS" read -r sec name val state note; do
|
|
566
|
+
[ -z "$sec" ] && continue
|
|
567
|
+
[ "$first" -eq 1 ] || printf ','; first=0
|
|
568
|
+
esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr -d '\000-\037'; }
|
|
569
|
+
printf '{"section":"%s","name":"%s","value":"%s","state":"%s","note":"%s"}' \
|
|
570
|
+
"$(esc "$sec")" "$(esc "$name")" "$(esc "$val")" "$(esc "$state")" "$(esc "$note")"
|
|
571
|
+
done < "$ROWS"
|
|
572
|
+
printf ']}\n'
|
|
573
|
+
else
|
|
574
|
+
echo "── metrics ${SLUG:-session} ──"
|
|
575
|
+
last=""
|
|
576
|
+
while IFS="$_ROW_FS" read -r sec name val state note; do
|
|
577
|
+
[ -z "$sec" ] && continue
|
|
578
|
+
[ "$sec" != "$last" ] && { echo " [$sec]"; last="$sec"; }
|
|
579
|
+
# `-` not an em-dash: printf's %-28s pads by BYTES, and a 3-byte glyph in a
|
|
580
|
+
# 1-column slot shifts every row that uses it. A report whose own columns
|
|
581
|
+
# drift is a report people stop scanning.
|
|
582
|
+
printf ' %-24s %-28s %-6s %s\n' "$name" "${val:--}" "$state" "$note"
|
|
583
|
+
done < "$ROWS"
|
|
584
|
+
printf ' ok=%d bad=%d unrun=%d n/a=%d %ds\n' "$OK" "$BAD" "$UNRUN" "$NA" "$ELAPSED"
|
|
585
|
+
[ "$UNRUN" -gt 0 ] && echo " NOTE: an unrun row is NOT a good row. It is a number nobody has."
|
|
586
|
+
fi
|
|
587
|
+
exit 0
|