loopforge 1.15.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +172 -95
  2. package/dist/backends/interface.d.ts +3 -9
  3. package/dist/backends/interface.d.ts.map +1 -1
  4. package/dist/backends/interface.js +1 -5
  5. package/dist/backends/interface.js.map +1 -1
  6. package/dist/canonical-state.d.ts +53 -0
  7. package/dist/canonical-state.d.ts.map +1 -0
  8. package/dist/canonical-state.js +161 -0
  9. package/dist/canonical-state.js.map +1 -0
  10. package/dist/cli.d.ts +4 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +227 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/enforcement-gate.d.ts.map +1 -1
  15. package/dist/enforcement-gate.js +28 -10
  16. package/dist/enforcement-gate.js.map +1 -1
  17. package/dist/engine.d.ts +7 -4
  18. package/dist/engine.d.ts.map +1 -1
  19. package/dist/engine.js +78 -138
  20. package/dist/engine.js.map +1 -1
  21. package/dist/evidence-provider.d.ts +113 -0
  22. package/dist/evidence-provider.d.ts.map +1 -0
  23. package/dist/evidence-provider.js +419 -0
  24. package/dist/evidence-provider.js.map +1 -0
  25. package/dist/index.d.ts +18 -10
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +15 -9
  28. package/dist/index.js.map +1 -1
  29. package/dist/init.d.ts +15 -0
  30. package/dist/init.d.ts.map +1 -0
  31. package/dist/init.js +49 -0
  32. package/dist/init.js.map +1 -0
  33. package/dist/interop.d.ts +30 -0
  34. package/dist/interop.d.ts.map +1 -0
  35. package/dist/interop.js +29 -0
  36. package/dist/interop.js.map +1 -0
  37. package/dist/loop-compiler.d.ts +14 -64
  38. package/dist/loop-compiler.d.ts.map +1 -1
  39. package/dist/loop-compiler.js +303 -2206
  40. package/dist/loop-compiler.js.map +1 -1
  41. package/dist/loop-store.d.ts +82 -0
  42. package/dist/loop-store.d.ts.map +1 -0
  43. package/dist/loop-store.js +332 -0
  44. package/dist/loop-store.js.map +1 -0
  45. package/dist/mcp/server.d.ts +9 -6
  46. package/dist/mcp/server.d.ts.map +1 -1
  47. package/dist/mcp/server.js +109 -73
  48. package/dist/mcp/server.js.map +1 -1
  49. package/dist/mcp/session.d.ts +75 -19
  50. package/dist/mcp/session.d.ts.map +1 -1
  51. package/dist/mcp/session.js +707 -361
  52. package/dist/mcp/session.js.map +1 -1
  53. package/dist/mcp/tools.d.ts +18 -268
  54. package/dist/mcp/tools.d.ts.map +1 -1
  55. package/dist/mcp/tools.js +225 -12
  56. package/dist/mcp/tools.js.map +1 -1
  57. package/dist/observability.d.ts +36 -16
  58. package/dist/observability.d.ts.map +1 -1
  59. package/dist/observability.js +82 -23
  60. package/dist/observability.js.map +1 -1
  61. package/dist/policy-metrics.d.ts +46 -0
  62. package/dist/policy-metrics.d.ts.map +1 -0
  63. package/dist/policy-metrics.js +146 -0
  64. package/dist/policy-metrics.js.map +1 -0
  65. package/dist/policy.d.ts +53 -140
  66. package/dist/policy.d.ts.map +1 -1
  67. package/dist/policy.js +119 -184
  68. package/dist/policy.js.map +1 -1
  69. package/dist/prompt-assembler.d.ts +30 -0
  70. package/dist/prompt-assembler.d.ts.map +1 -0
  71. package/dist/prompt-assembler.js +257 -0
  72. package/dist/prompt-assembler.js.map +1 -0
  73. package/dist/prompt-policy.d.ts +29 -0
  74. package/dist/prompt-policy.d.ts.map +1 -0
  75. package/dist/prompt-policy.js +51 -0
  76. package/dist/prompt-policy.js.map +1 -0
  77. package/dist/protocol.d.ts +88 -93
  78. package/dist/protocol.d.ts.map +1 -1
  79. package/dist/protocol.js +23 -39
  80. package/dist/protocol.js.map +1 -1
  81. package/dist/replay.d.ts.map +1 -1
  82. package/dist/replay.js +1 -27
  83. package/dist/replay.js.map +1 -1
  84. package/dist/round-coordinator.d.ts +90 -0
  85. package/dist/round-coordinator.d.ts.map +1 -0
  86. package/dist/round-coordinator.js +186 -0
  87. package/dist/round-coordinator.js.map +1 -0
  88. package/dist/round-driver.d.ts +53 -0
  89. package/dist/round-driver.d.ts.map +1 -0
  90. package/dist/round-driver.js +101 -0
  91. package/dist/round-driver.js.map +1 -0
  92. package/dist/round-transaction.d.ts +70 -0
  93. package/dist/round-transaction.d.ts.map +1 -0
  94. package/dist/round-transaction.js +290 -0
  95. package/dist/round-transaction.js.map +1 -0
  96. package/dist/runtime.d.ts +33 -19
  97. package/dist/runtime.d.ts.map +1 -1
  98. package/dist/runtime.js +355 -336
  99. package/dist/runtime.js.map +1 -1
  100. package/dist/storage.d.ts +38 -0
  101. package/dist/storage.d.ts.map +1 -0
  102. package/dist/storage.js +201 -0
  103. package/dist/storage.js.map +1 -0
  104. package/dist/verification-gate.d.ts +33 -7
  105. package/dist/verification-gate.d.ts.map +1 -1
  106. package/dist/verification-gate.js +195 -7
  107. package/dist/verification-gate.js.map +1 -1
  108. package/loop_policy.json +22 -48
  109. package/package.json +13 -10
  110. package/skills/perception/SKILL.md +80 -267
  111. package/dist/backends/fs.d.ts +0 -36
  112. package/dist/backends/fs.d.ts.map +0 -1
  113. package/dist/backends/fs.js +0 -362
  114. package/dist/backends/fs.js.map +0 -1
  115. package/dist/builder.d.ts +0 -19
  116. package/dist/builder.d.ts.map +0 -1
  117. package/dist/builder.js +0 -215
  118. package/dist/builder.js.map +0 -1
  119. package/dist/mcp-server.d.ts +0 -12
  120. package/dist/mcp-server.d.ts.map +0 -1
  121. package/dist/mcp-server.js +0 -14
  122. package/dist/mcp-server.js.map +0 -1
  123. package/dist/memory-bridge.d.ts +0 -47
  124. package/dist/memory-bridge.d.ts.map +0 -1
  125. package/dist/memory-bridge.js +0 -290
  126. package/dist/memory-bridge.js.map +0 -1
  127. package/dist/tests/_helpers.d.ts +0 -25
  128. package/dist/tests/_helpers.d.ts.map +0 -1
  129. package/dist/tests/_helpers.js +0 -47
  130. package/dist/tests/_helpers.js.map +0 -1
  131. package/dist/tests/builder.test.d.ts +0 -2
  132. package/dist/tests/builder.test.d.ts.map +0 -1
  133. package/dist/tests/builder.test.js +0 -112
  134. package/dist/tests/builder.test.js.map +0 -1
  135. package/dist/tests/enforcement-gate.test.d.ts +0 -2
  136. package/dist/tests/enforcement-gate.test.d.ts.map +0 -1
  137. package/dist/tests/enforcement-gate.test.js +0 -328
  138. package/dist/tests/enforcement-gate.test.js.map +0 -1
  139. package/dist/tests/engine.test.d.ts +0 -2
  140. package/dist/tests/engine.test.d.ts.map +0 -1
  141. package/dist/tests/engine.test.js +0 -375
  142. package/dist/tests/engine.test.js.map +0 -1
  143. package/dist/tests/generate-schema.test.d.ts +0 -8
  144. package/dist/tests/generate-schema.test.d.ts.map +0 -1
  145. package/dist/tests/generate-schema.test.js +0 -199
  146. package/dist/tests/generate-schema.test.js.map +0 -1
  147. package/dist/tests/loop-compiler.test.d.ts +0 -2
  148. package/dist/tests/loop-compiler.test.d.ts.map +0 -1
  149. package/dist/tests/loop-compiler.test.js +0 -1059
  150. package/dist/tests/loop-compiler.test.js.map +0 -1
  151. package/dist/tests/mcp.test.d.ts +0 -7
  152. package/dist/tests/mcp.test.d.ts.map +0 -1
  153. package/dist/tests/mcp.test.js +0 -505
  154. package/dist/tests/mcp.test.js.map +0 -1
  155. package/dist/tests/memory-bridge.test.d.ts +0 -8
  156. package/dist/tests/memory-bridge.test.d.ts.map +0 -1
  157. package/dist/tests/memory-bridge.test.js +0 -383
  158. package/dist/tests/memory-bridge.test.js.map +0 -1
  159. package/dist/tests/policy.test.d.ts +0 -2
  160. package/dist/tests/policy.test.d.ts.map +0 -1
  161. package/dist/tests/policy.test.js +0 -49
  162. package/dist/tests/policy.test.js.map +0 -1
  163. package/dist/tests/protocol.test.d.ts +0 -2
  164. package/dist/tests/protocol.test.d.ts.map +0 -1
  165. package/dist/tests/protocol.test.js +0 -73
  166. package/dist/tests/protocol.test.js.map +0 -1
  167. package/dist/tests/replay.test.d.ts +0 -2
  168. package/dist/tests/replay.test.d.ts.map +0 -1
  169. package/dist/tests/replay.test.js +0 -222
  170. package/dist/tests/replay.test.js.map +0 -1
  171. package/dist/tests/runtime.test.d.ts +0 -7
  172. package/dist/tests/runtime.test.d.ts.map +0 -1
  173. package/dist/tests/runtime.test.js +0 -337
  174. package/dist/tests/runtime.test.js.map +0 -1
  175. package/dist/tests/verification-gate.test.d.ts +0 -2
  176. package/dist/tests/verification-gate.test.d.ts.map +0 -1
  177. package/dist/tests/verification-gate.test.js +0 -407
  178. package/dist/tests/verification-gate.test.js.map +0 -1
  179. package/skills/prompt-techniques/SKILL.md +0 -52
  180. package/skills/prompt-techniques/references/chain-of-thought.md +0 -207
  181. package/skills/prompt-techniques/references/few-shot.md +0 -174
  182. package/skills/prompt-techniques/references/least-to-most.md +0 -182
  183. package/skills/prompt-techniques/references/step-back.md +0 -160
  184. package/skills/prompt-techniques/references/tree-of-thought.md +0 -191
  185. package/skills/prompt-techniques/references/zero-shot.md +0 -97
