@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.
Files changed (230) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/abm-strategist.md +67 -1
  3. package/agents/ads-meta.md +67 -1
  4. package/agents/analyst.md +67 -1
  5. package/agents/animator.md +108 -0
  6. package/agents/architect.md +269 -20
  7. package/agents/brand-guardian.md +67 -1
  8. package/agents/brand-strategist.md +67 -1
  9. package/agents/campaign-content.md +67 -1
  10. package/agents/campaign-email.md +67 -1
  11. package/agents/campaign-sms.md +67 -1
  12. package/agents/campaign-social.md +67 -1
  13. package/agents/cco.md +83 -2
  14. package/agents/ceo.md +108 -11
  15. package/agents/chairman.md +197 -0
  16. package/agents/cmo.md +82 -2
  17. package/agents/community-greeter.md +67 -1
  18. package/agents/community-moderator.md +67 -1
  19. package/agents/compliance.md +67 -1
  20. package/agents/copywriter.md +67 -1
  21. package/agents/creative-strategist.md +67 -1
  22. package/agents/cro.md +81 -1
  23. package/agents/cto.md +266 -28
  24. package/agents/customer-interviewer.md +67 -1
  25. package/agents/customer-researcher.md +67 -1
  26. package/agents/customer-success-manager.md +67 -1
  27. package/agents/customer-trainer.md +67 -1
  28. package/agents/cxo.md +82 -1
  29. package/agents/demand-creator.md +67 -1
  30. package/agents/demo-mover.md +67 -1
  31. package/agents/demo-specialist.md +67 -1
  32. package/agents/demo-thai-family-law.md +67 -1
  33. package/agents/designer.md +67 -1
  34. package/agents/discovery-caller.md +67 -1
  35. package/agents/doctor.md +269 -0
  36. package/agents/educate-coach.md +67 -1
  37. package/agents/elevate-tutor.md +67 -1
  38. package/agents/email-lifecycle-marketer.md +67 -1
  39. package/agents/engage-specialist.md +67 -1
  40. package/agents/events-coordinator.md +67 -1
  41. package/agents/foundation-builder.md +67 -1
  42. package/agents/funnel-architect.md +67 -1
  43. package/agents/gift-creator.md +67 -1
  44. package/agents/google-ads.md +67 -1
  45. package/agents/guide.md +67 -1
  46. package/agents/helpdesk-dispatcher.md +67 -1
  47. package/agents/hook-specialist.md +67 -1
  48. package/agents/identify-optimizer.md +67 -1
  49. package/agents/implementer.md +313 -45
  50. package/agents/incident-commander.md +67 -1
  51. package/agents/insights-lead.md +87 -1
  52. package/agents/journey-runner.md +67 -1
  53. package/agents/linkedin-ads.md +67 -1
  54. package/agents/live-sales-chat.md +67 -1
  55. package/agents/market-researcher.md +67 -1
  56. package/agents/media-buyer.md +67 -1
  57. package/agents/memory-keeper.md +195 -0
  58. package/agents/movers-customer-researcher.md +67 -1
  59. package/agents/movers-foundation-builder.md +67 -1
  60. package/agents/movers-market-researcher.md +67 -1
  61. package/agents/movers-pricing-strategist.md +67 -1
  62. package/agents/nurture-architect.md +67 -1
  63. package/agents/offer-architect.md +67 -1
  64. package/agents/onboarder.md +67 -1
  65. package/agents/onboarding-specialist.md +67 -1
  66. package/agents/operations-dashboard.md +87 -1
  67. package/agents/perf-engineer.md +333 -37
  68. package/agents/playbook-writer.md +67 -1
  69. package/agents/plg-strategist.md +67 -1
  70. package/agents/positioning-architect.md +67 -1
  71. package/agents/press-officer.md +67 -1
  72. package/agents/pricing-strategist.md +67 -1
  73. package/agents/privacy-officer.md +67 -1
  74. package/agents/referral-manager.md +67 -1
  75. package/agents/refine-analyst.md +67 -1
  76. package/agents/release-manager.md +446 -39
  77. package/agents/renewals-upsell-rep.md +67 -1
  78. package/agents/review-engineer.md +319 -45
  79. package/agents/rewards-steward.md +67 -1
  80. package/agents/sales-call-coach.md +67 -1
  81. package/agents/sales-closer.md +67 -1
  82. package/agents/security-auditor.md +343 -48
  83. package/agents/sell-closer.md +67 -1
  84. package/agents/share-amplifier.md +67 -1
  85. package/agents/social-media-manager.md +67 -1
  86. package/agents/storyteller.md +301 -0
  87. package/agents/strategist.md +67 -1
  88. package/agents/strategy-aligner.md +67 -1
  89. package/agents/support-agent.md +67 -1
  90. package/agents/tagger.md +327 -0
  91. package/agents/tech-writer.md +195 -22
  92. package/agents/test-engineer.md +398 -29
  93. package/agents/tiktok-ads.md +67 -1
  94. package/agents/tracking-engineer.md +67 -1
  95. package/agents/trailkeeper.md +181 -0
  96. package/agents/upsell-strategist.md +67 -1
  97. package/agents/voice.md +67 -1
  98. package/agents/w1-recon.md +1 -1
  99. package/agents/w2-decide.md +1 -1
  100. package/agents/w3-edit.md +8 -2
  101. package/agents/w4-verify.md +13 -0
  102. package/agents/workflow-optimiser.md +81 -1
  103. package/commands/close.md +916 -160
  104. package/commands/deploy.md +102 -724
  105. package/commands/do.md +58 -2
  106. package/commands/sweep.md +159 -0
  107. package/commands/tasks.md +222 -0
  108. package/hooks/scripts/dev-only.sh +135 -0
  109. package/hooks/scripts/git-add-guard.sh +37 -2
  110. package/hooks/scripts/session-start.sh +32 -4
  111. package/package.json +1 -1
  112. package/rules/scripts.md +85 -0
  113. package/scripts/CLAUDE.md +315 -0
  114. package/scripts/ad-copy-lint.sh +656 -0
  115. package/scripts/agent-actor-parity.sh +129 -0
  116. package/scripts/blocks-manifest-cached.sh +100 -0
  117. package/scripts/chat-context-check.sh +89 -0
  118. package/scripts/chrome.mjs +18 -0
  119. package/scripts/close-metrics.sh +587 -0
  120. package/scripts/close-owner.sh +326 -0
  121. package/scripts/db-sync-lock-check.sh +116 -0
  122. package/scripts/deploy-emit.sh +311 -0
  123. package/scripts/deploy-gate-check.sh +155 -0
  124. package/scripts/deploy-ready.sh +78 -0
  125. package/scripts/deploy-record.sh +605 -0
  126. package/scripts/deploy-schema-check.sh +58 -0
  127. package/scripts/deploy.sh +393 -243
  128. package/scripts/do-auto.sh +127 -26
  129. package/scripts/do-board.sh +429 -0
  130. package/scripts/do-close.sh +1184 -0
  131. package/scripts/do-consumer-sweep.sh +18 -1
  132. package/scripts/do-decide.sh +476 -0
  133. package/scripts/do-fleet.sh +8 -2
  134. package/scripts/do-plan-json.mjs +110 -12
  135. package/scripts/do-prove-selftest.sh +108 -0
  136. package/scripts/do-prove.sh +86 -10
  137. package/scripts/do-rank.py +200 -3
  138. package/scripts/do-reconcile.sh +73 -12
  139. package/scripts/do-signal.sh +101 -23
  140. package/scripts/do-smoke.sh +18 -1
  141. package/scripts/do-w4-gates.sh +11 -1
  142. package/scripts/do-world-check.sh +153 -0
  143. package/scripts/download-stats.sh +172 -0
  144. package/scripts/factory-brief-check.sh +330 -0
  145. package/scripts/factory-check.sh +18 -1
  146. package/scripts/factory-close-check.sh +257 -0
  147. package/scripts/factory-emit.sh +211 -0
  148. package/scripts/factory-executor-check.mjs +353 -0
  149. package/scripts/factory-peak.sh +301 -0
  150. package/scripts/factory-repo.sh +71 -0
  151. package/scripts/factory-review-check.mjs +61 -0
  152. package/scripts/factory-tasks-check.sh +18 -1
  153. package/scripts/fixtures/factory-brief-real.md +44 -0
  154. package/scripts/flywheel-outcome.sh +63 -0
  155. package/scripts/gate-reaper-check.sh +98 -0
  156. package/scripts/gate-reaper.sh +9 -0
  157. package/scripts/gate-watchdog.sh +619 -0
  158. package/scripts/gc-content-check.sh +142 -0
  159. package/scripts/gh-traffic-capture.sh +153 -0
  160. package/scripts/govern-order-check.sh +202 -0
  161. package/scripts/governor-doors-check.sh +86 -5
  162. package/scripts/health.sh +448 -0
  163. package/scripts/id-inventory.mjs +418 -0
  164. package/scripts/incident.sh +212 -0
  165. package/scripts/land.sh +755 -45
  166. package/scripts/lib/gc-finished.sh +77 -0
  167. package/scripts/livekit-ratchet.sh +18 -1
  168. package/scripts/machine-check.sh +1 -1
  169. package/scripts/memory-index-budget.sh +79 -0
  170. package/scripts/npm-downloads.sh +109 -0
  171. package/scripts/one-agents.mjs +204 -8
  172. package/scripts/one-resume.sh +31 -3
  173. package/scripts/pr-body.sh +335 -0
  174. package/scripts/preview-fd-check.sh +289 -0
  175. package/scripts/redirect-lint.sh +169 -0
  176. package/scripts/release.sh +40 -6
  177. package/scripts/resume-lost-sessions.sh +68 -0
  178. package/scripts/shoot-pages.mjs +140 -0
  179. package/scripts/signal-meta-backfill.ts +451 -0
  180. package/scripts/signal-watch.sh +63 -6
  181. package/scripts/speed-cache-check.sh +12 -2
  182. package/scripts/sweep.sh +426 -0
  183. package/scripts/task-titles-dump.ts +101 -0
  184. package/scripts/test-cached.sh +47 -10
  185. package/scripts/test-lanes.sh +14 -0
  186. package/scripts/thread-name-backfill.ts +215 -0
  187. package/scripts/triage-shape-check.sh +149 -0
  188. package/scripts/tsc-cached.sh +155 -8
  189. package/scripts/typedb-flake-check.sh +3 -1
  190. package/scripts/urls-lint.sh +8 -0
  191. package/scripts/verify-board-doors.sh +80 -0
  192. package/scripts/verify-fast.sh +159 -6
  193. package/scripts/worktree-up.sh +21 -3
  194. package/skills/astro/SKILL.md +9 -3
  195. package/skills/astro/optimize-performance.md +3 -2
  196. package/skills/cloudflare/SKILL.md +3 -2
  197. package/skills/cloudflare-security-audit/AI-AND-LLM.md +83 -0
  198. package/skills/cloudflare-security-audit/ATTACK-CLASSES.md +130 -0
  199. package/skills/cloudflare-security-audit/CLIENT-SIDE.md +83 -0
  200. package/skills/cloudflare-security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
  201. package/skills/cloudflare-security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
  202. package/skills/cloudflare-security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
  203. package/skills/cloudflare-security-audit/HUNTING.md +251 -0
  204. package/skills/cloudflare-security-audit/LICENSE +21 -0
  205. package/skills/cloudflare-security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
  206. package/skills/cloudflare-security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
  207. package/skills/cloudflare-security-audit/PROVENANCE.md +78 -0
  208. package/skills/cloudflare-security-audit/RECONNAISSANCE.md +156 -0
  209. package/skills/cloudflare-security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
  210. package/skills/cloudflare-security-audit/SKILL.md +192 -0
  211. package/skills/cloudflare-security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
  212. package/skills/cloudflare-security-audit/VALIDATION-AND-REPORTING.md +186 -0
  213. package/skills/cloudflare-security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
  214. package/skills/cloudflare-security-audit/report-schema.json +461 -0
  215. package/skills/cloudflare-security-audit/validate-coverage-ledger.cjs +872 -0
  216. package/skills/cloudflare-security-audit/validate-coverage-ledger.test.cjs +740 -0
  217. package/skills/cloudflare-security-audit/validate-findings.cjs +773 -0
  218. package/skills/cloudflare-security-audit/validate-findings.test.cjs +652 -0
  219. package/skills/deploy/REFERENCE.md +713 -0
  220. package/skills/deploy/SKILL.md +140 -0
  221. package/skills/fleet-audit/SKILL.md +58 -0
  222. package/skills/meeting/SKILL.md +220 -0
  223. package/skills/planning/SKILL.md +256 -0
  224. package/skills/shadcn/SKILL.md +1 -1
  225. package/skills/typedb/SKILL.md +7 -0
  226. package/skills/voice/SKILL.md +94 -6
  227. package/skills/voice/corpus-check.sh +87 -0
  228. package/templates/template-agent.md +7 -1
  229. package/templates/template-feature.md +9 -0
  230. 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