Skip to content

v0.5.0 — Layer 2 (plan-v1 flow) accepted and shipped#12

Merged
hamr0 merged 18 commits into
mainfrom
layer-2-plan-v1
Jul 23, 2026
Merged

v0.5.0 — Layer 2 (plan-v1 flow) accepted and shipped#12
hamr0 merged 18 commits into
mainfrom
layer-2-plan-v1

Conversation

@hamr0

@hamr0 hamr0 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Layer 2 rung landing — v0.5.0

The agent-authored plan-v1 flow (SCOUT → PLAN → per-step micro-loops judged by the exit evaluator → one replan → the operator's close), under the same approval gate, smoke, ledger, and inexpressible arbiter.

Accepted (F47)

Job #4 (TESTGEN) through the real plan flow: 3/3 convert, 3/3 at the 45 bar on the API surface. The in-run operator-signed check translates the semantic ask into the mechanical genre (F46 → F47).

Cross-surface verdict (F48)

clipipe-subscription native surface is OUT as an API peer — capable at the step, does not carry a job to a grade (0/2 vs API 3/3), budget hypothesis refuted, ~2.5–3× notional cost + slower + no resume. Only the anthropic-api surface is guaranteed. Local LLMs deferred/unmeasured.

New modules

src/plan.js (plan-v1 validator), src/exits.js (exit evaluator), src/planrun.js (executor), src/job.js four-field plan shape, ralph.js judge seam, native clipipe read-cap (BA-17, bare-agent 0.33.1).

Pre-release review (F48) — 2 correctness fixes (TDD)

  • mid-step provider-red collapsed to step-red (casualty → tier data, missed F44 floor) — now rides out under its own category (F11).
  • tree-changed counted a sibling scope's files as deletions with ≥2 tree-changed exits — deletions now scoped to the exit's prefix.

Security

Clean on every arbiter-integrity threat (secrets, fence, close, budget, argv injection, path traversal). One LOW self-DoS follow-up logged: F49 — bound the agent-authored artifact-written regex.

Gates: typecheck ✓ · build:types ✓ · tests 519/519 ✓ · security clean (1 LOW follow-up).

🤖 Generated with Claude Code

hamr0 and others added 18 commits July 21, 2026 13:38
Decision 5+6 land in the validator: goal/verdictType/close/checks[] as an
exclusive sibling of the legacy steps[] chain (shape-conflict red on both;
steps[] unchanged during the rung, staged sunset). VERDICT_TYPES frozen radio
green|soft-green|hitl with soft-green/hitl declared-but-locked (request-red
with the type as a structured verb field — the tool-menu pattern). checks[]
reuse the predicate-close body via one extracted helper (predicateBody /
validateClose shared by legacy step closes, the plan close, and checks — one
shape, one validator, no F9 two-transforms). Top-level tools ceiling with the
same run-locked request-red; close-hierarchy lifted to verdictType (green
demands a hard-class close). 401/401, typecheck clean; legacy path
byte-identical (job #1 spec validates unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent-authored plan doc's gate (decisions 7-9): ordered steps, no
dependsOn (inert-knob class); verbs ⊆ signed ceiling with verb-escape carrying
the verb as structured data (run is locked at every layer); rounds ≤ shell cap
(interpret's 40-turn tool-mode attempt bound); target v1.18 required on
write-granted steps, inside the signed fence; exits AND-only max 2 from the
closed menu (exit-illegal = arbiter inexpressibility), check-passes resolving
against the SIGNED checks menu only (check-unknown names the menu so the
replan can aim). F17 pairing law: check-passes on a write step demands the
tree-changed conjunct — stated in the plan, never hardwired shell code.
Fail-closed on a missing/non-plan-shape job. 466/466, typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The shell's fixed code for the closed exit menu — nothing here executes
agent-authored text. tree-changed reads OUTCOME: sha256 snapshot-vs-now under
the scope prefix (snapshotScope), so an identical re-write is NOT a change
(F43) and git status is never consulted (F45 blind-instrument class);
deletions and new files count. artifact-written rejects zero-byte artifacts;
check-passes delegates through the runCheck seam (runner wires runClose) and
fails CLOSED when unwired or crashed — an unrunnable check is a stop, never a
silent pass. AND-only, never short-circuits: the gap names every wall.
Details carry counts and names only, never file bodies. 481/481, typecheck
clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PRD v1.12 §4 executed: opts.judge — a SHELL-injected replacement for runClose
so a plan step's micro-loop is judged by the exit evaluator. Same verdict
vocabulary, so the forbidden zone, F32 worker-crash routing (a check crashed
by the worker's own test file feeds back — the F46 mechanism), and the
cap-halt taxonomy apply unchanged. close becomes optional when judge is
present; close-unaudited stays a close-only note. No-judge path byte-identical
(44/44 including all priors).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ault tests, 3 mutations killed)

runPlan: close precheck (already-green distinct, F17; forbidden zone before
tokens) → checks preflight (every signed check runs once at $0 — an unwired
detector is prose, F45) → read-only SCOUT (write verbs absent from its menu)
→ PLAN drafted against a schema description with check NAMES only, gated by
validatePlan, one redraft with reds fed back → strictly-sequential micro-loops
(ralph + exit-evaluator judge; snapshots at step start; every failing wall in
the gap — F46 measured mechanism, proven live in-test: a red check's gapKeep
line converted attempt 2) → ONE replan on exhaustion only (instrument stops
never replan) → the operator's close, red feeding one bounded fix loop judged
by the REAL close. Every round metered as worker-round with a phase label
(F12); prompt contract v1.12 §5 mutation-proven (close cmd leak killed).
exits.js grows fault propagation: instrument faults ride out by runClose
verdict name, so crashes keep F32 routing and unwired seams escalate instead
of faking gaps. interpret.js exports the shared seams (personas, strategies,
toolAction, ctx tools) — one spelling, no drift. 497 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A four-field spec routes through the ONE runJob entry (N2 lock): same
approval gate, same primitive smoke, same metered ledger — runPlan's
worker-round emissions are accounted natively (F12) and the job-end money
contract (spentUsd + spendComplete) is unchanged. The text-mode target red
stays a legacy-steps rule; job-start carries shape:'plan' + goal instead of a
steps list. step-red:<id> splits into {outcome:'step-red', step} on job-end
(the ledger's outcome vocabulary stays closed). 503 tests, typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… exit menu, runPlan flow), CHANGELOG, LAYERS status, design record status

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ests)

Whole-branch review found 8 confirmed defects, all in the graduated plan
flow (none in pre-existing modules), all restoring guards the legacy path
already has. Validated against source (0 refuted) + a failing-then-passing
test each; suite 503→512 green, typecheck clean.

1 [HIGH] planrun: a GOLD close validates under verdictType green (gold is
  hard-class) but carries no `cmd`; `close.cmd.trim()` TypeError'd out of
  runJob with no job-end, dangling the spine. Guard non-predicate closes at
  runPlan entry → close-unsupported, before tokens (mirrors run.js:463).
2 [HIGH] exits: the check-passes gap was re-sliced to 400 chars, deleting the
  gapKeep failing-test NAMES runClose preserved — F28 reintroduced on the
  F46-critical path. Carry the already-bounded gap whole (cap 12000).
3 [HIGH] run/planrun: no in-flight pricing-red — an unpriced provider burned
  the whole plan before F6 fired. Thread isUnpriced; bail at scout/plan/step.
4 [MED-HIGH] planrun: the plan drafter's Gate budget was frozen at pre-execute
  remaining and reused for the replan → replan spend could exceed budgetUsd.
  Build a fresh drafter per obtainPlan (current-wallet snapshot).
5 [MED-HIGH] planrun: replan triggered on any cap-halt, so a money-gate halt
  (drained wallet) replanned instead of stopping. Gate replan on funds; a
  drained wallet returns honest cap-halt, never a mislabeled step-red (F45).
6 [MED] planrun: the step-setup catch recorded interpreter-red while relay
  emitted provider-red — a self-contradicting spine record. Agree the two
  (interpreter-red for infra setup faults; F11 misfiling).
7 [MED] run: the plan branch dropped F44's spendComplete:false on a
  transport-throw provider-red, laundering an unknown floor as exact.
8 [LOW] job: a write-only tool ceiling validated, leaving the scout an empty
  read-only menu. Require >=1 read-capable verb in a plan-shape ceiling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…moke)

The plan flow now runs on TWO surfaces — the Loop (API, byte-identical) and,
when job.provider is clipipe-subscription, the claude CLI's native tool
channel (the subscription path, no metered API). bare-agent ^0.33.0.

Design (POC-proven on the real CLI before wiring): native governance is
constructor-time + per-worker, so runJob/runPlan take a nativeProvider FACTORY
called fresh per worker as ({policy, onTurn?, maxTurns, hasTools}) => provider.
mkWorker branches:
  - hasTools:true  → native tool mode; the SAME wireGate policy clips onto the
    provider (live POC: an out-of-scope write is DENIED), onTurn meters,
    maxTurns bounds the session (max_turns = a BOUNDED attempt, gap fed
    forward — the loop.stop() analog).
  - hasTools:false → the toolless drafter; a native session reports NO cost
    (live-verified), so it runs metered claude-json TEXT mode via the Loop's
    onLlmResult — the drafter's spend is never invisible (F6/F44).
Money reconciles per SESSION (accounted worker-round = session total; per-turn
worker-turn = attribution only). A missing factory on a clipipe job is
interpreter-red, never a silent fall-back to the API.

Validated: 5 scripted native tests (fence-deny, per-session metering, bounded
attempt, wiring guard, parity) + a LIVE end-to-end smoke through runJob on the
real CLI — green, all three workers metered, spendComplete honest. The live
smoke caught a real spend-leak (the toolless drafter was unmetered) that the
scripted tests masked via an unfaithful fake; both the src and the fake fixed.
517 tests green, typecheck clean; the Loop/API path is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…(pre-number)

The rung's exit gate — job #4 (TESTGEN) through the REAL plan flow (scout →
Planner → plan-v1 validator → per-step Loop+Gate executor + signed clean-run
check → outer grader close + fix loop), NOT the POC's hardwired harness.

- jobs/aurora-testgen-l2accept.json: four-field plan shape (goal / verdictType
  green / grader predicate close / clean-run check), tools ceiling, writeScope
  tests/testgen/**. validateJob-green; specHash af338c9b…
- scripts/run-battery-l2accept.mjs: hash-gated driver, anthropic-api, $8/row,
  n=3 acting rows, $30 hard-stop, capRuns=4. Records L2-CONVERT + whether the
  Planner itself composed check-passes(clean-run) + 45-bar grades (recorded).
- TESTGEN-PREREG.md amendment 2026-07-22a: frozen read rules. PRIMARY = ≥2/3
  acting rows convert the clean wall through the real flow; SECONDARY (recorded,
  axis-split) = kill-rate / greens@45 (F38's claim) / plan-composed-check rate.

hamr-authorized surface/budget (2026-07-22); STOP for sign-off before any spend.
Harness pre-validated $0 (--dry run mrvp7tsq): reset/seed/dispatch/precheck-15/
spine-read green. No worker round has run; no number exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he 45 bar (F47)

The acceptance gate (prereg 2026-07-22a) run through the REAL plan flow across
three runs (mrvpteca / mrvwjrop / mrvyexy4), an Overloaded provider window:

- 3/3 valid acting rows L2-CONVERT (≥2/3 frozen bar) → ACCEPTANCE MET.
- 3/3 green above the 45 bar (67.5/55/55 vs the POC's 27.5/40/37.5, 0 at 45) →
  the "path closes green end-to-end" milestone also met (steps[] sunset).
- 3/3 the Planner composed check-passes(clean-run) ITSELF (POC hardwired it);
  the step check-loop alone drove every green (no grader fix loop fired).
- 7 provider-red casualties (never evidence) + 1 valid-inert; $27.36 of $30;
  all writes fenced, source frozen, secrets clean; F45 spend guard stopped an
  unpriced casualty. No root-injected → Layer R stays OFF.

Docs: FINDINGS F47, TESTGEN-PREREG amendment 2026-07-22b. Driver gained
--need / --priorUsd for the multi-run continuation under one governed cap
(spec hash unchanged, read rules unchanged).

Process notes recorded: run 1 fired without the frozen pre-fire health probe
(4 casualties); the single-message probe is a weak sustained-load instrument.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…README

- CHANGELOG [Unreleased]: acceptance battery entry (3/3 convert, 3/3 at the 45
  bar, agent composed the check exit itself); steps[]/config-v1 sunset on landing;
  driver --need/--priorUsd note. Corrected the "battery not yet run" line.
- PRD Addendum v1.22: Layer 2 accepted; genre chain F38→F39→F46→F47; the two
  carried gaps (within-run resume, separate clipipe battery); next rung N3.
- bareloop.context.md (adopter contract): status → "through Layer 2 (accepted)";
  plan shape is the primary path, steps[] sunsets; two worker surfaces.
- README (pitch only): status blockquote + badge → Layer 2 accepted; next N3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (F48/BA-17)

The claude CLI truncates a large tool result (~40-50KB) before the model sees
it, spilling the remainder to a fenced-off tool-results file and wrapping it in a
"read in chunks" notice the model distrusts as injection — so a whole-file
shell_read of a large file blinded the native worker (0-write stall). Cap OUR
read below the CLI cap and hand back a trusted notice steering to ctx_get ranged
retrieval, plus a native-only strategy line. API path untouched. Bumps bare-agent
0.33.0 -> 0.33.1 (delivers the native ranged read, BA-17).

Measured effect on the L2 clipipe row: 0 -> 7 writes across 3 test files, 137
bounded reads, no stall.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-16/17 asks

Cross-surface replication of F47 (job #4 TESTGEN) on the native clipipe-
subscription surface. Driver sizes the per-session CLI clock to the step round
budget (session_timeout was firing as a pricing-red casualty). Job spec budgetUsd
raised 8 -> 28 per hamr's explicit in-turn approval ("raise it to 28 and try") to
fund a full 7-step plan + outer grade in one row — the prior $8 cap-halted at
$8.61 with 1 step green and a second iterating 4x on real gaps, before reaching
the 45-bar grade. New signed hash faf9304710ea. UPSTREAM-ASKS records BA-16
(native MCP surface) and BA-17 (ranged read).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… guaranteed

The $28 funded shot refuted the budget hypothesis: 3.5x the cap spent $7 and
escalated on the F39 semantic-stall (non-changed suite, 8 iterations), not money.
Across native rows 0/2 reached a grade vs API 3/3. Read-cap enabler exonerated
(worker read seeds + aimed 11/18 fine). clipipe = capable at the step, does not
finish the job; buys $0-marginal billing at a ~2.5-3x notional / slower / no-resume
tax + the inherited semantic ceiling. IN only as a babysat fallback, never a peer.
Local LLMs: not a clipipe capability, deferred + unmeasured. PRD §9 handle added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the changelog current with the last 3 commits before the Layer 2 merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Medium whole-branch review before the v0.5.0 merge. Two correctness bugs, both
watched failing first:
- planrun: a mid-step provider-red/gate-red was returned as step-red:<id> — a
  transport casualty laundered into capability tier data, missing F44
  spendComplete:false. Each terminal category now returns under its own name so
  the outcome and the escalation agree (F11).
- exits: tree-changed counted a sibling scope's files as deletions when a step
  had >=2 tree-changed exits (one merged snapshot), falsely passing an unchanged
  scope. Deletions now scoped to the exit's own prefix.
Plus: clear abandoned-plan artifacts on replan; drop dead isUnpriced() branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Layer 2 rung landing: the agent-authored plan-v1 flow (SCOUT → PLAN → per-step
micro-loops judged by the exit evaluator → one replan → operator's close),
accepted on job #4 (F47: 3/3 convert, 3/3 at the 45 bar). Cross-surface clipipe
verdict OUT-as-peer (F48): only the API is guaranteed. Pre-release review fixed 2
correctness bugs (F48 review). Security scan clean on all arbiter-integrity
threats; one LOW self-DoS follow-up logged (F49 — bound the agent-authored exit
regex). CHANGELOG rolled to 0.5.0, LAYERS status → built+accepted, 519/519.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hamr0
hamr0 merged commit 077f889 into main Jul 23, 2026
2 checks passed
@hamr0
hamr0 deleted the layer-2-plan-v1 branch July 23, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant