loop-constructor-codex
Design an engineered gated loop for a medium/large (semi-)autonomous AI-coding task executed with the Codex CLI (single-agent, `codex exec`), emitted as a runnable .loop/ runbook. …
VincentJiang06
@vincentjiang06
Install
$ openclaw skills install @vincentjiang06/loop-constructor-codexloop-constructor-codex
Design the engineered loop for a medium/large (semi-)autonomous coding task run with
the OpenAI Codex CLI (single-agent, codex exec) by running an explicit selection
procedure that decomposes it into a tree of gated sub-loops, then emit a
machine-checkable loop-design JSON (which scripts/lint_loop_design.mjs PASSes) plus
a decision log, and persist it as a runnable runbook under the project's .loop/.
The anchor (read first): a loop closes autonomously only when a fast,
machine-runnable check can answer "is it done?". So design backward from the
check — principle.closed_loop_needs_a_check. No runnable check ⇒ it is not a
loop; the linter rejects it.
This skill is the applied front-end over the loop-principle KB. It does not restate theory — it RETRIEVES from the KB and REUSES its templates/checklists by path. Resolve the KB path once (see "Grounding"), then cite node ids for design judgments instead of asserting from memory.
The mechanism: SELECT → NEGOTIATE → FILL → VERIFY → PERSIST
Five phases. SELECT derives the loop's shape from an ordered decision procedure.
NEGOTIATE turns that shape into a loop that won't converge on slop — separate the
roles, agree the contract (the LOOPS.md operating model, references/loops-model.md).
FILL writes the machine-checkable JSON; VERIFY + PERSIST gate and emit it. The whole
point — write the loop, not the prompt — every hard call becomes an ordered,
reviewable derivation, not judgment-by-vibes.
Codex runtime mapping
The design vocabulary above (roles, contract, separate-context evaluator, restart,
gate, harness_primitives) is runtime-neutral — it names loop-engineering concepts,
not any runtime's primitives. How each concept lands on the Codex CLI lives in
references/codex-runtime.md — load it at NEGOTIATE, FILL and PERSIST (its phase map
says what each takes). The design JSON itself stays neutral.
1. SELECT — run the decision procedure (references/loop-selection.md)
Answer D0–D6 in order (D7 closes after NEGOTIATE); each answer shapes the
loop and is recorded with a one-line justification (the decision log). The ordered
decisions: D0 is-it-a-loop (name the runnable "done?" check or route away) ·
D1 decompose (seam test → flat vs staged) · D2 per-stage pattern + check
(+ falsifiable_when/passing_but_wrong) · D3 autonomy (in_the_loop vs
on_the_loop) · D4 parallelism (large fan-out vs medium sequential — on
Codex, fan-out = concurrent codex exec processes, never in-process subagents) ·
D5 guards (caps + on_failure + risk guards) · D6 iteration profile /
cadence (completeness-first vs iteration-first, a dial that re-tunes D2/D3/D5) ·
D7 number provenance (closing sweep: each digit-bearing string classed
decision | definitional | empirical; empirical ⇒ derived, never hand-fixed).
Load references/loop-selection.md and run the full procedure — each D-item there
is the operational decision rule. Record the answers as the selection_log array.
2. NEGOTIATE — separate the roles + agree the contract (references/loops-model.md)
Two moves from the LOOPS.md operating model, both linter-enforced for staged:
- Separate the roles (§II).
roles.{planner,generator,evaluator}= three contexts: planner→spec+contract (no code), generator→writes all (never grades itself), evaluator→fresh, adversarial (separate_context:true,adversarial:true), told the artifact is broken and to prove it. Self-grading breeds sycophancy — the #1 loop failure. On Codex these are three separatecodex execinvocations (references/codex-runtime.md§1). - Negotiate the contract (§III). Generator proposes "done", evaluator pushes back
→ agreed testable assertions (
contract.assertions[], each gradable + stage-traced). The contract, not the spec, is graded. The per-surface numbers are lower bounds over machine-gradable assertions (endpoint ≥8, module ≥12, app ≥20; ceiling 3×) — a contract too thin to disagree with gets rubber-stamped.
3. FILL — write the loop-design JSON (references/loop-design-shape.md)
The decisions above mostly determine the spec. Fill the canonical staged
object (or flat if D1 found 0 seams): per-stage definition_of_done (a
machine-verifiable predicate, not prose — each tracing back to a contract
assertion) · loop_pattern · feedback_signal (check + expect:"pass" +
falsifiable_when + passing_but_wrong) · stop_conditions (per-stage cap +
on_failure, incl. restart where a build can become archaeology) · depends_on;
and design-level loop_altitude (+rationale) · roles · contract ·
human_placement · maker_checker · harness_primitives (name the durable
on-disk state so the loop survives context loss — each codex exec is fresh; disk
is the only memory, see references/codex-runtime.md §2) · outer stop_conditions
(with a non-empty success) · risk_guards (map to Codex sandbox / approval
levers, codex-runtime.md §4) · the parameter_provenance declaration (D7's
output — FAIL/WARN rules in references/loop-design-shape.md). Include the
selection_log. Reuse KB templates by path (references/loop-principle-map.md).
4. VERIFY — linter + fresh-reader (eat the dogfood)
Run the linter on the produced JSON before returning it:
node scripts/lint_loop_design.mjs <produced-design.json>
It must print all PASS and exit 0. Any FAIL <field>: <reason> → fix and re-run.
For a newly-emitted design, clean = zero FAIL and zero WARN lines — a
WARN parameter_provenance means D7 was skipped (absence is legal only for
pre-0.4 designs; warns never change the exit code).
Then do the fresh-reader pass with the operational template
assets/fresh-reader-checklist.md — the linter checks structure, not meaning.
Re-read the design cold and confirm, per stage, that the check would actually
fail on a broken impl, falsifiable_when is a real break (not a goal
restatement), passing_but_wrong is an honest concrete false-pass, failure
branches are reachable, and success matches what the checks prove. It also
judges what the linter structurally can't: whether the contract is actually
sufficient (≈20 assertions for an app-sized task, not a rubber-stampable
handful), the roles are genuinely separate (the evaluator never saw the
impl), and — the numbers-audit box — that every digit-bearing string is
classified in parameter_provenance (an empty declaration above unclassified
empirical literals is a lie). A green linter on a hollow check — or a thin
contract — is the exact trap this pass exists to catch.
5. PERSIST — render the runbook
node scripts/render_loop_doc.mjs <design.json> # writes .loop/<slug>.loop.{md,json}
render_loop_doc.mjs re-validates first and refuses to emit a runbook for a
design the linter rejects — a written .loop/ doc is itself proof the design
passed. The emitted Markdown carries a "How to run this loop (Codex CLI)"
preamble (codex-runtime.md phase map). A
REFUSED: line → fix the design and re-run. Tell the user the two paths.
Report
Hand back: the decision log (D0–D7), the roles + negotiated contract, the
loop-design JSON, the lint result (PASS), the fresh-reader verdict, a self-scored
rubric (loop-principle/templates/loop_quality_rubric.template.json), the
current bottleneck (where the weakest link is now — plan / verification / taste;
LOOPS.md §IX), and residual risks. State the run-report contract the designed loop
must honour when it stops: every success/autonomy metric paired with its
integrity/damage counterpart or tagged not measured (references/loops-model.md
§VII·b) — an unpaired success number is the shape of slop, not evidence. If the
loop-principle KB was not found (see Grounding), say so out loud — the design ran
in KB-degraded mode.
Grounding (KB path resolution)
The skill reads from the loop-principle KB, which this Codex skill does not
embed (avoiding a duplicate copy). Default: resolve <kb> to the sibling skill's
copy — try, in order, ../loop-constructor/loop-principle then
../vince-loop-constructor/loop-principle (installed sibling dirs carry the
vince- prefix), relative to this skill folder. If an
operator overrides it with $LOOP_PRINCIPLE, use that absolute path. Do not
hardcode-fail; if the KB is absent (e.g. this skill is installed on a machine
without the sibling), say so out loud in the report and degrade to the cited
node ids in references/ — KB-degraded mode is acceptable.
Retrieval recipe: node <kb>/tools/query_kb.mjs "<topic>".
Modules
| File | When to load |
|---|---|
references/loop-selection.md | Phase 1 (SELECT) — the D0–D7 decision procedure that derives the loop shape + decision log. |
references/loop-design-shape.md | Phase 3 (FILL) — the exact canonical loop-design JSON keys the linter validates (flat + staged, incl. roles/contract/restart, parameter_provenance + its FAIL/WARN rules, the persist contract). |
references/loops-model.md | Phase 2 (NEGOTIATE) + judgment layer — the LOOPS.md operating model: separate roles, negotiate the contract, write-to-disk state, score-the-subjective, read-the-traces, delete-the-harness (time + information dimension), the moving bottleneck. |
references/codex-runtime.md | Codex realization — how roles/state/parallelism/guards land on codex exec. Load during NEGOTIATE (roles), FILL (harness_primitives + D4), PERSIST (runbook preamble). |
references/loop-principle-map.md | KB grounding: each decision/field → loop-principle node ids + docs + which templates/checklists to reuse, and the query_kb recipe. |
assets/fresh-reader-checklist.md | Phase 4 (VERIFY) — the operational fresh-reader template (per-stage + design-level boxes the linter can't check, incl. the numbers-audit). |
scripts/lint_loop_design.mjs | The deterministic verifier. Flat or staged. CLI or import { validate }. |
scripts/render_loop_doc.mjs | Renders a linter-valid design into a runnable runbook (with the Codex how-to-run preamble); validates first, refuses invalid. |
assets/golden-loop-design.json | A passing flat fixture (the atomic single-stage unit). |
assets/golden-loop-design-medium.json | A passing staged fixture — copy as the starting point for a decomposed design. |
assets/golden-loop-design-large.json | A passing large-altitude (fan-out) fixture — exercises the concurrent-codex exec Orchestration preamble; copy for a parallel-shard design. |
evals/run_all.mjs | Re-runnable adversarial battery over the linter + renderer; node evals/run_all.mjs. |
Controls
- Design-only — persist, don't execute. Writing the loop-design JSON + the
runbook to
.loop/is producing the design artifact. Never run the designed loop, run the target's code, or modify the loop-principle KB. - One process per role. Never design a stage that requires in-process subagents
or a Task/Workflow tool; parallelism and fresh-evaluator contexts are realized as
separate
codex execOS processes (multi_agentexists on codex-cli 0.144.4, its isolation is unverified —references/codex-runtime.md). - Run the selection procedure. Don't pick a shape by vibes — derive it from D0–D7 and emit the decision log. A design without a decision log is incomplete.
- Don't write numbers nobody measured (D7). Decision numbers stay
pre-registered; definitional ones are fixed with a red fixture; empirical
magnitudes are declared
derived— formula at design time, value at run time. - Emit STAGED unless D1 genuinely finds 0 seams. The flat shape stays valid as the atomic single-stage unit (linter still accepts it).
- Separate the roles; the evaluator is adversarial. planner/generator/evaluator
are three contexts (§II) — three separate
codex execinvocations; a model that grades its own work turns sycophantic, so the evaluator is a fresh read-onlycodex exectold the artifact is broken. Read-only limits what it writes, not what it obeys: it runs where the generator cannot have editedAGENTS*.md/.codex//its prompts (codex-runtime.md §1), or independence isL-i incomplete. Required for staged. - Negotiate the contract; grade it, not the spec. Agree the testable assertions before building (§III); too few lets the evaluator rubber-stamp. Required for staged.
- Route failures by what they accuse (§V): escalate → re-plane → loopback →
restart, first hit wins. Restarting the stage's own stalled work stays autonomous
(no human). Escalate = stop for the owner on a wrong contract, an impossible or
blocked task (never sealed), or a fixer signature such as a P0/P1 inside the
previous fix; the owner first asks whether the judgment should be mechanized at
all — re-plane is theirs, never an
on_failurethe loop picks. Every trigger is a counter fixed before the run, never an in-flight call. - Stop on both sides.
stop_conditionscarries a zero-change gate ("N iterations with zero new changes → stop", the anti-arms-race brake) and a minimum-progress floor below which an early stop escalates instead of counting as done (D5). - Settle the harness both ways at each model or codex-cli release (§VIII). Delete
what the model now does for free, add back that version's named failure modes, stamp
each change with
model_baseline(model id + effort + codex-cli version); match degrees-of-freedom to the task. A growing-only harness is one you've stopped reading. - Reject-on-no-check (per stage). A stage with no runnable feedback signal FAILs the linter; the anchor holds for every stage.
- Mandatory caps. Every stage + the outer loop carry a finite
max_iterations, written insidestop_conditions; the stage graph must be acyclic. A loop may trip a cap, never raise one — cap changes happen outside the loop. - Self-verification gate. Return a design only after the linter PASSes and the fresh-reader checklist is clean.
- Cite, don't assert. Back design choices with loop-principle node ids.
Lifecycle
- version in frontmatter (
0.3.0); tracks loop-constructor 0.5.0. - Shared schema + linter.
scripts/lint_loop_design.mjs= loop-constructor 0.5.0 (unchanged since 0.4.0), sha2561fec173225e5c671086da11fc6b85bb2183f6da636e0db7d25cdb16ae256fd36— designs are cross-compatible between the two skills; the shared references/assets differ only by the Codex hunks listed inCHANGELOG.md, and the renderer adds the Codex preamble. A change to the schema the linter binds to (a new required field, a renamed key) is the only kind of breaking change. 0.3.0— routing + evaluator surface (non-breaking). Pre-0.3 Codex runbooks still lint green but may route "own fix → restart" and leaveAGENTS.mdgenerator-writable: re-review them with the fresh-reader §V and evaluator-instruction-file boxes; never auto-rewrite. History:CHANGELOG.md.- Rollback =
git restorethe skill dir; the skill only writes design artifacts under the target's.loop/and never executes a loop, so a bad design is inert.
Top skills in this category
Skill Vetter
@spclaudehomeSecurity-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns.
Clawdhub
@steipeteUse the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/updated skill folders with the npm-installed clawdhub CLI.
Evolver
@autogame-17A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution. Communicates with EvoMap...
Evolver
@autogame-17A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution. Communicates with EvoMap...
OpenClaw Command Center
@jontsaiMission control dashboard for OpenClaw - real-time session monitoring, LLM usage tracking, cost intelligence, and system vitals. View all your AI agents in one place.