loopforge 3.8.3 → 3.9.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 (135) hide show
  1. package/README.md +15 -0
  2. package/dist/audit.d.ts +13 -1
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/audit.js +18 -3
  5. package/dist/audit.js.map +1 -1
  6. package/dist/canonical-state.d.ts +1 -2
  7. package/dist/canonical-state.d.ts.map +1 -1
  8. package/dist/canonical-state.js +4 -12
  9. package/dist/canonical-state.js.map +1 -1
  10. package/dist/cli.js +12 -12
  11. package/dist/committed-round.d.ts +48 -23
  12. package/dist/committed-round.d.ts.map +1 -1
  13. package/dist/committed-round.js +214 -149
  14. package/dist/committed-round.js.map +1 -1
  15. package/dist/contract-items.d.ts +3 -2
  16. package/dist/contract-items.d.ts.map +1 -1
  17. package/dist/contract-items.js +18 -7
  18. package/dist/contract-items.js.map +1 -1
  19. package/dist/enforcement-gate.d.ts +15 -5
  20. package/dist/enforcement-gate.d.ts.map +1 -1
  21. package/dist/enforcement-gate.js +60 -159
  22. package/dist/enforcement-gate.js.map +1 -1
  23. package/dist/engine.d.ts.map +1 -1
  24. package/dist/engine.js +20 -14
  25. package/dist/engine.js.map +1 -1
  26. package/dist/evidence-claims.d.ts +6 -5
  27. package/dist/evidence-claims.d.ts.map +1 -1
  28. package/dist/evidence-claims.js +21 -20
  29. package/dist/evidence-claims.js.map +1 -1
  30. package/dist/evidence-provider.d.ts +73 -42
  31. package/dist/evidence-provider.d.ts.map +1 -1
  32. package/dist/evidence-provider.js +437 -138
  33. package/dist/evidence-provider.js.map +1 -1
  34. package/dist/explain.d.ts +18 -3
  35. package/dist/explain.d.ts.map +1 -1
  36. package/dist/explain.js +26 -5
  37. package/dist/explain.js.map +1 -1
  38. package/dist/field-accounting.d.ts +29 -0
  39. package/dist/field-accounting.d.ts.map +1 -0
  40. package/dist/field-accounting.js +132 -0
  41. package/dist/field-accounting.js.map +1 -0
  42. package/dist/index.d.ts +7 -3
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +4 -1
  45. package/dist/index.js.map +1 -1
  46. package/dist/loop-compiler.d.ts +5 -11
  47. package/dist/loop-compiler.d.ts.map +1 -1
  48. package/dist/loop-compiler.js +30 -90
  49. package/dist/loop-compiler.js.map +1 -1
  50. package/dist/loop-store.d.ts +3 -0
  51. package/dist/loop-store.d.ts.map +1 -1
  52. package/dist/loop-store.js +21 -11
  53. package/dist/loop-store.js.map +1 -1
  54. package/dist/mcp/round-lifecycle.d.ts +30 -2
  55. package/dist/mcp/round-lifecycle.d.ts.map +1 -1
  56. package/dist/mcp/round-lifecycle.js +206 -25
  57. package/dist/mcp/round-lifecycle.js.map +1 -1
  58. package/dist/mcp/server.d.ts.map +1 -1
  59. package/dist/mcp/server.js +17 -14
  60. package/dist/mcp/server.js.map +1 -1
  61. package/dist/mcp/session.d.ts +15 -1
  62. package/dist/mcp/session.d.ts.map +1 -1
  63. package/dist/mcp/session.js +34 -1
  64. package/dist/mcp/session.js.map +1 -1
  65. package/dist/mcp/submission-boundary.d.ts +5 -2
  66. package/dist/mcp/submission-boundary.d.ts.map +1 -1
  67. package/dist/mcp/submission-boundary.js +38 -6
  68. package/dist/mcp/submission-boundary.js.map +1 -1
  69. package/dist/mcp/tools.d.ts.map +1 -1
  70. package/dist/mcp/tools.js +73 -45
  71. package/dist/mcp/tools.js.map +1 -1
  72. package/dist/policy-metrics.d.ts +14 -0
  73. package/dist/policy-metrics.d.ts.map +1 -1
  74. package/dist/policy-metrics.js +53 -1
  75. package/dist/policy-metrics.js.map +1 -1
  76. package/dist/policy.d.ts +1 -3
  77. package/dist/policy.d.ts.map +1 -1
  78. package/dist/policy.js +3 -4
  79. package/dist/policy.js.map +1 -1
  80. package/dist/prompt-assembler.d.ts.map +1 -1
  81. package/dist/prompt-assembler.js +71 -35
  82. package/dist/prompt-assembler.js.map +1 -1
  83. package/dist/protocol.d.ts +186 -19
  84. package/dist/protocol.d.ts.map +1 -1
  85. package/dist/protocol.js +4 -3
  86. package/dist/protocol.js.map +1 -1
  87. package/dist/replay.d.ts +3 -0
  88. package/dist/replay.d.ts.map +1 -1
  89. package/dist/replay.js +46 -7
  90. package/dist/replay.js.map +1 -1
  91. package/dist/round-contract.d.ts +5 -4
  92. package/dist/round-contract.d.ts.map +1 -1
  93. package/dist/round-contract.js +4 -4
  94. package/dist/round-contract.js.map +1 -1
  95. package/dist/round-coordinator.d.ts +11 -1
  96. package/dist/round-coordinator.d.ts.map +1 -1
  97. package/dist/round-coordinator.js +33 -14
  98. package/dist/round-coordinator.js.map +1 -1
  99. package/dist/round-driver.d.ts +6 -1
  100. package/dist/round-driver.d.ts.map +1 -1
  101. package/dist/round-driver.js +3 -0
  102. package/dist/round-driver.js.map +1 -1
  103. package/dist/round-facts.d.ts +3 -2
  104. package/dist/round-facts.d.ts.map +1 -1
  105. package/dist/round-facts.js +4 -4
  106. package/dist/round-facts.js.map +1 -1
  107. package/dist/round-transaction.d.ts +24 -10
  108. package/dist/round-transaction.d.ts.map +1 -1
  109. package/dist/round-transaction.js +83 -19
  110. package/dist/round-transaction.js.map +1 -1
  111. package/dist/self-eval.d.ts +28 -10
  112. package/dist/self-eval.d.ts.map +1 -1
  113. package/dist/self-eval.js +522 -128
  114. package/dist/self-eval.js.map +1 -1
  115. package/dist/submission-diagnostics.d.ts +12 -0
  116. package/dist/submission-diagnostics.d.ts.map +1 -0
  117. package/dist/submission-diagnostics.js +12 -0
  118. package/dist/submission-diagnostics.js.map +1 -0
  119. package/dist/submission-guidance.d.ts +119 -0
  120. package/dist/submission-guidance.d.ts.map +1 -0
  121. package/dist/submission-guidance.js +766 -0
  122. package/dist/submission-guidance.js.map +1 -0
  123. package/dist/submission-receipt.d.ts +48 -0
  124. package/dist/submission-receipt.d.ts.map +1 -0
  125. package/dist/submission-receipt.js +336 -0
  126. package/dist/submission-receipt.js.map +1 -0
  127. package/dist/verification-gate.d.ts +13 -7
  128. package/dist/verification-gate.d.ts.map +1 -1
  129. package/dist/verification-gate.js +149 -90
  130. package/dist/verification-gate.js.map +1 -1
  131. package/dist/version.d.ts +1 -1
  132. package/dist/version.js +1 -1
  133. package/loop_policy.json +58 -59
  134. package/package.json +68 -67
  135. package/skills/perception/SKILL.md +90 -42
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.3";
4
+ export declare const VERSION = "3.9.1";
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.3";
4
+ export const VERSION = "3.9.1";
5
5
  //# sourceMappingURL=version.js.map
