@oneie/claude 0.2.1 → 0.3.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/commands/do.md CHANGED
@@ -122,7 +122,7 @@ For each **enabled** stop (per the pruned spine), in order: check if its artifac
122
122
  | ↳ *ANALYZE* | — | `do-analyze.sh plans/<slug>-todo.md` — CRITICAL exit 1 blocks BUILD | bash · none |
123
123
  | **code** | survey verdict = `build` (≥70% match → `expose`/`extend` instead) | the BUILD engine (Step 3) | sonnet · low–medium |
124
124
  | **tests** | test file in the repo folder | test-first, one assertion per deliverable | sonnet · low |
125
- | **proof** | proof artifact captured | `do-prove.sh` (browser / curl / contract / sync) + `accessibility`; **promise-check** the shipped thing against `text/<slug>.md`; FEATURE/SCHEMA built in a worktree **merge to trunk only on PROVE pass**, abandon on fail | sonnet · low |
125
+ | **proof** | proof artifact captured | `do-prove.sh` (browser / curl / contract / sync) + `accessibility`; **promise-check** the shipped thing against `text/<slug>.md`. A multi-cycle plan already built on its own `do/<slug>` branch (worktree isolation see Step 2); PROVE is the gate that branch must clear before a human merges it to trunk | sonnet · low |
126
126
  | **docs** | feature doc + runbook exist | `tutorial` + `writer` — written against the *proven* behavior | sonnet · medium |
127
127
  | **release** | changelog / README row | `/release` + adoption signal | sonnet · low |
128
128
 
@@ -163,6 +163,8 @@ bun .claude/scripts/do-auto.sh <slug>
163
163
 
164
164
  `do-auto.sh` loops: each iteration spawns a clean `/do <slug> --next-cycle` that runs exactly one batch (W1→W4), ticks its boxes, writes state, and exits. Because each cycle starts from near-zero context, prior-cycle recon/edit/verify chatter never accumulates. The main session just kicks off the loop and reports the close.
165
165
 
166
+ **Worktree isolation comes free with the loop.** The loop's existence *is* the trigger — `do-auto.sh` only runs for multi-cycle plans, which is exactly the FEATURE/SCHEMA work that must not land half-built on trunk. So before the first cycle it cuts a worktree `.do-worktrees/<slug>` on branch `do/<slug>` (reusing it on resume), syncs the plan's spine artifacts into it, and runs **every cycle inside it** — each cycle's edits and box-ticks commit to that branch. Trunk never moves while the loop runs; a halt (trust `cautious` / stall / max-cycles) leaves a clean, inspectable WIP branch, and re-running `/do <slug>` resumes in the same worktree. On plan-complete the loop **reports** the merge (`git merge --no-ff do/<slug>`) rather than running it — landing to trunk is a human decision (commit only when asked), and PROVE is the gate that branch cleared to earn the merge. PATCH/FIX never reach the loop, so they run inline with no worktree.
167
+
166
168
  A **single** incomplete cycle (or a PATCH/FIX) runs inline — there's nothing to isolate from, and spawning a subprocess would cost more than it saves.
167
169
 
168
170
  **`--next-cycle` is internal.** It means "run one batch, tick boxes, exit — do **not** loop." Only `do-auto.sh` passes it; it is the recursion guard that keeps a fresh `/do` from re-entering the loop. A human never types it.
@@ -266,7 +268,7 @@ PATCH clears {1,2,3,8}. FEATURE clears all eight.
266
268
 
267
269
  ## Available to /do — the toolbox
268
270
 
