loopforge 3.7.0 → 3.7.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 (95) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +17 -5
  3. package/dist/canonical-state.d.ts +23 -2
  4. package/dist/canonical-state.d.ts.map +1 -1
  5. package/dist/canonical-state.js +148 -27
  6. package/dist/canonical-state.js.map +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +8 -8
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cognitive-facts.d.ts.map +1 -1
  11. package/dist/cognitive-facts.js +2 -3
  12. package/dist/cognitive-facts.js.map +1 -1
  13. package/dist/cognitive-governance.d.ts +30 -6
  14. package/dist/cognitive-governance.d.ts.map +1 -1
  15. package/dist/cognitive-governance.js +74 -18
  16. package/dist/cognitive-governance.js.map +1 -1
  17. package/dist/committed-round.d.ts +7 -4
  18. package/dist/committed-round.d.ts.map +1 -1
  19. package/dist/committed-round.js +48 -8
  20. package/dist/committed-round.js.map +1 -1
  21. package/dist/enforcement-gate.d.ts +24 -19
  22. package/dist/enforcement-gate.d.ts.map +1 -1
  23. package/dist/enforcement-gate.js +100 -20
  24. package/dist/enforcement-gate.js.map +1 -1
  25. package/dist/engine.d.ts +10 -5
  26. package/dist/engine.d.ts.map +1 -1
  27. package/dist/engine.js +50 -30
  28. package/dist/engine.js.map +1 -1
  29. package/dist/evidence-provider.d.ts +7 -2
  30. package/dist/evidence-provider.d.ts.map +1 -1
  31. package/dist/evidence-provider.js +54 -9
  32. package/dist/evidence-provider.js.map +1 -1
  33. package/dist/generate-schema.js +104 -43
  34. package/dist/generate-schema.js.map +1 -1
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/loop-compiler.d.ts +18 -4
  40. package/dist/loop-compiler.d.ts.map +1 -1
  41. package/dist/loop-compiler.js +167 -83
  42. package/dist/loop-compiler.js.map +1 -1
  43. package/dist/mcp/round-lifecycle.d.ts +10 -0
  44. package/dist/mcp/round-lifecycle.d.ts.map +1 -1
  45. package/dist/mcp/round-lifecycle.js +126 -17
  46. package/dist/mcp/round-lifecycle.js.map +1 -1
  47. package/dist/mcp/server.d.ts.map +1 -1
  48. package/dist/mcp/server.js +12 -3
  49. package/dist/mcp/server.js.map +1 -1
  50. package/dist/mcp/session.d.ts +32 -2
  51. package/dist/mcp/session.d.ts.map +1 -1
  52. package/dist/mcp/session.js +166 -50
  53. package/dist/mcp/session.js.map +1 -1
  54. package/dist/mcp/tools.d.ts.map +1 -1
  55. package/dist/mcp/tools.js +169 -38
  56. package/dist/mcp/tools.js.map +1 -1
  57. package/dist/policy.d.ts +10 -2
  58. package/dist/policy.d.ts.map +1 -1
  59. package/dist/policy.js +3 -2
  60. package/dist/policy.js.map +1 -1
  61. package/dist/prompt-assembler.d.ts +6 -1
  62. package/dist/prompt-assembler.d.ts.map +1 -1
  63. package/dist/prompt-assembler.js +41 -48
  64. package/dist/prompt-assembler.js.map +1 -1
  65. package/dist/protocol.d.ts +47 -27
  66. package/dist/protocol.d.ts.map +1 -1
  67. package/dist/protocol.js +5 -6
  68. package/dist/protocol.js.map +1 -1
  69. package/dist/round-coordinator.d.ts +19 -0
  70. package/dist/round-coordinator.d.ts.map +1 -1
  71. package/dist/round-coordinator.js +62 -4
  72. package/dist/round-coordinator.js.map +1 -1
  73. package/dist/round-driver.d.ts +4 -0
  74. package/dist/round-driver.d.ts.map +1 -1
  75. package/dist/round-driver.js +2 -0
  76. package/dist/round-driver.js.map +1 -1
  77. package/dist/round-transaction.d.ts +4 -0
  78. package/dist/round-transaction.d.ts.map +1 -1
  79. package/dist/round-transaction.js +9 -0
  80. package/dist/round-transaction.js.map +1 -1
  81. package/dist/self-eval.d.ts +41 -3
  82. package/dist/self-eval.d.ts.map +1 -1
  83. package/dist/self-eval.js +125 -13
  84. package/dist/self-eval.js.map +1 -1
  85. package/dist/verification-gate.d.ts +14 -16
  86. package/dist/verification-gate.d.ts.map +1 -1
  87. package/dist/verification-gate.js +162 -93
  88. package/dist/verification-gate.js.map +1 -1
  89. package/dist/version.d.ts +5 -0
  90. package/dist/version.d.ts.map +1 -0
  91. package/dist/version.js +5 -0
  92. package/dist/version.js.map +1 -0
  93. package/loop_policy.json +19 -3
  94. package/package.json +7 -7
  95. package/skills/perception/SKILL.md +53 -15