package/loop_policy.json CHANGED
@@ -1,59 +1,58 @@
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": "5",
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": 5000,
21
+ "l1_max_chars": 10000,
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
+ "max_active_subgoals": 12
36
+ },
37
+ "checkpoint": {
38
+ "outcome_max_chars": 200
39
+ },
40
+ "state_file": {
41
+ "enabled": true,
42
+ "directory": ".loopforge/state"
43
+ },
44
+ "evidence": {
45
+ "providers": [
46
+ "git"
47
+ ],
48
+ "timeout_ms": 120000,
49
+ "commands": []
50
+ },
51
+ "mcp": {
52
+ "session_lease_ms": 30000,
53
+ "session_lease_renew_interval_ms": 10000
54
+ },
55
+ "gate": {
56
+ "enabled": false
57
+ }
58
+ }
package/package.json CHANGED
@@ -1,67 +1,68 @@
1
- {
2
- "name": "loopforge",
3
- "version": "3.8.3",
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.9.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
+ "measure:boundary": "node scripts/measure-boundary.mjs",
44
+ "prepack": "npm run verify:artifacts && npm run build"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/kyrielrving11/LoopForge.git"
49
+ },
50
+ "keywords": [
51
+ "cognitive-state",
52
+ "ai-agent",
53
+ "durable-agent",
54
+ "claude-code",
55
+ "llm",
56
+ "cognitive-stability",
57
+ "constraint-management",
58
+ "mcp"
59
+ ],
60
+ "engines": {
61
+ "node": ">=18"
62
+ },
63
+ "license": "MIT",
64
+ "devDependencies": {
65
+ "@types/node": "^20.0.0",
66
+ "typescript": "^5.4.0"
67
+ }
68
+ }
@@ -60,13 +60,18 @@ completed task.
60
60
  ## Plan the next slice