269
- **Scripts** (`.claude/scripts/`): `do-auto.sh` (*internal* — the context-isolated loop `/do` drives for multi-cycle plans) · `do-tier.sh` (tier + pruned spine + classifier + ceiling) · `do-folder.sh` (folder-aware verify/build) · `do-survey.sh` (reuse verdict) · `do-reconcile.sh` (substrate dim/verb/dead-name gate) · `do-analyze.sh` (deliverable↔cycle coverage gate) · `do-prove.sh` (surface-detect proof) · `do-smoke.sh` (deterministic outcome) · `w1-recon.ts` (prompt-cached recon) · `w4-rubric.ts` (cached parallel rubric).
271
+ **Scripts** (`.claude/scripts/`): `do-auto.sh` (*internal* — the context-isolated, worktree-isolated loop `/do` drives for multi-cycle plans; builds on branch `do/<slug>`, merges to trunk only on a human's say-so) · `do-tier.sh` (tier + pruned spine + classifier + ceiling) · `do-folder.sh` (folder-aware verify/build) · `do-survey.sh` (reuse verdict) · `do-reconcile.sh` (substrate dim/verb/dead-name gate) · `do-analyze.sh` (deliverable↔cycle coverage gate) · `do-prove.sh` (surface-detect proof) · `do-smoke.sh` (deterministic outcome) · `w1-recon.ts` (prompt-cached recon) · `w4-rubric.ts` (cached parallel rubric).
270
272
 
271
273
  **Templates**: `text/template-frame.md` (promise) · `plans/template-spec.md` (design + pre-mortem + decisions) · `plans/template-todo.md` (plan + parallel budget + testing policy) · `plans/agent-template.md` (agent definition).
272
274
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneie/claude",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "ONE Claude Code plugin — /do lifecycle, W1-W4 BUILD engine, ONE substrate via MCP, signals, and rules",
5
5
  "files": [
6
6
  ".claude-plugin",
@@ -40,15 +40,73 @@ fi
40
40
  # claude subprocess uses --dangerously-skip-permissions because it is non-interactive
41
41
  # — it cannot prompt the human for tool approvals. The workspace is the isolation
42
42
  # boundary. Do not expose this script to untrusted input or run it in shared environments.
43
- TODO="plans/${SLUG}-todo.md"
44
- TRUST=".do-trust.json"
43
+ [ -f "plans/${SLUG}-todo.md" ] || { echo "[do-auto] plans/${SLUG}-todo.md not found — run /do $SLUG first" >&2; exit 1; }
45
44
 
46
- [ -f "$TODO" ] || { echo "[do-auto] $TODO not found — run /do $SLUG first" >&2; exit 1; }
45
+ # ── Worktree isolation (one per plan) ────────────────────────────────────────
46
+ # The loop's existence IS the trigger: do-auto only runs for multi-cycle plans
47
+ # (>=2 incomplete cycles) = exactly the FEATURE/SCHEMA work that must not land
48
+ # half-built on trunk. So every loop builds in its own worktree on branch
49
+ # do/<slug>, leaving trunk green until a human merges. No tier plumbing, no flag.
50
+ #
51
+ # Why a worktree and not just a branch: the main session keeps observing trunk
52
+ # while the loop's subprocesses build in a separate checkout — they never fight
53
+ # over HEAD or the working tree. A halt leaves a clean, inspectable WIP branch.
54
+ #
55
+ # trunk (BASE) ── never moves during the loop
56
+ # └─ do/<slug> (worktree .do-worktrees/<slug>) ── every cycle commits here
57
+ # plan complete → report `git merge do/<slug>` (human lands it — never auto)
58
+ # halt → worktree persists → re-run /do <slug> resumes in place
59
+ BASE="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo HEAD)"
60
+ BR="do/${SLUG}"
61
+ WT=".do-worktrees/${SLUG}"
62
+
63
+ _setup_worktree() {
64
+ # Idempotent: reuse an existing worktree (resume), else attach one to an
65
+ # existing branch (prior halt), else create branch+worktree fresh from HEAD.
66
+ if git -C "$WT" rev-parse --git-dir >/dev/null 2>&1; then
67
+ echo "[do-auto] resuming worktree $WT on $BR"
68
+ elif git show-ref --verify --quiet "refs/heads/$BR"; then
69
+ echo "[do-auto] re-attaching worktree $WT to existing branch $BR"
70
+ git worktree add "$WT" "$BR" >/dev/null
71
+ else
72
+ echo "[do-auto] creating worktree $WT on new branch $BR (from $BASE)"
73
+ git worktree add -b "$BR" "$WT" HEAD >/dev/null
74
+ fi
75
+
76
+ # Carry the plan's own artifacts into the worktree. The spine walk may have
77
+ # just written promise/spec/todo uncommitted in the main tree; a worktree cut
78
+ # from HEAD wouldn't have them. Copy only this slug's files — never unrelated
79
+ # working-tree changes — then commit them as the branch baseline.
80
+ local f changed=0
81
+ for f in "plans/${SLUG}.md" "plans/${SLUG}-todo.md" "text/${SLUG}.md" ".w4-improvements.json"; do
82
+ if [ -f "$f" ]; then
83
+ mkdir -p "$WT/$(dirname "$f")"
84
+ if ! cmp -s "$f" "$WT/$f" 2>/dev/null; then cp "$f" "$WT/$f"; changed=1; fi
85
+ fi
86
+ done
87
+ if [ "$changed" -eq 1 ]; then
88
+ git -C "$WT" add -A
89
+ git -C "$WT" commit -q -m "do(${SLUG}): sync spine artifacts" 2>/dev/null || true
90
+ fi
91
+ }
92
+
93
+ if ! $DRY_RUN; then
94
+ _setup_worktree
95
+ # All loop state now lives in the worktree — read the boxes the subprocess ticks.
96
+ TODO="$WT/plans/${SLUG}-todo.md"
97
+ TRUST="$WT/.do-trust.json"
98
+ else
99
+ TODO="plans/${SLUG}-todo.md"
100
+ TRUST=".do-trust.json"
101
+ fi
47
102
 
48
103
  _remaining() {
49
104
  # Count cycles in the Status section that are open ([ ]) or in-flight ([~]) — i.e. not [x].
50
105
  # Pattern starts with '\[' (not '-') so grep never mistakes it for an option flag.
51
- grep -cE '\[[ ~]\] C[0-9]+' "$TODO" 2>/dev/null || echo 0
106
+ # grep -c already prints a count (0 on no match) but exits 1 then — capture it so
107
+ # the `|| true` swallows the exit without appending a second "0" to the output.
108
+ local n; n=$(grep -cE '\[[ ~]\] C[0-9]+' "$TODO" 2>/dev/null) || true
109
+ echo "${n:-0}"
52
110
  }
53
111
 
54
112
  _trust() {
@@ -82,6 +140,7 @@ while [ "$i" -lt "$MAX_CYCLES" ]; do
82
140
  if [ "$stall" -ge 2 ]; then
83
141
  echo "[do-auto] no progress for 2 iterations (${remaining} cycle(s) stuck) — halting." >&2
84
142
  echo "[do-auto] The last cycle ticked no checkbox. Inspect $TODO, fix the blocker, then re-run /do $SLUG." >&2
143
+ echo "[do-auto] WIP preserved on branch $BR (worktree $WT)." >&2
85
144
  exit 1
86
145
  fi
87
146
  else
@@ -92,6 +151,7 @@ while [ "$i" -lt "$MAX_CYCLES" ]; do
92
151
  trust=$(_trust)
93
152
  if [ "$trust" = "cautious" ]; then
94
153
  echo "[do-auto] trust=cautious — halting. Fix the issue, then re-run /do $SLUG."
154
+ echo "[do-auto] WIP preserved on branch $BR (worktree $WT)."
95
155
  exit 1
96
156
  fi
97
157
 
@@ -107,11 +167,31 @@ while [ "$i" -lt "$MAX_CYCLES" ]; do
107
167
  break
108
168
  fi
109
169
 
110
- # Fresh context: no --resume, no --continue. Each cycle is a clean slate.
111
- claude --dangerously-skip-permissions -p "/do $SLUG --next-cycle"
170
+ # Fresh context, isolated tree: the subprocess runs INSIDE the worktree, so
171
+ # every edit/box-tick/state-write lands on branch $BR — trunk is never touched.
172
+ ( cd "$WT" && claude --dangerously-skip-permissions -p "/do $SLUG --next-cycle" )
173
+
174
+ # Commit the cycle on its branch. A cycle closes with a passing rubric, so it
175
+ # is the natural commit unit — and committed progress survives a later halt.
176
+ if [ -n "$(git -C "$WT" status --porcelain)" ]; then
177
+ git -C "$WT" add -A
178
+ git -C "$WT" commit -q -m "do(${SLUG}): cycle ${i}" || true
179
+ fi
112
180
  done
113
181
 
182
+ if $DRY_RUN; then exit 0; fi
183
+
114
184
  if [ "$i" -ge "$MAX_CYCLES" ]; then
115
185
  echo "[do-auto] hit --max-cycles $MAX_CYCLES — halting"
186
+ echo "[do-auto] WIP preserved on branch $BR (worktree $WT)."
116
187
  exit 1
117
188
  fi
189
+
190
+ # Plan complete. The branch holds every cycle, proven and committed; trunk is
191
+ # untouched. Landing it is a human decision (commit/push only when asked), so we
192
+ # report the merge instead of running it — the worktree stays for inspection.
193
+ echo ""
194
+ echo "[do-auto] ✓ plan complete on branch $BR — trunk ($BASE) untouched."
195
+ echo "[do-auto] land: git merge --no-ff $BR # from $BASE"
196
+ echo "[do-auto] inspect: git -C $WT log --oneline $BASE..$BR"
197
+ echo "[do-auto] discard: git worktree remove $WT && git branch -D $BR"