loopforge 3.8.1 → 3.8.2

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/README.md CHANGED
@@ -1,171 +1,123 @@
1
- # LoopForge
2
-
3
- **A context window is not memory. Memory needs a runtime.**
4
-
5
- > **Version per `package.json`** — `npm install -g loopforge`. Node.js ≥ 18. Zero runtime dependencies.
6
- > [中文文档](../README.zh-CN.md)
7
-
8
- ---
9
-
10
- ## The real problems with long-horizon tasks
11
-
12
- Any AI coding agent, given a long enough task, hits three walls. Not because the model isn't smart enough. Not because the context window isn't large enough. These are **architectural** problems.
13
-
14
- ### Problem 1: The summary cascade
15
-
16
- Context fills up → compress. Fills up again → compress again. The third compression is a summary of a summary of a summary. Every cycle evaporates information — critical constraints get silently deleted because the summarizer judged them "no longer relevant." Researchers found that after 3–4 summary cycles, constraint violation rates spike from 0% to 59%. The agent doesn't know what it forgot, because the forgetting itself was compressed away.
17
-
18
- ### Problem 2: Self-correction doesn't work
19
-
20
- Models cannot reliably improve themselves through introspection — they talk themselves out of correct answers. Effective recovery requires an **external verifier** — an independent observer that doesn't share the agent's context, doesn't participate in its reasoning, and only looks at inputs and outputs.
21
-
22
- ### Problem 3: Compound error (p^N)
23
-
24
- If each step succeeds with probability p, N sequential steps succeed with probability p^N. Frontier agents nail nearly 100% of tasks under 4 minutes but crater to under 10% on tasks over 4 hours. Small errors at each step become the correct input for the next step.
25
-
26
- **These three problems amplify each other. The summary cascade loses information → lost information becomes errors → the agent can't self-correct because those errors look reasonable within its own context.**
27
-
28
- ---
29
-
30
- ## What LoopForge does about it
31
-
32
- LoopForge runs outside the agent and owns the boundary between rounds. Its
33
- design has two explicit sources:
34
-
35
- - **One factual source:** committed typed round documents in the Vault.
36
- - **One cognitive source:** Canonical State compiled from those facts.
37
-
38
- `loopforge_next` accepts a structured evaluation. The core fields `success`,
39
- `output_summary`, `constraint_violations`, and `should_continue` are strict;
40
- optional fields are normalized. Invalid input returns `evaluation_invalid` and
41
- can be corrected with the same `roundId` without saving session state, writing
42
- a round, entering either gate, or changing metrics.
43
-
44
- Valid submissions pass through evidence collection, a verification gate
45
- organized into four domains (evaluation consistency, evidence integrity, plan
46
- & contract, progress & recovery), and an enforcement gate driven by one
47
- ordered strategy table — the row order is the priority, and each row names
48
- the check it reacts to plus its escalation ladder. Only an allowed round joins
49
- committed history. The shared internal `CommittedRoundView` gives Replay,
50
- Audit, Metrics, contracts, the compiler, and gate history one decoder and one
51
- filtering policy. It does not create another storage format.
52
-
53
- The compiler evolves Canonical State from committed history, then derives
54
- focus, todo, phase, delegation, and handoff for prompts and status views. The
55
- next prompt therefore comes from typed cognitive state, not from a summary of
56
- the previous prompt.
57
-
58
- ```text
59
- Traditional: prompt -> summary -> next prompt -> another summary
60
- LoopForge: committed rounds -> Canonical State -> next prompt
61
- ```
62
-
63
- The verification gate compares claims with Git snapshots, test output, and
64
- configured command evidence. The enforcement gate can accept, reject,
65
- backtrack, or terminate. A rejected submission commits nothing. A stalled-
66
- progress evaluator can restore the last clean round, inject a diagnosis, and
67
- verify workspace restoration before work continues.
68
-
69
- ---
70
-
71
- ## What LoopForge is not
72
-
73
- - **Not a memory database.** The optional state file is derived. Committed
74
- rounds hold facts, and Canonical State supplies runtime cognition.
75
- - **Not a context compressor.** It recompiles prompts from typed state instead
76
- of compressing the prior prompt.
77
- - **Not a constraint tracker.** Constraints are one input to external judgment.
78
- - **Not an agent or unattended executor.** The external agent owns planning,
79
- code changes, and tool use. LoopForge governs round transitions.
80
-
81
- ---
82
-
83
- ## Install
84
-
85
- ```bash
86
- npm install -g loopforge
87
- loopforge init --client claude
88
- claude mcp add loopforge -- npx loopforge mcp
89
- ```
90
-
91
- Works with Claude Code, Codex CLI, or any MCP-compatible client.
92
-
93
- The MCP server path (`loopforge mcp`) is the primary integration. It provides
94
- the full cognitive infrastructure: verification gate, enforcement gate,
95
- backtrack, evidence collection, and crash recovery. The engine is also
96
- available as a library for custom integrations.
97
-
98
- ---
99
-
100
- ## Architecture
101
-
102
- ```text
103
- External agent
104
- -> structured evaluation
105
- -> evidence / verification / enforcement
106
- -> accept, reject, backtrack, or terminate
107
- reject / terminate: no round commit
108
- accept / stop / backtrack: commit transaction decision
109
- -> committed round documents [factual source]
110
- -> CommittedRoundView [shared read model]
111
- -> Replay [what happened]
112
- -> Audit / Metrics [evidence and diagnostics]
113
- -> Canonical State [cognitive source]
114
- -> DerivedCognitiveFacts
115
- -> prompt / state file / status
116
- -> external agent, next round
117
- ```
118
-
119
- ---
120
-
121
- ## Key capabilities
122
-
123
- - Structured evaluation with strict core fields, lenient optional normalization,
124
- and retryable `evaluation_invalid` responses.
125
- - One committed-round history for the compiler, contracts, gates, Replay,
126
- Audit, and Metrics.
127
- - One Canonical State for prompts, the optional state file, and current-status
128
- cognition.
129
- - Evidence-backed accept, reject, backtrack, and terminate decisions, including
130
- Round Contract and workspace-restore checks. A backtrack carries a derived
131
- Recovery Brief — trigger rule, restore point, redo round ID, failed
132
- approaches, and falsified assumptions — sourced from committed rounds plus
133
- the in-flight attempt (never rejected payloads); the redo reuses the round
134
- ID and its commit retires the brief.
135
- - L0, L1, and L2 prompt density, five-state sub-goals with explicit
136
- `subgoal_updates` transitions (active `sg-` IDs only; done/canceled are
137
- terminal), constraint lifecycle, milestones, and agent-requested emphasis
138
- (by stable id or exact text) or confusion points. Prompts and the state file
139
- render active sub-goals only, capped by policy; the state file is grouped
140
- into Current / Recent / Historical Summary tiers with derived metadata
141
- (round, attempt, state hash) and is byte-identical when regenerated from the
142
- Vault — its content depends on committed facts, not on which prompt level
143
- compiled.
144
- - Separate Replay and Audit views. Replay answers what happened; Audit checks
145
- evidence and completeness.
146
- - Durable sessions with atomic round documents, sequence checks, owned locks,
147
- renewable leases, pause, resume, and idempotent recovery.
148
- - Nine MCP tools: `start`, `next`, `status`, `stop`, `pause`, `resume`, `replay`,
149
- `gate_check`, and `gate_resolve`. The two gate tools are opt-in
150
- (`policy.gate.enabled`, default false): hidden from `tools/list`, structured
151
- preflight via `gate_check`, round-blocking on unapproved `gate_ids`
152
- citations.
153
- - Zero runtime dependencies. Policy controls thresholds, budgets, and intervals.
154
-
155
- ---
156
-
157
- ## Development
158
-
159
- ```bash
160
- npm run check
161
- npm test
162
- npm pack --dry-run --json
163
- ```
164
-
165
- The protocol schema in `../loopforge-protocol.json` is generated from `src/protocol.ts`. Do not edit it by hand.
166
-
167
- ---
168
-
169
- ## License
170
-
171
- MIT
1
+ # LoopForge package
2
+
3
+ The `loopforge` package is the TypeScript runtime behind LoopForge. It keeps
4
+ round state durable, collects machine evidence, verifies submitted claims, and
5
+ compiles the next prompt. The external coding Agent still owns planning, file
6
+ changes, tool use, and execution.
7
+
8
+ For the product model and the contract mental model, read the
9
+ [root README](../README.md) or [中文说明](../README.zh-CN.md). This document is
10
+ the package and integration reference.
11
+
12
+ **Requirements:** Node.js >= 18. Zero runtime dependencies. The package version
13
+ is defined only by the `version` field in `package.json`.
14
+
15
+ ## Install and run
16
+
17
+ ```bash
18
+ npm install -g loopforge
19
+ loopforge init --client claude
20
+ claude mcp add loopforge -- npx loopforge mcp
21
+ ```
22
+
23
+ The CLI provides the following entry points:
24
+
25
+ ```text
26
+ loopforge mcp
27
+ loopforge init --client claude|codex|generic [--target DIR] [--force]
28
+ loopforge doctor [--json]
29
+ loopforge inspect LOOP_ID [--round N] [--prompt] [--json]
30
+ loopforge explain LOOP_ID [--round N] [--json]
31
+ ```
32
+
33
+ `loopforge mcp` starts the synchronous MCP server. `init` installs the client
34
+ configuration, `doctor` reports local readiness, `inspect` reads persisted loop
35
+ state, and `explain` shows why a committed round received its disposition.
36
+
37
+ ## MCP integration
38
+
39
+ The MCP server exposes nine tools:
40
+
41
+ - `loopforge_start` creates a session and returns the first prompt.
42
+ - `loopforge_next` submits the structured evaluation for the held round.
43
+ - `loopforge_status` returns session, loop, audit, or explain views.
44
+ - `loopforge_stop` intentionally stops a session.
45
+ - `loopforge_pause` pauses a session at a round boundary.
46
+ - `loopforge_resume` reconstructs a durable session.
47
+ - `loopforge_replay` reads the committed timeline and round diffs.
48
+ - `loopforge_gate_check` preflights a high-risk action.
49
+ - `loopforge_gate_resolve` records the decision for an opened user gate.
50
+
51
+ The two gate tools are opt-in through `policy.gate.enabled` and are hidden from
52
+ `tools/list` when disabled. A gate decision is an auditable process record. It
53
+ does not prove that a human was present because the Agent submits the resolve
54
+ call.
55
+
56
+ Every `loopforge_next` submission must include the four strict evaluation
57
+ fields: `success`, `output_summary`, `constraint_violations`, and
58
+ `should_continue`. `round_contract`, `subgoal_updates`, and
59
+ `execution_report.contract_item_claims` are also strict structural boundaries.
60
+ Malformed payloads return a retryable error for the same `roundId` without
61
+ writing session state, a round, gate records, rejection counters, or metrics.
62
+ Agent reports remain claims. Only independent observations can support a
63
+ verified fact.
64
+
65
+ ## TypeScript API
66
+
67
+ The package exports the runtime in separate entry points:
68
+
69
+ ```text
70
+ loopforge protocol types, policy, store, compiler, engine, evidence,
71
+ transactions, metrics, and MCP classes
72
+ loopforge/compiler compiler helpers
73
+ loopforge/replay ReplayBackend
74
+ loopforge/mcp MCP server entry point
75
+ ```
76
+
77
+ The main exports include `createEngine` and `LoopForgeEngine` for an in-process
78
+ engine, `FileLoopStore` for durable JSON storage, `compileLoop` for compiling a
79
+ prompt from committed facts, `ReplayBackend` for read-only history queries,
80
+ `McpServer` for the MCP transport, and `SessionManager` for durable MCP
81
+ sessions. Type declarations are emitted alongside the runtime in `dist/`.
82
+
83
+ Example import:
84
+
85
+ ```ts
86
+ import { createEngine, FileLoopStore, compileLoop } from "loopforge";
87
+ ```
88
+
89
+ Use the generated `.d.ts` files in `dist/` for the exact signatures and input
90
+ types. The public protocol constructors and types are exported from the main
91
+ entry point.
92
+
93
+ ## Persistence and policy
94
+
95
+ LoopForge stores durable loop data under `.loopforge/loops/` and derived human
96
+ state under `.loopforge/state/`. Committed typed round documents are the source
97
+ of truth. The state file can be regenerated and must not be treated as a second
98
+ history.
99
+
100
+ Runtime behavior is controlled by `loop_policy.json`. Evidence commands are
101
+ explicitly configured, run without a shell, and restricted to the workspace.
102
+ The default policy keeps the optional user gate disabled.
103
+
104
+ ## Development
105
+
106
+ Run these commands from this directory:
107
+
108
+ ```bash
109
+ npm run check
110
+ npm run build
111
+ npm test
112
+ npm pack --dry-run --json
113
+ npm run verify:artifacts
114
+ git diff --check
115
+ ```
116
+
117
+ The build generates `../loopforge-protocol.json` and `dist/`. Change protocol
118
+ types in `src/protocol.ts` first, then run the build. Do not edit generated
119
+ artifacts by hand.
120
+
121
+ ## License
122
+
123
+ MIT
package/dist/version.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Generated by scripts/sync-version.mjs — do not edit by hand.
2
2
  * Single version source: the `version` field of package.json.
3
3
  * CLI, MCP server info, and doctor reports all read this constant. */
4
- export declare const VERSION = "3.8.1";
4
+ export declare const VERSION = "3.8.2";
5
5
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Generated by scripts/sync-version.mjs — do not edit by hand.
2
2
  * Single version source: the `version` field of package.json.
3
3
  * CLI, MCP server info, and doctor reports all read this constant. */
4
- export const VERSION = "3.8.1";
4
+ export const VERSION = "3.8.2";
5
5
  //# sourceMappingURL=version.js.map
package/loop_policy.json CHANGED
@@ -1,59 +1,59 @@
1
- {
2
- "version": "4",
3
- "constraints": {
4
- "retire_window": 3
5
- },
6
- "summary": {
7
- "window": 5,
8
- "milestone_interval": 20
9
- },
10
- "engine": {
11
- "stall_lookback_rounds": 3,
12
- "max_rounds": 200,
13
- "enforcement_escalation_enabled": true,
14
- "backtrack_enabled": true,
15
- "backtrack_max_depth": 3,
16
- "backtrack_preserve_discoveries": true,
17
- "unverified_claim_streak_limit": 3
18
- },
19
- "prompt": {
20
- "l0_max_chars": 3000,
21
- "l1_max_chars": 7000,
22
- "l2_max_chars": 18000,
23
- "l2_pointer_enabled": true,
24
- "max_emphasize_l2": 5,
25
- "max_emphasize_l1": 3,
26
- "max_confusion_points": 3
27
- },
28
- "backend": {
29
- "root_dir": ".loopforge"
30
- },
31
- "evolution": {
32
- "max_discovered_constraints_per_round": 5,
33
- "max_active_constraints": 15,
34
- "max_objective_versions": 10,
35
- "progress_stall_threshold": 0.05,
36
- "max_active_subgoals": 12
37
- },
38
- "checkpoint": {
39
- "outcome_max_chars": 200
40
- },
41
- "state_file": {
42
- "enabled": true,
43
- "directory": ".loopforge/state"
44
- },
45
- "evidence": {
46
- "providers": [
47
- "git"
48
- ],
49
- "timeout_ms": 120000,
50
- "commands": []
51
- },
52
- "mcp": {
53
- "session_lease_ms": 30000,
54
- "session_lease_renew_interval_ms": 10000
55
- },
56
- "gate": {
57
- "enabled": false
58
- }
59
- }
1
+ {
2
+ "version": "4",
3
+ "constraints": {
4
+ "retire_window": 3
5
+ },
6
+ "summary": {
7
+ "window": 5,
8
+ "milestone_interval": 20
9
+ },
10
+ "engine": {
11
+ "stall_lookback_rounds": 3,
12
+ "max_rounds": 200,
13
+ "enforcement_escalation_enabled": true,
14
+ "backtrack_enabled": true,
15
+ "backtrack_max_depth": 3,
16
+ "backtrack_preserve_discoveries": true,
17
+ "unverified_claim_streak_limit": 3
18
+ },
19
+ "prompt": {
20
+ "l0_max_chars": 3000,
21
+ "l1_max_chars": 7000,
22
+ "l2_max_chars": 18000,
23
+ "l2_pointer_enabled": true,
24
+ "max_emphasize_l2": 5,
25
+ "max_emphasize_l1": 3,
26
+ "max_confusion_points": 3
27
+ },
28
+ "backend": {
29
+ "root_dir": ".loopforge"
30
+ },
31
+ "evolution": {
32
+ "max_discovered_constraints_per_round": 5,
33
+ "max_active_constraints": 15,
34
+ "max_objective_versions": 10,
35
+ "progress_stall_threshold": 0.05,
36
+ "max_active_subgoals": 12
37
+ },
38
+ "checkpoint": {
39
+ "outcome_max_chars": 200
40
+ },
41
+ "state_file": {
42
+ "enabled": true,
43
+ "directory": ".loopforge/state"
44
+ },
45
+ "evidence": {
46
+ "providers": [
47
+ "git"
48
+ ],
49
+ "timeout_ms": 120000,
50
+ "commands": []
51
+ },
52
+ "mcp": {
53
+ "session_lease_ms": 30000,
54
+ "session_lease_renew_interval_ms": 10000
55
+ },
56
+ "gate": {
57
+ "enabled": false
58
+ }
59
+ }
package/package.json CHANGED
@@ -1,67 +1,67 @@
1
- {
2
- "name": "loopforge",
3
- "version": "3.8.1",
4
- "description": "External cognitive infrastructure for AI coding agents — breaks the summary cascade, provides independent verification, and enables model-directed prompt prioritization for 100+ round agent loops.",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
12
- },
13
- "./compiler": {
14
- "import": "./dist/loop-compiler.js",
15
- "types": "./dist/loop-compiler.d.ts"
16
- },
17
- "./replay": {
18
- "import": "./dist/replay.js",
19
- "types": "./dist/replay.d.ts"
20
- },
21
- "./mcp": {
22
- "import": "./dist/mcp/server.js",
23
- "types": "./dist/mcp/server.d.ts"
24
- }
25
- },
26
- "bin": {
27
- "loopforge": "dist/cli.js"
28
- },
29
- "files": [
30
- "dist/",
31
- "!dist/tests/",
32
- "skills",
33
- "loop_policy.json",
34
- "LICENSE"
35
- ],
36
- "scripts": {
37
- "build": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs",
38
- "generate-schema": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs",
39
- "test": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs && node --test --test-concurrency=1 dist/tests/*.test.js",
40
- "test:watch": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node --test --watch dist/tests/*.test.js",
41
- "check": "node scripts/sync-version.mjs && tsc --noEmit",
42
- "verify:artifacts": "node scripts/verify-artifacts.mjs",
43
- "prepack": "npm run verify:artifacts && npm run build"
44
- },
45
- "repository": {
46
- "type": "git",
47
- "url": "git+https://github.com/kyrielrving11/LoopForge.git"
48
- },
49
- "keywords": [
50
- "cognitive-state",
51
- "ai-agent",
52
- "durable-agent",
53
- "claude-code",
54
- "llm",
55
- "cognitive-stability",
56
- "constraint-management",
57
- "mcp"
58
- ],
59
- "engines": {
60
- "node": ">=18"
61
- },
62
- "license": "MIT",
63
- "devDependencies": {
64
- "@types/node": "^20.0.0",
65
- "typescript": "^5.4.0"
66
- }
67
- }
1
+ {
2
+ "name": "loopforge",
3
+ "version": "3.8.2",
4
+ "description": "External cognitive infrastructure for AI coding agents — breaks the summary cascade, provides independent verification, and enables model-directed prompt prioritization for 100+ round agent loops.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./compiler": {
14
+ "import": "./dist/loop-compiler.js",
15
+ "types": "./dist/loop-compiler.d.ts"
16
+ },
17
+ "./replay": {
18
+ "import": "./dist/replay.js",
19
+ "types": "./dist/replay.d.ts"
20
+ },
21
+ "./mcp": {
22
+ "import": "./dist/mcp/server.js",
23
+ "types": "./dist/mcp/server.d.ts"
24
+ }
25
+ },
26
+ "bin": {
27
+ "loopforge": "dist/cli.js"
28
+ },
29
+ "files": [
30
+ "dist/",
31
+ "!dist/tests/",
32
+ "skills",
33
+ "loop_policy.json",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs",
38
+ "generate-schema": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs",
39
+ "test": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node dist/generate-schema.js && node scripts/trim-dist.mjs && node --test --test-concurrency=1 dist/tests/*.test.js",
40
+ "test:watch": "node scripts/sync-version.mjs && tsc && node scripts/trim-dist.mjs && node --test --watch dist/tests/*.test.js",
41
+ "check": "node scripts/sync-version.mjs && tsc --noEmit",
42
+ "verify:artifacts": "node scripts/verify-artifacts.mjs",
43
+ "prepack": "npm run verify:artifacts && npm run build"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/kyrielrving11/LoopForge.git"
48
+ },
49
+ "keywords": [
50
+ "cognitive-state",
51
+ "ai-agent",
52
+ "durable-agent",
53
+ "claude-code",
54
+ "llm",
55
+ "cognitive-stability",
56
+ "constraint-management",
57
+ "mcp"
58
+ ],
59
+ "engines": {
60
+ "node": ">=18"
61
+ },
62
+ "license": "MIT",
63
+ "devDependencies": {
64
+ "@types/node": "^20.0.0",
65
+ "typescript": "^5.4.0"
66
+ }
67
+ }
@@ -1,414 +1,264 @@
1
1
  ---
2
2
  name: perception
3
- description: Drive a multi-round coding task through LoopForge MCP so goals, constraints, evidence, and decisions survive context loss and restarts. Use when a task needs several rounds, must survive context compression or a process restart, or needs an auditable record of what was verified by the machine rather than claimed by the model. The external Agent stays the execution owner.
3
+ description: Drive multi-round coding tasks through LoopForge MCP so objectives, constraints, evidence, and decisions survive context loss and restarts. The external Agent remains responsible for planning, file changes, tools, and execution.
4
4
  ---
5
5
 
6
6
  # Perception
7
7
 
8
- Use LoopForge when a coding task needs several rounds, must survive context
9
- compression or process restart, or benefits from an auditable record of goals,
10
- constraints, evidence, and decisions.
8
+ Use LoopForge when a task spans several meaningful work slices, must survive a
9
+ restart or context loss, or needs an auditable distinction between Agent claims
10
+ and machine-verified facts.
11
11
 
12
- LoopForge has one factual source, the committed typed round documents in the
13
- Vault, and one cognitive source, the Canonical State compiled from them. You
14
- remain the Agent that reads files, edits code, runs commands, delegates work,
15
- and decides how to reason.
12
+ LoopForge has one factual source, committed typed round documents in the Vault,
13
+ and one cognitive source, Canonical State compiled from those documents. The
14
+ Agent still decides what to do and how to reason.
16
15
 
17
16
  ## Start
18
17
 
18
+ Call `loopforge_status` with `view: "all"` before starting. Reuse an existing
19
+ session for the same objective instead of opening a second loop.
20
+
19
21
  Call `loopforge_start` with:
20
22
 
21
- - `task`: the complete user objective.
22
- - `constraints`: hard boundaries that must survive every round.
23
- - `maxRounds`: optional positive safety limit. The default is 200 from policy.
24
- - `domain`: optional context label.
25
- - `loopId`: optional stable loop id. Generated for you when omitted — pass one
26
- when the caller already knows it, so later calls can address the loop.
27
- - `planSource`: optional path to a plan document to extract constraints from.
28
-
29
- Before starting, `loopforge_status` with `view: "all"` lists the loops the
30
- runtime already holds — reuse an existing session instead of opening a second
31
- one for the same objective.
32
-
33
- Keep the returned `sessionId`, `roundId`, prompt, and level. Always pass the
34
- most recent `roundId` to `loopforge_next`. It anchors the submission to the
35
- exact round being reported.
36
-
37
- ## Plan round boundaries
38
-
39
- LoopForge does not decide how the Agent thinks about a large task. The Agent
40
- chooses the next useful slice of work, while LoopForge checks the submitted
41
- facts and evidence at the round boundary. Do not try to predict an exact number
42
- of rounds before inspecting the repository. Re-plan after each committed round.
43
-
44
- Choose a round around a coherent, verifiable change:
45
-
46
- 1. Start with the dependency or discovery work that determines later choices.
47
- 2. Group changes that must be edited and tested together; split unrelated work
48
- or work with different rollback risks.
49
- 3. End the round when its slice has a concrete result, a known blocker, or a
50
- machine-checkable next boundary. A round may be small when uncertainty or
51
- risk is high, and larger when the changes are tightly coupled.
52
- 4. Before submitting, check the actual diff, relevant tests, hard constraints,
53
- and what is still open. Do not mark the whole task complete because one
54
- slice is complete.
55
-
56
- For work that spans several rounds, declare a `round_contract` as a proposal for
57
- the next slice. Keep its `work_item` narrow, declare `items` that each bind a
58
- configured evidence command in `verify_with`, and constrain `scope` to the files
59
- or directories that slice may touch. The proposal becomes active only after the
60
- current round commits, and the prompt then renders its `rc-` / `rci-` ids. If
61
- the slice is blocked, report `outcome: "blocked"` with a concrete `blocker`; do
62
- not silently replace the active contract.
63
-
64
- This is a granularity preflight, not another gate: ask whether the slice has a
65
- clear boundary, evidence, and recovery path. LoopForge cannot see an implicit
66
- plan inside the model. It learns only from committed evaluation fields,
67
- Round Contract proposals, observed evidence, and the resulting changes. A
68
- reasonable split may therefore be revised by the next prompt, a verification
69
- finding, or a backtrack diagnosis.
23
+ - `task`: the complete user objective;
24
+ - `constraints`: hard boundaries that must survive every round;
25
+ - optional `maxRounds`, `domain`, `loopId`, and `planSource`.
26
+
27
+ Keep the returned `sessionId`, `roundId`, prompt, and level. Pass the latest
28
+ `roundId` to every `loopforge_next`; it anchors the submission to the exact
29
+ round being reported.
30
+
31
+ ## What is a round?
32
+
33
+ A round is one coherent work slice that can be described, checked, and
34
+ disposed of at the next boundary. It is not a fixed number of files, tokens,
35
+ commits, or minutes. A capable Agent may complete a large change in one round
36
+ when the change shares one objective, one evidence story, and one recovery
37
+ path. Split it when those boundaries diverge.
38
+
39
+ Before choosing the slice, ask:
40
+
41
+ 1. **Coherence:** does the work serve one immediate objective rather than
42
+ several unrelated goals?
43
+ 2. **Verifiability:** can the result and its hard constraints be checked with
44
+ the available tests, commands, or other machine observations?
45
+ 3. **Disposition:** will the boundary produce a clear continuation, stop,
46
+ blocker, rejection, or recovery decision?
47
+ 4. **Recovery:** can the slice be safely retried or rolled back without
48
+ invalidating unrelated work?
49
+
50
+ Make a round larger when changes are tightly coupled and can be verified
51
+ together. Make it smaller when uncertainty, external effects, evidence gaps,
52
+ or rollback risk is high. Do not combine independent objectives merely because
53
+ the Agent can edit them in one context. Do not split a single atomic change
54
+ only to create more round records.
55
+
56
+ At the end of a round, inspect the actual diff, relevant tests, hard
57
+ constraints, and remaining work. A completed slice is not the same as a
58
+ completed task.
59
+
60
+ ## Plan the next slice
61
+
62
+ For work that spans rounds, submit `round_contract` as a proposal for the next
63
+ slice. Keep `work_item` narrow, bind each item to a configured evidence command
64
+ with `verify_with`, and limit `scope` to files or directories that slice may
65
+ touch. The proposal becomes active only after its declaring round commits.
66
+ While it is open, restating the same proposal continues it; a different
67
+ proposal is ignored as `contract_premature`. If the slice is blocked, report
68
+ `outcome: "blocked"` with a concrete `blocker` instead of silently replacing
69
+ the active contract.
70
+
71
+ This is a planning aid, not a second gate. LoopForge learns the plan only from
72
+ committed evaluation fields, contract proposals, observations, and changes.
70
73
 
71
74
  ## Execute a round
72
75
 
73
- 1. Execute the returned prompt and do real repository work.
74
- 2. Use the tools and reasoning approach that fit the task.
76
+ 1. Execute the returned prompt and do the repository work.
77
+ 2. Use the tools and reasoning approach that fit the slice.
75
78
  3. Check actual evidence before claiming success.
76
- 4. Submit one structured `evaluation` with `loopforge_next`.
79
+ 4. Submit exactly one structured evaluation with `loopforge_next`.
80
+
81
+ After the strict boundary accepts the payload, LoopForge collects before/after
82
+ evidence, runs the **verification gate**, then runs the **enforcement gate**.
83
+ The verification gate checks evaluation consistency, evidence integrity, plan
84
+ and contract conformance, and progress and recovery. The enforcement gate
85
+ turns those findings into one disposition: accept, reject, backtrack, or
86
+ terminate.
77
87
 
78
88
  The four core evaluation fields are strict:
79
89
 
80
- | Field | Rule |
90
+ | Field | Requirement |
81
91
  | --- | --- |
82
- | `success` | Boolean. Use `true` only when the whole objective and every hard constraint are satisfied. |
83
- | `output_summary` | String. State what changed and what was verified this round. |
84
- | `constraint_violations` | Array of strings. Report real violations; prefer constraint IDs such as `c-XXXXXXXX`. |
85
- | `should_continue` | Boolean. Use `false` only when the entire task is complete. |
86
-
87
- All other evaluation fields are optional and normalized by LoopForge. Useful
88
- fields include `execution_report` (`files_changed`, `tests_reported`,
89
- `criterion_claims`, `contract_item_claims`, `progress_estimate`),
90
- `discovered_constraints`, `emerged_subtasks` (the only sub-goal creation
91
- channel — never an `sg-` ID; at most 50 entries, 500 characters each),
92
- `subgoal_updates` (explicit status transitions: active `sg-` IDs with a target
93
- status; done/canceled are terminal and never reopen), `prompt_requests`,
94
- `round_contract`, `retroactiveClaims`, `gate_ids` (only when the gate layer is
95
- enabled), and `worker_results` (entries need `agentId`, `subTask`,
96
- `resultSummary` and an `outcome` of `success` / `partial` / `failed`; entries
97
- missing any of these are dropped).
98
-
99
- The objective and the constraint set evolve only through your own reports:
100
- `objective_refinement` deepens the objective, `revised_success_criteria` (each
101
- entry `{old, new}`) replaces a criterion, `retracted_constraints` retires a
102
- constraint you now consider wrong, `wrong_assumptions` records what you
103
- believed and had to correct, and `compression_checkpoint` with a
104
- `checkpoint_label` marks a subtask boundary that forces a full-state prompt.
105
- `outcome` is the declared outcome (`success` / `partial` / `failed` /
106
- `blocked`) and `blocker` describes a `blocked` outcome; `stop_reason`
107
- (`"blocked"` or `"needs_human_input"`) is how you stop without claiming
108
- success. `no_change_reason` is the honest escape hatch for a round that
109
- genuinely produced no machine-verifiable work: it downgrades the "success with
110
- no machine evidence" finding to info, but only while NO enabled verification
111
- command is configured — a configured command closes that escape. It never
112
- excuses a success claim with no `execution_report` at all, and it never
113
- excuses a contract check: every successful round still needs `execution_report`
114
- with `files_changed` and `tests_reported`.
115
-
116
- Optional malformed values are ignored or defaulted — the Round Contract
117
- declaration, `contract_item_claims`, and `subgoal_updates` are the strict
118
- exceptions. They do not turn a valid submission into a transport error. Missing
119
- or mistyped core fields return `evaluation_invalid` with `details.missing` and
120
- `details.invalid`. Correct the payload and resubmit the same `roundId`. This
121
- does not save session state, write a round, enter either gate, increment
122
- rejection state, or record metrics.
123
-
124
- Minimal evaluation:
125
-
126
- ```json
127
- {
128
- "success": false,
129
- "output_summary": "Implemented the parser and added 8 passing tests.",
130
- "constraint_violations": [],
131
- "should_continue": true,
132
- "execution_report": {
133
- "files_changed": ["src/parser.ts", "tests/parser.test.ts"],
134
- "tests_reported": { "passed": 8, "failed": 0, "skipped": 0 },
135
- "criterion_claims": [
136
- { "criterion_id": "cr-b5a6c7d8", "outcome": "remaining" }
137
- ],
138
- "contract_item_claims": [
139
- { "item_id": "rci-9c8b7a65", "outcome": "met" }
140
- ],
141
- "progress_estimate": 0.4
142
- }
143
- }
144
- ```
145
-
146
- Everything in `execution_report` is your CLAIM, quoted back for audit — it never
147
- becomes a verified fact. Only machine observations create facts. Do not put a
148
- guessed evaluation in free text. The structured object is the authoritative
149
- submission; `output` is optional supporting context.
150
-
151
- If a submission warns that its `roundId` no longer matches, the reported round
152
- already committed. Use the returned held prompt and its `roundId` rather than
153
- submitting against a later round.
154
-
155
- ## Stable IDs and contracts
92
+ | `success` | Boolean. `true` only when the whole objective and hard constraints are satisfied. |
93
+ | `output_summary` | String describing what changed and what was verified. |
94
+ | `constraint_violations` | Array of real violations, preferably using `c-XXXXXXXX` IDs. |
95
+ | `should_continue` | Boolean. `false` only when the whole task is complete. |
96
+
97
+ Useful optional fields include `execution_report` (`files_changed`,
98
+ `tests_reported`, `criterion_claims`, `contract_item_claims`, and
99
+ `progress_estimate`), `discovered_constraints`, `emerged_subtasks`,
100
+ `subgoal_updates`, `prompt_requests`, `round_contract`, `retroactiveClaims`,
101
+ `gate_ids`, `worker_results`, and objective or constraint revisions.
102
+
103
+ `emerged_subtasks` is the only sub-goal creation channel. It contains plain
104
+ descriptions, never `sg-` IDs. `subgoal_updates` changes existing active IDs;
105
+ done and canceled are terminal and cannot be reopened.
106
+
107
+ `outcome` may be `success`, `partial`, `failed`, or `blocked`. A blocked
108
+ outcome needs a concrete `blocker`; `stop_reason` of `blocked` or
109
+ `needs_human_input` also stops without claiming success.
110
+
111
+ Optional malformed values are normalized or dropped. The strict exceptions are
112
+ `subgoal_updates`, `round_contract`, and
113
+ `execution_report.contract_item_claims`. Shape, reference, duplicate, command,
114
+ and workspace-containment errors return `evaluation_invalid` or
115
+ `contract_invalid` before advance. Correct the payload and resubmit the same
116
+ `roundId`; nothing is committed and no rejection counter moves.
117
+
118
+ Every successful round still needs an `execution_report` with
119
+ `files_changed` and `tests_reported`. `no_change_reason` is an escape only when
120
+ no enabled verification command exists. It never creates evidence and never
121
+ excuses an open contract.
122
+
123
+ Agent reports are claims quoted for audit. They never become verified facts.
124
+ Do not infer a missing field from natural language or put a guessed evaluation
125
+ in free text.
126
+
127
+ ## IDs and contracts
156
128
 
157
129
  Prompts render stable IDs beside constraints, criteria, sub-goals, and contract
158
- items:
159
-
160
- - Constraints: `[c-a3f2b1c0] No plaintext passwords`
161
- - Criteria: `[cr-b5a6c7d8] Unit test coverage >= 90%`
162
- - Sub-goals: `[sg-f1e2d3c4] Add error handling to login`
163
- - Contract items: `[rci-9c8b7a65] All parser edge cases covered`
164
-
165
- Prefer IDs for `constraint_violations` and criterion claims. A sub-goal ID is
166
- scoped to its declaration event: re-declaring the same text in a later round is
167
- a NEW sub-goal, so never reuse an old `sg-` ID for a fresh item. Sub-goal status
168
- changes REQUIRE exact ACTIVE `sg-` IDs via `subgoal_updates` — description
169
- matching is not a fallback there. Unknown, terminal (done/canceled), or illegal
170
- transitions return `evaluation_invalid` before the round advances: fix the
171
- payload and resubmit the same `roundId` (nothing is committed, no rejection
172
- counter moves).
173
-
174
- An optional `round_contract` is a proposal for the next round. It becomes
175
- active only after the declaring round commits, and it is then derived from
176
- committed rounds on every later compile. A contract is items, not prose:
177
-
178
- ```json
179
- {
180
- "work_item": "Harden the parser",
181
- "scope": ["src/parser.ts", "tests/parser.test.ts"],
182
- "items": [
183
- {
184
- "description": "All parser edge cases covered",
185
- "criterion_refs": ["cr-b5a6c7d8"],
186
- "subgoal_refs": ["sg-f1e2d3c4"],
187
- "verify_with": ["unit-tests"]
188
- }
189
- ]
190
- }
191
- ```
192
-
193
- Every item must bind at least one configured, enabled, after-capable evidence
194
- command in `verify_with`, and `scope` entries must stay inside the workspace.
195
- The runtime derives one `rci-XXXXXXXX` ID per item and an `rc-XXXXXXXX`
196
- contract ID from the proposal's content only — restating an unchanged contract
197
- keeps both, so keep citing the IDs the prompt rendered.
198
-
199
- `subgoal_refs` sits on the ITEM: an item the machine verifies backs exactly the
200
- sub-goals it names here. That is what produces a derived verified-sub-goal fact
201
- — and it never changes `SubGoal.status`, which stays your declaration.
202
-
203
- Item status is machine-derived: `pending` (never claimed met), `insufficient`
204
- (claimed `met`, not backed), `contradicted` (a bound command failed, or a
205
- passing command's entrypoint changed that round), `verified` (you claimed `met`
206
- AND every bound command was observed passing — after phase, entrypoint
207
- untampered, same command configuration as at declaration). Claim an item by
208
- citing its `rci-` ID in `execution_report.contract_item_claims`.
209
-
210
- A claim never creates a verified fact, and machine evidence can only go stale
211
- in one direction: the LATEST observation at or after your claim decides, so a
212
- command that passed early and FAILED in the closing round makes the item
213
- `contradicted` — a pass cannot outlive a later failure. Claimed-but-unbacked is
214
- `insufficient`: the round still commits and the debt is surfaced, but once the
215
- debt persists for `engine.unverified_claim_streak_limit` consecutive rounds
216
- (default 3) the round is rejected; a repeat of the SAME check rejects again with
217
- an escalation notice, and the third consecutive same-check rejection terminates
218
- the loop as `incomplete`.
219
-
220
- The contract closes when every item is `verified`, or when a round reports
221
- `outcome: "blocked"` with a `blocker`. While it is open, a DIFFERENT proposal is
222
- ignored (`contract_premature`) — restate the active contract unchanged to
223
- continue it. Git changes outside the declared `scope` are scope drift, a machine
224
- fact no explanation waives: revert the out-of-scope files, or close the contract
225
- with `outcome: "blocked"` and declare the extended scope in the same submission.
226
- Repeated drift terminates the loop.
227
-
228
- Declaration and item claims are a strict structural boundary — `contract_invalid`
229
- with a same-`roundId` retry and zero state change: a contract with no items, more
230
- items/scope/refs than the declared limits allow (20 items, 20 `criterion_refs`,
231
- 20 `subgoal_refs` and 20 commands per item, 50 `scope` entries), an item with no
232
- `verify_with`, an item naming an unknown, disabled, or non-after-capable
233
- command, a `scope` entry that is not a string or that leaves the workspace, a
234
- malformed `subgoal_refs` entry, a `subgoal_refs` ID that names no sub-goal of
235
- this loop (including a sub-goal beyond the 50-entry `emerged_subtasks` intake),
236
- and a malformed, duplicate, or unknown `contract_item_claims` entry.
237
- `criterion_claims` are advisory and lenient: an entry with an unknown or
238
- malformed criterion ID, or an outcome other than `met` / `remaining`, is
239
- dropped with a warning and never rejects the round.
240
-
241
- The commands `verify_with` may name are the ones your `loop_policy.json`
242
- declares under `evidence.commands` and enables there; the runtime runs them
243
- itself, without a shell, inside the workspace. An item whose bound command
244
- changed configuration since the contract was declared is `insufficient`, not
245
- `verified` — the declaration stamps the command configuration it was made
246
- under.
247
-
248
- ## Backtrack
249
-
250
- A progress stall can trigger backtrack to the last clean committed round — the
251
- most recent committed round with no error-level verification flags. The stall
252
- window is 3 committed rounds (the breaker tier that follows it uses
253
- `engine.stall_lookback_rounds`, default 3), and the verdict is MACHINE-first:
254
- when git observations exist for the window, machine motion alone decides it,
255
- and your `progress_estimate` does not enter — a rising estimate cannot cancel a
256
- stall, and git motion can only excuse one (it never creates one). Your reported
257
- estimates are consulted only when the loop has no machine history to read (no
258
- git provider, or fewer rounds than the window). One machine fact is exempt by
259
- construction: a round whose success the machine verified is finishing, not
260
- churning — the closing round of a loop often changes no files at all. So the way
261
- out of a stall is real, observable work.
262
-
263
- The backtrack commits a rollback directive that stays out of final history:
264
- your next submission is the REDO of round `restorePoint + 1` and must reuse the
265
- round ID the prompt carries; when it commits, the rollback record is replaced
266
- and disappears from history views.
267
-
268
- The backtrack prompt opens with a derived **Recovery Brief**:
269
-
270
- - the trigger rule and the restore point;
271
- - the redo round's ID (pass it back unchanged to `loopforge_next`);
272
- - the failed rounds and their approaches — what must NOT be repeated;
273
- - falsified assumptions — do not rebuild on these;
274
- - discoveries from the skipped rounds that remain valid;
275
- - the files to revert and the HEAD the workspace must return to. The prompt
276
- states these as FACTS and never prescribes a command — the restore is yours
277
- to perform, by whatever means you judge best.
278
-
279
- The same brief renders in `.loopforge/state/<loopId>-state.md` under Recent
280
- while the recovery window is open; it is derived from committed rounds plus
281
- the in-flight attempt (rejected payloads are never a source) and disappears
282
- once the redo commits.
130
+ items. Prefer those IDs for `constraint_violations`, criterion claims, status
131
+ updates, and item claims.
132
+
133
+ A sub-goal ID belongs to its declaration event. Re-declaring the same text in a
134
+ later round creates a new sub-goal. Status changes require the exact active
135
+ `sg-` ID; description matching is not a fallback.
136
+
137
+ A Round Contract is a set of evidence-bound items, not prose. Each item must
138
+ bind at least one configured, enabled, after-capable command. The runtime
139
+ derives content-addressed `rc-XXXXXXXX` and `rci-XXXXXXXX` IDs, so restating an
140
+ unchanged proposal keeps its identity. `subgoal_refs` belongs on the item; a
141
+ machine-verified item backs exactly the sub-goals it names, without changing
142
+ their declared `SubGoal.status`.
143
+
144
+ Item status is machine-derived:
145
+
146
+ - `pending`: not claimed as met;
147
+ - `insufficient`: claimed as met but not backed by all required observations;
148
+ - `contradicted`: a bound observation fails, or its entrypoint/configuration is
149
+ no longer trustworthy;
150
+ - `verified`: the Agent claims `met`, every bound command passes in the closing
151
+ round's after phase, and the declaration binding remains intact.
152
+
153
+ The contract closes only when every item is `verified` or a round reports
154
+ `outcome: "blocked"`. Repeated unbacked claims create bounded verification
155
+ debt. The same-check streak escalates at
156
+ `engine.unverified_claim_streak_limit` (default 3) instead of retrying forever.
157
+
158
+ Sub-goals may evolve during execution. LoopForge does not use fuzzy intent or
159
+ similarity to judge drift. The enforced boundary is contract `scope`: work
160
+ outside it is `round_scope_drift`, a machine fact no explanation waives. Revert
161
+ the out-of-scope change, or close the contract as blocked and declare the
162
+ expanded scope in a new proposal.
163
+
164
+ ## Backtrack and recovery
165
+
166
+ A progress stall is machine-first when Git history is observable over the
167
+ lookback window. Self-reported `progress_estimate` is only a fallback when
168
+ machine history cannot be read. Machine motion can excuse a stall but cannot
169
+ create one. A machine-backed success round is finishing, even if its closing
170
+ round changes no files.
171
+
172
+ Backtrack records a rollback directive and restores the round counter to the
173
+ last clean committed round. Rejected attempts are never history. The next
174
+ submission is the redo of `restorePoint + 1` and must reuse the prompt's round
175
+ ID. A successful redo retires the rollback record.
176
+
177
+ The Recovery Brief identifies the trigger, restore point, redo ID, failed
178
+ approaches, falsified assumptions, valid discoveries, files to revert, and
179
+ target HEAD. It states restoration facts, not a prescribed command.
283
180
 
284
181
  When backtrack occurs:
285
182
 
286
- 1. Restore the workspace exactly as requested before doing more work — the
287
- next submission's git evidence is checked against the restore point's HEAD.
288
- 2. Read the Recovery Brief, the restored prompt, and the derived state.
289
- 3. Do not repeat a failed approach listed in the brief without addressing it.
290
- 4. Keep valid discoveries from skipped rounds in later evaluations.
183
+ 1. Restore the workspace exactly as requested before doing more work.
184
+ 2. Read the Recovery Brief, restored prompt, and derived state.
185
+ 3. Do not repeat a failed approach without addressing its cause.
186
+ 4. Carry valid discoveries into later evaluations.
291
187
 
292
- If the workspace is not restored, the next submission is rejected with
293
- `backtrack_workspace_not_restored`.
294
-
295
- When the rolled-back rounds executed under an ACTIVE contract, the redo follows
296
- the contract path instead of a plain retry: close the stalled contract in the
297
- redo submission with `outcome: "blocked"` plus a `blocker` explaining why it
298
- stalled, and declare the REVISED contract in the same submission. Restating the
299
- stalled contract unchanged keeps it active and commits more of the same, and a
300
- different proposal while an old contract is still open is ignored as
301
- `contract_premature`.
188
+ If the rolled-back work used an active contract, close the stalled contract in
189
+ the redo with `outcome: "blocked"` and declare the revised contract in that
190
+ same submission. Restating the stalled contract commits more of the same.
302
191
 
303
192
  ## Interpret results
304
193
 
305
- - `prompt` is non-null: execute it and submit the next evaluation.
306
- - `enforcementAction: "reject"`: redo the same logical round. The round ID is
307
- stable and the attempt increases.
194
+ - Non-null `prompt`: execute it and submit the next evaluation.
195
+ - `enforcementAction: "reject"`: retry the same logical round and ID; the
196
+ attempt increases.
308
197
  - `enforcementAction: "backtrack"`: restore the workspace, then continue from
309
198
  the restored prompt and round.
310
- - `prompt` is null: inspect `stopReason`.
311
-
312
- Each response also carries the posture of the round that just committed:
313
- `verificationStatus` (`trusted` when everything you claimed is machine-backed,
314
- `insufficient` when claims are unbacked but nothing is denied, `contradicted`
315
- when a machine fact denies a claim — it is never a judgement about the quality
316
- of your work), `roundSuccess`, `level`, and `warnings`. `enforcementReason`
317
- explains a rejection or termination. Read these before planning the next round:
318
- an `insufficient` posture is a statement about evidence, not about effort.
319
-
320
- Errors arrive as `{ok: false, error: {code, message, retryable, ...}}`. `code` is
321
- stable — branch on it, not on the prose in `message`. `evaluation_invalid`,
322
- `contract_invalid`, `policy_invalid`, `round_id_required`, `round_id_mismatch`,
323
- and `invalid_argument` are `retryable`: fix the payload and resubmit the same
324
- `roundId`. `state_unavailable` means the record you asked for is not there (no
325
- audit data for that loop, no such gate record), `session_not_found` that the
326
- session is gone: state conditions, not payload defects — do not resubmit the
327
- same payload hoping for a different answer. `gate_disabled` means the gate layer
328
- is off in this policy, and `loop_already_running` that a session for this loop
329
- already exists in this process — inspect or resume it instead of starting a
330
- duplicate.
331
-
332
- `completed` means the machine verified the completion: success plus every
333
- contract item `verified`, or no active contract. An explicit `outcome:
334
- "blocked"` (or `stop_reason: "blocked"` / `"needs_human_input"`) always stops as
335
- `blocked`, never as `completed`. `incomplete` means you stopped while the
336
- machine could not verify completion — claims the bound commands did not back;
337
- contract verification debt that persisted past
338
- `engine.unverified_claim_streak_limit` also ends here rather than accepting
339
- another unverified round. `failed` means the Agent gave up. `max_rounds` is the
340
- safety limit. `stalled` means the runtime could not produce the next round's
341
- prompt. `enforcement_terminated` means repeated integrity failures reached a
342
- terminal ladder. `paused` means the durable session remains available for
343
- resume, and `cancelled` that the session was deleted.
199
+ - Null `prompt`: inspect `stopReason`.
200
+
201
+ Read `verificationStatus`, `roundSuccess`, `level`, `warnings`, and
202
+ `enforcementReason` before planning the next slice. `trusted` means claimed
203
+ work is machine-backed, `insufficient` means evidence is missing, and
204
+ `contradicted` means a machine fact denies a claim. These are evidence
205
+ postures, not subjective quality scores.
206
+
207
+ Errors use `{ok: false, error: {code, message, retryable, ...}}`. Branch on the
208
+ stable `code`, not the prose in `message`. Payload errors such as
209
+ `evaluation_invalid`, `contract_invalid`, `policy_invalid`, and round-ID
210
+ errors are retryable with the same ID. `session_not_found`, `state_unavailable`,
211
+ and `gate_disabled` describe state or policy; do not blindly resubmit.
212
+
213
+ `completed` means success plus every active contract item is `verified`, or
214
+ there is no active contract. Explicit `blocked` always wins over success.
215
+ `incomplete` means completion was not machine-verified. Other terminal reasons
216
+ include `failed`, `max_rounds`, `stalled`, `enforcement_terminated`, `paused`,
217
+ and `cancelled`.
344
218
 
345
219
  ## Prompt levels and views
346
220
 
347
- L0 is a lean same-round retry, L1 is normal continuation, and L2 is full
348
- rehydration. They control state density only and never prescribe a reasoning
349
- technique. L2 is chosen from FACTS about the round — the first round, a plan or
350
- checkpoint boundary, a committed recovery, a machine contradiction, a repeated
351
- rejection, a changed objective, a previous state the runtime can no longer read
352
- — never from a round counter, so nothing changes in the prompt just because the
353
- loop has been running for a while. Protected prompt sections and
354
- the token budget remain enforced; when the protected content alone exceeds the
355
- ceiling the prompt records `protectedOverflow` rather than dropping it, and
356
- which sections were rendered is recorded in the prompt artifact.
357
-
358
- Use `loopforge_status` with `view: "session"` for the live round and typed
359
- projection, `view: "loop"` for machine counts over committed rounds, `view: "all"`
360
- after a restart, `view: "audit"` for the read-only completeness and evidence
361
- audit, and `view: "explain"` (loopId, optional `round`) for the per-round "why"
362
- view — the active contract, item statuses, observations, and flags. The same
363
- view is available from the CLI as `loopforge explain LOOP_ID [--round N]
364
- [--json]`. Use `loopforge_replay` for the committed timeline and round diffs.
365
- Replay answers what happened; Audit checks whether facts and claims are
366
- supported; Explain shows why a round was decided the way it was.
367
-
368
- The optional `.loopforge/state/<loopId>-state.md` file is derived and can be
369
- regenerated. In L2 the prompt may omit the full markdown state and point at
370
- that file instead (pointer mode), so read it when the prompt says so — but it
371
- is a derived view, never an independent source of truth.
372
-
373
- ## Control and delegation
374
-
375
- Use `loopforge_pause` before an intentional interruption,
221
+ L0 is a lean same-round retry, L1 normal continuation, and L2 full
222
+ rehydration. They control state density only, never a reasoning technique. L2
223
+ comes from round facts such as the first round, a plan or checkpoint boundary,
224
+ recovery, contradiction, or repeated rejection. It is not a round-count timer.
225
+
226
+ Use `loopforge_status` with `view: "session"` for the live round,
227
+ `view: "loop"` for committed health, `view: "all"` after a restart,
228
+ `view: "audit"` for completeness and evidence, and `view: "explain"` for a
229
+ round's active contract, observations, flags, and decision. Use
230
+ `loopforge_replay` for the committed timeline and diffs.
231
+
232
+ The optional `.loopforge/state/<loopId>-state.md` is derived and regenerable.
233
+ Read it when an L2 prompt points to it, but never treat it as a second source
234
+ of truth.
235
+
236
+ ## Gates and delegation
237
+
238
+ Use `loopforge_pause` for an intentional interruption,
376
239
  `loopforge_resume` to reconstruct a durable session, and `loopforge_stop` only
377
240
  for an intentional terminal stop.
378
241
 
379
- The two gate tools are opt-in (`policy.gate.enabled`, default false) and are
380
- hidden from `tools/list` when disabled (a direct call then returns
381
- `gate_disabled`). When enabled, preflight a high-risk action with
382
- `loopforge_gate_check`, whose `action` is a structured descriptor:
383
-
384
- - `description`: what the action does ("Deploy to production");
385
- - `scope`: files, systems or services it touches;
386
- - `effects`: any of `workspace_write`, `production`, `credentials`,
387
- `data_migration`, `public_api`, `publish`, `payment`,
388
- `external_communication`, `network`;
389
- - `reversibility`: `reversible` / `recoverable` / `irreversible` / `unknown`;
390
- - `authorization`: `agent_allowed` / `user_required` / `unknown`.
391
-
392
- Classification is conservative: anything not provably safe is `user_required`,
393
- which returns a gate id and an approval question. Present that question to the
394
- human, record their decision with `loopforge_gate_resolve`, and cite the
395
- approved gate id via `evaluation.gate_ids` in the round that performs the
396
- action — an unapproved or unknown cited gate rejects the round. Safe
397
- preparation work (investigation, dry-runs, rollback evidence) never needs a
398
- gate. Remember: approval is recorded through you, the Agent — LoopForge cannot
399
- machine-verify a human is present.
400
-
401
- Delegation does not create a separate LoopForge mode. Give each worker a
402
- self-contained subtask and relevant hard constraints, then place its result in
403
- `worker_results` so discoveries can enter the next Canonical State.
242
+ The two gate tools are opt-in through `policy.gate.enabled`. When enabled,
243
+ `loopforge_gate_check` preflights a structured action with its description,
244
+ scope, effects, reversibility, and authorization. Classification is
245
+ conservative: anything not provably safe becomes `user_required`. Present the
246
+ approval question, record the decision with `loopforge_gate_resolve`, and cite
247
+ the approved gate ID in `evaluation.gate_ids`. LoopForge records the process,
248
+ but cannot prove that a human was present because the Agent submits the resolve
249
+ call. Safe investigation and dry-runs need no gate.
250
+
251
+ Delegation does not create another LoopForge mode. Give each worker a
252
+ self-contained subtask and hard constraints, then place the result in
253
+ `worker_results` so it can enter the next Canonical State.
404
254
 
405
255
  ## Rules
406
256
 
407
257
  1. Execute the prompt instead of generating another prompt.
408
258
  2. Submit one honest structured evaluation after each attempt.
409
- 3. Restore the workspace before working after backtrack.
410
- 4. Treat required command evidence and verification errors as authoritative.
259
+ 3. Treat required command evidence and verification findings as authoritative.
260
+ 4. Restore the workspace before working after backtrack.
411
261
  5. Keep one loop focused on one user objective.
412
262
  6. Do not advance a paused or stopped session through another process.
413
- 7. Continue within the same Agent task when possible. LoopForge preserves state
414
- but does not create a background Agent.
263
+ 7. Continue in the same Agent task when possible. LoopForge preserves state but
264
+ does not create a background Agent.