61
61
 
62
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.
63
+ slice. Size the slice by what one machine-checkable outcome covers — a
64
+ requirements list is not a round list, and coupled changes that share one
65
+ objective, one evidence story, and one recovery path belong in the same round.
66
+ Bind each item to a configured evidence command with `verify_with`, and limit
67
+ `scope` to files or directories that slice may touch. The proposal becomes
68
+ active only after its declaring round commits.
69
+ While it is open, you do **not** need to restate it: omitting `round_contract`
70
+ continues the active contract. A different proposal is ignored as
71
+ `contract_premature`. If this round closes the contract and another slice
72
+ follows, declare the successor in this same submission. If the slice is
73
+ blocked, report `outcome: "blocked"` with a concrete `blocker` instead of
74
+ silently replacing the active contract.
70
75
 
71
76
  This is a planning aid, not a second gate. LoopForge learns the plan only from
72
77
  committed evaluation fields, contract proposals, observations, and changes.
@@ -94,15 +99,35 @@ The four core evaluation fields are strict:
94
99
  | `constraint_violations` | Array of real violations, preferably using `c-XXXXXXXX` IDs. |
95
100
  | `should_continue` | Boolean. `false` only when the whole task is complete. |
96
101
 
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
+ Before submitting, check whether any of these events actually happened. Fill the
103
+ matching field only when it did; omit it otherwise.
104
+
105
+ | Event | Field | What LoopForge does with it |
106
+ | --- | --- | --- |
107
+ | The round changed files or ran tests | `execution_report.files_changed`, `execution_report.tests_reported` | Compares the report with machine observations; test counts stay self-reported |
108
+ | You found a constraint later rounds must respect | `discovered_constraints` | The compiler merges it into the active set |
109
+ | Evidence falsified an earlier assumption | `wrong_assumptions` | Feeds corrected-assumption state and recovery facts |
110
+ | A sub-problem surfaced | `emerged_subtasks` | The only sub-goal creation channel |
111
+ | An active sub-goal moved status | `subgoal_updates` | Applies an explicit transition |
112
+ | You delegated work | `worker_results` | Saves the report and delegation journal entry; does **not** promote worker discoveries |
113
+ | You are planning the next slice | `round_contract` | Becomes active only after this round commits |
114
+ | A contract item progressed | `execution_report.contract_item_claims` | Starts machine evaluation; the item is verified only when its bound commands pass |
115
+ | You need context emphasized | `prompt_requests` | Exact-match reorder or confusion alerts in the next prompt; never long-term knowledge |
116
+ | You reached a meaningful boundary | `compression_checkpoint`, `checkpoint_label` | Creates a recoverable milestone |
117
+ | You are blocked or stopping | `outcome`, `blocker`, `stop_reason`, `no_change_reason` | Runs the corresponding stop/lifecycle rule |
118
+ | You understand the objective better | `objective_refinement` | Appends to the objective; never replaces it |
119
+ | A constraint or criterion is wrong | `retracted_constraints`, `revised_success_criteria` | Updates derived state within existing boundaries |
120
+ | You need a prior approval checked | `gate_ids`; `retroactiveClaims` | Checks existing gate references or prior-round evidence |
121
+
122
+ `execution_report.files_changed` is the **boundary net change**: paths whose
123
+ content or file type differs between round preparation and this submission,
124
+ including deletions. A commit alone adds no entry when content is unchanged.
125
+ Do not list gitignored paths merely to look complete.
102
126
 
103
127
  `emerged_subtasks` is the only sub-goal creation channel. It contains plain
104
128
  descriptions, never `sg-` IDs. `subgoal_updates` changes existing active IDs;
105
- done and canceled are terminal and cannot be reopened.
129
+ done and canceled are terminal and cannot be reopened. The prompt or
130
+ `submission_guidance` renders the real active IDs; never invent one.
106
131
 
107
132
  `outcome` may be `success`, `partial`, `failed`, or `blocked`. A blocked
108
133
  outcome needs a concrete `blocker`; `stop_reason` of `blocked` or
@@ -115,14 +140,23 @@ and workspace-containment errors return `evaluation_invalid` or
115
140
  `contract_invalid` before advance. Correct the payload and resubmit the same
116
141
  `roundId`; nothing is committed and no rejection counter moves.
117
142
 
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.
143
+ A successful round should include an `execution_report`. An empty or missing
144
+ report is a reporting gap (a `warn`), not by itself a rejection: acceptance is
145
+ decided by machine evidence and contract rules, never by how many optional
146
+ fields were filled. `no_change_reason` is an escape only when no enabled
147
+ verification command exists. It never creates evidence and never excuses an
148
+ open contract.
122
149
 
123
150
  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.
151
+ Do not infer a missing field from natural language, do not fill a field to
152
+ satisfy a coverage check, and do not put a guessed evaluation in free text.
153
+ When no event occurred, omit the field.
154
+
155
+ Each prepared response carries `submission_guidance` with the real contract
156
+ item ids/statuses, active sub-goal ids, usable commands and the fields that
157
+ apply now. Each submission returns `submission_receipt`, which separates:
158
+ reports that were saved, derived state that actually changed, and machine
159
+ verification results. A report marked `saved` is not a verified fact.
126
160
 
127
161
  ## IDs and contracts
128
162
 
@@ -171,7 +205,7 @@ server was started in:
171
205
 
172
206
  ```json
173
207
  {
174
- "version": "4",
208
+ "version": "5",
175
209
  "evidence": {
176
210
  "commands": [{
177
211
  "name": "verify",
@@ -194,11 +228,12 @@ workspace. `loopforge doctor` statically checks every configured command —
194
228
  its name, executable, arguments, timeouts, and workspace containment — and
195
229
  never executes one.
196
230
 
197
- Every prepared round returns `capability`: which providers are available, which
198
- commands are enabled and after-capable, and `contractVerificationAvailable`.
199
- When that is `false`, no configured command can back a contract item: run
200
- rounds without a contract instead of declaring items that cannot close. The
201
- `warnings` list states the same thing in words.
231
+ Every prepared response carries `submission_guidance.contract_commands` and
232
+ `submission_guidance.contract_verification_available`; `loopforge_status`
233
+ `view=session` also returns the full `capability` object. When verification is
234
+ unavailable, no configured command can back a contract item: run rounds without
235
+ a contract instead of declaring items that cannot close. The `warnings` list
236
+ states the same thing in words.
202
237
 
203
238
  A command's ENTRYPOINT is the file it names plus `package.json` when a package
204
239
  manager runs it. It must already be part of the workspace when the round
@@ -216,11 +251,12 @@ Prepare it before the round that depends on it.
216
251
 
217
252
  ## Backtrack and recovery
218
253
 
219
- A progress stall is machine-first when Git history is observable over the
220
- lookback window. Self-reported `progress_estimate` is only a fallback when
221
- machine history cannot be read. Machine motion can excuse a stall but cannot
222
- create one. A machine-backed success round is finishing, even if its closing
223
- round changes no files.
254
+ A progress stall requires observable Git history over the lookback window.
255
+ Committed work counts as motion through the Git HEAD change, even when the
256
+ closing worktree is clean, and the round you are submitting counts too: if it
257
+ moved files or committed, it cancels the verdict. If machine history cannot be
258
+ read, no stall verdict is made. A machine-backed success round is finishing,
259
+ even if its closing round changes no files.
224
260
 
225
261
  Backtrack records a rollback directive and restores the round counter to the
226
262
  last clean committed round. Rejected attempts are never history. The next
@@ -233,10 +269,14 @@ target HEAD. It states restoration facts, not a prescribed command.
233
269
 
234
270
  When backtrack occurs:
235
271
 
236
- 1. Restore the workspace exactly as requested before doing more work.
237
- 2. Read the Recovery Brief, restored prompt, and derived state.
238
- 3. Do not repeat a failed approach without addressing its cause.
239
- 4. Carry valid discoveries into later evaluations.
272
+ 1. Restore the workspace exactly as requested before doing more work: the
273
+ restore point's HEAD, with none of the failed rounds' changes left behind.
274
+ Work in progress the restore point already carried may stay.
275
+ 2. Submit one recovery evaluation from the restored state, so LoopForge can
276
+ verify the restore before the redo's own work — and any commit — follows.
277
+ 3. Read the Recovery Brief, restored prompt, and derived state.
278
+ 4. Do not repeat a failed approach without addressing its cause.
279
+ 5. Carry valid discoveries into later evaluations.
240
280
 
241
281
  If the rolled-back work used an active contract, close the stalled contract in
242
282
  the redo with `outcome: "blocked"` and declare the revised contract in that
@@ -247,15 +287,20 @@ same submission. Restating the stalled contract commits more of the same.
247
287
  - Non-null `prompt`: execute it and submit the next evaluation.
248
288
  - `enforcementAction: "reject"`: retry the same logical round and ID; the
249
289
  attempt increases.
250
- - `enforcementAction: "backtrack"`: restore the workspace, then continue from
251
- the restored prompt and round.
290
+ - `enforcementAction: "backtrack"`: restore the workspace, submit one recovery
291
+ evaluation from the restored state, then redo the round from its restored
292
+ prompt and round ID.
252
293
  - Null `prompt`: inspect `stopReason`.
253
294
 
254
- Read `verificationStatus`, `roundSuccess`, `level`, `warnings`, and
255
- `enforcementReason` before planning the next slice. `trusted` means claimed
256
- work is machine-backed, `insufficient` means evidence is missing, and
257
- `contradicted` means a machine fact denies a claim. These are evidence
258
- postures, not subjective quality scores.
295
+ Read `submission_guidance` before composing the next evaluation, and read
296
+ `verificationStatus`, `roundSuccess`, `level`, `warnings`, and
297
+ `enforcementReason` before planning the next slice. In
298
+ `submission_receipt.verification`, `contract_status` is the contract-item
299
+ posture and `evidence_status` is the round-level machine evidence posture; do
300
+ not read "no active contract" as "verified". `submission_receipt.reports`
301
+ distinguishes a saved report from derived state that changed and from a machine
302
+ verification result; `not_applied` means the submission did not become history.
303
+ These are evidence postures, not subjective quality scores.
259
304
 
260
305
  Errors use `{ok: false, error: {code, message, retryable, ...}}`. Branch on the
261
306
  stable `code`, not the prose in `message`. Payload errors such as
@@ -303,7 +348,10 @@ call. Safe investigation and dry-runs need no gate.
303
348
 
304
349
  Delegation does not create another LoopForge mode. Give each worker a
305
350
  self-contained subtask and hard constraints, then place the result in
306
- `worker_results` so it can enter the next Canonical State.
351
+ `worker_results`. A worker result is a report with its source: its
352
+ `discoveredConstraints` does **not** enter the global constraint set by itself.
353
+ If you accept a worker's finding, state it in top-level
354
+ `discovered_constraints` — that is the only promotion channel.
307
355
 
308
356
  ## Rules
309
357