@@ -1,305 +1,118 @@
1
1
  ---
2
2
  name: perception
3
- description: Multi-round autonomous loop driver powered by LoopForge MCP. Compiles context-aware prompts per iteration, tracks quality, inherits constraints, and stops when work is done — not when rounds run out. Supports single-agent and multi-agent (AgentTool / Coordinator) scenarios.
3
+ description: Drive a recoverable multi-round coding task through LoopForge MCP while the Agent remains the execution owner.
4
4
  ---
5
5
 
6
- # Perception — Loop-Time Intelligence Skill
6
+ # Perception
7
7
 
8
- **Perception** turns any AI agent into a self-aware multi-round executor. It
9
- drives the LoopForge MCP server (`loopforge-mcp`) to compile per-iteration
10
- prompts from running success trajectory, constraint inheritance, and drift
11
- detection — maintaining cognitive stability across long-horizon loops.
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.
12
11
 
13
- Works with Claude Code, Codex, and any MCP-capable host. Zero configuration
14
- beyond having `loopforge-mcp` registered as an MCP server.
12
+ LoopForge maintains cognitive state. You remain the Agent that reads files,
13
+ edits code, runs commands, delegates work, and decides how to reason.
15
14
 
16
- **Multi-Agent:** When you spawn sub-agents (AgentTool) or orchestrate Workers
17
- (Coordinator mode), LoopForge tracks delegation history, inherits constraints
18
- across Workers, and injects structured summaries into subsequent prompts.
19
- No separate mode required — LoopForge treats all agents the same.
15
+ ## Start
20
16
 
21
- ## When to Activate
17
+ Call `loopforge_start` with:
22
18
 
23
- Activate when the user says any of:
24
- - `/perception <task>` — start an autonomous multi-round loop
25
- - "do this in a loop", "keep going until done", "iterate on this"
26
- - Any task that clearly needs 3+ rounds (audit, refactor, migrate, review-and-fix cycles)
19
+ - `task`: the complete user objective.
20
+ - `constraints`: hard boundaries that must survive every round.
21
+ - `maxRounds`: optional safety limit. The default is 20.
22
+ - `domain`: optional context label.
27
23
 
28
- Also activate implicitly when the user's request is too large for a single
29
- round (e.g. "audit the entire codebase and fix every issue").
24
+ Keep the returned `sessionId`, `roundId`, prompt, and level.
30
25
 
31
- ## Core Workflow
26
+ ## Execute a round
32
27
 
33
- ```
34
- ┌──────────────────────────────────────────────────────────┐
35
- │ 1. loopforge_start(task, constraints, maxRounds) │
36
- │ → sessionId + Round 1 prompt │
37
- │ │
38
- │ 2. Execute the prompt (read, write, test, fix) │
39
- │ Prepare a structured self-evaluation │
40
- │ │
41
- │ 3. loopforge_next(sessionId, evaluation, output?) │
42
- │ → if prompt: go to step 2 │
43
- │ → if prompt=null: loop ended, read stopReason │
44
- │ │
45
- │ After restart: loopforge_resume(loopId) │
46
- │ → picks up from last saved round │
47
- └──────────────────────────────────────────────────────────┘
48
- ```
49
-
50
- ### Step-by-step
51
-
52
- **Step 1 — Start the loop:**
53
- ```
54
- Call loopforge_start with:
55
- task: required — the full task description
56
- maxRounds: optional — default 20 from policy
57
- constraints: optional — hard constraints as string[]
58
- domain: optional — domain hint (solidity, react, rust…)
59
-
60
- Keep the returned sessionId — you will need it for every subsequent call.
61
- ```
62
-
63
- **Step 2 — Execute the round:**
64
- - **BEFORE executing the prompt**: Read `.loopforge/state/{loopId}-state.md`
65
- for the loop's accumulated state — objective, constraints, progress, and
66
- cross-round summary. This file is rewritten each round and is the single
67
- source of truth for loop state. The prompt references this file; you must
68
- read it to know the active constraints and progress.
69
- - Execute the compiled prompt exactly as you would any user task. Read files,
70
- write code, run tests, fix bugs.
28
+ 1. Execute the returned prompt. Do real repository work.
29
+ 2. Use the available tools and reasoning approach that best fit the task.
30
+ 3. Check actual evidence before claiming success.
31
+ 4. Call `loopforge_next` with `sessionId` and a structured `evaluation`.
71
32
 
72
- After executing, prepare a structured self-evaluation. Pass it as the
73
- `evaluation` parameter to `loopforge_next` — do NOT embed it as a text block
74
- in the output. The `evaluation` parameter is a typed object with the fields
75
- described below.
33
+ Minimal evaluation:
76
34
 
77
- **New (v1.7+): Pass evaluation as a structured tool parameter.**
78
35
  ```json
79
36
  {
80
- "success": true,
81
- "output_summary": "Fixed 3 reentrancy bugs in withdraw() and deposit(). All 12 tests pass.",
37
+ "success": false,
38
+ "output_summary": "Implemented the parser and added 8 passing tests.",
82
39
  "constraint_violations": [],
83
- "should_continue": true,
84
- "discovered_constraints": [],
85
- "objective_refinement": "",
86
- "emerged_subtasks": [],
87
- "execution_evidence": {
88
- "files_changed": ["contracts/Token.sol", "test/Token.test.ts"],
89
- "test_results": {"passed": 24, "failed": 0, "skipped": 0},
90
- "success_criteria_met": ["No reentrancy vectors remain"],
91
- "success_criteria_remaining": ["Access control verified", "Overflow checks complete"],
92
- "progress_estimate": 0.4
93
- },
94
- "retracted_constraints": [],
95
- "revised_success_criteria": [],
96
- "wrong_assumptions": []
40
+ "should_continue": true
97
41
  }
98
42
  ```
99
43
 
100
- **Legacy (still supported):** Embed a `---loopforge-eval` block in output text
101
- when the agent cannot pass structured tool parameters. The new parameter form
102
- is preferred — it's validated by the MCP client before reaching the server.
44
+ Important fields:
103
45
 
104
- **Field rules:**
46
+ | Field | Rule |
47
+ | --- | --- |
48
+ | `success` | Use `true` only when the whole objective and every hard constraint are satisfied. |
49
+ | `output_summary` | State what changed and what was verified. |
50
+ | `constraint_violations` | Report real violations. Do not hide them to force progress. |
51
+ | `should_continue` | Use `false` only when the entire task is complete. |
52
+ | `execution_evidence` | Report changed files, test counts, met and remaining criteria, and progress when known. |
53
+ | `discovered_constraints` | Add newly discovered guardrails. |
54
+ | `objective_refinement` | Refine the objective when repository evidence changes its meaning. |
55
+ | `wrong_assumptions` | Record assumptions disproved this round. |
56
+ | `worker_results` | Record delegated subtask results and discoveries. |
105
57
 
106
- | Field | Type | Rule |
107
- |-------|------|------|
108
- | `success` | boolean | `true` ONLY if all hard constraints met AND the task goal achieved |
109
- | `output_summary` | string | Specific, actionable. What was DONE this round — not what was attempted |
110
- | `constraint_violations` | string[] | Constraints the agent actually violated this round. Be honest — hiding violations corrupts the success signal and defeats the circuit breaker |
111
- | `should_continue` | boolean | `false` ONLY when the ENTIRE task is complete. Partial progress = `true` |
112
- | `discovered_constraints` | string[] | **P0 (optional)** — New constraints discovered this round. They become active guardrails for future rounds. Example: `["All external calls must use SafeERC20"]`. Empty `[]` if none. |
113
- | `objective_refinement` | string | **P1 (optional)** — If this round deepened your understanding of what the task is really about, describe the refinement. APPENDED to (never replaces) the original objective. Empty `""` if unchanged. |
114
- | `emerged_subtasks` | string[] | **P2 (optional)** — Sub-problems that surfaced during execution and need separate attention. Feed into next-round task suggestions. Example: `["Audit upgrade proxy", "Verify timelock"]`. Empty `[]` if none. |
115
- | `execution_evidence` | object | **P4 (recommended)** — Structured record of what actually happened. `files_changed` (string[]), `test_results` ({passed, failed, skipped} | null), `success_criteria_met` (string[]), `success_criteria_remaining` (string[]), `progress_estimate` (0.0–1.0). Use this to give LoopForge real visibility into your progress. |
116
- | `retracted_constraints` | string[] | **P5 (optional)** — Constraints you now believe are wrong. Removed from active guardrails. Only retract with evidence. Empty `[]` if none. |
117
- | `revised_success_criteria` | object[] | **P5 (optional)** — Success criteria that need reformulation. Array of `{old: string, new: string}`. Applied to Loop Objective. Empty `[]` if none. |
118
- | `wrong_assumptions` | string[] | **P5 (optional)** — Assumptions from earlier rounds that turned out to be incorrect. Recorded as key lessons. Empty `[]` if none. |
119
- | `worker_results` | object[] | **Multi-Agent (optional)** — Results of sub-agent / Worker delegations this round. Each entry: `{ agentId, subAgentType, subTask, resultSummary, success, discoveredConstraints? }`. Engine auto-records to delegation journal. Empty `[]` if no delegations. |
58
+ Do not embed an evaluation marker in ordinary output when the MCP client accepts
59
+ the structured `evaluation` argument.
120
60
 
121
- **Why this matters:** The evaluation is validated by the MCP client before
122
- reaching the server — a missing or malformed evaluation causes an immediate
123
- error, not a silent stall. The circuit breaker uses `success` + `violations`
124
- to determine loop trajectory — lying here defeats the only mechanism that
125
- prevents infinite loops. The optional fields (P0–P5) enable cognitive
126
- evolution: discovering constraints, deepening understanding, surfacing
127
- sub-problems, tracking real progress, and correcting wrong assumptions as
128
- the loop executes.
61
+ ## Interpret the result
129
62
 
130
- **Step 3 — Advance to next round:**
131
- ```
132
- Call loopforge_next with:
133
- sessionId: from loopforge_start
134
- evaluation: REQUIRED — structured self-evaluation object (see field table below)
135
- output: OPTIONAL — raw output text for audit trail (can be omitted)
136
- ```
137
-
138
- If the result has `prompt: null`, the loop has ended. Read `stopReason`:
139
- - `task_complete` — you reported should_continue=false. Work is done.
140
- - `circuit_breaker` — 3 consecutive failed rounds. Review your approach.
141
- - `max_rounds` — hit the round limit. Decide whether to extend or accept.
142
- - `stalled` — no valid self-evaluation provided. Check your evaluation parameter.
143
-
144
- If the result has a non-null `prompt`, execute it and repeat from Step 2.
63
+ If `prompt` is non-null, execute it and submit the next evaluation.
145
64
 
146
- ## Tool Reference
65
+ If `enforcementAction` is `reject`, redo the same logical round. The round ID
66
+ stays stable and the attempt number increases. Follow the retry requirements;
67
+ the rejected attempt has not been committed.
147
68
 
148
- | Tool | When to call | Key input | Key output |
149
- |------|-------------|-----------|------------|
150
- | `loopforge_start` | Beginning of every loop | `task`, `maxRounds?`, `constraints?` | `sessionId`, round 1 `prompt` |
151
- | `loopforge_next` | After executing every round | `sessionId`, `output` (with eval block) | next `prompt` or `null` + `stopReason` |
152
- | `loopforge_status` | Mid-loop checkpoint, user asks "how's it going" | `sessionId` | `round`, `successTrajectory`, `status`, `technique` |
153
- | `loopforge_stop` | User wants to abort, fatal error | `sessionId` | `roundsCompleted`, final trajectory |
154
- | `loopforge_list` | User asks "what loops are running" | — | `sessions[]` (includes vault-persisted) |
155
- | `loopforge_replay` | After loop ends, user asks "show me what happened" | `sessionId` | `timeline[]` with all rounds |
156
- | `loopforge_resume` | Resume a loop after process restart | `loopId` | next `prompt` or `null` + `stopReason` |
157
- | `loopforge_health` | Check loop health mid-run | `loopId` | goal alignment, constraint integrity, drift, strategy |
69
+ If `prompt` is null, inspect `stopReason`:
158
70
 
159
- ## Delegation Helpers (AgentTool Mode)
71
+ | Reason | Meaning |
72
+ | --- | --- |
73
+ | `task_complete` | The complete objective was reported finished. |
74
+ | `circuit_breaker` | Repeated failed rounds require a different approach or user input. |
75
+ | `max_rounds` | The safety limit was reached. Summarize remaining work. |
76
+ | `stalled` | Evaluation or execution did not produce a usable next state. |
77
+ | `enforcement_terminated` | Repeated invalid claims or stalled progress terminated the loop. |
78
+ | `paused` | The durable session remains available for resume. |
160
79
 
161
- When you spawn sub-agents via `AgentTool` (Explore, General-purpose, Plan)
162
- during a loop round, use these helpers to improve delegation quality:
80
+ ## Prompt levels
163
81
 
164
- **Before delegating:**
165
- 1. **Filter constraints** — not all active constraints apply to every sub-agent.
166
- An Explore agent searching for deprecated APIs doesn't need "all files must
167
- have a license header." Use `filterConstraintsForSubTask(allConstraints, subTask)`
168
- to get only the relevant subset.
169
- 2. **Format the prompt** — use `formatDelegationPrompt(subTask, subAgentType,
170
- relevantConstraints, options?)` to produce a self-contained prompt. This is
171
- critical: sub-agents cannot see your conversation. Every prompt must stand
172
- alone — no "based on above," no "continue from previous."
82
+ - L0 is a same-round retry with the rejection reason and changed evidence.
83
+ - L1 is the normal compact continuation view.
84
+ - L2 is a full rehydration for the first round, a checkpoint, or a goal change.
173
85
 
174
- **After delegating (in your self-evaluation):**
175
- Include `worker_results` in your evaluation to record what you delegated.
176
- The engine auto-detects this field and writes delegation journals to the vault:
86
+ These levels control state density only. LoopForge does not choose a reasoning
87
+ technique for you.
177
88
 
178
- ```json
179
- {
180
- "worker_results": [
181
- {
182
- "agentId": "abc123",
183
- "subAgentType": "explore",
184
- "subTask": "Search for deprecated API usage in src/",
185
- "resultSummary": "Found 12 deprecated calls across 8 files",
186
- "success": true,
187
- "discoveredConstraints": ["All API calls must be versioned"]
188
- }
189
- ]
190
- }
191
- ```
89
+ ## Recovery and control
192
90
 
193
- This feeds into the delegation history table displayed in future rounds.
194
- Constraints discovered by sub-agents flow into the active constraint set
195
- automatically — they appear in future prompts alongside main-agent constraints.
196
- Delegation recording is lightweight — it's the main agent's memory,
197
- not sub-agent memory.
91
+ - Use `loopforge_status` to inspect the live round and trajectory.
92
+ - Use `loopforge_pause` before an intentional interruption.
93
+ - Use `loopforge_resume` with the loop ID to reconstruct a durable session.
94
+ - Use `loopforge_list` after a client restart to find recoverable sessions.
95
+ - Use `loopforge_replay` for the committed timeline.
96
+ - Use `loopforge_health` to inspect goal alignment and drift.
97
+ - Use `loopforge_stop` only for an intentional terminal stop.
198
98
 
199
- **Important:** These helpers are optional. If your sub-task is trivial (e.g.
200
- "read file X and report line 42"), a raw prompt is fine. Use the helpers when
201
- sub-tasks involve constraints, specific output formats, or results worth
202
- remembering across rounds.
99
+ The optional `.loopforge/state/<loopId>-state.md` file is a readable derived
100
+ view. The typed JSON session and round documents are the recovery truth. If the
101
+ state file exists, it can help you review the full state, but do not assume it is
102
+ enabled.
203
103
 
204
- ## Quality Signals (Read the Room)
104
+ ## Delegation
205
105
 
206
- The prompt changes between rounds based on your trajectory. Pay attention to:
207
-
208
- - **Compile level** — `l0` (retry — honest failure, no new info, same prompt),
209
- `l1` (continue — default path, state evolved, technique keyword-routed from Tier 1),
210
- `l2` (restart — Round 1, checkpoint boundary, or goal_id change; full
211
- context rebuild. **At L2**: LoopForge provides a Technique Selection block —
212
- read `skills/prompt-techniques/SKILL.md`, freely choose the best reasoning
213
- strategy for this round, read the corresponding reference file, and apply
214
- the technique directly to the task). L2 means you have a new chance to
215
- pick the right approach.
216
- - **Warnings** — constraint violations accumulating, task drift, quality
217
- decline. These are the compiler begging you to course-correct.
218
- - **Technique autonomy (v1.15)** — at L2 restarts, you freely choose your
219
- reasoning technique. LoopForge no longer auto-selects or forces technique
220
- changes after failures. Read the technique catalog, pick what fits the
221
- current challenge, and apply it. Trust your own judgment — you have the
222
- full loop state in the state file.
223
-
224
- ## Stop Condition Matrix
225
-
226
- | Condition | stopReason | What to do |
227
- |-----------|-----------|------------|
228
- | You set `should_continue: false` | `task_complete` | Report final results to user |
229
- | 3 consecutive failed rounds | `circuit_breaker` | Tell user the approach is stuck, suggest a different strategy |
230
- | Round count reached `maxRounds` | `max_rounds` | Summarize progress, ask user whether to extend |
231
- | No `---loopforge-eval` block found | `stalled` | Fix your output format and restart |
232
- | Enforcement gate rejected your eval | `enforcementAction: "reject"` | Read the rejection prompt's **Required Fix** section, redo the SAME round, re-submit a corrected self-evaluation |
233
- | Enforcement gate terminated loop | `enforcement_terminated` | Too many rejections or progress stalled — report to user and suggest a different approach |
234
- | User interrupts or fatal error | (call `loopforge_stop`) | Clean stop with trajectory preserved |
106
+ Delegation does not create a separate LoopForge mode. Give each worker a
107
+ self-contained subtask and relevant hard constraints. Add the returned result to
108
+ `worker_results` so discoveries can enter the next canonical state.
235
109
 
236
110
  ## Rules
237
111
 
