@oneie/claude 0.7.0 → 0.9.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/agents/abm-strategist.md +89 -0
- package/agents/ads-meta.md +97 -0
- package/agents/analyst.md +173 -0
- package/agents/architect.md +280 -0
- package/agents/brand-guardian.md +88 -0
- package/agents/brand-strategist.md +92 -0
- package/agents/campaign-content.md +90 -0
- package/agents/campaign-email.md +88 -0
- package/agents/campaign-sms.md +87 -0
- package/agents/campaign-social.md +87 -0
- package/agents/cco.md +99 -0
- package/agents/ceo.md +106 -0
- package/agents/chairman.md +120 -0
- package/agents/cmo.md +101 -0
- package/agents/community-greeter.md +89 -0
- package/agents/community-moderator.md +92 -0
- package/agents/compliance.md +92 -0
- package/agents/copywriter.md +100 -0
- package/agents/creative-strategist.md +95 -0
- package/agents/cro.md +98 -0
- package/agents/cto.md +267 -0
- package/agents/customer-interviewer.md +93 -0
- package/agents/customer-researcher.md +89 -0
- package/agents/customer-success-manager.md +90 -0
- package/agents/customer-trainer.md +90 -0
- package/agents/cxo.md +100 -0
- package/agents/demand-creator.md +89 -0
- package/agents/demo-mover.md +83 -0
- package/agents/demo-specialist.md +89 -0
- package/agents/demo-thai-family-law.md +87 -0
- package/agents/designer.md +112 -0
- package/agents/discovery-caller.md +98 -0
- package/agents/doctor.md +139 -0
- package/agents/educate-coach.md +100 -0
- package/agents/elevate-tutor.md +83 -0
- package/agents/email-lifecycle-marketer.md +91 -0
- package/agents/engage-specialist.md +99 -0
- package/agents/events-coordinator.md +90 -0
- package/agents/foundation-builder.md +94 -0
- package/agents/funnel-architect.md +89 -0
- package/agents/gift-creator.md +100 -0
- package/agents/google-ads.md +103 -0
- package/agents/guide.md +292 -0
- package/agents/helpdesk-dispatcher.md +88 -0
- package/agents/hook-specialist.md +91 -0
- package/agents/identify-optimizer.md +101 -0
- package/agents/implementer.md +305 -0
- package/agents/incident-commander.md +120 -0
- package/agents/insights-lead.md +93 -0
- package/agents/journey-runner.md +113 -0
- package/agents/linkedin-ads.md +123 -0
- package/agents/live-sales-chat.md +90 -0
- package/agents/market-researcher.md +88 -0
- package/agents/media-buyer.md +96 -0
- package/agents/movers-customer-researcher.md +95 -0
- package/agents/movers-foundation-builder.md +96 -0
- package/agents/movers-market-researcher.md +97 -0
- package/agents/movers-pricing-strategist.md +171 -0
- package/agents/nurture-architect.md +99 -0
- package/agents/offer-architect.md +92 -0
- package/agents/onboarder.md +222 -0
- package/agents/onboarding-specialist.md +92 -0
- package/agents/operations-dashboard.md +98 -0
- package/agents/perf-engineer.md +348 -0
- package/agents/playbook-writer.md +71 -0
- package/agents/plg-strategist.md +91 -0
- package/agents/positioning-architect.md +88 -0
- package/agents/press-officer.md +89 -0
- package/agents/pricing-strategist.md +94 -0
- package/agents/privacy-officer.md +92 -0
- package/agents/referral-manager.md +91 -0
- package/agents/refine-analyst.md +102 -0
- package/agents/release-manager.md +261 -0
- package/agents/renewals-upsell-rep.md +90 -0
- package/agents/review-engineer.md +327 -0
- package/agents/rewards-steward.md +82 -0
- package/agents/sales-call-coach.md +94 -0
- package/agents/sales-closer.md +98 -0
- package/agents/security-auditor.md +313 -0
- package/agents/sell-closer.md +101 -0
- package/agents/share-amplifier.md +99 -0
- package/agents/social-media-manager.md +92 -0
- package/agents/storyteller.md +250 -0
- package/agents/strategist.md +83 -0
- package/agents/strategy-aligner.md +94 -0
- package/agents/support-agent.md +90 -0
- package/agents/tagger.md +245 -0
- package/agents/tech-writer.md +216 -0
- package/agents/test-engineer.md +243 -0
- package/agents/tiktok-ads.md +105 -0
- package/agents/tracking-engineer.md +92 -0
- package/agents/upsell-strategist.md +101 -0
- package/agents/voice.md +85 -0
- package/agents/w4-tools.md +153 -0
- package/agents/w4-verify.md +20 -138
- package/agents/workflow-optimiser.md +84 -0
- package/commands/close.md +814 -160
- package/commands/create.md +2 -2
- package/commands/deploy.md +554 -175
- package/commands/do.md +119 -109
- package/commands/fast.md +67 -0
- package/commands/improve.md +2 -2
- package/commands/one.md +418 -0
- package/commands/see.md +1 -1
- package/commands/sync.md +1 -1
- package/commands/tasks.md +222 -0
- package/commands/vespio.md +110 -0
- package/commands/vespio.remote.md +227 -0
- package/hooks/hooks.json +25 -79
- package/hooks/lib/governor-escape-match.sh +88 -0
- package/hooks/lib/hook.sh +4 -13
- package/hooks/lib/signal.sh +9 -2
- package/hooks/scripts/branch-pin.sh +6 -0
- package/hooks/scripts/config-protect.sh +6 -0
- package/hooks/scripts/do-outcome-gate.sh +19 -2
- package/hooks/scripts/git-add-guard.sh +43 -2
- package/hooks/scripts/governor-escape.sh +96 -0
- package/hooks/scripts/load-guard.sh +127 -0
- package/hooks/scripts/post-edit-check.sh +36 -29
- package/hooks/scripts/session-start.sh +34 -80
- package/hooks/scripts/task-complete-verify.sh +46 -40
- package/package.json +1 -1
- package/rules/documentation.md +9 -0
- package/scripts/ad-copy-lint.sh +656 -0
- package/scripts/agentverse-audit.sh +256 -0
- package/scripts/asi-walk.sh +435 -0
- package/scripts/astro-build-cached.sh +143 -0
- package/scripts/blocks-manifest-cached.sh +100 -0
- package/scripts/blocks-manifest.mjs +497 -0
- package/scripts/blocks-ratchet.sh +116 -0
- package/scripts/blocks-render-probe.mjs +529 -0
- package/scripts/blocks-usage.mjs +334 -0
- package/scripts/chat-context-check.sh +89 -0
- package/scripts/close-metrics.sh +558 -0
- package/scripts/close-owner.sh +268 -0
- package/scripts/db-sync-lock-check.sh +116 -0
- package/scripts/deploy-dev.sh +35 -0
- package/scripts/deploy-emit.sh +298 -0
- package/scripts/deploy-gate-check.sh +128 -0
- package/scripts/deploy-ready.sh +78 -0
- package/scripts/deploy-record.sh +605 -0
- package/scripts/deploy.sh +1273 -0
- package/scripts/do-auto.sh +598 -48
- package/scripts/do-brief.sh +113 -0
- package/scripts/do-close.sh +1137 -0
- package/scripts/do-commit.sh +75 -0
- package/scripts/do-consumer-sweep.sh +18 -1
- package/scripts/do-cycle-shape-check.sh +160 -0
- package/scripts/do-decide.sh +476 -0
- package/scripts/do-derive-check.sh +436 -0
- package/scripts/do-fleet.sh +106 -28
- package/scripts/do-folder.sh +10 -1
- package/scripts/do-next.sh +106 -0
- package/scripts/do-orchestrate.sh +17 -5
- package/scripts/do-plan-json.mjs +201 -0
- package/scripts/do-plan-json.sh +8 -0
- package/scripts/do-preflight.sh +117 -0
- package/scripts/do-project.sh +157 -0
- package/scripts/do-prove-selftest.sh +108 -0
- package/scripts/do-prove.sh +295 -23
- package/scripts/do-rank.py +31 -1
- package/scripts/do-recon-cache.sh +7 -1
- package/scripts/do-recon-pack.sh +196 -0
- package/scripts/do-reconcile.sh +121 -4
- package/scripts/do-signal.sh +280 -23
- package/scripts/do-smoke.sh +18 -1
- package/scripts/do-test-gate.sh +80 -0
- package/scripts/do-tick.sh +102 -0
- package/scripts/do-tier.sh +6 -0
- package/scripts/do-triage.sh +182 -0
- package/scripts/do-ui-gate.sh +1 -1
- package/scripts/do-w4-gates.sh +451 -0
- package/scripts/do-walk.sh +12 -1
- package/scripts/env-sync.sh +173 -0
- package/scripts/factory-brief-check.sh +330 -0
- package/scripts/factory-check.sh +68 -14
- 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 +118 -3
- package/scripts/factory-review-check.mjs +61 -0
- package/scripts/factory-ship.sh +61 -0
- package/scripts/factory-tasks-check.sh +18 -1
- package/scripts/factory-turn.sh +326 -0
- package/scripts/factory-walk.sh +396 -0
- package/scripts/factory-width.sh +57 -0
- package/scripts/fade-toxic.sh +4 -3
- package/scripts/fixtures/factory-brief-real.md +44 -0
- package/scripts/fixtures/triage-dupe.md +5 -0
- package/scripts/fleet-manifest.mjs +108 -0
- package/scripts/fleet-status.sh +110 -0
- package/scripts/full-suite-paths-check.sh +144 -0
- package/scripts/gate-reaper-check.sh +98 -0
- package/scripts/gate-reaper.sh +125 -0
- package/scripts/gate-run.sh +73 -0
- package/scripts/gc-content-check.sh +140 -0
- package/scripts/gen-dev-config.py +20 -0
- package/scripts/govern-bound-check.sh +60 -0
- package/scripts/govern-claims-check.sh +233 -0
- package/scripts/govern-mem-check.sh +290 -0
- package/scripts/governor-doors-check.sh +362 -0
- package/scripts/governor-escape-check.sh +171 -0
- package/scripts/health.sh +413 -0
- package/scripts/id-inventory.mjs +418 -0
- package/scripts/land.sh +551 -0
- package/scripts/lib/gc-finished.sh +77 -0
- package/scripts/lib/govern.sh +361 -0
- package/scripts/lib/govern.ts +756 -0
- package/scripts/lighthouse-run.sh +187 -0
- package/scripts/livekit-live-check.sh +61 -0
- package/scripts/livekit-ratchet.sh +46 -0
- package/scripts/load-guard-check.sh +49 -0
- package/scripts/machine-check.sh +102 -0
- package/scripts/machine-watch.sh +177 -0
- package/scripts/one-agents.mjs +415 -0
- package/scripts/one-resume.sh +78 -0
- package/scripts/orphan-baseline.json +182 -0
- package/scripts/orphan-modules.mjs +179 -0
- package/scripts/pr-body.sh +335 -0
- package/scripts/preview-fd-check.sh +289 -0
- package/scripts/promise-manifest.mjs +24 -1
- package/scripts/release.sh +322 -0
- package/scripts/roles-check.sh +946 -0
- package/scripts/sdk-build-cached.sh +64 -0
- package/scripts/signal-watch.sh +241 -0
- package/scripts/skills-publish.sh +94 -0
- package/scripts/speed-cache-check.sh +173 -0
- package/scripts/speed-check.mjs +907 -0
- package/scripts/speed-parity-check.sh +648 -0
- package/scripts/speed-waterfall-check.sh +355 -0
- package/scripts/substrate-env-parity.mjs +156 -0
- package/scripts/tasks-claim-race.mjs +108 -0
- package/scripts/tasks-loop.sh +185 -0
- package/scripts/test-cached.sh +255 -0
- package/scripts/test-full.sh +87 -0
- package/scripts/test-honesty.mjs +137 -0
- package/scripts/test-lanes.sh +166 -0
- package/scripts/test-speed.sh +94 -0
- package/scripts/triage-shape-check.sh +149 -0
- package/scripts/tsc-cached.sh +179 -0
- package/scripts/typedb-flake-check.sh +197 -0
- package/scripts/urls-lint.sh +15 -0
- package/scripts/verify-fast.sh +445 -0
- package/scripts/vespio-sync.sh +149 -0
- package/scripts/wf-check.mjs +104 -1
- package/scripts/worktree-preview.sh +879 -0
- package/scripts/worktree-up.sh +208 -0
- package/skills/livekit-agents/SKILL.md +285 -0
- package/skills/livekit-agents/references/freshness-rules.md +168 -0
- package/skills/shadcn/SKILL.md +1 -1
- package/skills/signal/SKILL.md +0 -1
- package/skills/voice/SKILL.md +94 -6
- package/skills/voice/corpus-check.sh +87 -0
- package/hooks/scripts/compact-hint.sh +0 -35
- package/hooks/scripts/gate-guard.sh +0 -83
- package/hooks/scripts/read-tracker.sh +0 -26
- package/hooks/scripts/session-end-verify.sh +0 -51
- package/hooks/scripts/stop-reflect.sh +0 -140
- package/hooks/scripts/sync-priority-todo.sh +0 -57
- package/hooks/scripts/sync-todo-docs.sh +0 -46
- package/hooks/scripts/tool-signal.sh +0 -48
- package/scripts/do-tasks-bridge.py +0 -366
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# govern-mem-check.sh — prove the machine governor's memory probe can say NO.
|
|
3
|
+
#
|
|
4
|
+
# bash .claude/scripts/govern-mem-check.sh # all checks
|
|
5
|
+
# bash .claude/scripts/govern-mem-check.sh --self-test # same, explicit
|
|
6
|
+
# bash .claude/scripts/govern-mem-check.sh --live # just read this box
|
|
7
|
+
#
|
|
8
|
+
# WHY THIS EXISTS
|
|
9
|
+
# gate_headroom used to compute availability as
|
|
10
|
+
# hw.memsize * (memory_pressure "free percentage") / 100
|
|
11
|
+
# and that percentage counts reclaimable memory — file cache, purgeable, and
|
|
12
|
+
# already-compressed pages — as free. It is a PRESSURE signal, not a quantity.
|
|
13
|
+
# Measured three times on one 24GB box, all while ~1% of RAM was actually free
|
|
14
|
+
# and 9-12 GB sat in swap, the old probe answered "room for 2 / 7 / 7 more
|
|
15
|
+
# 2GB cycles". A governor that cannot say no is not a governor.
|
|
16
|
+
#
|
|
17
|
+
# Every check below drives a SYNTHETIC machine state — a fake vm_stat, a fake
|
|
18
|
+
# memory_pressure block and a fake vm.swapusage line, together, so the old
|
|
19
|
+
# formula and the new one see the SAME input and the comparison is honest.
|
|
20
|
+
# Stubbing is done by overriding _gv_vm_stat / _gv_swapusage / _gv_memsize,
|
|
21
|
+
# the same idiom govern-claims-check.sh uses to stub _gv_alive.
|
|
22
|
+
#
|
|
23
|
+
# Nothing here touches the real machine, the real $GOVERN_DIR, or any gate.
|
|
24
|
+
set -uo pipefail
|
|
25
|
+
|
|
26
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
27
|
+
cd "$ROOT" || exit 1
|
|
28
|
+
|
|
29
|
+
# Sandbox: never touch the machine-wide governor dir.
|
|
30
|
+
export GOVERN_DIR="${TMPDIR:-/tmp}/one-govern-memcheck.$$"
|
|
31
|
+
mkdir -p "$GOVERN_DIR"
|
|
32
|
+
trap 'rm -rf "$GOVERN_DIR"' EXIT
|
|
33
|
+
|
|
34
|
+
# shellcheck source=lib/govern.sh
|
|
35
|
+
. "$ROOT/.claude/scripts/lib/govern.sh"
|
|
36
|
+
|
|
37
|
+
PASS=0; FAIL=0
|
|
38
|
+
ok() { PASS=$((PASS+1)); printf ' \033[32mPASS\033[0m %s\n' "$*"; }
|
|
39
|
+
bad() { FAIL=$((FAIL+1)); printf ' \033[31mFAIL\033[0m %s\n' "$*"; }
|
|
40
|
+
hdr() { printf '\n\033[1m%s\033[0m\n' "$*"; }
|
|
41
|
+
|
|
42
|
+
# ── the pre-fix arithmetic, VERBATIM ────────────────────────────────────────
|
|
43
|
+
# Copied unchanged from lib/govern.sh before 2026-09-03 (the `deploy-gate-check.sh`
|
|
44
|
+
# idiom: carry the old code so the red proof is a real comparison, not a story).
|
|
45
|
+
_old_gate_headroom() {
|
|
46
|
+
local total_gb free_pct avail_gb usable_gb per_cycle reserve slots
|
|
47
|
+
total_gb=$(( $(_gv_memsize 2>/dev/null || echo 0) / 1073741824 ))
|
|
48
|
+
[ "$total_gb" -lt 1 ] && { echo 99; return 0; }
|
|
49
|
+
free_pct=$(_gv_memory_pressure 2>/dev/null | awk -F': ' '/free percentage/{gsub(/%/,"",$2); print int($2)}')
|
|
50
|
+
[ -z "$free_pct" ] && { echo 99; return 0; }
|
|
51
|
+
per_cycle="${GOVERN_GB_PER_CYCLE:-2}"
|
|
52
|
+
reserve="${GOVERN_RESERVE_GB:-2}"
|
|
53
|
+
avail_gb=$(( total_gb * free_pct / 100 ))
|
|
54
|
+
usable_gb=$(( avail_gb - reserve ))
|
|
55
|
+
[ "$usable_gb" -lt 0 ] && usable_gb=0
|
|
56
|
+
slots=$(( usable_gb / per_cycle ))
|
|
57
|
+
[ "$slots" -lt 1 ] && slots=1
|
|
58
|
+
echo "$slots"
|
|
59
|
+
}
|
|
60
|
+
_old_gate_pressure() {
|
|
61
|
+
local free_pct
|
|
62
|
+
free_pct=$(_gv_memory_pressure 2>/dev/null | awk -F': ' '/free percentage/{gsub(/%/,"",$2); print $2}')
|
|
63
|
+
[ -z "$free_pct" ] && return 0
|
|
64
|
+
[ "$free_pct" -lt "${GOVERN_MIN_FREE_PCT:-12}" ] && return 1
|
|
65
|
+
return 0
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# ── synthetic machine states ────────────────────────────────────────────────
|
|
69
|
+
# All on a 24 GB / 16384-byte-page box, so hw.memsize is constant and only the
|
|
70
|
+
# page counts move. FIX_* are set by fixture(); the stubs read them.
|
|
71
|
+
FIX_FREE=0; FIX_PURGE=0; FIX_INACT=0; FIX_FILEBK=0; FIX_ACTIVE=0; FIX_WIRED=0
|
|
72
|
+
FIX_COMPRESSOR=0; FIX_PCT=0; FIX_SWAP_USED="0.00"; FIX_SWAP_TOTAL="0.00"
|
|
73
|
+
FIX_MODE=normal # normal | empty | garbage | nopagesize
|
|
74
|
+
|
|
75
|
+
_gv_memsize() { [ "$FIX_MODE" = "nomemsize" ] && return 1; echo 25769803776; }
|
|
76
|
+
_gv_swapusage() { echo "total = ${FIX_SWAP_TOTAL}M used = ${FIX_SWAP_USED}M free = 0.00M (encrypted)"; }
|
|
77
|
+
_gv_memory_pressure() {
|
|
78
|
+
cat <<PRESSURE
|
|
79
|
+
Swapins: 1614739
|
|
80
|
+
Swapouts: 2928367
|
|
81
|
+
|
|
82
|
+
Page Q counts:
|
|
83
|
+
Pages active: $FIX_ACTIVE
|
|
84
|
+
Pages inactive: $FIX_INACT
|
|
85
|
+
Pages speculative: 6772
|
|
86
|
+
Pages throttled: 0
|
|
87
|
+
Pages wired down: $FIX_WIRED
|
|
88
|
+
|
|
89
|
+
Compressor Stats:
|
|
90
|
+
Pages used by compressor: $FIX_COMPRESSOR
|
|
91
|
+
|
|
92
|
+
System-wide memory free percentage: ${FIX_PCT}%
|
|
93
|
+
PRESSURE
|
|
94
|
+
}
|
|
95
|
+
_gv_vm_stat() {
|
|
96
|
+
case "$FIX_MODE" in
|
|
97
|
+
empty) return 0 ;;
|
|
98
|
+
garbage) echo "vm_stat: command not found"; return 0 ;;
|
|
99
|
+
nopagesize) echo "Mach Virtual Memory Statistics:" ;;
|
|
100
|
+
*) echo "Mach Virtual Memory Statistics: (page size of 16384 bytes)" ;;
|
|
101
|
+
esac
|
|
102
|
+
cat <<VMSTAT
|
|
103
|
+
Pages free: $FIX_FREE.
|
|
104
|
+
Pages active: $FIX_ACTIVE.
|
|
105
|
+
Pages inactive: $FIX_INACT.
|
|
106
|
+
Pages speculative: 6772.
|
|
107
|
+
Pages throttled: 0.
|
|
108
|
+
Pages wired down: $FIX_WIRED.
|
|
109
|
+
Pages purgeable: $FIX_PURGE.
|
|
110
|
+
File-backed pages: $FIX_FILEBK.
|
|
111
|
+
Anonymous pages: 893951.
|
|
112
|
+
Pages occupied by compressor: $FIX_COMPRESSOR.
|
|
113
|
+
Swapins: 1614739.
|
|
114
|
+
Swapouts: 2928367.
|
|
115
|
+
VMSTAT
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fixture() {
|
|
119
|
+
FIX_MODE=normal
|
|
120
|
+
case "$1" in
|
|
121
|
+
# ── The live reading taken 2026-09-03 at load 8, verbatim from vm_stat and
|
|
122
|
+
# memory_pressure on the box the operator was complaining about. It
|
|
123
|
+
# reproduces Receipt B: 1.3% of RAM free, 9.4 GB in swap, probe says 7.
|
|
124
|
+
thrash-now)
|
|
125
|
+
FIX_FREE=21032; FIX_PURGE=646; FIX_INACT=547837; FIX_FILEBK=216477
|
|
126
|
+
FIX_ACTIVE=555819; FIX_WIRED=250202; FIX_COMPRESSOR=135982
|
|
127
|
+
FIX_PCT=74; FIX_SWAP_USED="9400.56"; FIX_SWAP_TOTAL="10240.00" ;;
|
|
128
|
+
# ── Receipt A: the verifier's sample at load 27, with hook:load-guard itself
|
|
129
|
+
# reporting the machine saturated. free 15798 pages, compressor 8.7 GB,
|
|
130
|
+
# swap 11997/13312 M, memory_pressure 32%. Old probe answered 2.
|
|
131
|
+
thrash-A)
|
|
132
|
+
FIX_FREE=15798; FIX_PURGE=500; FIX_INACT=137812; FIX_FILEBK=100000
|
|
133
|
+
FIX_ACTIVE=600000; FIX_WIRED=250000; FIX_COMPRESSOR=569254
|
|
134
|
+
FIX_PCT=32; FIX_SWAP_USED="11997.44"; FIX_SWAP_TOTAL="13312.00" ;;
|
|
135
|
+
# ── The row that kills a swap-subtraction design: genuinely idle NOW
|
|
136
|
+
# (8 GB free, 6 GB cache) but macOS has not released the 9.4 GB swapfile
|
|
137
|
+
# it grew an hour ago. A probe that charges for history serialises this.
|
|
138
|
+
recovered-idle)
|
|
139
|
+
FIX_FREE=524288; FIX_PURGE=1000; FIX_INACT=655360; FIX_FILEBK=393216
|
|
140
|
+
FIX_ACTIVE=200000; FIX_WIRED=200000; FIX_COMPRESSOR=50000
|
|
141
|
+
FIX_PCT=85; FIX_SWAP_USED="9400.56"; FIX_SWAP_TOTAL="10240.00" ;;
|
|
142
|
+
# ── Fresh idle: 12 GB free, swap never grown.
|
|
143
|
+
fresh-idle)
|
|
144
|
+
FIX_FREE=786432; FIX_PURGE=500; FIX_INACT=65536; FIX_FILEBK=131072
|
|
145
|
+
FIX_ACTIVE=100000; FIX_WIRED=150000; FIX_COMPRESSOR=20000
|
|
146
|
+
FIX_PCT=90; FIX_SWAP_USED="0.00"; FIX_SWAP_TOTAL="0.00" ;;
|
|
147
|
+
# ── Absurd: nothing available at all. Must floor to 1, never 0 —
|
|
148
|
+
# do-fleet.sh clamps its slot count to this with no floor of its own.
|
|
149
|
+
starved)
|
|
150
|
+
FIX_FREE=0; FIX_PURGE=0; FIX_INACT=0; FIX_FILEBK=0
|
|
151
|
+
FIX_ACTIVE=1000000; FIX_WIRED=500000; FIX_COMPRESSOR=72864
|
|
152
|
+
FIX_PCT=1; FIX_SWAP_USED="16000.00"; FIX_SWAP_TOTAL="16384.00" ;;
|
|
153
|
+
*) echo "unknown fixture $1" >&2; exit 2 ;;
|
|
154
|
+
esac
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# The environment the checks are scored in: the box's real settings.json values
|
|
158
|
+
# minus the stale GOVERN_GB_PER_CYCLE pin, so the derived price is live.
|
|
159
|
+
unset GOVERN_GB_PER_CYCLE
|
|
160
|
+
export GOVERN_RESERVE_GB=3
|
|
161
|
+
export VITEST_MAX_FORKS=4 # what a Claude Code session actually sets
|
|
162
|
+
|
|
163
|
+
[ "${1:-}" = "--live" ] && { echo "live: $(gate_mem_report)"; exit 0; }
|
|
164
|
+
|
|
165
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
166
|
+
hdr "1. THRASH — the new probe says no, and the OLD one says yes (red proof)"
|
|
167
|
+
for st in thrash-now thrash-A; do
|
|
168
|
+
fixture "$st"
|
|
169
|
+
new=$(gate_headroom); old=$(_old_gate_headroom)
|
|
170
|
+
avail=$(gate_mem_avail_mb)
|
|
171
|
+
oldpct=$FIX_PCT
|
|
172
|
+
if _old_gate_pressure; then oldp="0 (has headroom)"; else oldp="1 (thrashing)"; fi
|
|
173
|
+
if gate_pressure; then newp="0 (has headroom)"; else newp="1 (thrashing)"; fi
|
|
174
|
+
echo " [$st] memory_pressure says ${oldpct}% free · vm_stat says $((FIX_FREE*16384/1048576))MB free · swap ${FIX_SWAP_USED}M used"
|
|
175
|
+
echo " OLD: headroom=$old pressure=$oldp NEW: avail=${avail}MB headroom=$new pressure=$newp"
|
|
176
|
+
[ "$new" -eq 1 ] && ok "$st: new cap FELL to 1" || bad "$st: new cap is $new, expected 1"
|
|
177
|
+
[ "$old" -gt 1 ] && ok "$st: OLD arithmetic authorised $old cycles on this same state (red proof)" \
|
|
178
|
+
|| bad "$st: OLD arithmetic did not over-authorise — red proof is inert"
|
|
179
|
+
_old_gate_pressure && ok "$st: OLD gate_pressure called it healthy (red proof)" \
|
|
180
|
+
|| bad "$st: OLD gate_pressure already fired — red proof is inert"
|
|
181
|
+
gate_pressure && bad "$st: NEW gate_pressure still calls it healthy" \
|
|
182
|
+
|| ok "$st: NEW gate_pressure fires"
|
|
183
|
+
done
|
|
184
|
+
|
|
185
|
+
hdr "2. HEALTHY — not replaced by a serialising bug"
|
|
186
|
+
for st in recovered-idle fresh-idle; do
|
|
187
|
+
fixture "$st"
|
|
188
|
+
new=$(gate_headroom); avail=$(gate_mem_avail_mb)
|
|
189
|
+
echo " [$st] avail=${avail}MB swap ${FIX_SWAP_USED}M used -> headroom=$new"
|
|
190
|
+
[ "$new" -ge 2 ] && ok "$st: healthy box still funds $new cycles (>=2)" \
|
|
191
|
+
|| bad "$st: healthy box collapsed to $new — this is the serialising bug"
|
|
192
|
+
gate_pressure && ok "$st: gate_pressure stays quiet" || bad "$st: gate_pressure fired on a healthy box"
|
|
193
|
+
done
|
|
194
|
+
echo " (recovered-idle is the row that refutes any design subtracting vm.swapusage:"
|
|
195
|
+
echo " 9.4GB of stale swap would drive it to 1 while 8GB of RAM sits free.)"
|
|
196
|
+
|
|
197
|
+
hdr "3. BROKEN SENSOR — 99, never 0, never 1"
|
|
198
|
+
for mode in empty garbage nopagesize; do
|
|
199
|
+
fixture thrash-now; FIX_MODE="$mode"
|
|
200
|
+
h=$(gate_headroom)
|
|
201
|
+
[ "$h" = "99" ] && ok "vm_stat '$mode' -> headroom=99 (do not constrain)" \
|
|
202
|
+
|| bad "vm_stat '$mode' -> headroom=$h, expected 99"
|
|
203
|
+
gate_pressure && ok "vm_stat '$mode' -> gate_pressure does not block" \
|
|
204
|
+
|| bad "vm_stat '$mode' -> gate_pressure blocked on a broken probe"
|
|
205
|
+
done
|
|
206
|
+
|
|
207
|
+
hdr "4. FLOOR — a starved box slows down, it never stops"
|
|
208
|
+
fixture starved
|
|
209
|
+
h=$(gate_headroom); a=$(gate_mem_avail_mb)
|
|
210
|
+
echo " avail=${a}MB, reserve=$((GOVERN_RESERVE_GB*1024))MB, price=$(gate_price_mb)MB -> headroom=$h"
|
|
211
|
+
[ "$h" = "1" ] && ok "starved box -> 1 (do-fleet.sh clamps to this with no floor of its own; 0 would launch nothing)" \
|
|
212
|
+
|| bad "starved box -> $h, expected 1"
|
|
213
|
+
|
|
214
|
+
hdr "5. PRICE — derived from the live fork count, not a stale constant"
|
|
215
|
+
p4=$(VITEST_MAX_FORKS=4 gate_price_mb)
|
|
216
|
+
p8=$(VITEST_MAX_FORKS=8 gate_price_mb)
|
|
217
|
+
pdef=$(unset VITEST_MAX_FORKS; gate_price_mb)
|
|
218
|
+
povr=$(GOVERN_GB_PER_CYCLE=2 gate_price_mb)
|
|
219
|
+
echo " forks=4 -> ${p4}MB · forks=8 -> ${p8}MB · unset -> ${pdef}MB · GOVERN_GB_PER_CYCLE=2 -> ${povr}MB"
|
|
220
|
+
[ "$p8" -gt "$p4" ] && ok "price tracks fork count (8 forks cost more than 4)" || bad "price ignores fork count"
|
|
221
|
+
[ "$p4" -gt 2048 ] && ok "a 4-fork slot is priced above the old flat 2048MB" || bad "4-fork slot still priced at or below the stale constant ($p4)"
|
|
222
|
+
[ "$pdef" = "$p8" ] && ok "unset VITEST_MAX_FORKS prices the config default of 8" || bad "unset != 8-fork price"
|
|
223
|
+
[ "$povr" = "2048" ] && ok "explicit GOVERN_GB_PER_CYCLE still wins (operator override)" || bad "override ignored"
|
|
224
|
+
if grep -q '"GOVERN_GB_PER_CYCLE"' "$ROOT/.claude/settings.json" 2>/dev/null; then
|
|
225
|
+
bad "settings.json still pins GOVERN_GB_PER_CYCLE — the derivation is dead code in every Claude Code session"
|
|
226
|
+
else
|
|
227
|
+
ok "settings.json no longer pins GOVERN_GB_PER_CYCLE"
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
hdr "6. SELF-RED — gut the probe and the checks above MUST go red"
|
|
231
|
+
# A checker that stays green against a gutted probe proves nothing
|
|
232
|
+
# (govern-claims-check.sh stubs _gv_alive for exactly this reason). Here we
|
|
233
|
+
# put the OLD arithmetic back behind the new name and re-run section 1's
|
|
234
|
+
# assertions: they have to fail.
|
|
235
|
+
_saved_headroom=$(declare -f gate_headroom)
|
|
236
|
+
_saved_pressure=$(declare -f gate_pressure)
|
|
237
|
+
gate_headroom() { _old_gate_headroom; }
|
|
238
|
+
gate_pressure() { _old_gate_pressure; }
|
|
239
|
+
red=0
|
|
240
|
+
for st in thrash-now thrash-A; do
|
|
241
|
+
fixture "$st"
|
|
242
|
+
h=$(gate_headroom)
|
|
243
|
+
[ "$h" -eq 1 ] || red=$((red+1))
|
|
244
|
+
gate_pressure && red=$((red+1))
|
|
245
|
+
done
|
|
246
|
+
if [ "$red" -ge 4 ]; then
|
|
247
|
+
ok "with the old arithmetic restored, all 4 thrash assertions fail ($red/4) — the checks have power"
|
|
248
|
+
else
|
|
249
|
+
bad "gutted probe still satisfied $(( 4 - red ))/4 thrash assertions — this checker proves nothing"
|
|
250
|
+
fi
|
|
251
|
+
eval "$_saved_headroom"; eval "$_saved_pressure"
|
|
252
|
+
|
|
253
|
+
hdr "7. LOAD-GUARD's MEMORY ARM — the one site that actually BLOCKS"
|
|
254
|
+
# load-guard-check.sh exercises the regex classifier (which commands count as
|
|
255
|
+
# heavy), never the memory state. This drives the real hook against the REAL
|
|
256
|
+
# box with only the memory threshold moving, so the arm is seen firing AND
|
|
257
|
+
# staying silent — a guard only ever seen to fire is an unproven guard. The load
|
|
258
|
+
# and running-gate arms are pinned out of the way so nothing else can explain
|
|
259
|
+
# the verdict.
|
|
260
|
+
_lg_run() { # _lg_run <GUARD_MIN_FREE_PCT> -> prints "deny" or "allow"
|
|
261
|
+
local out
|
|
262
|
+
out=$(CLAUDE_PROJECT_DIR="$ROOT" GUARD_MIN_FREE_PCT="$1" \
|
|
263
|
+
GUARD_LOAD_FACTOR=100000 GUARD_MAX_RUNNING=100000 \
|
|
264
|
+
bash "$ROOT/.claude/hooks/load-guard.sh" \
|
|
265
|
+
'{"tool_name":"Bash","tool_input":{"command":"bunx vitest run"}}' 2>/dev/null)
|
|
266
|
+
case "$out" in *'"deny"'*) echo deny ;; *) echo allow ;; esac
|
|
267
|
+
}
|
|
268
|
+
_lg_hi=$(_lg_run 101) # threshold above any possible reading -> must deny
|
|
269
|
+
_lg_lo=$(_lg_run 0) # threshold below any possible reading -> must allow
|
|
270
|
+
echo " GUARD_MIN_FREE_PCT=101 -> $_lg_hi · GUARD_MIN_FREE_PCT=0 -> $_lg_lo"
|
|
271
|
+
[ "$_lg_hi" = "deny" ] && ok "memory arm FIRES (hook emits a deny decision, does not crash open)" \
|
|
272
|
+
|| bad "memory arm did not fire — the blocking hook failed OPEN"
|
|
273
|
+
[ "$_lg_lo" = "allow" ] && ok "memory arm stays silent on a satisfied threshold" \
|
|
274
|
+
|| bad "memory arm fires unconditionally — it is not reading memory"
|
|
275
|
+
# And it must survive a probe that cannot be read at all: point the hook at a
|
|
276
|
+
# project dir with no govern.sh. FREE falls back to 100, so the arm goes quiet
|
|
277
|
+
# rather than taking the hook down with it.
|
|
278
|
+
_lg_nolib=$(CLAUDE_PROJECT_DIR="$GOVERN_DIR" GUARD_MIN_FREE_PCT=101 \
|
|
279
|
+
GUARD_LOAD_FACTOR=100000 GUARD_MAX_RUNNING=100000 \
|
|
280
|
+
bash "$ROOT/.claude/hooks/load-guard.sh" \
|
|
281
|
+
'{"tool_name":"Bash","tool_input":{"command":"bunx vitest run"}}' 2>/dev/null; echo "rc=$?")
|
|
282
|
+
case "$_lg_nolib" in
|
|
283
|
+
*rc=0*) ok "missing govern.sh -> hook still exits 0 (FREE=100, arm silent, nothing crashes)" ;;
|
|
284
|
+
*) bad "missing govern.sh -> hook exited non-zero: $_lg_nolib" ;;
|
|
285
|
+
esac
|
|
286
|
+
|
|
287
|
+
hdr "RESULT"
|
|
288
|
+
echo " $PASS passed, $FAIL failed"
|
|
289
|
+
[ "$FAIL" -eq 0 ] || { echo " GOVERN-MEM-CHECK: RED"; exit 1; }
|
|
290
|
+
echo " GOVERN-MEM-CHECK: GREEN"
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# governor-doors-check.sh — the DOORS half of the governor guard.
|
|
3
|
+
#
|
|
4
|
+
# bash .claude/scripts/governor-doors-check.sh # audit + reentrancy
|
|
5
|
+
# bash .claude/scripts/governor-doors-check.sh --list # every heavy script
|
|
6
|
+
# bash .claude/scripts/governor-doors-check.sh --self-test
|
|
7
|
+
#
|
|
8
|
+
# hook:governor-escape guards what an executor TYPES. This guards what the tree
|
|
9
|
+
# OFFERS. They are different holes and only the second one explains the real
|
|
10
|
+
# failure: `cd channels && bun run test` is an ungoverned 135-file two-runner
|
|
11
|
+
# suite, and nothing about that command string looks like an escape. The hole
|
|
12
|
+
# was the package script, not the command.
|
|
13
|
+
#
|
|
14
|
+
# Enumerated from `git ls-files` at run time, never from a hardcoded package
|
|
15
|
+
# list -- the rot test-lanes.sh explicitly avoided. A NEW package, or a new
|
|
16
|
+
# heavy script in an existing one, is therefore a failure the day it lands
|
|
17
|
+
# rather than the day someone remembers to look.
|
|
18
|
+
#
|
|
19
|
+
# WHAT COUNTS AS A DOOR: a package.json script that reaches a runner pool --
|
|
20
|
+
# vitest / bun test / playwright / astro check -- directly, or one hop through
|
|
21
|
+
# `bash <script>.sh`. `channels`' test is the one-hop case and the reason the
|
|
22
|
+
# hop is followed: its own file, not its package.json, holds the two runners.
|
|
23
|
+
#
|
|
24
|
+
# WHAT IS DELIBERATELY NOT A DOOR is in SKIP below, each with its reason. That
|
|
25
|
+
# list is the argument, not an allowlist of convenience.
|
|
26
|
+
#
|
|
27
|
+
# A LOCK IS NOT A SLOT. Until 2026-09-07 the typecheck skip below read "tsc
|
|
28
|
+
# already has its own lock via tsc-cached.sh", and that reasoning is wrong in a
|
|
29
|
+
# way that cost the machine: gate_lock is keyed by FOLDER and dedupes identical
|
|
30
|
+
# work, while a SLOT caps concurrent heavy work machine-wide. N worktrees are N
|
|
31
|
+
# folders, so N locks are all uncontended while N typecheckers run. Measured that
|
|
32
|
+
# day: three 2.5GB tsc processes at once, load 171, localhost at 8.4s a page, and
|
|
33
|
+
# THIS CHECKER REPORTING "0 open". The "2-second typecheck" half was wrong too --
|
|
34
|
+
# the measured runs were 2.5GB and 7+ minutes. The compute sites now take a slot
|
|
35
|
+
# (see the `compute sites` section below, which is what would have caught it).
|
|
36
|
+
# SHIPS (needs-env). In a generated factory clone this enumerates THAT repo
|
|
37
|
+
# package.json files, while every line in the skip list names a monorepo path
|
|
38
|
+
# that can never match there -- so it may report open doors it has no opinion
|
|
39
|
+
# about. That is loud rather than wrong: the doors it names really are
|
|
40
|
+
# ungoverned in that tree. Read the skip list as this repo argument, not as a
|
|
41
|
+
# universal one.
|
|
42
|
+
set -uo pipefail
|
|
43
|
+
# GOV_DOORS_ROOT lets --self-test point the REAL audit at a sandbox tree.
|
|
44
|
+
# Without it the red proof has to duplicate the classifier, and a duplicated
|
|
45
|
+
# classifier is the drift this file exists to avoid.
|
|
46
|
+
ROOT="${GOV_DOORS_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
47
|
+
cd "$ROOT" || exit 1
|
|
48
|
+
|
|
49
|
+
HEAVY_RE='vitest|tsc[[:space:]]+--noEmit|astro[[:space:]]+check|playwright[[:space:]]+test|(^|[^a-zA-Z0-9_-])bun[[:space:]]+test([^a-zA-Z0-9_:-]|$)'
|
|
50
|
+
|
|
51
|
+
# ── the reasoned skips ──────────────────────────────────────────────────────
|
|
52
|
+
# <pkg-relpath>::<script> why
|
|
53
|
+
skips() {
|
|
54
|
+
cat <<'SKIP'
|
|
55
|
+
*::typecheck routes through tsc-cached.sh, which since 2026-09-07 takes a real SLOT around its compute (gate-run.sh), not merely its dedupe lock -- enforced by the `compute sites` section, not asserted here
|
|
56
|
+
*::test:watch a watch never exits; a wall-clock bound would kill it
|
|
57
|
+
*::test:raw an escape hatch by definition -- ungoverned is the whole point
|
|
58
|
+
*::verify:raw an escape hatch by definition
|
|
59
|
+
*::test:coverage watch-mode vitest (no `run`); a bound would kill it
|
|
60
|
+
one.ie/web::test:e2e:pw opt-in e2e needing a live server; a 1800s bound could kill a legitimate long run
|
|
61
|
+
one.ie/web::test:e2e:pw:ui interactive -- a bound would kill a human's session
|
|
62
|
+
one.ie/web::test:e2e:pw:debug interactive -- a bound would kill a human's session
|
|
63
|
+
backup::test 2 test files under `bun test`, no fork pool -- cannot be the memory driver
|
|
64
|
+
packages/evals::test 1 test file -- cannot be the memory driver
|
|
65
|
+
packages/plugin-pages::test 1 test file -- cannot be the memory driver
|
|
66
|
+
packages/plugin-pages::build tsc --noEmit wearing a build's name; same reason as typecheck
|
|
67
|
+
pay/packages/one-protocol::test watch-mode vitest (no `run`) AND 0 test files -- see FINDINGS
|
|
68
|
+
pay/packages/sdk::test 0 test files
|
|
69
|
+
oo-brain::typecheck not a deployed service
|
|
70
|
+
template/site::typecheck Astro 7 template, not a deployed service
|
|
71
|
+
template-release::test a release template, not a live package
|
|
72
|
+
template-release::verify a TEMPLATE: it is copied out to users WITHOUT .claude/, so wrapping it would bake in a gate-run.sh path that does not exist downstream and break the template itself
|
|
73
|
+
SKIP
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
is_skipped() { # is_skipped <pkgdir> <script>
|
|
77
|
+
local pkg="$1" name="$2" k v
|
|
78
|
+
while read -r k v; do
|
|
79
|
+
[ -z "$k" ] && continue
|
|
80
|
+
case "$k" in
|
|
81
|
+
"*::$name") return 0 ;;
|
|
82
|
+
"$pkg::$name") return 0 ;;
|
|
83
|
+
esac
|
|
84
|
+
done < <(skips)
|
|
85
|
+
return 1
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# ── enumerate ───────────────────────────────────────────────────────────────
|
|
89
|
+
# Emits: <state> <pkgdir> <script> <command> state = GOVERNED|OPEN|SKIP
|
|
90
|
+
# Tracked files in a repo; a plain walk in a sandbox. Never node_modules.
|
|
91
|
+
_list_package_jsons() {
|
|
92
|
+
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
93
|
+
git ls-files '*package.json' | grep -v node_modules
|
|
94
|
+
else
|
|
95
|
+
find . -name package.json -not -path '*/node_modules/*' | sed 's|^\./||'
|
|
96
|
+
fi
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
enumerate() {
|
|
100
|
+
local pj
|
|
101
|
+
while IFS= read -r pj; do
|
|
102
|
+
[ -f "$pj" ] || continue
|
|
103
|
+
node -e '
|
|
104
|
+
const fs=require("fs"), path=require("path");
|
|
105
|
+
const pj=process.argv[1], dir=path.dirname(pj);
|
|
106
|
+
let j; try{ j=JSON.parse(fs.readFileSync(pj,"utf8")); }catch(e){ process.exit(0); }
|
|
107
|
+
const heavy=/vitest|tsc\s+--noEmit|astro\s+check|playwright\s+test|(^|[^\w-])bun\s+test([^\w:-]|$)/;
|
|
108
|
+
const scripts=j.scripts||{};
|
|
109
|
+
for(const [k,v] of Object.entries(scripts)){
|
|
110
|
+
let reaches=heavy.test(v), via="", hopGoverned=false;
|
|
111
|
+
// ONE HOP: `bash scripts/test.sh` hides its runners in its own file.
|
|
112
|
+
// Two traps, both hit on the FIRST run of this checker:
|
|
113
|
+
// - install-hooks.sh only NAMES tsc, in a comment and an echo. A bare
|
|
114
|
+
// mention is not an invocation, so the hop is position-anchored the
|
|
115
|
+
// same way hook:governor-escape is. It is the same scar
|
|
116
|
+
// this repo already carries under "a hook greps the whole
|
|
117
|
+
// command"; reproducing it here made the checker cry wolf
|
|
118
|
+
// on six innocent scripts.
|
|
119
|
+
// - verify-fast.sh IS governed: it routes everything through
|
|
120
|
+
// gate-run.sh internally. Governance can live in the HOPPED file,
|
|
121
|
+
// so it has to be read there too, not only in package.json.
|
|
122
|
+
if(!reaches){
|
|
123
|
+
// Take EVERY `bash <x>.sh` in the value and skip gate-run.sh itself:
|
|
124
|
+
// once a one-hop script is wrapped, the first .sh in the string is the
|
|
125
|
+
// wrapper, and matching only that made channels and the three demos
|
|
126
|
+
// vanish from this audit the moment they were fixed. A guard that goes
|
|
127
|
+
// blind on the thing it just repaired cannot detect a later regression.
|
|
128
|
+
const all=[...v.matchAll(/bash\s+([^\s;&|]+\.sh)/g)].map(function(x){return x[1];});
|
|
129
|
+
const wrapped=all.some(function(x){return /gate-run\.sh$/.test(x);});
|
|
130
|
+
const m=all.filter(function(x){return !/gate-run\.sh$/.test(x);}).map(function(x){return [null,x];})[0];
|
|
131
|
+
if(m){
|
|
132
|
+
const hp=path.join(dir,m[1]);
|
|
133
|
+
try{
|
|
134
|
+
// Comments are prose, never invocations. install-hooks.sh
|
|
135
|
+
// line 2 reads "(astro check + tsc)" -- the bare paren made
|
|
136
|
+
// it look like a command position. Strip comments first.
|
|
137
|
+
const body=fs.readFileSync(hp,"utf8")
|
|
138
|
+
.split("\n").filter(function(l){return !/^\s*#/.test(l);}).join("\n");
|
|
139
|
+
const invoked=new RegExp(
|
|
140
|
+
"(^|[;&|(]|&&|\\|\\|)[ \\t]*([A-Za-z_][A-Za-z0-9_]*=[^ \\t]*[ \\t]+)*"+
|
|
141
|
+
"((bunx|npx|bun|npm|xargs)[ \\t]+)*"+
|
|
142
|
+
"(vitest|tsc[ \\t]+--noEmit|astro[ \\t]+check|playwright[ \\t]+test|bun[ \\t]+test)","m");
|
|
143
|
+
if(invoked.test(body)){
|
|
144
|
+
reaches=true; via=" [via "+m[1]+"]";
|
|
145
|
+
// governed either by the wrapper in package.json, or because the
|
|
146
|
+
// hopped file routes through gate-run.sh internally (verify-fast).
|
|
147
|
+
if(wrapped || /gate-run\.sh/.test(body)) hopGoverned=true;
|
|
148
|
+
}
|
|
149
|
+
}catch(e){}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if(!reaches) continue;
|
|
153
|
+
const governed=/gate-run\.sh/.test(v) || hopGoverned;
|
|
154
|
+
console.log((governed?"GOVERNED":"OPEN")+"\t"+dir+"\t"+k+"\t"+v+via);
|
|
155
|
+
}
|
|
156
|
+
' "$pj"
|
|
157
|
+
done < <(_list_package_jsons)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
bad=0
|
|
161
|
+
ok() { printf ' ok %s\n' "$*"; }
|
|
162
|
+
nope() { printf ' FAIL %s\n' "$*"; bad=$((bad + 1)); }
|
|
163
|
+
|
|
164
|
+
audit() {
|
|
165
|
+
echo "== doors — every heavy package script is governed, or skipped for a stated reason"
|
|
166
|
+
local state pkg name cmd n_gov=0 n_skip=0
|
|
167
|
+
while IFS=$'\t' read -r state pkg name cmd; do
|
|
168
|
+
[ -z "${state:-}" ] && continue
|
|
169
|
+
if [ "$state" = "GOVERNED" ]; then n_gov=$((n_gov+1)); continue; fi
|
|
170
|
+
if is_skipped "$pkg" "$name"; then n_skip=$((n_skip+1)); continue; fi
|
|
171
|
+
nope "UNGOVERNED heavy script: (cd $pkg && bun run $name) -> $cmd"
|
|
172
|
+
printf ' fix: wrap it — bash <rel>/.claude/scripts/gate-run.sh %s -- %s\n' "$name" "$cmd"
|
|
173
|
+
done < <(enumerate)
|
|
174
|
+
[ "$bad" -eq 0 ] && ok "$n_gov governed, $n_skip skipped with a reason, 0 open"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# ── the wrapped paths must actually resolve ────────────────────────────────
|
|
178
|
+
# Every wrap names gate-run.sh RELATIVELY, resolved from the package dir that
|
|
179
|
+
# `bun run` cd's into. A wrong `../` count is the one way wrapping can break a
|
|
180
|
+
# script, and it would surface only when somebody ran it -- months later, as a
|
|
181
|
+
# "test command is broken" that nobody connects to this change. Derived from the
|
|
182
|
+
# enumeration, never from a list, so a package wrapped tomorrow is checked too.
|
|
183
|
+
paths() {
|
|
184
|
+
echo "== wrapped paths — every relative gate-run.sh resolves from its package dir"
|
|
185
|
+
local state pkg name cmd rel n=0
|
|
186
|
+
while IFS=$'\t' read -r state pkg name cmd; do
|
|
187
|
+
[ "${state:-}" = "GOVERNED" ] || continue
|
|
188
|
+
rel=$(printf '%s' "$cmd" | sed -nE 's|.*bash ([^ ]*gate-run\.sh) .*|\1|p' | head -1)
|
|
189
|
+
[ -n "$rel" ] || continue
|
|
190
|
+
case "$rel" in /*) [ -f "$rel" ] && { n=$((n+1)); continue; } ;; esac
|
|
191
|
+
if [ -f "$pkg/$rel" ]; then
|
|
192
|
+
n=$((n+1))
|
|
193
|
+
else
|
|
194
|
+
nope "$pkg :: $name names $rel, which does NOT resolve from $pkg"
|
|
195
|
+
fi
|
|
196
|
+
done < <(enumerate)
|
|
197
|
+
[ "$bad" -eq 0 ] && ok "$n wrapped scripts, every relative path resolves"
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# ── re-entrancy: the one way wrapping could make things WORSE ───────────────
|
|
201
|
+
# gate-run is re-entrant by design (GOVERN_IN_GATE), so a wrapped `test` called
|
|
202
|
+
# from a wrapped `verify` must inherit the outer slot rather than queue behind
|
|
203
|
+
# it. With the cap at 1 a non-re-entrant nest DEADLOCKS -- which is exactly what
|
|
204
|
+
# the red half below forces, so this check is not taking re-entrancy on trust.
|
|
205
|
+
reentrancy() {
|
|
206
|
+
echo "== re-entrancy — a wrapped gate nested in a wrapped gate must not deadlock"
|
|
207
|
+
local sandbox G o e
|
|
208
|
+
sandbox="$(mktemp -d)"
|
|
209
|
+
G="$ROOT/.claude/scripts/gate-run.sh"
|
|
210
|
+
o="$sandbox/out"; e="$sandbox/err"
|
|
211
|
+
local T=30 # bound the whole experiment; the commands under test are echoes
|
|
212
|
+
|
|
213
|
+
# NEVER capture a gate with `out=$(gate-run ... 2>&1)`. run_bounded
|
|
214
|
+
# (govern.sh:130-134) forks a watchdog holding `sleep $GOVERN_GATE_TIMEOUT`,
|
|
215
|
+
# deliberately detached from STDOUT on 2026-09-01 so a command substitution
|
|
216
|
+
# would not block on it -- but `2>&1` reattaches it to the captured pipe, and
|
|
217
|
+
# the substitution then hangs for the FULL timeout after the command has
|
|
218
|
+
# already finished. Measured here: 1800s of nothing, killed at 144.
|
|
219
|
+
# Redirect to files and read the files.
|
|
220
|
+
|
|
221
|
+
# GREEN: the nested gate inherits the outer slot even with the cap at 1.
|
|
222
|
+
GOVERN_DIR="$sandbox" GOVERN_MAX_GATES=1 GOVERN_QUEUE_WAIT=8 GOVERN_GATE_TIMEOUT=$T \
|
|
223
|
+
bash "$G" outer -- bash -c \
|
|
224
|
+
"GOVERN_DIR='$sandbox' GOVERN_MAX_GATES=1 GOVERN_QUEUE_WAIT=8 GOVERN_GATE_TIMEOUT=$T bash '$G' inner -- echo NESTED_OK" \
|
|
225
|
+
>"$o" 2>"$e"
|
|
226
|
+
if grep -q NESTED_OK "$o"; then
|
|
227
|
+
ok "nested gate inherited the outer slot at cap 1 (no deadlock)"
|
|
228
|
+
else
|
|
229
|
+
nope "nested gate did NOT complete at cap 1 — deadlock. out=[$(cat "$o")] err=[$(cat "$e")]"
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
# RED: clear GOVERN_IN_GATE inside, so the nest asks for a SECOND slot at cap
|
|
233
|
+
# 1. It must starve -- proving the green above was re-entrancy doing the work
|
|
234
|
+
# and not merely a cap that never bound.
|
|
235
|
+
: > "$o"; : > "$e"
|
|
236
|
+
GOVERN_DIR="$sandbox" GOVERN_MAX_GATES=1 GOVERN_QUEUE_WAIT=4 GOVERN_GATE_TIMEOUT=$T \
|
|
237
|
+
bash "$G" outer2 -- bash -c \
|
|
238
|
+
"unset GOVERN_IN_GATE; GOVERN_DIR='$sandbox' GOVERN_MAX_GATES=1 GOVERN_QUEUE_WAIT=4 GOVERN_GATE_TIMEOUT=$T bash '$G' inner2 -- echo SHOULD_NOT_RUN" \
|
|
239
|
+
>"$o" 2>"$e"
|
|
240
|
+
if grep -q SHOULD_NOT_RUN "$o"; then
|
|
241
|
+
nope "a second slot was granted at cap 1 — the cap does not bind, so the green proves nothing"
|
|
242
|
+
elif grep -q "no slot after" "$e"; then
|
|
243
|
+
ok "without re-entrancy the same nest starves at cap 1 (the cap really binds)"
|
|
244
|
+
else
|
|
245
|
+
nope "unexpected red-half output. out=[$(cat "$o")] err=[$(cat "$e")]"
|
|
246
|
+
fi
|
|
247
|
+
# RED PROOF for `compute sites`: a script that spawns a heavy compute with no
|
|
248
|
+
# gate-run.sh must turn compute_sites red. This is the exact shape tsc-cached.sh
|
|
249
|
+
# had before 2026-09-07 -- a gate_lock, and a bare bunx tsc inside it.
|
|
250
|
+
local probe_dir probe
|
|
251
|
+
probe_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
252
|
+
# NOT a dotfile: `for f in "$d"/*.sh` does not glob dotfiles, so a probe named
|
|
253
|
+
# .zz-*.sh is invisible to the very check it is supposed to drive red -- the
|
|
254
|
+
# proof would pass by never being seen. Named plainly, and rm'd below.
|
|
255
|
+
probe="$probe_dir/zz-compute-probe.sh"
|
|
256
|
+
cat > "$probe" <<'PROBE'
|
|
257
|
+
#!/usr/bin/env bash
|
|
258
|
+
# a lock, and a heavy compute with no slot -- the 2026-09-07 defect, in miniature
|
|
259
|
+
gate_lock "probe" 10 && bunx tsc --noEmit
|
|
260
|
+
PROBE
|
|
261
|
+
local b0=$bad
|
|
262
|
+
compute_sites >/dev/null 2>&1
|
|
263
|
+
if [ "$bad" -gt "$b0" ]; then
|
|
264
|
+
ok "a lock-without-slot compute site turns the audit RED"
|
|
265
|
+
bad=$b0
|
|
266
|
+
else
|
|
267
|
+
nope "compute_sites stayed green against a bare 'bunx tsc --noEmit' with no gate-run"
|
|
268
|
+
fi
|
|
269
|
+
rm -f "$probe"
|
|
270
|
+
|
|
271
|
+
rm -rf "$sandbox"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# ── compute sites — a gate_lock is not a slot ───────────────────────────────
|
|
275
|
+
#
|
|
276
|
+
# The `doors` section above audits PACKAGE SCRIPTS. It cannot see the defect
|
|
277
|
+
# that actually cost the machine on 2026-09-07, because that one lived one layer
|
|
278
|
+
# down: tsc-cached.sh held a per-folder gate_lock and spawned `bunx tsc` with no
|
|
279
|
+
# slot at all. Every door was green, the skip list had a stated reason, and three
|
|
280
|
+
# 2.5GB typecheckers ran concurrently while the governor reported 1 of 2 slots.
|
|
281
|
+
#
|
|
282
|
+
# The rule this enforces: ANY script here that spawns a heavy compute must also
|
|
283
|
+
# reference gate-run.sh. Not "takes a lock" -- a lock dedupes identical work, a
|
|
284
|
+
# slot bounds the machine, and only one of those is a concurrency cap.
|
|
285
|
+
compute_sites() {
|
|
286
|
+
echo "== compute sites — a heavy compute behind a lock still needs a SLOT"
|
|
287
|
+
local d f n_ok=0 hits
|
|
288
|
+
d="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
289
|
+
for f in "$d"/*.sh; do
|
|
290
|
+
case "$(basename "$f")" in
|
|
291
|
+
gate-run.sh|governor-doors-check.sh|governor-escape-check.sh|machine-check.sh) continue ;;
|
|
292
|
+
# FIXTURES — these NAME a heavy command as test data and spawn nothing:
|
|
293
|
+
# load-guard-check.sh passes command STRINGS to the hook ( check 1 "bunx ..." )
|
|
294
|
+
# govern-mem-check.sh embeds them in JSON tool_input payloads
|
|
295
|
+
# deploy-gate-check.sh greps deploy.sh for the command as a PATTERN
|
|
296
|
+
# Each was verified by reading the matching lines, not assumed.
|
|
297
|
+
load-guard-check.sh|govern-mem-check.sh|deploy-gate-check.sh) continue ;;
|
|
298
|
+
esac
|
|
299
|
+
# PRESENCE, not command-position. The first version of this asked "is the
|
|
300
|
+
# compute in command position", blanking quoted regions -- and it could not
|
|
301
|
+
# see the very defect it was written for: tsc-cached.sh spawned its tsc from
|
|
302
|
+
# inside a quoted `bash -c "... ${TSC_CACHE_CMD:-bunx tsc --noEmit} ..."`.
|
|
303
|
+
# Reverting tsc-cached.sh to its pre-fix state left that check GREEN, which
|
|
304
|
+
# is the only test of a checker that matters.
|
|
305
|
+
#
|
|
306
|
+
# So the rule is blunt on purpose: if a heavy token appears outside a comment,
|
|
307
|
+
# this file must reference gate-run.sh somewhere. Scripts that only NAME a
|
|
308
|
+
# command as a test fixture are handled by FIXTURES below, by name and with a
|
|
309
|
+
# reason -- the same "the skip list is the argument" doctrine as the doors.
|
|
310
|
+
hits=$(grep -nE '(bunx|npx|bun x) +(tsc +--noEmit|vitest +run)' "$f" 2>/dev/null \
|
|
311
|
+
| grep -vE '^[0-9]+:[[:space:]]*#' || true)
|
|
312
|
+
[ -n "$hits" ] || continue
|
|
313
|
+
if grep -q 'gate-run\.sh' "$f"; then
|
|
314
|
+
n_ok=$((n_ok+1))
|
|
315
|
+
else
|
|
316
|
+
nope "$(basename "$f") spawns a heavy compute with no gate-run.sh anywhere:
|
|
317
|
+
$(printf '%s' "$hits" | head -3 | sed 's/^/ /')"
|
|
318
|
+
fi
|
|
319
|
+
done
|
|
320
|
+
[ "$bad" -eq 0 ] && ok "$n_ok script(s) spawn a heavy compute, every one routes through gate-run.sh"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
# ── red proof ───────────────────────────────────────────────────────────────
|
|
324
|
+
self_test() {
|
|
325
|
+
echo "== self-test — plant an open door, the REAL audit must go RED"
|
|
326
|
+
local sandbox out rc
|
|
327
|
+
sandbox="$(mktemp -d)"
|
|
328
|
+
mkdir -p "$sandbox/planted"
|
|
329
|
+
cat > "$sandbox/planted/package.json" <<'PKG'
|
|
330
|
+
{ "name": "planted", "scripts": { "test": "vitest run" } }
|
|
331
|
+
PKG
|
|
332
|
+
# Drive audit() itself, in a sandbox tree, through the same enumerate().
|
|
333
|
+
out=$(GOV_DOORS_ROOT="$sandbox" GOV_DOORS_INNER=1 bash "${BASH_SOURCE[0]}" 2>&1); rc=$?
|
|
334
|
+
if [ $rc -ne 0 ] && printf '%s' "$out" | grep -q 'UNGOVERNED heavy script'; then
|
|
335
|
+
ok "a planted ungoverned test makes the real audit go RED"
|
|
336
|
+
else
|
|
337
|
+
nope "planted open door did not turn the audit red (rc=$rc): $out"
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
# And the inverse: wrapping the SAME script must clear the SAME audit.
|
|
341
|
+
cat > "$sandbox/planted/package.json" <<'PKG'
|
|
342
|
+
{ "name": "planted", "scripts": { "test": "bash ../.claude/scripts/gate-run.sh t -- vitest run" } }
|
|
343
|
+
PKG
|
|
344
|
+
out=$(GOV_DOORS_ROOT="$sandbox" GOV_DOORS_INNER=1 bash "${BASH_SOURCE[0]}" 2>&1); rc=$?
|
|
345
|
+
if [ $rc -eq 0 ]; then
|
|
346
|
+
ok "wrapping the same script clears the same audit"
|
|
347
|
+
else
|
|
348
|
+
nope "wrapped script still reads open: $out"
|
|
349
|
+
fi
|
|
350
|
+
rm -rf "$sandbox"
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
case "${1:-}" in
|
|
354
|
+
--list) enumerate | sort | column -t -s$'\t' 2>/dev/null || enumerate | sort; exit 0 ;;
|
|
355
|
+
--self-test) self_test ;;
|
|
356
|
+
*) if [ -n "${GOV_DOORS_INNER:-}" ]; then audit
|
|
357
|
+
else audit; echo; paths; echo; compute_sites; echo; reentrancy; echo; self_test; fi ;;
|
|
358
|
+
esac
|
|
359
|
+
|
|
360
|
+
echo
|
|
361
|
+
if [ "$bad" -eq 0 ]; then echo "RESULT: PASS — no ungoverned heavy door, and nesting does not deadlock"
|
|
362
|
+
else echo "RESULT: RED — $bad failure(s)"; exit 1; fi
|