@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.
Files changed (263) hide show
  1. package/agents/abm-strategist.md +89 -0
  2. package/agents/ads-meta.md +97 -0
  3. package/agents/analyst.md +173 -0
  4. package/agents/architect.md +280 -0
  5. package/agents/brand-guardian.md +88 -0
  6. package/agents/brand-strategist.md +92 -0
  7. package/agents/campaign-content.md +90 -0
  8. package/agents/campaign-email.md +88 -0
  9. package/agents/campaign-sms.md +87 -0
  10. package/agents/campaign-social.md +87 -0
  11. package/agents/cco.md +99 -0
  12. package/agents/ceo.md +106 -0
  13. package/agents/chairman.md +120 -0
  14. package/agents/cmo.md +101 -0
  15. package/agents/community-greeter.md +89 -0
  16. package/agents/community-moderator.md +92 -0
  17. package/agents/compliance.md +92 -0
  18. package/agents/copywriter.md +100 -0
  19. package/agents/creative-strategist.md +95 -0
  20. package/agents/cro.md +98 -0
  21. package/agents/cto.md +267 -0
  22. package/agents/customer-interviewer.md +93 -0
  23. package/agents/customer-researcher.md +89 -0
  24. package/agents/customer-success-manager.md +90 -0
  25. package/agents/customer-trainer.md +90 -0
  26. package/agents/cxo.md +100 -0
  27. package/agents/demand-creator.md +89 -0
  28. package/agents/demo-mover.md +83 -0
  29. package/agents/demo-specialist.md +89 -0
  30. package/agents/demo-thai-family-law.md +87 -0
  31. package/agents/designer.md +112 -0
  32. package/agents/discovery-caller.md +98 -0
  33. package/agents/doctor.md +139 -0
  34. package/agents/educate-coach.md +100 -0
  35. package/agents/elevate-tutor.md +83 -0
  36. package/agents/email-lifecycle-marketer.md +91 -0
  37. package/agents/engage-specialist.md +99 -0
  38. package/agents/events-coordinator.md +90 -0
  39. package/agents/foundation-builder.md +94 -0
  40. package/agents/funnel-architect.md +89 -0
  41. package/agents/gift-creator.md +100 -0
  42. package/agents/google-ads.md +103 -0
  43. package/agents/guide.md +292 -0
  44. package/agents/helpdesk-dispatcher.md +88 -0
  45. package/agents/hook-specialist.md +91 -0
  46. package/agents/identify-optimizer.md +101 -0
  47. package/agents/implementer.md +305 -0
  48. package/agents/incident-commander.md +120 -0
  49. package/agents/insights-lead.md +93 -0
  50. package/agents/journey-runner.md +113 -0
  51. package/agents/linkedin-ads.md +123 -0
  52. package/agents/live-sales-chat.md +90 -0
  53. package/agents/market-researcher.md +88 -0
  54. package/agents/media-buyer.md +96 -0
  55. package/agents/movers-customer-researcher.md +95 -0
  56. package/agents/movers-foundation-builder.md +96 -0
  57. package/agents/movers-market-researcher.md +97 -0
  58. package/agents/movers-pricing-strategist.md +171 -0
  59. package/agents/nurture-architect.md +99 -0
  60. package/agents/offer-architect.md +92 -0
  61. package/agents/onboarder.md +222 -0
  62. package/agents/onboarding-specialist.md +92 -0
  63. package/agents/operations-dashboard.md +98 -0
  64. package/agents/perf-engineer.md +348 -0
  65. package/agents/playbook-writer.md +71 -0
  66. package/agents/plg-strategist.md +91 -0
  67. package/agents/positioning-architect.md +88 -0
  68. package/agents/press-officer.md +89 -0
  69. package/agents/pricing-strategist.md +94 -0
  70. package/agents/privacy-officer.md +92 -0
  71. package/agents/referral-manager.md +91 -0
  72. package/agents/refine-analyst.md +102 -0
  73. package/agents/release-manager.md +261 -0
  74. package/agents/renewals-upsell-rep.md +90 -0
  75. package/agents/review-engineer.md +327 -0
  76. package/agents/rewards-steward.md +82 -0
  77. package/agents/sales-call-coach.md +94 -0
  78. package/agents/sales-closer.md +98 -0
  79. package/agents/security-auditor.md +313 -0
  80. package/agents/sell-closer.md +101 -0
  81. package/agents/share-amplifier.md +99 -0
  82. package/agents/social-media-manager.md +92 -0
  83. package/agents/storyteller.md +250 -0
  84. package/agents/strategist.md +83 -0
  85. package/agents/strategy-aligner.md +94 -0
  86. package/agents/support-agent.md +90 -0
  87. package/agents/tagger.md +245 -0
  88. package/agents/tech-writer.md +216 -0
  89. package/agents/test-engineer.md +243 -0
  90. package/agents/tiktok-ads.md +105 -0
  91. package/agents/tracking-engineer.md +92 -0
  92. package/agents/upsell-strategist.md +101 -0
  93. package/agents/voice.md +85 -0
  94. package/agents/w4-tools.md +153 -0
  95. package/agents/w4-verify.md +20 -138
  96. package/agents/workflow-optimiser.md +84 -0
  97. package/commands/close.md +814 -160
  98. package/commands/create.md +2 -2
  99. package/commands/deploy.md +554 -175
  100. package/commands/do.md +119 -109
  101. package/commands/fast.md +67 -0
  102. package/commands/improve.md +2 -2
  103. package/commands/one.md +418 -0
  104. package/commands/see.md +1 -1
  105. package/commands/sync.md +1 -1
  106. package/commands/tasks.md +222 -0
  107. package/commands/vespio.md +110 -0
  108. package/commands/vespio.remote.md +227 -0
  109. package/hooks/hooks.json +25 -79
  110. package/hooks/lib/governor-escape-match.sh +88 -0
  111. package/hooks/lib/hook.sh +4 -13
  112. package/hooks/lib/signal.sh +9 -2
  113. package/hooks/scripts/branch-pin.sh +6 -0
  114. package/hooks/scripts/config-protect.sh +6 -0
  115. package/hooks/scripts/do-outcome-gate.sh +19 -2
  116. package/hooks/scripts/git-add-guard.sh +43 -2
  117. package/hooks/scripts/governor-escape.sh +96 -0
  118. package/hooks/scripts/load-guard.sh +127 -0
  119. package/hooks/scripts/post-edit-check.sh +36 -29
  120. package/hooks/scripts/session-start.sh +34 -80
  121. package/hooks/scripts/task-complete-verify.sh +46 -40
  122. package/package.json +1 -1
  123. package/rules/documentation.md +9 -0
  124. package/scripts/ad-copy-lint.sh +656 -0
  125. package/scripts/agentverse-audit.sh +256 -0
  126. package/scripts/asi-walk.sh +435 -0
  127. package/scripts/astro-build-cached.sh +143 -0
  128. package/scripts/blocks-manifest-cached.sh +100 -0
  129. package/scripts/blocks-manifest.mjs +497 -0
  130. package/scripts/blocks-ratchet.sh +116 -0
  131. package/scripts/blocks-render-probe.mjs +529 -0
  132. package/scripts/blocks-usage.mjs +334 -0
  133. package/scripts/chat-context-check.sh +89 -0
  134. package/scripts/close-metrics.sh +558 -0
  135. package/scripts/close-owner.sh +268 -0
  136. package/scripts/db-sync-lock-check.sh +116 -0
  137. package/scripts/deploy-dev.sh +35 -0
  138. package/scripts/deploy-emit.sh +298 -0
  139. package/scripts/deploy-gate-check.sh +128 -0
  140. package/scripts/deploy-ready.sh +78 -0
  141. package/scripts/deploy-record.sh +605 -0
  142. package/scripts/deploy.sh +1273 -0
  143. package/scripts/do-auto.sh +598 -48
  144. package/scripts/do-brief.sh +113 -0
  145. package/scripts/do-close.sh +1137 -0
  146. package/scripts/do-commit.sh +75 -0
  147. package/scripts/do-consumer-sweep.sh +18 -1
  148. package/scripts/do-cycle-shape-check.sh +160 -0
  149. package/scripts/do-decide.sh +476 -0
  150. package/scripts/do-derive-check.sh +436 -0
  151. package/scripts/do-fleet.sh +106 -28
  152. package/scripts/do-folder.sh +10 -1
  153. package/scripts/do-next.sh +106 -0
  154. package/scripts/do-orchestrate.sh +17 -5
  155. package/scripts/do-plan-json.mjs +201 -0
  156. package/scripts/do-plan-json.sh +8 -0
  157. package/scripts/do-preflight.sh +117 -0
  158. package/scripts/do-project.sh +157 -0
  159. package/scripts/do-prove-selftest.sh +108 -0
  160. package/scripts/do-prove.sh +295 -23
  161. package/scripts/do-rank.py +31 -1
  162. package/scripts/do-recon-cache.sh +7 -1
  163. package/scripts/do-recon-pack.sh +196 -0
  164. package/scripts/do-reconcile.sh +121 -4
  165. package/scripts/do-signal.sh +280 -23
  166. package/scripts/do-smoke.sh +18 -1
  167. package/scripts/do-test-gate.sh +80 -0
  168. package/scripts/do-tick.sh +102 -0
  169. package/scripts/do-tier.sh +6 -0
  170. package/scripts/do-triage.sh +182 -0
  171. package/scripts/do-ui-gate.sh +1 -1
  172. package/scripts/do-w4-gates.sh +451 -0
  173. package/scripts/do-walk.sh +12 -1
  174. package/scripts/env-sync.sh +173 -0
  175. package/scripts/factory-brief-check.sh +330 -0
  176. package/scripts/factory-check.sh +68 -14
  177. package/scripts/factory-close-check.sh +257 -0
  178. package/scripts/factory-emit.sh +211 -0
  179. package/scripts/factory-executor-check.mjs +353 -0
  180. package/scripts/factory-peak.sh +301 -0
  181. package/scripts/factory-repo.sh +118 -3
  182. package/scripts/factory-review-check.mjs +61 -0
  183. package/scripts/factory-ship.sh +61 -0
  184. package/scripts/factory-tasks-check.sh +18 -1
  185. package/scripts/factory-turn.sh +326 -0
  186. package/scripts/factory-walk.sh +396 -0
  187. package/scripts/factory-width.sh +57 -0
  188. package/scripts/fade-toxic.sh +4 -3
  189. package/scripts/fixtures/factory-brief-real.md +44 -0
  190. package/scripts/fixtures/triage-dupe.md +5 -0
  191. package/scripts/fleet-manifest.mjs +108 -0
  192. package/scripts/fleet-status.sh +110 -0
  193. package/scripts/full-suite-paths-check.sh +144 -0
  194. package/scripts/gate-reaper-check.sh +98 -0
  195. package/scripts/gate-reaper.sh +125 -0
  196. package/scripts/gate-run.sh +73 -0
  197. package/scripts/gc-content-check.sh +140 -0
  198. package/scripts/gen-dev-config.py +20 -0
  199. package/scripts/govern-bound-check.sh +60 -0
  200. package/scripts/govern-claims-check.sh +233 -0
  201. package/scripts/govern-mem-check.sh +290 -0
  202. package/scripts/governor-doors-check.sh +362 -0
  203. package/scripts/governor-escape-check.sh +171 -0
  204. package/scripts/health.sh +413 -0
  205. package/scripts/id-inventory.mjs +418 -0
  206. package/scripts/land.sh +551 -0
  207. package/scripts/lib/gc-finished.sh +77 -0
  208. package/scripts/lib/govern.sh +361 -0
  209. package/scripts/lib/govern.ts +756 -0
  210. package/scripts/lighthouse-run.sh +187 -0
  211. package/scripts/livekit-live-check.sh +61 -0
  212. package/scripts/livekit-ratchet.sh +46 -0
  213. package/scripts/load-guard-check.sh +49 -0
  214. package/scripts/machine-check.sh +102 -0
  215. package/scripts/machine-watch.sh +177 -0
  216. package/scripts/one-agents.mjs +415 -0
  217. package/scripts/one-resume.sh +78 -0
  218. package/scripts/orphan-baseline.json +182 -0
  219. package/scripts/orphan-modules.mjs +179 -0
  220. package/scripts/pr-body.sh +335 -0
  221. package/scripts/preview-fd-check.sh +289 -0
  222. package/scripts/promise-manifest.mjs +24 -1
  223. package/scripts/release.sh +322 -0
  224. package/scripts/roles-check.sh +946 -0
  225. package/scripts/sdk-build-cached.sh +64 -0
  226. package/scripts/signal-watch.sh +241 -0
  227. package/scripts/skills-publish.sh +94 -0
  228. package/scripts/speed-cache-check.sh +173 -0
  229. package/scripts/speed-check.mjs +907 -0
  230. package/scripts/speed-parity-check.sh +648 -0
  231. package/scripts/speed-waterfall-check.sh +355 -0
  232. package/scripts/substrate-env-parity.mjs +156 -0
  233. package/scripts/tasks-claim-race.mjs +108 -0
  234. package/scripts/tasks-loop.sh +185 -0
  235. package/scripts/test-cached.sh +255 -0
  236. package/scripts/test-full.sh +87 -0
  237. package/scripts/test-honesty.mjs +137 -0
  238. package/scripts/test-lanes.sh +166 -0
  239. package/scripts/test-speed.sh +94 -0
  240. package/scripts/triage-shape-check.sh +149 -0
  241. package/scripts/tsc-cached.sh +179 -0
  242. package/scripts/typedb-flake-check.sh +197 -0
  243. package/scripts/urls-lint.sh +15 -0
  244. package/scripts/verify-fast.sh +445 -0
  245. package/scripts/vespio-sync.sh +149 -0
  246. package/scripts/wf-check.mjs +104 -1
  247. package/scripts/worktree-preview.sh +879 -0
  248. package/scripts/worktree-up.sh +208 -0
  249. package/skills/livekit-agents/SKILL.md +285 -0
  250. package/skills/livekit-agents/references/freshness-rules.md +168 -0
  251. package/skills/shadcn/SKILL.md +1 -1
  252. package/skills/signal/SKILL.md +0 -1
  253. package/skills/voice/SKILL.md +94 -6
  254. package/skills/voice/corpus-check.sh +87 -0
  255. package/hooks/scripts/compact-hint.sh +0 -35
  256. package/hooks/scripts/gate-guard.sh +0 -83
  257. package/hooks/scripts/read-tracker.sh +0 -26
  258. package/hooks/scripts/session-end-verify.sh +0 -51
  259. package/hooks/scripts/stop-reflect.sh +0 -140
  260. package/hooks/scripts/sync-priority-todo.sh +0 -57
  261. package/hooks/scripts/sync-todo-docs.sh +0 -46
  262. package/hooks/scripts/tool-signal.sh +0 -48
  263. package/scripts/do-tasks-bridge.py +0 -366