package/loop_policy.json CHANGED
@@ -13,7 +13,13 @@
13
13
  },
14
14
  "engine": {
15
15
  "stall_lookback_rounds": 3,
16
- "max_rounds": 20
16
+ "max_rounds": 200,
17
+ "enforcement_escalation_enabled": true,
18
+ "backtrack_enabled": true,
19
+ "backtrack_max_depth": 3,
20
+ "backtrack_preserve_discoveries": true,
21
+ "drift_clarification_max_streak": 3,
22
+ "backtrack_auto_restore": false
17
23
  },
18
24
  "prompt": {
19
25
  "full_refresh_interval": 0,
@@ -25,7 +31,12 @@
25
31
  "l2_adaptive_milestone_factor": 1000,
26
32
  "l2_adaptive_max_chars": 40000,
27
33
  "l2_adaptive_subgoal_factor": 100,
34
+ "l2_pointer_enabled": true,
28
35
  "l1_collapse_enabled": true,
36
+ "contract_nudge_on_l2": true,
37
+ "max_emphasize_l2": 5,
38
+ "max_emphasize_l1": 3,
39
+ "max_confusion_points": 3,
29
40
  "confusion_section_threshold": 0.15
30
41
  },
31
42
  "backend": {
@@ -37,13 +48,15 @@
37
48
  "max_objective_versions": 10,
38
49
  "progress_stall_threshold": 0.05,
39
50
  "progress_mismatch_threshold": 0.3,
51
+ "task_continuity_threshold": 0.2,
52
+ "intent_drift_threshold": 0.15,
40
53
  "criteria_dedup_threshold": 0.45,
41
54
  "subgoal_dedup_threshold": 0.6,
42
55
  "subgoal_match_threshold": 0.5,
43
- "intent_drift_threshold": 0.15,
56
+ "max_active_subgoals": 12,
44
57
  "constraint_match_threshold": 0.5,
45
58
  "subgoal_drift_alignment_threshold": 0.3,
46
- "task_continuity_threshold": 0.2
59
+ "constraint_id_enabled": true
47
60
  },
48
61
  "checkpoint": {
49
62
  "outcome_max_chars": 200
@@ -63,5 +76,8 @@
63
76
  "mcp": {
64
77
  "session_lease_ms": 30000,
65
78
  "session_lease_renew_interval_ms": 10000
79
+ },
80
+ "gate": {
81
+ "enabled": false
66
82
  }
67
83
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loopforge",
3
- "version": "3.7.0",
4
- "description": "External cognitive infrastructure for AI coding agents \u2014 breaks the summary cascade, provides independent verification, and enables model-directed prompt prioritization for 100+ round agent loops.",
3
+ "version": "3.7.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
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -34,11 +34,11 @@
34
34
  "LICENSE"
35
35
  ],
36
36
  "scripts": {
37
- "build": "tsc && node dist/generate-schema.js",
38
- "generate-schema": "tsc && node dist/generate-schema.js",
39
- "test": "tsc && node dist/generate-schema.js && node --test --test-concurrency=1 dist/tests/*.test.js",
40
- "test:watch": "tsc && node --test --watch dist/tests/*.test.js",
41
- "check": "tsc --noEmit",
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
42
  "verify:artifacts": "node scripts/verify-artifacts.mjs",
43
43
  "prepack": "npm run verify:artifacts && npm run build"
44
44
  },
@@ -79,10 +79,13 @@ The four core evaluation fields are strict:
79
79
 
80
80
  All other evaluation fields are optional and normalized by LoopForge. Useful
81
81
  fields include `execution_evidence`, `discovered_constraints`,
82
- `emerged_subtasks`, `completed_subtasks`, `blocked_subtasks`,
83
- `canceled_subtasks`, `next_action`, `drift_clarification`, `prompt_requests`,
84
- `outcome`, `blocker`, `round_contract`, `retroactiveClaims`, and
85
- `worker_results`.
82
+ `emerged_subtasks` (the only sub-goal creation channel — never an `sg-` ID),
83
+ `subgoal_updates` (explicit status transitions: active `sg-` IDs with a target
84
+ status; done/canceled are terminal and never reopen), `next_action`,
85
+ `drift_clarification`, `prompt_requests`, `outcome`, `blocker`,
86
+ `round_contract`, `retroactiveClaims`, `gate_ids` (only when the gate layer is
87
+ enabled), and `worker_results` (each entry declares an `outcome`; entries
88
+ without one are dropped).
86
89
 
87
90
  Optional malformed values are ignored or defaulted. They do not turn a valid
88
91
  submission into a transport error. Missing or mistyped core fields return
@@ -123,9 +126,13 @@ Prompts render stable IDs beside constraints, criteria, and sub-goals:
123
126
  - Criteria: `[cr-b5a6c7d8] Unit test coverage >= 90%`
124
127
  - Sub-goals: `[sg-f1e2d3c4] Add error handling to login`
125
128
 
126
- Prefer IDs for `constraint_violations`, criteria lists, subtask status changes,
127
- and drift clarifications. Natural-language matching remains a policy-controlled
128
- fallback when an ID is unavailable.
129
+ Prefer IDs for `constraint_violations`, criteria lists, and drift
130
+ clarifications (which may also anchor on real file paths). Sub-goal status
131
+ changes REQUIRE exact ACTIVE `sg-` IDs via `subgoal_updates` — description
132
+ matching is not a fallback there. Unknown, terminal (done/canceled), or
133
+ illegal transitions return `evaluation_invalid` before the round advances:
134
+ fix the payload and resubmit the same `roundId` (nothing is committed, no
135
+ rejection counter moves).
129
136
 
130
137
  An optional `round_contract` is a proposal for the next round. It becomes
131
138
  active only after the declaring round commits. While active, its `done_when`,
@@ -136,19 +143,40 @@ observed passing in the closing round.
136
143
  ## Backtrack
137
144
 
138
145
  A progress stall (stalled or exactly-flat window over the lookback rounds)
139
- can trigger backtrack to the last clean committed round. The prompt includes a
140
- diagnosis and workspace-restore requirements.
146
+ can trigger backtrack to the last clean committed round — the most recent
147
+ committed round with no error-level verification flags. The backtrack commits
148
+ a rollback directive that stays out of final history: your next submission is
149
+ the REDO of round `restorePoint + 1` and must reuse the round ID the prompt
150
+ carries; when it commits, the rollback record is replaced and disappears from
151
+ history views.
152
+
153
+ The backtrack prompt opens with a derived **Recovery Brief**:
154
+
155
+ - the trigger rule and the restore point;
156
+ - the redo round's ID (pass it back unchanged to `loopforge_next`);
157
+ - the failed rounds and their approaches — what must NOT be repeated;
158
+ - falsified assumptions — do not rebuild on these;
159
+ - discoveries from the skipped rounds that remain valid;
160
+ - the files to revert and the git commands to do it (the prompt may offer
161
+ `git stash` / `git checkout -- .` / `git reset --hard <restore-commit>`).
162
+
163
+ The same brief renders in `.loopforge/state/<loopId>-state.md` under Recent
164
+ while the recovery window is open; it is derived from committed rounds plus
165
+ the in-flight attempt (rejected payloads are never a source) and disappears
166
+ once the redo commits.
141
167
 
142
168
  When backtrack occurs:
143
169
 
144
- 1. Restore the workspace exactly as requested before doing more work.
145
- 2. Read the restored prompt and derived state.
146
- 3. Do not repeat the failed approach without addressing the diagnosis.
170
+ 1. Restore the workspace exactly as requested before doing more work — the
171
+ next submission's git evidence is checked against the restore point's HEAD.
172
+ 2. Read the Recovery Brief, the restored prompt, and the derived state.
173
+ 3. Do not repeat a failed approach listed in the brief without addressing it.
147
174
  4. Keep valid discoveries from skipped rounds in later evaluations.
148
175
 
149
176
  If the workspace is not restored, the next submission is rejected with
150
177
  `backtrack_workspace_not_restored`. A stalled active contract should be closed
151
- with `outcome: "blocked"` and a blocker while proposing the revision.
178
+ with `outcome: "blocked"` and a blocker while proposing the revised contract
179
+ in the same submission.
152
180
 
153
181
  ## Drift
154
182
 
@@ -193,8 +221,18 @@ but do not treat it as an independent source of truth.
193
221
 
194
222
  Use `loopforge_pause` before an intentional interruption,
195
223
  `loopforge_resume` to reconstruct a durable session, and `loopforge_stop` only
196
- for an intentional terminal stop. Use `loopforge_gate_check` and
197
- `loopforge_gate_resolve` for recorded human or agent gates.
224
+ for an intentional terminal stop.
225
+
226
+ The two gate tools are opt-in (`policy.gate.enabled`, default false) and are
227
+ hidden from `tools/list` when disabled. When enabled, preflight a high-risk
228
+ action with `loopforge_gate_check` (a structured `GateActionDescriptor`): a
229
+ `user_required` verdict returns a gate id and an approval question, and only
230
+ an approved gate may be cited via `evaluation.gate_ids` in the round that
231
+ performs the action. Present the approval question to the human and record
232
+ their decision with `loopforge_gate_resolve`. Safe preparation work
233
+ (investigation, dry-runs, rollback evidence) never needs a gate. Remember:
234
+ approval is recorded through you, the Agent — LoopForge cannot machine-verify
235
+ a human is present.
198
236
 
199
237
  Delegation does not create a separate LoopForge mode. Give each worker a
200
238
  self-contained subtask and relevant hard constraints, then place its result in