238
- 1. **Always pass the evaluation parameter.** `loopforge_next` requires it.
239
- If you omit it, the MCP client will reject the call with a schema error.
240
- 2. **Read the state file every round.** Before executing the prompt, read
241
- `.loopforge/state/{loopId}-state.md`. It contains the accumulated constraints,
242
- progress, and cross-round summary. Skip this and you'll miss active guardrails.
243
- 3. **Be honest in self-evaluation.** Lying about success or hiding violations
244
- produces a false success signal. The enforcement gate will REJECT fake
245
- successes, and the circuit breaker exists to stop bad loops.
246
- 4. **One loop per task.** Don't reuse a sessionId across different tasks.
247
- 5. **Execute the prompt you're given — and own your technique choice.** At L2
248
- restarts, read the technique catalog and freely choose the best strategy.
249
- At L1, follow the keyword-routed technique. The compiler provides context
250
- and guardrails — you provide the reasoning strategy.
251
- 6. **Call loopforge_next within the same turn.** Don't leave a round hanging
252
- across conversation turns. The MCP server is in-memory.
253
- 7. **After process restart, use loopforge_resume.** The session state is saved
254
- to vault every round. Call `loopforge_resume` with the original `loopId` to
255
- pick up where you left off — no need to restart from round 1.
256
-
257
- ## Example
258
-
259
- ```
260
- User: /perception "Audit the ERC20 token in contracts/Token.sol for security issues"
261
-
262
- Agent:
263
- → loopforge_start({ task: "Audit ERC20 token in contracts/Token.sol for security issues",
264
- domain: "solidity",
265
- constraints: ["must not break existing tests", "follow check-effects-interactions"] })
266
- ← { sessionId: "abc-123", round: 1, prompt: "## LoopForge Loop Compile — Round 1\n...", level: "l2" }
267
-
268
- [Executes prompt: reads Token.sol, identifies 4 issues, discovers a new constraint]
269
-
270
- → loopforge_next({ sessionId: "abc-123",
271
- evaluation: {
272
- success: false,
273
- output_summary: "Found 4 potential issues: 2 reentrancy, 1 overflow, 1 access control. Not yet fixed.",
274
- constraint_violations: [],
275
- should_continue: true,
276
- discovered_constraints: ["All _mint() calls must emit Transfer event per ERC20 spec"]
277
- } })
278
- ← { sessionId: "abc-123", round: 2, prompt: "## LoopForge Loop Compile — Round 2\n...", level: "l1" }
279
-
280
- [Executes prompt: fixes 3 issues, deepens understanding of access control problem]
281
-
282
- → loopforge_next({ sessionId: "abc-123",
283
- evaluation: {
284
- success: false,
285
- output_summary: "Fixed reentrancy in withdraw() and overflow in calcReward(). Access control in setOwner() needs design discussion — discovered it's part of a larger upgradeability concern.",
286
- constraint_violations: [],
287
- should_continue: true,
288
- objective_refinement: "Access control audit scope expanded: setOwner() is unprotected because the contract follows an upgradeable proxy pattern where owner is set via initializer — need to verify the initializer guard and proxy admin separately",
289
- emerged_subtasks: ["Audit upgrade proxy initialization flow", "Verify proxy admin is not renounced without recovery path"]
290
- } })
291
- ← { sessionId: "abc-123", round: 3, prompt: "## LoopForge Loop Compile — Round 3\n Suggested Next Task: Audit upgrade proxy initialization flow; Verify proxy admin is not renounced without recovery path\n...", level: "l0" }
292
-
293
- [Executes prompt: audits proxy pattern, documents findings, all fixes pass tests]
294
-
295
- → loopforge_next({ sessionId: "abc-123",
296
- evaluation: {
297
- success: true,
298
- output_summary: "All fixable issues resolved. Proxy initialization verified — initializer modifier prevents double-init. Proxy admin held by multisig — low risk. 24/24 tests pass.",
299
- constraint_violations: [],
300
- should_continue: false
301
- } })
302
- ← { sessionId: "abc-123", round: 3, prompt: null, stopReason: "task_complete", roundSuccess: true }
303
-
304
- Reports to user: "Audit complete in 3 rounds. 3 issues fixed, 1 design question flagged. Discovered 1 new constraint during audit. Objective deepened to include proxy pattern verification."
305
- ```
112
+ 1. Execute the prompt instead of generating another prompt.
113
+ 2. Submit one honest structured evaluation after each attempt.
114
+ 3. Treat required command evidence and verification errors as authoritative.
115
+ 4. Keep one loop focused on one user objective.
116
+ 5. Do not advance a paused or stopped session through another process.
117
+ 6. Continue within the same Agent task when possible; LoopForge preserves state,
118
+ but it does not create a background Agent.
@@ -1,36 +0,0 @@
1
- /** FSBackend — filesystem implementation of VaultBackend.
2
- *
3
- * Wraps Node.js fs for JSON vault read/write and Markdown lineage I/O.
4
- * All file I/O is contained in this single module — engine.ts never
5
- * touches the filesystem directly.
6
- */
7
- import type { VaultBackend, VaultEntry } from "./interface.js";
8
- export declare function readLineageMd(loopId: string, roundNum: number, vaultPath?: string): {
9
- full_prompt: string;
10
- metadata: Record<string, unknown>;
11
- } | null;
12
- export declare function writeLineageMd(loopId: string, roundNum: number, content: string, metadata: Record<string, unknown>, vaultPath?: string): string | null;
13
- export declare function scanLineageMd(loopId: string, vaultPath?: string): VaultEntry[];
14
- export declare class FSBackend implements VaultBackend {
15
- private readonly vaultPath;
16
- private readonly globalVaultPath;
17
- /** Re-entrant lock depth — >0 means this process holds the lock. */
18
- private lockDepth;
19
- constructor(vaultPath?: string, globalVaultPath?: string);
20
- /** File-system mutex via mkdir (atomic on POSIX and Windows).
21
- * Re-entrant: nested calls from the same process bypass the lock. */
22
- withLock<T>(fn: () => T): T;
23
- readVault(): Record<string, unknown>;
24
- writeVault(data: Record<string, unknown>): void;
25
- queryEntries(opts?: {
26
- prefix?: string;
27
- taskIdPattern?: string;
28
- feedbackOnly?: boolean;
29
- }): VaultEntry[];
30
- appendEntry(entry: VaultEntry): void;
31
- appendEntries(entries: VaultEntry[]): number;
32
- writeLineageMd(loopId: string, roundNum: number, content: string, metadata: Record<string, unknown>): string | null;
33
- readLineageMd(loopId: string, roundNum: number): string | null;
34
- scanLineageMd(loopId: string): VaultEntry[];
35
- }
36
- //# sourceMappingURL=fs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/backends/fs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAsJ/D,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAkBnE;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAef;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,EAAE,CAoDd;AAMD,qBAAa,SAAU,YAAW,YAAY;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,oEAAoE;IACpE,OAAO,CAAC,SAAS,CAAK;gBAGpB,SAAS,SAAmC,EAC5C,eAAe,SAAqC;IAMtD;0EACsE;IACtE,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IA+C3B,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUpC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAU/C,YAAY,CAAC,IAAI,CAAC,EAAE;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,GAAG,UAAU,EAAE;IA+BhB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAUpC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IAa5C,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,GAAG,IAAI;IAIhB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK9D,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE;CAG5C"}