@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,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# do-commit.sh <worktree> <slug> <cid> <path>... — stage EXACTLY these paths and
|
|
3
|
+
# commit them as one cycle, holding a per-worktree lock so two parallel cycles
|
|
4
|
+
# cannot interleave their staging.
|
|
5
|
+
#
|
|
6
|
+
# manifest: needs-env
|
|
7
|
+
#
|
|
8
|
+
# WHY (measured 2026-08-31, lifecycle-money). A batch's cycles run in PARALLEL in
|
|
9
|
+
# ONE worktree. W4 was told to `git -C $WT add -A && git commit`, so whichever
|
|
10
|
+
# cycle committed first swept every sibling's in-progress edits into its own
|
|
11
|
+
# commit. Commit c5eeeb9ec is labelled "C4" and carries C3's escrow + market work
|
|
12
|
+
# and C5's money/sui-network work; its own verifier called it "commit
|
|
13
|
+
# contamination". The repo already forbids blanket staging on the shared tree
|
|
14
|
+
# (hook:git-add-guard) for precisely this reason — the worktree exemption assumed
|
|
15
|
+
# one worker per worktree, which stopped being true when batches went parallel.
|
|
16
|
+
#
|
|
17
|
+
# Two independent problems, two mechanisms:
|
|
18
|
+
# 1. WHAT gets staged — explicit paths only. Never add -A / add . / commit -a.
|
|
19
|
+
# 2. WHEN — `git add` and `git commit` are two calls against one index. Between
|
|
20
|
+
# them a sibling's `git add` can land, and its files join this commit even
|
|
21
|
+
# though this one named only its own. The lock closes that window.
|
|
22
|
+
#
|
|
23
|
+
# It is deliberately NOT an error for a named path to be missing or unchanged: a
|
|
24
|
+
# cycle whose W3 dissolved one spec still commits the rest.
|
|
25
|
+
set -uo pipefail
|
|
26
|
+
|
|
27
|
+
WT="${1:-}"; SLUG="${2:-}"; CID="${3:-}"
|
|
28
|
+
shift 3 2>/dev/null || { echo "usage: do-commit.sh <worktree> <slug> <cid> <path>..." >&2; exit 2; }
|
|
29
|
+
[ -n "$WT" ] && [ -n "$SLUG" ] && [ -n "$CID" ] && [ "$#" -gt 0 ] || {
|
|
30
|
+
echo "usage: do-commit.sh <worktree> <slug> <cid> <path>..." >&2; exit 2; }
|
|
31
|
+
[ -d "$WT/.git" ] || [ -f "$WT/.git" ] || { echo "do-commit: not a worktree: $WT" >&2; exit 3; }
|
|
32
|
+
|
|
33
|
+
for p in "$@"; do
|
|
34
|
+
case "$p" in
|
|
35
|
+
-A|.|--all|-a) echo "do-commit: REFUSING blanket stage '$p' — name the cycle's own paths" >&2; exit 4 ;;
|
|
36
|
+
esac
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# shellcheck source=lib/govern.sh
|
|
40
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib/govern.sh"
|
|
41
|
+
LOCK="commit-$(printf '%s' "$WT" | tr '/' '_')"
|
|
42
|
+
|
|
43
|
+
if ! gate_lock "$LOCK" "${DO_COMMIT_WAIT:-300}"; then
|
|
44
|
+
echo "do-commit: could not take the commit lock for $WT within ${DO_COMMIT_WAIT:-300}s" >&2
|
|
45
|
+
exit 5
|
|
46
|
+
fi
|
|
47
|
+
trap 'gate_release_all' EXIT INT TERM
|
|
48
|
+
|
|
49
|
+
# Only stage paths that exist or are tracked-and-deleted; a dissolved spec is normal.
|
|
50
|
+
staged=0
|
|
51
|
+
for p in "$@"; do
|
|
52
|
+
if [ -e "$WT/$p" ] || git -C "$WT" ls-files --error-unmatch -- "$p" >/dev/null 2>&1; then
|
|
53
|
+
git -C "$WT" add -- "$p" 2>/dev/null && staged=$((staged + 1))
|
|
54
|
+
else
|
|
55
|
+
echo "do-commit: skip (absent, never tracked): $p" >&2
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
if [ "$staged" -eq 0 ] || git -C "$WT" diff --cached --quiet 2>/dev/null; then
|
|
60
|
+
echo "do-commit: ${SLUG} ${CID} — nothing staged to commit"
|
|
61
|
+
gate_release_all; trap - EXIT INT TERM
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Report exactly what this commit carries, so contamination is visible in the log
|
|
66
|
+
# rather than discovered by a later verifier.
|
|
67
|
+
echo "do-commit: ${SLUG} ${CID} staging $(git -C "$WT" diff --cached --name-only | wc -l | tr -d ' ') file(s):"
|
|
68
|
+
git -C "$WT" diff --cached --name-only | sed 's/^/ /'
|
|
69
|
+
|
|
70
|
+
git -C "$WT" commit -m "do(${SLUG}): ${CID}" >/dev/null 2>&1 \
|
|
71
|
+
&& echo "do-commit: ${SLUG} ${CID} -> $(git -C "$WT" rev-parse --short HEAD)" \
|
|
72
|
+
|| { echo "do-commit: commit FAILED for ${SLUG} ${CID}" >&2; gate_release_all; trap - EXIT INT TERM; exit 6; }
|
|
73
|
+
|
|
74
|
+
gate_release_all; trap - EXIT INT TERM
|
|
75
|
+
exit 0
|
|
@@ -9,6 +9,23 @@
|
|
|
9
9
|
# default: prints one command per matched rule (no execution)
|
|
10
10
|
# --exec: also runs each printed command; any non-zero exit fails the sweep
|
|
11
11
|
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
# _GATE — route a heavy compute through the machine governor. A gate_lock only
|
|
14
|
+
# dedupes IDENTICAL work; a SLOT is what bounds N worktrees each running one of
|
|
15
|
+
# these at once (measured 2026-09-07: three concurrent 2.5GB typecheckers, every
|
|
16
|
+
# lock uncontended, load 171). Empty when already inside a gate, so a nested call
|
|
17
|
+
# inherits the outer slot rather than taking a second one.
|
|
18
|
+
#
|
|
19
|
+
# Resolves gate-run.sh from its OWN directory, deliberately: an earlier version
|
|
20
|
+
# keyed off $ROOT and got inserted above the line that sets it, so _GATE was
|
|
21
|
+
# silently empty and every call ran ungoverned -- a fail-OPEN, which is the exact
|
|
22
|
+
# defect this preamble exists to close.
|
|
23
|
+
_GATE=()
|
|
24
|
+
if [ "${GOVERN_IN_GATE:-0}" != "1" ]; then
|
|
25
|
+
_GR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/gate-run.sh"
|
|
26
|
+
[ -f "$_GR" ] && _GATE=( bash "$_GR" "compute:$(basename "${BASH_SOURCE[0]}")" -- )
|
|
27
|
+
fi
|
|
28
|
+
|
|
12
29
|
cd "$(dirname "${BASH_SOURCE[0]}")/../.." || exit 2
|
|
13
30
|
|
|
14
31
|
EXEC=false
|
|
@@ -63,7 +80,7 @@ for f in "${FILES[@]}"; do
|
|
|
63
80
|
[ -z "$cmd" ] && continue
|
|
64
81
|
echo "[consumer-sweep] $f → $cmd"
|
|
65
82
|
if $EXEC; then
|
|
66
|
-
|
|
83
|
+
"${_GATE[@]}" bash -c "$cmd" || { echo "[consumer-sweep] FAIL: consumer command failed for $f: $cmd" >&2; rc=1; }
|
|
67
84
|
fi
|
|
68
85
|
done <<< "$cmds"
|
|
69
86
|
done
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# do-cycle-shape-check.sh — BEHAVIOURAL parity gate for the /do Status-kanban
|
|
3
|
+
# cycle-line shape, which is implemented four times in three languages:
|
|
4
|
+
# 1. .claude/workflows/do-engine.js openCyclesFromTodo() (JS regex, reader)
|
|
5
|
+
# 2. .claude/scripts/do-auto.sh _remaining() (grep -E, reader)
|
|
6
|
+
# 3. .claude/scripts/do-auto.sh _sync_status() (sed -E, writer)
|
|
7
|
+
# 4. .claude/scripts/do-tick.sh (grep + perl, writer)
|
|
8
|
+
#
|
|
9
|
+
# It does NOT string-compare the four regexes (that goes stale the day someone
|
|
10
|
+
# reformats one). It runs the REAL implementations — reader #2's pattern is
|
|
11
|
+
# scraped out of the live source at runtime, never pasted here — against one
|
|
12
|
+
# fixture matrix and asserts:
|
|
13
|
+
# READER PARITY both readers see the same open cycle ids
|
|
14
|
+
# WRITER CLOSES READER do-tick.sh can close every id a reader calls open
|
|
15
|
+
# RATCHET do-tick.sh never turns [x] back into [ ]
|
|
16
|
+
#
|
|
17
|
+
# --self-test proves each assertion can go RED (mutated copies in a scratch dir;
|
|
18
|
+
# the real repo files are never touched).
|
|
19
|
+
#
|
|
20
|
+
# manifest: portable
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
24
|
+
ENGINE_JS="${DO_SHAPE_ENGINE:-$REPO/.claude/workflows/do-engine.js}"
|
|
25
|
+
AUTO_SH="${DO_SHAPE_AUTO:-$REPO/.claude/scripts/do-auto.sh}"
|
|
26
|
+
TICK_SH="${DO_SHAPE_TICK:-$REPO/.claude/scripts/do-tick.sh}"
|
|
27
|
+
SLUG=shapefixture
|
|
28
|
+
FAILED=0
|
|
29
|
+
|
|
30
|
+
ok() { printf 'ok %s\n' "$*"; }
|
|
31
|
+
fail() { printf 'FAIL %s\n' "$*"; FAILED=1; }
|
|
32
|
+
|
|
33
|
+
# ── fixture ───────────────────────────────────────────────────────────────
|
|
34
|
+
make_fixture() { # $1 = root dir
|
|
35
|
+
mkdir -p "$1/text"
|
|
36
|
+
cat > "$1/text/${SLUG}-todo.md" <<'MD'
|
|
37
|
+
# Status
|
|
38
|
+
|
|
39
|
+
- [ ] C1 — plain
|
|
40
|
+
- [~] C2 — in progress
|
|
41
|
+
- [x] C3 — done
|
|
42
|
+
- [ ] **C4** — bold
|
|
43
|
+
- [ ] C5 — indented two spaces
|
|
44
|
+
- [ ] C10 — two digit
|
|
45
|
+
- [ ] C6 - hyphen not em-dash
|
|
46
|
+
- [ ] D1 — wrong prefix
|
|
47
|
+
Prose mentioning C1 inline should never count.
|
|
48
|
+
MD
|
|
49
|
+
}
|
|
50
|
+
# Expected OPEN set (the contract all four implementations must agree on).
|
|
51
|
+
EXPECTED="C1 C2 C4 C5 C10"
|
|
52
|
+
|
|
53
|
+
# ── reader #1: the real openCyclesFromTodo, sliced out of do-engine.js ─────
|
|
54
|
+
read_engine() { # $1 = todo path, $2 = engine js path
|
|
55
|
+
node -e '
|
|
56
|
+
const fs = require("fs");
|
|
57
|
+
const src = fs.readFileSync(process.argv[1], "utf8");
|
|
58
|
+
const i = src.indexOf("function openCyclesFromTodo");
|
|
59
|
+
if (i < 0) { console.error("openCyclesFromTodo not found"); process.exit(9); }
|
|
60
|
+
const j = src.indexOf("\n}\n", i);
|
|
61
|
+
if (j < 0) { console.error("could not slice function body"); process.exit(9); }
|
|
62
|
+
const fn = (0, eval)("(" + src.slice(i, j + 2) + ")");
|
|
63
|
+
console.log(fn(fs.readFileSync(process.argv[2], "utf8")).join(" "));
|
|
64
|
+
' "$2" "$1"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# ── reader #2: the LIVE grep pattern scraped out of do-auto.sh _remaining() ─
|
|
68
|
+
auto_pattern() { # prints the pattern do-auto.sh actually greps with
|
|
69
|
+
local line
|
|
70
|
+
line=$(grep -nE "grep -cE .*C\[0-9\]" "$AUTO_SH" | head -1)
|
|
71
|
+
[ -n "$line" ] || { echo "do-auto _remaining pattern not found" >&2; return 9; }
|
|
72
|
+
sed -E "s/^[^']*'//; s/'.*$//" <<<"${line#*:}"
|
|
73
|
+
}
|
|
74
|
+
read_auto() { # $1 = todo path
|
|
75
|
+
local pat matched
|
|
76
|
+
pat=$(auto_pattern)
|
|
77
|
+
# SIGPIPE trap: never pipe a producer into a short-circuiting consumer.
|
|
78
|
+
matched=$(grep -oE "$pat" "$1" 2>/dev/null || true)
|
|
79
|
+
local ids; ids=$(grep -oE 'C[0-9]+' <<<"$matched" || true)
|
|
80
|
+
tr '\n' ' ' <<<"$ids" | sed -E 's/ +$//'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
norm() { tr -s ' ' '\n' <<<"$1" | sed '/^$/d' | tr '\n' ' ' | sed -E 's/ +$//'; }
|
|
84
|
+
|
|
85
|
+
# ── the three checks, parameterised so --self-test can mutate the inputs ───
|
|
86
|
+
run_checks() { # $1 = label prefix, $2 = engine js, $3 = tick cmd, $4 = strict(1)|report(0)
|
|
87
|
+
local label="$1" engine="$2" tick="$3"
|
|
88
|
+
local root; root=$(mktemp -d); trap 'rm -rf "$root"' RETURN
|
|
89
|
+
make_fixture "$root"
|
|
90
|
+
local todo="$root/text/${SLUG}-todo.md"
|
|
91
|
+
local a b
|
|
92
|
+
a=$(norm "$(read_engine "$todo" "$engine")")
|
|
93
|
+
b=$(norm "$(read_auto "$todo")")
|
|
94
|
+
local rc=0
|
|
95
|
+
if [ "$a" = "$b" ]; then ok "$label reader parity — both readers: [$a]"; else
|
|
96
|
+
fail "$label reader parity — do-engine:[$a] != do-auto:[$b]"; rc=1; fi
|
|
97
|
+
if [ "$b" = "$(norm "$EXPECTED")" ]; then ok "$label reader vs contract — [$b]"; else
|
|
98
|
+
fail "$label reader vs contract — expected [$EXPECTED] got [$b]"; rc=1; fi
|
|
99
|
+
|
|
100
|
+
# WRITER CLOSES READER
|
|
101
|
+
local cid wrc=0
|
|
102
|
+
for cid in $b; do
|
|
103
|
+
DO_TICK_ROOT="$root" bash $tick "$SLUG" "$cid" >/dev/null 2>&1 || { fail "$label do-tick failed on $cid"; wrc=1; }
|
|
104
|
+
local a2 b2
|
|
105
|
+
a2=" $(norm "$(read_engine "$todo" "$engine")") "
|
|
106
|
+
b2=" $(norm "$(read_auto "$todo")") "
|
|
107
|
+
case "$a2$b2" in *" $cid "*) fail "$label writer-closes-reader — $cid still open after tick"; wrc=1;; esac
|
|
108
|
+
done
|
|
109
|
+
[ "$wrc" = 0 ] && ok "$label writer closes reader — all of [$b] closed by do-tick" || rc=1
|
|
110
|
+
|
|
111
|
+
# RATCHET — a closed cycle must not reopen
|
|
112
|
+
local before after
|
|
113
|
+
before=$(cksum < "$todo")
|
|
114
|
+
DO_TICK_ROOT="$root" bash $tick "$SLUG" C3 >/dev/null 2>&1 || true
|
|
115
|
+
after=$(cksum < "$todo")
|
|
116
|
+
if [ "$before" = "$after" ]; then ok "$label ratchet — [x] C3 untouched"; else
|
|
117
|
+
fail "$label ratchet — do-tick mutated an already-closed cycle"; rc=1; fi
|
|
118
|
+
return $rc
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# ── self-test: prove each assertion can go RED ────────────────────────────
|
|
122
|
+
if [ "${1:-}" = "--self-test" ]; then
|
|
123
|
+
SCRATCH="${TMPDIR:-/tmp}/do-cycle-shape-selftest.$$"
|
|
124
|
+
case "${SCRATCH_BASE:-}" in "") ;; *) SCRATCH="$SCRATCH_BASE/do-cycle-shape-selftest.$$";; esac
|
|
125
|
+
mkdir -p "$SCRATCH"; trap 'rm -rf "$SCRATCH"' EXIT
|
|
126
|
+
|
|
127
|
+
# A fixed reader (tolerates **C4**) — the green control.
|
|
128
|
+
cat > "$SCRATCH/engine-fixed.js" <<'JS'
|
|
129
|
+
function openCyclesFromTodo(todoText) {
|
|
130
|
+
const re = /^[ \t]*-\s\[[ ~]\]\s\*{0,2}(C\d+)\*{0,2}\s—/gm
|
|
131
|
+
const out = []
|
|
132
|
+
let m
|
|
133
|
+
while ((m = re.exec(todoText))) out.push(m[1])
|
|
134
|
+
return out
|
|
135
|
+
}
|
|
136
|
+
JS
|
|
137
|
+
# The bug: drop \*{0,2} — blind to the bold form.
|
|
138
|
+
sed 's/\\\*{0,2}//g' "$SCRATCH/engine-fixed.js" > "$SCRATCH/engine-bold-blind.js"
|
|
139
|
+
# A stubbed writer that ticks nothing.
|
|
140
|
+
printf '#!/usr/bin/env bash\nexit 0\n' > "$SCRATCH/tick-stub.sh"; chmod +x "$SCRATCH/tick-stub.sh"
|
|
141
|
+
|
|
142
|
+
echo "-- control: fixed reader + real writer (must be GREEN)"
|
|
143
|
+
FAILED=0; run_checks "[control]" "$SCRATCH/engine-fixed.js" "$TICK_SH" || true
|
|
144
|
+
ctrl=$FAILED
|
|
145
|
+
echo "-- red proof (a): reader without \\*{0,2} (must go RED)"
|
|
146
|
+
FAILED=0; run_checks "[red-a]" "$SCRATCH/engine-bold-blind.js" "$TICK_SH" >/dev/null 2>&1 || true
|
|
147
|
+
reda=$FAILED
|
|
148
|
+
echo "-- red proof (b): do-tick stubbed to write nothing (must go RED)"
|
|
149
|
+
FAILED=0; run_checks "[red-b]" "$SCRATCH/engine-fixed.js" "$SCRATCH/tick-stub.sh" >/dev/null 2>&1 || true
|
|
150
|
+
redb=$FAILED
|
|
151
|
+
|
|
152
|
+
FAILED=0
|
|
153
|
+
[ "$ctrl" = 0 ] && ok "self-test control green" || fail "self-test control should be green"
|
|
154
|
+
[ "$reda" = 1 ] && ok "self-test red-proof (a) bold-blind reader goes RED" || fail "self-test (a) stayed green against a reintroduced bug"
|
|
155
|
+
[ "$redb" = 1 ] && ok "self-test red-proof (b) no-op writer goes RED" || fail "self-test (b) stayed green against a writer that writes nothing"
|
|
156
|
+
exit $FAILED
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
run_checks "" "$ENGINE_JS" "$TICK_SH" || true
|
|
160
|
+
exit $FAILED
|