loopforge 3.0.0 → 3.2.1

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 (178) hide show
  1. package/README.md +128 -145
  2. package/dist/audit.d.ts +50 -0
  3. package/dist/audit.d.ts.map +1 -0
  4. package/dist/audit.js +158 -0
  5. package/dist/audit.js.map +1 -0
  6. package/dist/canonical-state.d.ts +28 -20
  7. package/dist/canonical-state.d.ts.map +1 -1
  8. package/dist/canonical-state.js +82 -173
  9. package/dist/canonical-state.js.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +25 -16
  12. package/dist/cli.js.map +1 -1
  13. package/dist/cognitive-governance.d.ts +25 -33
  14. package/dist/cognitive-governance.d.ts.map +1 -1
  15. package/dist/cognitive-governance.js +38 -138
  16. package/dist/cognitive-governance.js.map +1 -1
  17. package/dist/enforcement-gate.d.ts +76 -0
  18. package/dist/enforcement-gate.d.ts.map +1 -0
  19. package/dist/enforcement-gate.js +1071 -0
  20. package/dist/enforcement-gate.js.map +1 -0
  21. package/dist/engine.d.ts +99 -0
  22. package/dist/engine.d.ts.map +1 -0
  23. package/dist/engine.js +839 -0
  24. package/dist/engine.js.map +1 -0
  25. package/dist/evidence-claims.d.ts +50 -0
  26. package/dist/evidence-claims.d.ts.map +1 -0
  27. package/dist/evidence-claims.js +134 -0
  28. package/dist/evidence-claims.js.map +1 -0
  29. package/dist/evidence-provider.d.ts +21 -23
  30. package/dist/evidence-provider.d.ts.map +1 -1
  31. package/dist/evidence-provider.js +74 -34
  32. package/dist/evidence-provider.js.map +1 -1
  33. package/dist/generate-schema.js +1 -84
  34. package/dist/generate-schema.js.map +1 -1
  35. package/dist/index.d.ts +19 -22
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +16 -15
  38. package/dist/index.js.map +1 -1
  39. package/dist/loop-compiler.d.ts +41 -3
  40. package/dist/loop-compiler.d.ts.map +1 -1
  41. package/dist/loop-compiler.js +632 -273
  42. package/dist/loop-compiler.js.map +1 -1
  43. package/dist/loop-extras-parser.d.ts +2 -2
  44. package/dist/loop-extras-parser.d.ts.map +1 -1
  45. package/dist/loop-extras-parser.js +2 -2
  46. package/dist/loop-extras-parser.js.map +1 -1
  47. package/dist/loop-projection.d.ts +26 -0
  48. package/dist/loop-projection.d.ts.map +1 -0
  49. package/dist/loop-projection.js +142 -0
  50. package/dist/loop-projection.js.map +1 -0
  51. package/dist/loop-store.d.ts +112 -24
  52. package/dist/loop-store.d.ts.map +1 -1
  53. package/dist/loop-store.js +365 -218
  54. package/dist/loop-store.js.map +1 -1
  55. package/dist/mcp/round-lifecycle.d.ts +216 -0
  56. package/dist/mcp/round-lifecycle.d.ts.map +1 -0
  57. package/dist/mcp/round-lifecycle.js +926 -0
  58. package/dist/mcp/round-lifecycle.js.map +1 -0
  59. package/dist/mcp/server.d.ts +2 -1
  60. package/dist/mcp/server.d.ts.map +1 -1
  61. package/dist/mcp/server.js +28 -42
  62. package/dist/mcp/server.js.map +1 -1
  63. package/dist/mcp/session.d.ts +53 -101
  64. package/dist/mcp/session.d.ts.map +1 -1
  65. package/dist/mcp/session.js +306 -1105
  66. package/dist/mcp/session.js.map +1 -1
  67. package/dist/mcp/tools.d.ts +13 -16
  68. package/dist/mcp/tools.d.ts.map +1 -1
  69. package/dist/mcp/tools.js +479 -413
  70. package/dist/mcp/tools.js.map +1 -1
  71. package/dist/policy-metrics.d.ts +12 -17
  72. package/dist/policy-metrics.d.ts.map +1 -1
  73. package/dist/policy-metrics.js +95 -161
  74. package/dist/policy-metrics.js.map +1 -1
  75. package/dist/policy.d.ts +44 -35
  76. package/dist/policy.d.ts.map +1 -1
  77. package/dist/policy.js +31 -115
  78. package/dist/policy.js.map +1 -1
  79. package/dist/prompt-assembler.d.ts +37 -6
  80. package/dist/prompt-assembler.d.ts.map +1 -1
  81. package/dist/prompt-assembler.js +389 -160
  82. package/dist/prompt-assembler.js.map +1 -1
  83. package/dist/prompt-policy.d.ts +1 -8
  84. package/dist/prompt-policy.d.ts.map +1 -1
  85. package/dist/prompt-policy.js +8 -26
  86. package/dist/prompt-policy.js.map +1 -1
  87. package/dist/protocol.d.ts +357 -229
  88. package/dist/protocol.d.ts.map +1 -1
  89. package/dist/protocol.js +139 -15
  90. package/dist/protocol.js.map +1 -1
  91. package/dist/replay.d.ts +5 -13
  92. package/dist/replay.d.ts.map +1 -1
  93. package/dist/replay.js +19 -55
  94. package/dist/replay.js.map +1 -1
  95. package/dist/round-coordinator.d.ts +20 -24
  96. package/dist/round-coordinator.d.ts.map +1 -1
  97. package/dist/round-coordinator.js +99 -92
  98. package/dist/round-coordinator.js.map +1 -1
  99. package/dist/round-driver.d.ts +14 -13
  100. package/dist/round-driver.d.ts.map +1 -1
  101. package/dist/round-driver.js +26 -14
  102. package/dist/round-driver.js.map +1 -1
  103. package/dist/round-transaction.d.ts +15 -18
  104. package/dist/round-transaction.d.ts.map +1 -1
  105. package/dist/round-transaction.js +38 -47
  106. package/dist/round-transaction.js.map +1 -1
  107. package/dist/self-eval.d.ts +53 -0
  108. package/dist/self-eval.d.ts.map +1 -0
  109. package/dist/self-eval.js +284 -0
  110. package/dist/self-eval.js.map +1 -0
  111. package/dist/storage.d.ts +9 -4
  112. package/dist/storage.d.ts.map +1 -1
  113. package/dist/storage.js +18 -6
  114. package/dist/storage.js.map +1 -1
  115. package/dist/token-utils.d.ts +15 -3
  116. package/dist/token-utils.d.ts.map +1 -1
  117. package/dist/token-utils.js +24 -5
  118. package/dist/token-utils.js.map +1 -1
  119. package/dist/verification-gate.d.ts +108 -0
  120. package/dist/verification-gate.d.ts.map +1 -0
  121. package/dist/verification-gate.js +971 -0
  122. package/dist/verification-gate.js.map +1 -0
  123. package/loop_policy.json +44 -15
  124. package/package.json +5 -10
  125. package/skills/perception/SKILL.md +182 -199
  126. package/dist/canonical-event-writer.d.ts +0 -20
  127. package/dist/canonical-event-writer.d.ts.map +0 -1
  128. package/dist/canonical-event-writer.js +0 -131
  129. package/dist/canonical-event-writer.js.map +0 -1
  130. package/dist/compiler-subgoals.d.ts +0 -7
  131. package/dist/compiler-subgoals.d.ts.map +0 -1
  132. package/dist/compiler-subgoals.js +0 -93
  133. package/dist/compiler-subgoals.js.map +0 -1
  134. package/dist/derive-id.d.ts +0 -12
  135. package/dist/derive-id.d.ts.map +0 -1
  136. package/dist/derive-id.js +0 -31
  137. package/dist/derive-id.js.map +0 -1
  138. package/dist/mcp/session-projection.d.ts +0 -5
  139. package/dist/mcp/session-projection.d.ts.map +0 -1
  140. package/dist/mcp/session-projection.js +0 -18
  141. package/dist/mcp/session-projection.js.map +0 -1
  142. package/dist/mcp/session-queue.d.ts +0 -3
  143. package/dist/mcp/session-queue.d.ts.map +0 -1
  144. package/dist/mcp/session-queue.js +0 -18
  145. package/dist/mcp/session-queue.js.map +0 -1
  146. package/dist/mcp/session-types.d.ts +0 -72
  147. package/dist/mcp/session-types.d.ts.map +0 -1
  148. package/dist/mcp/session-types.js +0 -2
  149. package/dist/mcp/session-types.js.map +0 -1
  150. package/dist/round-commit-store.d.ts +0 -12
  151. package/dist/round-commit-store.d.ts.map +0 -1
  152. package/dist/round-commit-store.js +0 -13
  153. package/dist/round-commit-store.js.map +0 -1
  154. package/dist/round-gate.d.ts +0 -31
  155. package/dist/round-gate.d.ts.map +0 -1
  156. package/dist/round-gate.js +0 -259
  157. package/dist/round-gate.js.map +0 -1
  158. package/dist/round-recovery.d.ts +0 -17
  159. package/dist/round-recovery.d.ts.map +0 -1
  160. package/dist/round-recovery.js +0 -117
  161. package/dist/round-recovery.js.map +0 -1
  162. package/dist/round-report.d.ts +0 -16
  163. package/dist/round-report.d.ts.map +0 -1
  164. package/dist/round-report.js +0 -401
  165. package/dist/round-report.js.map +0 -1
  166. package/dist/runtime-services.d.ts +0 -59
  167. package/dist/runtime-services.d.ts.map +0 -1
  168. package/dist/runtime-services.js +0 -460
  169. package/dist/runtime-services.js.map +0 -1
  170. package/dist/vault-format.d.ts +0 -4
  171. package/dist/vault-format.d.ts.map +0 -1
  172. package/dist/vault-format.js +0 -4
  173. package/dist/vault-format.js.map +0 -1
  174. package/dist/vault-types.d.ts +0 -24
  175. package/dist/vault-types.d.ts.map +0 -1
  176. package/dist/vault-types.js +0 -2
  177. package/dist/vault-types.js.map +0 -1
  178. package/loopforge-policy.json +0 -340
package/README.md CHANGED
@@ -1,13 +1,71 @@
1
- # LoopForge package
1
+ # LoopForge
2
2
 
3
- LoopForge is a cognitive state runtime for AI coding agents. It keeps a long
4
- task's objective, constraints, evidence, decisions and recovery state stable
5
- across many Agent-driven rounds.
3
+ **A context window is not memory. Memory needs a runtime.**
6
4
 
7
- The Agent remains the executor: it reads code, edits files, runs tools and
8
- decides how to reason. LoopForge is the external round boundary that checks
9
- claims, commits canonical facts and rebuilds the next prompt. It is not a model,
10
- scheduler, unattended worker or second planning system.
5
+ > **v3.2.1** — `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 doesn't compete on context window size. It runs **outside** the agent and provides three things:
33
+
34
+ ### 1. Breaks the summary cascade: Vault → compile, not summary → summary
35
+
36
+ Each round's self-evaluation is written to a **typed vault** (JSON documents). The next round's prompt is not generated from the previous prompt's summary — it's **recompiled from the vault**. Milestones aren't summaries of summaries; they're recomputed from raw vault entries. Constraints and criteria carry stable IDs (`c-XXXXXXXX`, `cr-XXXXXXXX`) for exact matching — no Jaccard guesswork.
37
+
38
+ ```
39
+ ❌ Traditional: prompt → summary → next prompt → re-summarize → … (information evaporates each cycle)
40
+ ✅ LoopForge: prompt → vault entry → next prompt (recompiled from vault, zero evaporation)
41
+ ```
42
+
43
+ ### 2. External judgment: the perspective the agent cannot provide for itself
44
+
45
+ The verification gate cross-checks every agent claim against independent evidence — Git snapshots, test runner output, explicit verification commands. The enforcement gate detects what the agent cannot self-diagnose:
46
+
47
+ - R1: You claimed success but criteria remain unmet → **you're deceiving yourself**
48
+ - R3: You claimed success with no verifiable evidence → **your claim is empty**
49
+ - R4: You've been stuck for 3 rounds → **you're stalled and you don't know it**
50
+ - R5: Your progress is exactly zero → **you're going through the motions**
51
+ - R7: You said you'd do X but did Y → **your intent and actions are disconnected**
52
+
53
+ **The agent cannot self-detect these. The agent is the system that produced those narratives. External judgment is necessary.**
54
+
55
+ ### 3. Walk back from dead ends
56
+
57
+ Progress stall or flatline → roll back to the last clean round instead of terminating. A diagnosis of why the path failed is injected. The backtrack prompt includes concrete workspace restore commands — `git checkout -- . && git clean -fd` with affected file lists. The verification gate checks that the workspace was actually restored before the next submission. Valid discoveries from skipped rounds are preserved.
58
+
59
+ ---
60
+
61
+ ## What LoopForge is not
62
+
63
+ - ❌ **Not a memory system** — the state file is a derived view. The vault is truth. No RAG, no vector DB.
64
+ - ❌ **Not a context compressor** — doesn't compress prompts, doesn't do smart summarization. Recompiles from vault, not from the previous prompt.
65
+ - ❌ **Not a constraint tracker** — constraints are one signal the verification gate monitors. The core value is external judgment.
66
+ - ❌ **Not a replacement for the agent** — the agent still reads code, edits files, runs tools, and decides how to reason. LoopForge owns the **round boundary**.
67
+
68
+ ---
11
69
 
12
70
  ## Install
13
71
 
@@ -17,154 +75,79 @@ loopforge init --client claude
17
75
  claude mcp add loopforge -- npx loopforge mcp
18
76
  ```
19
77
 
20
- For Codex use `loopforge init --client codex` and register the same MCP command.
21
- The generic initializer prints an MCP configuration fragment. The package
22
- requires Node.js 18 or newer and has zero runtime dependencies.
23
-
24
- ## How a loop works
25
-
26
- 1. The Agent calls `loopforge_start` with one objective and its hard constraints.
27
- 2. LoopForge compiles a prompt from canonical state.
28
- 3. The Agent executes that prompt and submits a structured `RoundReport`.
29
- 4. Runtime evidence is checked, the round boundary is enforced, and the result is accepted, rejected, backtracked or stopped.
30
- 5. If work remains, the next prompt is compiled again from committed facts.
31
-
32
- The report deliberately separates `outcome` (`success`, `partial`, `failed` or
33
- `blocked`) from `continuation` (`continue` or `stop`). This prevents a local
34
- round result from being mistaken for completion of the whole objective. The old
35
- `status` report and free-form evaluation text are not accepted at the public
36
- boundary.
37
-
38
- ```json
39
- {
40
- "format": "loopforge.round-report",
41
- "outcome": "partial",
42
- "continuation": "continue",
43
- "summary": "Implemented the parser and ran focused tests.",
44
- "violations": [],
45
- "agentIntent": "Add parser regression coverage next",
46
- "evidence": {"files": ["src/parser.ts"], "checks": [], "claims": [], "provenance": {}},
47
- "discoveries": {"wrongAssumptions": [], "emergedWork": [], "facts": [], "newConstraints": []},
48
- "subGoalEvents": {"completed": [], "blocked": [], "canceled": []}
49
- }
50
- ```
78
+ Works with Claude Code, Codex CLI, or any MCP-compatible client.
79
+
80
+ The MCP server path (`loopforge mcp`) is the primary integration. It provides
81
+ the full cognitive infrastructure: verification gate, enforcement gate,
82
+ backtrack, evidence collection, and crash recovery. The engine is also
83
+ available as a library for custom integrations.
84
+
85
+ ---
86
+
87
+ ## Architecture
51
88
 
52
- `blocked` reports include a blocker. User decisions and external side effects
53
- must stop at a User Gate; an Agent-resolvable technical blocker may continue
54
- only with concrete evidence requirements.
55
-
56
- ## State model and prompt artifact
57
-
58
- The package follows a single-source rule: Goal, RoundEvent, EvidenceEnvelope,
59
- Constraint, SubGoal and GateDecision are durable facts; phase history, Current
60
- Focus, Todo, Handoff, progress, failed patterns and prompt diagnostics are
61
- rebuildable projections, never a competing plan or persistence layer. Compiler
62
- responses keep those derived views in one `projection` object. The full model,
63
- the L0/L1/L2 prompt levels and the immutable prompt artifact are described in
64
- the [project README](https://github.com/kyrielrving11/LoopForge/blob/main/README.md)
65
- under “Canonical cognitive state” and “One prompt artifact per attempt”.
66
-
67
- The default store is `.loopforge`. Events are written through the canonical
68
- writer and receive a monotonic `event_sequence` within each loop. Prompt and
69
- state hashes make a restart or replay auditable. Markdown state is only a
70
- replaceable view, not the recovery truth.
71
-
72
- Evidence collection and recovery are asynchronous. A malformed report is an
73
- input error; corrupt JSON, an invalid event format, or a sequence gap is a
74
- `storage_corruption` error and is never auto-repaired. The configured
75
- `maxRounds` must be a positive integer no greater than the policy limit.
76
-
77
- ## Verification, enforcement and gates
78
-
79
- Git evidence is enabled by default. Explicit command providers run with an
80
- executable and argument array (`shell: false`), bounded output, a timeout and a
81
- workspace path check; required command failures contradict an unsupported
82
- success claim. Agent claims remain `claimed` until a provider observes them —
83
- provenance is owned by the runtime, and criteria coverage comes from verified
84
- claims, never from a progress estimate. A successful report that requests a
85
- stop is accepted as completion only when a live evidence provider produced
86
- verifiable evidence; with no provider, completion stays unresolved.
87
-
88
- Gate checks use `GateActionDescriptor` to make risk explicit: production,
89
- credentials, data migration, publishing, payment, external communication,
90
- public API changes, irreversible actions and unknown authorization are User
91
- Gates; bounded, reversible, explicitly agent-allowed workspace work is an
92
- Agent Gate. Decisions bind to an `actionHash`, so changing an action
93
- invalidates an earlier approval.
94
-
95
- For the full decision semantics — what the gate detects, how enforcement
96
- decides accept, reject, backtrack and stop — see the corresponding sections in
97
- the [project README](https://github.com/kyrielrving11/LoopForge/blob/main/README.md).
98
-
99
- ## Recovery semantics
100
-
101
- A rejected attempt is zero-commit: its report does not enter canonical state.
102
- `loopforge_retry` keeps the same logical round ID and increments the attempt;
103
- `loopforge_next` cannot bypass a rejection. `loopforge_backtrack` returns a
104
- bounded restore point and verification requirements but never changes workspace
105
- files. Pause and resume preserve the transaction across client or process
106
- boundaries. Stop records termination without deleting the vault.
107
-
108
- `agentIntent` is an optional, non-authoritative suggestion retained inside the
109
- report for audit and drift comparison. It never overwrites Current Focus, Todo,
110
- runtime progress, completion, or the compiler's Suggested Next Action.
111
-
112
- Terminal enforcement escalation is tracked per rule. A rule can issue one
113
- guided retry before a repeated hit terminates it; accepting progress or
114
- backtracking clears the active rejection episode.
115
-
116
- ## MCP surface
117
-
118
- The server exposes exactly twelve Agent-driven tools:
119
-
120
- ```text
121
- loopforge_start loopforge_next loopforge_retry
122
- loopforge_backtrack loopforge_resume loopforge_pause
123
- loopforge_stop loopforge_status loopforge_history
124
- loopforge_gate_check loopforge_gate_resolve loopforge_audit
125
89
  ```
90
+ ┌─────────────────────────────────────────────────────┐
91
+ │ Agent executes round │
92
+ │ Reads code · Edits files · Runs tools · Reasons │
93
+ └──────────────────────┬──────────────────────────────┘
94
+ │ Agent submits SelfEvaluation
95
+ ▼
96
+ ┌─────────────────────────────────────────────────────┐
97
+ │ LoopForge round boundary │
98
+ │ │
99
+ │ Evidence → Verify → Enforce → Commit → Compile │
100
+ │ (Git/cmd) (19 checks) (10 rules) (vault) (next) │
101
+ │ │
102
+ │ accept: commit state, compile next round │
103
+ │ reject: retry same round, zero state mutation │
104
+ │ backtrack: roll back to last clean round, restore │
105
+ │ terminate: persist terminal state │
106
+ └──────────────────────┬──────────────────────────────┘
107
+ │ Recompile prompt from vault
108
+ ▼
109
+ ┌─────────────────────────────────────────────────────┐
110
+ │ Vault (typed JSON persistence) │
111
+ │ loops/<id>/rounds/<n>.json · session.json · policy │
112
+ │ Source of truth. Not a summary chain. │
113
+ └─────────────────────────────────────────────────────┘
114
+ ```
115
+
116
+ ---
126
117
 
127
- `status` combines session, loop and persisted-loop views. `history` combines
128
- single-round inspection and event-timeline replay with sequence pagination. The
129
- old `list`, `health`, `inspect` and `replay` MCP names are not aliases. MCP
130
- Tasks and background Agent execution are intentionally outside this package.
131
-
132
- ## Long-horizon use
133
-
134
- LoopForge can support dozens or hundreds of explicit rounds, context
135
- compression, restart, rejection and backtrack because every prompt is compiled
136
- from durable facts rather than from a summary of the previous prompt. It does
137
- not keep an Agent running after the client task ends. Use one loop per clear
138
- objective; for a large roadmap, let the Agent carry explicit outcomes between
139
- independent loops instead of creating an endless session.
140
-
141
- ## Reliability boundaries
142
-
143
- Malformed canonical reports are rejected without changing the current session,
144
- round or vault, so callers can retry the same logical round. Persistence
145
- failures are returned as errors and never become a successful or partial
146
- commit. Drift clarification requires an explanation and a runtime-verifiable
147
- anchor; agent waiver flags are not accepted. `loopforge doctor` diagnoses
148
- unknown, deprecated, type-invalid and removed policy keys. Automatic Git
149
- restore is intentionally not implemented. Persistence and evidence collection
150
- are asynchronous; corrupt JSON, invalid event formats and sequence gaps return
151
- `storage_corruption` instead of a partial status. `maxRounds` must be a positive
152
- integer within the configured policy limit.
118
+ ## Key capabilities
119
+
120
+ **Vault → compile, not summary → summary.** Every round's self-evaluation is written to the vault. The next prompt is recompiled from vault entries. Stable IDs (`c-` / `cr-` / `sg-XXXXXXXX`) enable exact constraint, criterion, and sub-goal matching — no Jaccard false positives.
121
+
122
+ **External judgment.** The verification gate cross-checks agent claims against independent evidence. The enforcement gate detects cognitive integrity violations — progress stalls, intent-action gaps, empty success claims. The judge never shares the agent's context.
123
+
124
+ **Model expresses information needs.** Each round, the agent tells the compiler: what to emphasize, which sections to expand, where it's confused. The compiler reorders within safety boundaries — mandatory sections untouched, budget respected.
125
+
126
+ **Walk back from dead ends.** Progress stall → roll back to last clean round with a diagnosis. Workspace restore is prompted and verified — the next submission is rejected if files from skipped rounds are still dirty.
127
+
128
+ **Substantive drift, not filler.** R7 accepts intentional pivots only when the clarification references concrete IDs or file paths. Three consecutive weak clarifications terminate the loop.
129
+
130
+ **Thin prompt, fat state file.** L0 (retry) / L1 (continuation) / L2 (full rehydration) control density only — reasoning strategy belongs to the agent. Truth is in the vault.
131
+
132
+ **Pause · Resume · Replay.** Cross-process session leases. Idempotent resume after interruption. Time-travel queries over committed rounds.
133
+
134
+ **Nine MCP tools.** `start` · `next` · `status` · `stop` · `pause` · `resume` · `replay` + `gate_check` · `gate_resolve`. `status` is the unified inspection tool (`view=session|loop|all|audit`). Every tool returns JSON content blocks.
135
+
136
+ **Zero dependencies. Policy-driven.** Node.js stdlib only. All thresholds, budgets, and intervals live in `loop_policy.json`. 715 tests.
137
+
138
+ ---
153
139
 
154
140
  ## Development
155
141
 
156
142
  ```bash
157
143
  npm run check
158
144
  npm test
159
- npm run build
160
- npm run verify:artifacts
161
- npm pack --dry-run --json --ignore-scripts
145
+ npm pack --dry-run --json
162
146
  ```
163
147
 
164
- The schema in the repository's `loopforge-protocol.json` is generated from
165
- `src/protocol.ts`.
166
- Do not edit it by hand. `init` installs `skills/perception/SKILL.md` for the
167
- selected client and prints its MCP registration command.
148
+ The protocol schema in `../loopforge-protocol.json` is generated from `src/protocol.ts`. Do not edit it by hand.
149
+
150
+ ---
168
151
 
169
152
  ## License
170
153
 
@@ -0,0 +1,50 @@
1
+ /** v2.12: Read-only, replayable end-of-loop audit — the verification view.
2
+ *
3
+ * Positioning vs loopforge_replay: replay is the factual timeline (what
4
+ * happened per round); audit is the assessment layer (which claims are
5
+ * machine-verified, which gates were decided, is the sequence intact).
6
+ * Everything is derived from committed vault entries — audit never writes.
7
+ */
8
+ import type { LoopStore } from "./loop-store.js";
9
+ import type { VaultEntry } from "./loop-store.js";
10
+ export interface AuditRound {
11
+ round: number;
12
+ outcome: string;
13
+ claims: Array<{
14
+ text: string;
15
+ status: "verified" | "unverified" | "no_evidence";
16
+ }>;
17
+ checks: Array<{
18
+ check: string;
19
+ severity: string;
20
+ verdict: "failed" | "warn" | "info";
21
+ }>;
22
+ }
23
+ export interface AuditGate {
24
+ gateId: string;
25
+ kind: "user" | "agent";
26
+ actionHash: string;
27
+ approved: boolean;
28
+ decidedAt: string;
29
+ round: number;
30
+ }
31
+ export interface AuditResult {
32
+ loopId: string;
33
+ verdict: "passed" | "incomplete" | "contradicted";
34
+ rounds: AuditRound[];
35
+ gates: AuditGate[];
36
+ unresolvedUserGates: string[];
37
+ criteria: {
38
+ declared: number;
39
+ evidenced: number;
40
+ missing: number;
41
+ };
42
+ sequenceComplete: boolean;
43
+ /** False when no LoopStore was provided (sequence/provenance degraded). */
44
+ provenanceAvailable: boolean;
45
+ }
46
+ /** Build the audit from committed vault entries. Pure, read-only.
47
+ * @param store Optional LoopStore — when provided, sequence integrity is
48
+ * checked and provenanceAvailable becomes true. */
49
+ export declare function buildAudit(loopId: string, entries: VaultEntry[], store?: LoopStore): AuditResult;
50
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAKjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIlD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,aAAa,CAAA;KAAE,CAAC,CAAC;IACnF,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CACzF;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,GAAG,YAAY,GAAG,cAAc,CAAC;IAClD,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,2EAA2E;IAC3E,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAqCD;;oDAEoD;AACpD,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,UAAU,EAAE,EACrB,KAAK,CAAC,EAAE,SAAS,GAChB,WAAW,CAgHb"}
package/dist/audit.js ADDED
@@ -0,0 +1,158 @@
1
+ /** v2.12: Read-only, replayable end-of-loop audit — the verification view.
2
+ *
3
+ * Positioning vs loopforge_replay: replay is the factual timeline (what
4
+ * happened per round); audit is the assessment layer (which claims are
5
+ * machine-verified, which gates were decided, is the sequence intact).
6
+ * Everything is derived from committed vault entries — audit never writes.
7
+ */
8
+ import { eventSequence, StorageCorruptionError } from "./loop-store.js";
9
+ import { auditOrder, deriveGate } from "./cognitive-governance.js";
10
+ import { rederiveClaimViewWithFlags, listVerifiedClaims } from "./evidence-claims.js";
11
+ import { effectiveOutcome } from "./self-eval.js";
12
+ import { isRecord, entryRound as sharedEntryRound } from "./token-utils.js";
13
+ function entryRound(entry) {
14
+ return sharedEntryRound(entry);
15
+ }
16
+ /** Committed transaction payload from a feedback entry. */
17
+ function committedTransaction(entry) {
18
+ if (!isRecord(entry.loop_lineage))
19
+ return null;
20
+ const transaction = entry.loop_lineage.round_transaction;
21
+ if (!isRecord(transaction) || !isRecord(transaction.snapshot))
22
+ return null;
23
+ const snapshot = transaction.snapshot;
24
+ const evaluation = isRecord(snapshot.evaluation)
25
+ ? snapshot.evaluation
26
+ : null;
27
+ const result = isRecord(snapshot.result) ? snapshot.result : null;
28
+ const flags = Array.isArray(result?.verificationFlags)
29
+ ? result.verificationFlags
30
+ : [];
31
+ const evidence = Array.isArray(snapshot.afterEvidence)
32
+ ? snapshot.afterEvidence
33
+ : Array.isArray(snapshot.roundEvidence)
34
+ ? snapshot.roundEvidence
35
+ : [];
36
+ return {
37
+ evaluation,
38
+ flags,
39
+ afterEvidence: evidence,
40
+ action: typeof result?.action === "string" ? result.action : undefined,
41
+ };
42
+ }
43
+ /** Build the audit from committed vault entries. Pure, read-only.
44
+ * @param store Optional LoopStore — when provided, sequence integrity is
45
+ * checked and provenanceAvailable becomes true. */
46
+ export function buildAudit(loopId, entries, store) {
47
+ const ordered = auditOrder(entries);
48
+ // ── Rounds: per-round claims + checks from committed snapshots ─────────
49
+ const rounds = [];
50
+ for (const entry of ordered) {
51
+ const taskId = String(entry.task_id ?? "");
52
+ if (!taskId.startsWith(`loop:${loopId}:r`) || !taskId.endsWith(":feedback"))
53
+ continue;
54
+ const committed = committedTransaction(entry);
55
+ if (!committed)
56
+ continue;
57
+ // v2.14: rounds committed with action="backtrack" were rolled back —
58
+ // they are not part of the loop's final history. Counting them would
59
+ // inflate the round list and let their error flags flip the verdict.
60
+ if (committed.action === "backtrack")
61
+ continue;
62
+ const round = entryRound(entry);
63
+ const outcome = committed.evaluation
64
+ ? effectiveOutcome(committed.evaluation)
65
+ : "unknown";
66
+ const claimView = committed.evaluation
67
+ ? rederiveClaimViewWithFlags(committed.evaluation, committed.afterEvidence, committed.flags)
68
+ : null;
69
+ rounds.push({
70
+ round,
71
+ outcome,
72
+ claims: claimView
73
+ ? claimView.claims.map((claim) => ({
74
+ text: claim.targetId,
75
+ status: claim.status === "verified" ? "verified" : "unverified",
76
+ }))
77
+ : [],
78
+ checks: committed.flags.map((flag) => ({
79
+ check: flag.check,
80
+ severity: flag.severity,
81
+ verdict: flag.severity === "error" ? "failed" : flag.severity,
82
+ })),
83
+ });
84
+ }
85
+ // ── Gates: latest decision wins; opened-without-decision stays open ────
86
+ const decisionsByGate = new Map();
87
+ const openedGates = new Map();
88
+ for (const entry of ordered) {
89
+ const gateId = String(entry.gate_id ?? "");
90
+ if (!gateId)
91
+ continue;
92
+ if (entry.task_type === "gate_decision" && isRecord(entry.gate_decision)) {
93
+ const decision = entry.gate_decision;
94
+ decisionsByGate.set(gateId, {
95
+ gateId,
96
+ kind: decision.kind === "agent" ? "agent" : "user",
97
+ actionHash: typeof decision.actionHash === "string" ? decision.actionHash : "",
98
+ approved: decision.approved === true,
99
+ decidedAt: typeof decision.decidedAt === "string" ? decision.decidedAt : "",
100
+ round: entryRound(entry),
101
+ });
102
+ }
103
+ else if (entry.task_type === "gate_opened") {
104
+ openedGates.set(gateId, {
105
+ description: typeof entry.gate_action === "string" ? entry.gate_action : gateId,
106
+ round: entryRound(entry),
107
+ });
108
+ }
109
+ }
110
+ const gates = [...decisionsByGate.values()];
111
+ const unresolvedUserGates = [];
112
+ for (const [gateId, opened] of openedGates) {
113
+ if (decisionsByGate.has(gateId))
114
+ continue;
115
+ // Re-derive the classification from the recorded action text.
116
+ const { gate } = deriveGate(opened.description);
117
+ if (gate.kind === "user") {
118
+ unresolvedUserGates.push(`${gateId} (round ${opened.round}): ${opened.description}`);
119
+ }
120
+ }
121
+ // ── Sequence integrity (P0) ────────────────────────────────────────────
122
+ let sequenceComplete = true;
123
+ let provenanceAvailable = store !== undefined;
124
+ if (store) {
125
+ try {
126
+ const sequences = eventSequence(store, loopId);
127
+ const max = sequences.length > 0 ? Math.max(...sequences) : 0;
128
+ sequenceComplete = sequences.length === max;
129
+ }
130
+ catch (error) {
131
+ sequenceComplete = false;
132
+ if (!(error instanceof StorageCorruptionError))
133
+ throw error;
134
+ }
135
+ }
136
+ // ── Criteria accounting + verdict ──────────────────────────────────────
137
+ const verified = listVerifiedClaims(entries, loopId);
138
+ const declared = rounds.reduce((sum, round) => sum + round.claims.length, 0);
139
+ const evidenced = verified.length;
140
+ let verdict = "passed";
141
+ if (rounds.some((round) => round.checks.some((check) => check.verdict === "failed"))) {
142
+ verdict = "contradicted";
143
+ }
144
+ else if (unresolvedUserGates.length > 0 || (declared > 0 && evidenced === 0)) {
145
+ verdict = "incomplete";
146
+ }
147
+ return {
148
+ loopId,
149
+ verdict,
150
+ rounds,
151
+ gates,
152
+ unresolvedUserGates,
153
+ criteria: { declared, evidenced, missing: Math.max(0, declared - evidenced) },
154
+ sequenceComplete,
155
+ provenanceAvailable,
156
+ };
157
+ }
158
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
@@ -3,16 +3,33 @@
3
3
  * The canonical state is data, not Markdown. Prompt and state-file renderers
4
4
  * consume the same value so they cannot silently drift apart.
5
5
  */
6
- import type { ConstraintMeta, LoopCompileRequest, LoopCompileResponse, SubGoal, VerificationFlag, DerivedGate, HandoffProjection, PhaseHistoryEntry, TodoProjection } from "./protocol.js";
7
- export declare const CANONICAL_STATE_FORMAT: "loopforge.state";
6
+ import type { ConstraintMeta, CriterionStatus, Lesson, LoopCompileRequest, LoopCompileResponse, MilestoneSummary, SubGoal, VerificationFlag } from "./protocol.js";
7
+ export declare const CANONICAL_STATE_SCHEMA_VERSION: 1;
8
+ /** v3.2: Durable snapshot of what an L1 prompt actually presented last round.
9
+ * Used as the diff baseline for L1 collapse. Persisted inside the lineage
10
+ * entry's loop_lineage (field extension — no new persistence format) and
11
+ * carried on PromptArtifact for the compile-to-persist round-trip. */
12
+ export interface PresentedStateSnapshot {
13
+ /** Round whose presentation this snapshot describes (the baseline round). */
14
+ round: number;
15
+ /** Stable IDs (c-XXXXXXXX) of constraints rendered in the L1 Active
16
+ * Constraints section (post-emphasize, non-hard). */
17
+ constraintIds: string[];
18
+ /** [sub-goal id, status] pairs rendered in the L1 Active Sub-Goals section
19
+ * (in_progress + pending only). Statuses enable transition detection. */
20
+ subGoals: Array<[string, string]>;
21
+ /** [start, end] round ranges of all milestones at presentation time. */
22
+ milestoneRanges: Array<[number, number]>;
23
+ }
8
24
  export interface CanonicalLoopState {
9
- format: "loopforge.state";
25
+ schemaVersion: typeof CANONICAL_STATE_SCHEMA_VERSION;
10
26
  loopId: string;
11
27
  round: number;
12
28
  maxRounds: number;
13
29
  goalId: string;
14
30
  objective: string;
15
31
  objectiveVersion: number;
32
+ currentTask: string;
16
33
  successCriteria: string[];
17
34
  hardConstraints: string[];
18
35
  activeConstraints: string[];
@@ -26,17 +43,25 @@ export interface CanonicalLoopState {
26
43
  blockers: string[];
27
44
  verificationFlags: VerificationFlag[];
28
45
  discoveries: string[];
46
+ nextAction: string;
29
47
  rollingOutcomes: string[];
30
48
  recurringIssues: string[];
31
49
  failedPatterns: string[];
50
+ /** v2.1: Phase-boundary milestone summaries that survive window eviction. */
51
+ milestones: MilestoneSummary[];
32
52
  /** v2.1: Single-paragraph loop-level synthesis (formulaic). */
33
53
  loopSynthesis: string;
34
54
  /** v2.2: Structured sub-goals with compiler-managed lifecycle. */
35
55
  subGoals: SubGoal[];
56
+ /** v3.2: Derived per-criterion status (goal → criteria → evidence view). */
57
+ criterionStatuses: CriterionStatus[];
58
+ /** v3.2: Deterministic lessons learned (repeated violations / failures). */
59
+ lessons: Lesson[];
36
60
  /** v2.5: Agent trust score [0, 1] from verification flags. */
37
61
  agentTrustScore: number | undefined;
38
62
  /** v2.5: Trust trend over last 10 rounds. */
39
63
  agentTrustTrend: number[];
64
+ suggestedNextTask: string;
40
65
  externalContext: string;
41
66
  stateFilePath: string;
42
67
  progress: {
@@ -50,23 +75,6 @@ export interface CanonicalLoopState {
50
75
  skipped: number;
51
76
  } | null;
52
77
  };
53
- /** Derived obligations that must be rechecked after a change. */
54
- regressionObligations: Array<{
55
- id: string;
56
- description: string;
57
- sourceRound: number;
58
- evidenceRefs: string[];
59
- status: "open" | "satisfied" | "contradicted";
60
- }>;
61
- /** Derived views. They are rebuilt on every compile and are not a
62
- * second transaction truth. */
63
- phaseHistory: PhaseHistoryEntry[];
64
- currentFocus: string;
65
- todoProjection: TodoProjection | null;
66
- suggestedNextAction: string;
67
- activeGate: DerivedGate | null;
68
- stateFreshness: "fresh" | "stale" | "missing";
69
- handoff: HandoffProjection;
70
78
  }
71
79
  /** Deterministic JSON serialization used by state and prompt hashes. */
72
80
  export declare function stableStringify(value: unknown): string;
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-state.d.ts","sourceRoot":"","sources":["../src/canonical-state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical-state.d.ts","sourceRoot":"","sources":["../src/canonical-state.ts"],"names":[],"mappings":"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"}