@@ -0,0 +1,140 @@
1
+ #!/bin/bash
2
+ # gc-content-check.sh — the red proof for lib/gc-finished.sh.
3
+ #
4
+ # manifest: portable
5
+ #
6
+ # Builds a sandbox repo carrying the branch shapes the sweep meets, drives the
7
+ # REAL predicate (sourced, never re-implemented), and then proves the OLD
8
+ # commit-count predicate gets the important one wrong. A checker that only shows
9
+ # the new code passing would not tell you the change was worth making.
10
+ #
11
+ # NOT reproduced here: `git cherry`'s blind spot on a merge commit. That was
12
+ # measured on this repo (merge/trunk-reconcile, 2026-09-07: cherry reported
13
+ # 0-new for a branch holding 24 files and 3416 lines dev had never seen) and the
14
+ # reasoning lives in lib/gc-finished.sh. Faking a multi-merge-base history to
15
+ # re-stage it would be asserting a claim this sandbox does not actually show —
16
+ # the fourth case below covers the same risk directly: a merge carrying unique
17
+ # content must read NOT finished.
18
+ #
19
+ # bash .claude/scripts/gc-content-check.sh # exits non-zero on failure
20
+ set -uo pipefail
21
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
+ . "$HERE/lib/gc-finished.sh"
23
+
24
+ SANDBOX="$(mktemp -d)"; trap 'rm -rf "$SANDBOX"' EXIT
25
+ fails=0
26
+ EXPECT_RED=0 # set while driving the neutered predicate, so an INTENDED failure
27
+ # does not print the word FAIL and read as a broken checker.
28
+ ok() { printf ' ok %s\n' "$1"; }
29
+ bad() {
30
+ if [ "$EXPECT_RED" = 1 ]; then printf ' red %s — as intended\n' "$1"
31
+ else printf ' FAIL %s\n' "$1"; fi
32
+ fails=$((fails+1))
33
+ }
34
+ want() { # <expected 0|1> <branch> <what>
35
+ gc_finished trunk "$2"; local got=$?
36
+ [ "$got" -eq "$1" ] && ok "$3" || bad "$3 (wanted finished=$1, got $got)"
37
+ }
38
+
39
+ cd "$SANDBOX"
40
+ git init -q -b trunk .
41
+ git config user.email t@e.st; git config user.name t
42
+ git config commit.gpgsign false
43
+ echo base > a.txt; git add a.txt; git commit -qm base
44
+ echo one > c.txt; git add c.txt; git commit -qm second
45
+ B1="$(git rev-parse HEAD)"
46
+
47
+ # 1 — REBASED DUPLICATE: the branch's patch reaches trunk under a DIFFERENT sha.
48
+ # This is the case the commit count gets wrong, and the reason for this file.
49
+ git checkout -q -b dup "$B1"
50
+ echo fixed > a.txt; git commit -qam "fix a"
51
+ git checkout -q trunk
52
+ git cherry-pick dup >/dev/null 2>&1 || { bad "sandbox: cherry-pick failed"; exit 1; }
53
+ # Re-message it. A cherry-pick onto the same parent, in the same second, with the
54
+ # same author and message, produces a byte-identical commit OBJECT — trunk then
55
+ # fast-forwards onto the branch and there is no divergence left to detect. That
56
+ # is a sandbox artifact, not the real world, where a re-landed patch always
57
+ # arrives with a different sha. The amend forces the sha apart while leaving the
58
+ # patch identical, which is precisely the case under test.
59
+ git commit -q --amend -m "fix a (relanded under a different sha)"
60
+
61
+ # 2 — ORDINARY UNLANDED BRANCH.
62
+ git checkout -q -b ahead trunk
63
+ echo new > b.txt; git add b.txt; git commit -qm "adds b"
64
+
65
+ # 3 — FULLY CONTAINED: tip is an ancestor of trunk.
66
+ git checkout -q -b behind "$B1"
67
+
68
+ # 4 — MERGE COMMIT CARRYING UNIQUE CONTENT. The shape that makes a
69
+ # patch-counting test (git cherry) unsafe on its own.
70
+ git checkout -q -b side "$B1"
71
+ echo unique > only-here.txt; git add only-here.txt; git commit -qm "unique file"
72
+ git checkout -q -b mergey trunk
73
+ git merge --no-edit side >/dev/null 2>&1 || { bad "sandbox: merge failed"; exit 1; }
74
+
75
+ echo "== the predicate the sweep runs"
76
+ want 0 dup "a rebased duplicate reads FINISHED — its content is already on the platform"
77
+ want 1 ahead "an ordinary unlanded branch reads NOT finished"
78
+ want 0 behind "a branch fully contained in the base reads FINISHED"
79
+ want 1 mergey "a merge carrying a file the base lacks reads NOT finished"
80
+
81
+ echo "== what the OLD commit-count predicate would have said"
82
+ old_finished() { [ "$(git rev-list --count "trunk..$1" 2>/dev/null || echo 1)" -eq 0 ]; }
83
+ if old_finished dup
84
+ then bad "the count predicate should MISS the duplicate — this proof is broken"
85
+ else ok "the count predicate hoards the duplicate for ever — the ~120MB this fixes"; fi
86
+ if old_finished ahead
87
+ then bad "the count predicate wrongly sweeps an unlanded branch"
88
+ else ok "the count predicate keeps an unlanded branch (both agree here)"; fi
89
+
90
+ echo "== the clean-worktree path survives set -e"
91
+ # The sweep runs under `set -euo pipefail`, and `grep -v` exits 1 when it filters
92
+ # EVERYTHING out — the clean-worktree case. Inline, that killed the sweep at the
93
+ # first worktree it was meant to remove: four keep lines, exit 1, no summary, and
94
+ # invisible behind a `| cat`. Drive the real function in a real subshell under
95
+ # the real flags, because that is the only way this comes back red.
96
+ git checkout -q trunk
97
+ if out="$(bash -c '
98
+ set -euo pipefail
99
+ . "'"$HERE"'/lib/gc-finished.sh"
100
+ d="$(gc_real_dirt "'"$SANDBOX"'")"
101
+ [ -z "$d" ] && echo CLEAN-AND-ALIVE
102
+ ' 2>&1)" && [ "$out" = "CLEAN-AND-ALIVE" ]; then
103
+ ok "a clean worktree reports no dirt AND the shell survives it"
104
+ else
105
+ bad "the clean-tree path died under set -e (got: ${out:-<nothing>})"
106
+ fi
107
+ # And it still SEES real work, or the fix would be a mute button.
108
+ echo scratch > "$SANDBOX/uncommitted.txt"
109
+ if [ -n "$(gc_real_dirt "$SANDBOX")" ]
110
+ then ok "uncommitted work is still reported — the guard did not silence it"
111
+ else bad "gc_real_dirt missed an uncommitted file"; fi
112
+ rm -f "$SANDBOX/uncommitted.txt"
113
+ # Ephemera alone must NOT read as work, or nothing is ever swept.
114
+ # The tracked file is required, not decoration: git COLLAPSES a wholly-untracked
115
+ # directory to its top level, so an unrepresentative sandbox reports `?? one.ie/`
116
+ # and no path pattern can match. A real worktree has one.ie/web/ tracked, so git
117
+ # descends and reports `?? one.ie/web/.astro` — which is what the filter is
118
+ # written against. Committing one file reproduces that.
119
+ mkdir -p "$SANDBOX/one.ie/web"; echo keep > "$SANDBOX/one.ie/web/keep.txt"
120
+ git add one.ie/web/keep.txt; git commit -qm "tracked file under one.ie/web"
121
+ mkdir -p "$SANDBOX/one.ie/web/.astro"; echo x > "$SANDBOX/one.ie/web/.astro/gen.d.ts"
122
+ if [ -z "$(gc_real_dirt "$SANDBOX")" ]
123
+ then ok "build output alone does not count as work"
124
+ else bad "ephemeral dirt was reported as work — nothing would ever be swept"; fi
125
+ rm -rf "$SANDBOX/one.ie/web/.astro"
126
+
127
+ echo "== red proof: neuter the predicate and the checks must fail"
128
+ gc_finished() { return 0; } # claim every branch is finished
129
+ before=$fails; EXPECT_RED=1
130
+ want 1 ahead "(neutered) an unlanded branch must NOT read finished"
131
+ want 1 mergey "(neutered) a unique-content merge must NOT read finished"
132
+ if [ "$fails" -eq $((before+2)) ]; then
133
+ fails=$before; EXPECT_RED=0; ok "both checks bite when the predicate is gutted"
134
+ else
135
+ fails=$((before+1)); EXPECT_RED=0; printf ' FAIL a gutted predicate still passed — this checker proves nothing\n'
136
+ fi
137
+
138
+ echo
139
+ [ "$fails" -eq 0 ] && { echo "gc-content-check: PASS"; exit 0; }
140
+ echo "gc-content-check: FAIL ($fails)"; exit 1
@@ -0,0 +1,20 @@
1
+ import json, pathlib, sys
2
+ # Patch the ASTRO-GENERATED config (which carries `main` + the assets binding)
3
+ # rather than hand-rolling one: wrangler.toml omits `main` by design, so a
4
+ # standalone copy deploys as an assets-only Worker and is rejected.
5
+ p = pathlib.Path("dist/server/wrangler.json")
6
+ if not p.exists():
7
+ print("[gen-dev-config] FATAL: dist/server/wrangler.json missing - build first"); sys.exit(1)
8
+ c = json.loads(p.read_text())
9
+ c["name"] = "one-dev"
10
+ c["routes"] = [{"pattern": "dev.one.ie", "custom_domain": True}]
11
+ # STRIP CRONS. The dev worker shares production's D1/KV bindings, so inheriting
12
+ # prod's schedules means TWO workers running the same handlers against the same
13
+ # rows - double sends, double syncs, races. Dev observes prod data; it must not
14
+ # also drive prod's clock. (Measured 2026-08-25: the first dev deploy shipped
15
+ # 6 schedules including */5 * * * *.)
16
+ for k in ("triggers", "crons"):
17
+ c.pop(k, None)
18
+ out = pathlib.Path("dist/server/wrangler.dev.json")
19
+ out.write_text(json.dumps(c, indent=2))
20
+ print(f"[gen-dev-config] {out} -> name={c['name']} routes={c['routes']} main={c.get('main')}")
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env bash
2
+ # govern-bound-check.sh — prove run_bounded neither hangs its caller nor leaks
3
+ # its watchdog. Three checks, each one a measured outage.
4
+ #
5
+ # manifest: portable
6
+ #
7
+ # 1. A CAPTURED call returns when the command returns. `$(run_bounded 60 true
8
+ # 2>&1)` must come back in ~0s, not 60s. The watchdog used to inherit the
9
+ # caller's stdout (fixed 2026-09-01, `>&2`) and then its stderr (measured
10
+ # 2026-09-03 as 1800s of nothing inside `$(… 2>&1)`, and again inside
11
+ # `… 2>&1 | tail`). A wait that reads as a hang gets killed at 144 = UNRUN.
12
+ # 2. NO ORPHAN SLEEP survives a bounded call. `kill "$watch_pid"` reaped the
13
+ # watchdog subshell but not the `sleep` it forked — 21 `sleep 1800` with
14
+ # ppid 1 were on the box on 2026-09-04, each holding a dead caller's pipe.
15
+ # 3. The bound still BITES: a command that outlives its cap is killed, the
16
+ # whole process group with it, and the parent says so on stderr.
17
+ #
18
+ # Exit 0 = all three hold · 1 = one did not. Touches nothing machine-wide:
19
+ # GOVERN_DIR is a sandbox.
20
+ set -uo pipefail
21
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
22
+ export GOVERN_DIR="${TMPDIR:-/tmp}/one-govern-boundcheck.$$"
23
+ mkdir -p "$GOVERN_DIR"; trap 'rm -rf "$GOVERN_DIR"' EXIT
24
+ # shellcheck source=lib/govern.sh
25
+ . "$ROOT/.claude/scripts/lib/govern.sh"
26
+ fails=0
27
+ ok() { printf ' ok %s\n' "$*"; }
28
+ bad() { printf ' FAIL %s\n' "$*"; fails=$((fails+1)); }
29
+ now() { date +%s; }
30
+ tag="bound-check-$$"
31
+
32
+ echo "== 1. a captured call returns with the command, not with the watchdog"
33
+ t0=$(now)
34
+ out="$(run_bounded 61 bash -c "echo answer-$tag" 2>&1)"; rc=$?
35
+ dt=$(( $(now) - t0 ))
36
+ if [ "$rc" -eq 0 ] && [ "$dt" -le 3 ] && [ "$out" = "answer-$tag" ]; then ok "\$(run_bounded 60 …) returned in ${dt}s with the output intact"
37
+ else bad "captured call took ${dt}s rc=$rc out='$out' (a 60s wait here is the watchdog holding the pipe)"; fi
38
+ t0=$(now)
39
+ out="$(run_bounded 61 bash -c "echo answer2-$tag" 2>&1 | cat)"
40
+ dt=$(( $(now) - t0 ))
41
+ [ "$dt" -le 3 ] && ok "… and through a pipe (${dt}s)" || bad "piped call took ${dt}s"
42
+
43
+ echo "== 2. no orphaned watchdog sleep survives"
44
+ sleep 1
45
+ n=$(ps -Ao command= | grep -c "^sleep 61$")
46
+ [ "$n" -eq 0 ] && ok "no 'sleep 61' left behind" || bad "$n orphaned 'sleep 61' still running (the watchdog's child outlived it)"
47
+
48
+ echo "== 3. the bound still bites, and the group goes with it"
49
+ t0=$(now)
50
+ err="$(run_bounded 1 bash -c "sleep 31 & sleep 31; echo lived-$tag" 2>&1 >/dev/null)"; rc=$?
51
+ dt=$(( $(now) - t0 ))
52
+ if [ "$rc" -ne 0 ] && [ "$dt" -le 12 ]; then ok "a 31s command under a 1s cap died in ${dt}s (rc=$rc)"
53
+ else bad "cap did not bite: rc=$rc after ${dt}s"; fi
54
+ case "$err" in *TIMEOUT*) ok "the parent printed the TIMEOUT line" ;; *) bad "no TIMEOUT line on stderr: '$err'" ;; esac
55
+ sleep 1
56
+ n=$(ps -Ao command= | grep -c "^sleep 31$")
57
+ [ "$n" -eq 0 ] && ok "the process group was reaped (no 'sleep 31' survivors)" || bad "$n 'sleep 31' survived the group kill"
58
+
59
+ [ "$fails" -eq 0 ] && { echo "govern-bound-check: PASS"; exit 0; }
60
+ echo "govern-bound-check: FAILED ($fails)"; exit 1
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env bash
2
+ # govern-claims-check.sh — the two properties the claim registry exists for.
3
+ #
4
+ # C1 MUTUAL EXCLUSION two workers cannot hold the same claim
5
+ # C2 EVAPORATION a dead owner's claim expires with no human in the loop
6
+ #
7
+ # Plus the checks that stop C1/C2 from passing against a gutted implementation:
8
+ # C3 the TTL branch also evaporates (the pid branch is not the only one)
9
+ # C4 a partial claim rolls back (a loser holds no ground)
10
+ # C5 do-fleet's has_conflict seam inherits the reap — the caller, not just
11
+ # the primitive
12
+ # R1/R2 RED-PROOF: with the reaper disabled, C2 and C5 must FAIL. A checker
13
+ # that stays green against a broken implementation is not a check.
14
+ #
15
+ # No coordinator anywhere in here — every worker is an independent process and
16
+ # mkdir(2) is the only arbiter.
17
+ #
18
+ # bash .claude/scripts/govern-claims-check.sh
19
+ set -uo pipefail
20
+
21
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
+ SANDBOX="$(mktemp -d)"
23
+ trap 'rm -rf "$SANDBOX"' EXIT
24
+
25
+ # Point the whole library at a throwaway dir — this test must never touch the
26
+ # real machine registry other sessions are coordinating through.
27
+ export GOVERN_DIR="$SANDBOX/govern"
28
+ export GOVERN_CLAIMS_DIR="$GOVERN_DIR/claims"
29
+ # shellcheck source=lib/govern.sh
30
+ . "$HERE/lib/govern.sh"
31
+
32
+ PASS=0; FAIL=0
33
+ ok() { echo " ok $*"; PASS=$(( PASS + 1 )); }
34
+ bad() { echo " FAIL $*"; FAIL=$(( FAIL + 1 )); }
35
+ head_() { echo ""; echo "$*"; }
36
+
37
+ reset_registry() { rm -rf "$GOVERN_CLAIMS_DIR"; mkdir -p "$GOVERN_CLAIMS_DIR"; }
38
+
39
+ # A worker is a separate bash process that sources the library and tries to
40
+ # claim. It records WON or LOST and then HOLDS — a worker that exits the instant
41
+ # it wins is a DEAD owner, and the next contender would rightly reap it, so the
42
+ # exclusion test would end up measuring evaporation instead of exclusion (it did,
43
+ # first run: 12 winners). Nothing coordinates these processes; mkdir(2) is the
44
+ # only arbiter between them.
45
+ worker() { # worker <region> <slug> <outfile>
46
+ bash -c '
47
+ . "$1/lib/govern.sh"
48
+ if claim_take "$2" "$3"; then echo WON > "$4"; else echo LOST > "$4"; fi
49
+ sleep 20
50
+ ' _ "$HERE" "$1" "$2" "$3" >/dev/null 2>&1
51
+ }
52
+
53
+ # ─── C1 · two workers cannot hold the same claim ──────────────────────────────
54
+ head_ "C1 mutual exclusion — N concurrent workers, one region"
55
+ reset_registry
56
+ N=12
57
+ WPIDS=""
58
+ for i in $(seq 1 $N); do
59
+ worker "one.ie/web/src/lib/resolvers" "fleet-$i" "$SANDBOX/w$i" &
60
+ WPIDS="$WPIDS $!"
61
+ disown %% 2>/dev/null || true # keep the reap quiet; we kill by pid below
62
+ done
63
+ # Wait until every worker has decided — all of them are still holding.
64
+ for _ in $(seq 1 100); do
65
+ [ "$(cat "$SANDBOX"/w* 2>/dev/null | grep -c . || true)" = "$N" ] && break
66
+ sleep 0.1
67
+ done
68
+ WON=$(cat "$SANDBOX"/w* 2>/dev/null | grep -c WON || true)
69
+ LOST=$(cat "$SANDBOX"/w* 2>/dev/null | grep -c LOST || true)
70
+ HOLDERS=$(claim_list | grep -c . || true)
71
+ [ "$WON" = "1" ] && ok "exactly 1 of $N concurrent workers won the region (won=$WON lost=$LOST)" \
72
+ || bad "expected exactly 1 winner, got $WON (lost=$LOST)"
73
+ [ "$HOLDERS" = "1" ] && ok "registry holds exactly 1 claim on the region" \
74
+ || bad "registry holds $HOLDERS claims on one region"
75
+ # shellcheck disable=SC2086
76
+ kill -9 $WPIDS 2>/dev/null || true
77
+ rm -f "$SANDBOX"/w*
78
+
79
+ # Two DIFFERENT regions must never collide into one claim. Sanitising a path
80
+ # into a filename is lossy (a/b and a_b sanitise alike); the key must not be.
81
+ reset_registry
82
+ claim_take "a/b" "p1" >/dev/null 2>&1
83
+ claim_take "a_b" "p2" >/dev/null 2>&1
84
+ KEYS=$(claim_list | grep -c . || true)
85
+ [ "$KEYS" = "2" ] && ok "distinct regions a/b and a_b get distinct claims (key is injective)" \
86
+ || bad "a/b and a_b produced $KEYS claim(s) — the claim key collides"
87
+
88
+ # ─── C2 · a dead owner's claim evaporates ─────────────────────────────────────
89
+ head_ "C2 evaporation — kill the owner, prove the claim clears"
90
+ reset_registry
91
+ REGION="auth-seam"
92
+ # Spawn a real process, let IT take the claim, then kill it. The claim outlives
93
+ # the process on disk — that is the whole hazard.
94
+ bash -c '. "$1/lib/govern.sh"; claim_take "$2" "dead-fleet" >/dev/null; sleep 300' \
95
+ _ "$HERE" "$REGION" &
96
+ DEAD_PID=$!
97
+ for _ in 1 2 3 4 5 6 7 8 9 10; do
98
+ [ -n "$(claim_owner "$REGION")" ] && break
99
+ sleep 0.2
100
+ done
101
+ OWNER_BEFORE="$(claim_owner "$REGION")"
102
+ [ -n "$OWNER_BEFORE" ] && ok "claim is held while the owner lives ($OWNER_BEFORE)" \
103
+ || bad "owner never took the claim — test is not exercising anything"
104
+
105
+ kill -9 "$DEAD_PID" 2>/dev/null || true
106
+ wait "$DEAD_PID" 2>/dev/null || true
107
+
108
+ # No sweeper ran. No human intervened. The next contender's own read reaps it.
109
+ OWNER_AFTER="$(claim_owner "$REGION")"
110
+ [ -z "$OWNER_AFTER" ] && ok "after the owner dies, claim_owner reports nobody" \
111
+ || bad "dead owner still reads as holding the claim ($OWNER_AFTER)"
112
+
113
+ if claim_take "$REGION" "next-fleet"; then
114
+ NEW_OWNER="$(claim_owner "$REGION" | awk '{print $1}')"
115
+ [ "$NEW_OWNER" = "next-fleet" ] \
116
+ && ok "the ground is reclaimable — new owner is next-fleet" \
117
+ || bad "claim taken but metadata still names '$NEW_OWNER'"
118
+ else
119
+ bad "a dead owner's region could not be reclaimed — evaporation failed"
120
+ fi
121
+ claim_release "$REGION"
122
+
123
+ # ─── C3 · the TTL branch evaporates too ───────────────────────────────────────
124
+ head_ "C3 evaporation — an expired lease clears even while the owner lives"
125
+ reset_registry
126
+ GOVERN_CLAIM_TTL_SECS=5400 claim_take "stale-region" "silent-fleet" >/dev/null
127
+ KEY="$GOVERN_CLAIMS_DIR/$(_gv_claim_key "stale-region")"
128
+ # Backdate the deposit past its lease. Owner (this shell) is very much alive,
129
+ # so ONLY the timestamp branch can clear this.
130
+ sed -i.bak "s/^started=.*/started=$(( $(date +%s) - 6000 ))/" "$KEY/meta" && rm -f "$KEY/meta.bak"
131
+ [ -z "$(claim_owner "stale-region")" ] \
132
+ && ok "a lease older than ttl reads as free although the owner is alive" \
133
+ || bad "expired lease still reads as held — the TTL branch never fires"
134
+
135
+ # …and an in-lease claim from a live owner is NOT reaped (the check can say no).
136
+ reset_registry
137
+ claim_take "fresh-region" "live-fleet" >/dev/null
138
+ [ -n "$(claim_owner "fresh-region")" ] \
139
+ && ok "a fresh claim from a live owner is still held (reaper is not indiscriminate)" \
140
+ || bad "reaper cleared a live, in-lease claim"
141
+ claim_release "fresh-region"
142
+
143
+ # ─── C4 · partial claim rolls back ────────────────────────────────────────────
144
+ head_ "C4 rollback — a worker that loses one region holds none"
145
+ reset_registry
146
+ # Another live worker owns region B.
147
+ bash -c '. "$1/lib/govern.sh"; claim_take "regionB" "other" >/dev/null; sleep 60' _ "$HERE" &
148
+ OTHER=$!
149
+ for _ in 1 2 3 4 5 6 7 8 9 10; do [ -n "$(claim_owner regionB)" ] && break; sleep 0.2; done
150
+ # Our worker wants A and B; it must end up holding neither.
151
+ bash -c '
152
+ . "$1/lib/govern.sh"
153
+ taken=()
154
+ for r in regionA regionB; do
155
+ if claim_take "$r" "mine"; then taken+=("$r"); else
156
+ for t in "${taken[@]}"; do claim_release "$t"; done
157
+ exit 1
158
+ fi
159
+ done
160
+ exit 0' _ "$HERE" 2>/dev/null
161
+ [ $? -ne 0 ] && ok "the multi-region worker correctly failed" || bad "worker claimed a region another holds"
162
+ [ -z "$(claim_owner regionA)" ] \
163
+ && ok "regionA was released on rollback — no orphan ground" \
164
+ || bad "regionA left claimed by a worker that never launched"
165
+ kill -9 "$OTHER" 2>/dev/null || true; wait "$OTHER" 2>/dev/null || true
166
+
167
+ # ─── C5 · the do-fleet seam inherits the reap ─────────────────────────────────
168
+ head_ "C5 seam — do-fleet's REAL has_conflict/free_dirs read through the reaper"
169
+ reset_registry
170
+ # Lift the ACTUAL function bodies out of do-fleet.sh — not a hand-written copy.
171
+ # A copy passes while the shipped function dies on an unquoted var or a stray
172
+ # awk field, which is precisely the drift this check exists to catch.
173
+ FLEET="$HERE/do-fleet.sh"
174
+ eval "$(awk '/^has_conflict\(\) \{/,/^\}/' "$FLEET")"
175
+ eval "$(awk '/^free_dirs\(\) \{/,/^\}/' "$FLEET")"
176
+ # do-fleet gets its dir list from do-rank.py; stub that one seam so the test
177
+ # needs no plan files. Everything below is do-fleet's own code.
178
+ deliverable_dirs() { case "$1" in newplan|ghostplan) echo "one.ie/web/src/pages";; *) : ;; esac; }
179
+ declare -f has_conflict >/dev/null && ok "lifted the real has_conflict() out of do-fleet.sh" \
180
+ || bad "could not lift has_conflict() — check the awk range"
181
+
182
+ bash -c '. "$1/lib/govern.sh"; claim_take "one.ie/web/src/pages" "ghostplan" >/dev/null; sleep 300' \
183
+ _ "$HERE" &
184
+ GHOST=$!
185
+ for _ in 1 2 3 4 5 6 7 8 9 10; do [ -n "$(claim_owner "one.ie/web/src/pages")" ] && break; sleep 0.2; done
186
+ if has_conflict "newplan" >/dev/null 2>&1; then
187
+ ok "a live ghost blocks the region (real has_conflict says conflict)"
188
+ else
189
+ bad "real has_conflict failed to see another fleet's live claim"
190
+ fi
191
+ kill -9 "$GHOST" 2>/dev/null || true; wait "$GHOST" 2>/dev/null || true
192
+ if has_conflict "newplan" >/dev/null 2>&1; then
193
+ bad "real has_conflict still blocks on a DEAD owner — the fleet would stay wedged"
194
+ else
195
+ ok "after the owner dies the real has_conflict clears — the fleet reroutes in"
196
+ fi
197
+
198
+ # free_dirs must not hand back a sentinel this slug never took.
199
+ reset_registry
200
+ claim_take "__ANY__" "unscoped-plan" >/dev/null
201
+ free_dirs "newplan" # a DIFFERENT, scoped plan finishing
202
+ [ "$(claim_owner "__ANY__" | awk '{print $1}')" = "unscoped-plan" ] \
203
+ && ok "free_dirs leaves another slug's __ANY__ sentinel alone" \
204
+ || bad "a scoped plan's free_dirs released the unscoped plan's sole-slot claim"
205
+ free_dirs "unscoped-plan"
206
+ [ -z "$(claim_owner "__ANY__")" ] \
207
+ && ok "the sentinel's own slug can still release it" \
208
+ || bad "__ANY__ could not be released by its owner"
209
+
210
+ # ─── R1/R2 · prove the checker can go RED ─────────────────────────────────────
211
+ head_ "R1/R2 red-proof — with the reaper gutted, C2 and C5 must FAIL"
212
+ reset_registry
213
+ (
214
+ # A gutted implementation: the owner is always "alive", so nothing evaporates.
215
+ _gv_alive() { return 0; }
216
+ bash -c '. "$1/lib/govern.sh"; claim_take "red-region" "zombie" >/dev/null; sleep 300' \
217
+ _ "$HERE" &
218
+ Z=$!
219
+ for _ in 1 2 3 4 5 6 7 8 9 10; do [ -d "$GOVERN_CLAIMS_DIR/$(_gv_claim_key red-region)" ] && break; sleep 0.2; done
220
+ kill -9 "$Z" 2>/dev/null || true; wait "$Z" 2>/dev/null || true
221
+ if [ -n "$(claim_owner "red-region")" ]; then
222
+ echo " ok with _gv_alive stubbed true, the dead owner's claim does NOT clear"
223
+ echo " -> C2/C5 are testing the reaper, not an empty directory"
224
+ exit 0
225
+ fi
226
+ echo " FAIL C2/C5 pass even with the reaper disabled — they prove nothing"
227
+ exit 1
228
+ )
229
+ if [ $? -eq 0 ]; then PASS=$(( PASS + 1 )); else FAIL=$(( FAIL + 1 )); fi
230
+
231
+ echo ""
232
+ echo "govern-claims-check: $PASS passed, $FAIL failed"
233
+ [ "$FAIL" -eq 0 ] || exit 1