loopforge 3.7.1 → 3.8.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 (144) hide show
  1. package/README.md +171 -169
  2. package/dist/audit.d.ts +53 -1
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/audit.js +106 -22
  5. package/dist/audit.js.map +1 -1
  6. package/dist/canonical-state.d.ts +52 -67
  7. package/dist/canonical-state.d.ts.map +1 -1
  8. package/dist/canonical-state.js +134 -147
  9. package/dist/canonical-state.js.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +103 -4
  12. package/dist/cli.js.map +1 -1
  13. package/dist/cognitive-facts.d.ts +13 -0
  14. package/dist/cognitive-facts.d.ts.map +1 -1
  15. package/dist/cognitive-facts.js +28 -13
  16. package/dist/cognitive-facts.js.map +1 -1
  17. package/dist/committed-round.d.ts +103 -21
  18. package/dist/committed-round.d.ts.map +1 -1
  19. package/dist/committed-round.js +188 -45
  20. package/dist/committed-round.js.map +1 -1
  21. package/dist/contract-items.d.ts +55 -0
  22. package/dist/contract-items.d.ts.map +1 -0
  23. package/dist/contract-items.js +180 -0
  24. package/dist/contract-items.js.map +1 -0
  25. package/dist/enforcement-gate.d.ts +20 -2
  26. package/dist/enforcement-gate.d.ts.map +1 -1
  27. package/dist/enforcement-gate.js +197 -386
  28. package/dist/enforcement-gate.js.map +1 -1
  29. package/dist/engine.d.ts +1 -1
  30. package/dist/engine.d.ts.map +1 -1
  31. package/dist/engine.js +53 -38
  32. package/dist/engine.js.map +1 -1
  33. package/dist/evidence-claims.d.ts +4 -4
  34. package/dist/evidence-claims.d.ts.map +1 -1
  35. package/dist/evidence-claims.js +16 -14
  36. package/dist/evidence-claims.js.map +1 -1
  37. package/dist/evidence-provider.d.ts +85 -89
  38. package/dist/evidence-provider.d.ts.map +1 -1
  39. package/dist/evidence-provider.js +328 -184
  40. package/dist/evidence-provider.js.map +1 -1
  41. package/dist/explain.d.ts +76 -0
  42. package/dist/explain.d.ts.map +1 -0
  43. package/dist/explain.js +127 -0
  44. package/dist/explain.js.map +1 -0
  45. package/dist/generate-schema.js +152 -16
  46. package/dist/generate-schema.js.map +1 -1
  47. package/dist/index.d.ts +6 -6
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +5 -5
  50. package/dist/index.js.map +1 -1
  51. package/dist/loop-compiler.d.ts +40 -53
  52. package/dist/loop-compiler.d.ts.map +1 -1
  53. package/dist/loop-compiler.js +229 -553
  54. package/dist/loop-compiler.js.map +1 -1
  55. package/dist/loop-extras-parser.d.ts +0 -1
  56. package/dist/loop-extras-parser.d.ts.map +1 -1
  57. package/dist/loop-extras-parser.js +0 -4
  58. package/dist/loop-extras-parser.js.map +1 -1
  59. package/dist/loop-projection.d.ts.map +1 -1
  60. package/dist/loop-projection.js +3 -1
  61. package/dist/loop-projection.js.map +1 -1
  62. package/dist/mcp/round-lifecycle.d.ts +30 -21
  63. package/dist/mcp/round-lifecycle.d.ts.map +1 -1
  64. package/dist/mcp/round-lifecycle.js +47 -103
  65. package/dist/mcp/round-lifecycle.js.map +1 -1
  66. package/dist/mcp/server.d.ts.map +1 -1
  67. package/dist/mcp/server.js +51 -7
  68. package/dist/mcp/server.js.map +1 -1
  69. package/dist/mcp/session.d.ts +39 -23
  70. package/dist/mcp/session.d.ts.map +1 -1
  71. package/dist/mcp/session.js +148 -163
  72. package/dist/mcp/session.js.map +1 -1
  73. package/dist/mcp/submission-boundary.d.ts +89 -0
  74. package/dist/mcp/submission-boundary.d.ts.map +1 -0
  75. package/dist/mcp/submission-boundary.js +203 -0
  76. package/dist/mcp/submission-boundary.js.map +1 -0
  77. package/dist/mcp/tools.d.ts.map +1 -1
  78. package/dist/mcp/tools.js +249 -128
  79. package/dist/mcp/tools.js.map +1 -1
  80. package/dist/policy-metrics.js +2 -2
  81. package/dist/policy-metrics.js.map +1 -1
  82. package/dist/policy.d.ts +55 -93
  83. package/dist/policy.d.ts.map +1 -1
  84. package/dist/policy.js +149 -38
  85. package/dist/policy.js.map +1 -1
  86. package/dist/prompt-assembler.d.ts +1 -32
  87. package/dist/prompt-assembler.d.ts.map +1 -1
  88. package/dist/prompt-assembler.js +282 -435
  89. package/dist/prompt-assembler.js.map +1 -1
  90. package/dist/prompt-policy.d.ts +1 -4
  91. package/dist/prompt-policy.d.ts.map +1 -1
  92. package/dist/prompt-policy.js +6 -7
  93. package/dist/prompt-policy.js.map +1 -1
  94. package/dist/protocol.d.ts +365 -142
  95. package/dist/protocol.d.ts.map +1 -1
  96. package/dist/protocol.js +21 -66
  97. package/dist/protocol.js.map +1 -1
  98. package/dist/replay.js +2 -2
  99. package/dist/replay.js.map +1 -1
  100. package/dist/round-contract.d.ts +69 -57
  101. package/dist/round-contract.d.ts.map +1 -1
  102. package/dist/round-contract.js +104 -64
  103. package/dist/round-contract.js.map +1 -1
  104. package/dist/round-coordinator.d.ts +36 -16
  105. package/dist/round-coordinator.d.ts.map +1 -1
  106. package/dist/round-coordinator.js +166 -102
  107. package/dist/round-coordinator.js.map +1 -1
  108. package/dist/round-driver.d.ts +3 -5
  109. package/dist/round-driver.d.ts.map +1 -1
  110. package/dist/round-driver.js +0 -1
  111. package/dist/round-driver.js.map +1 -1
  112. package/dist/round-facts.d.ts +96 -0
  113. package/dist/round-facts.d.ts.map +1 -0
  114. package/dist/round-facts.js +216 -0
  115. package/dist/round-facts.js.map +1 -0
  116. package/dist/round-transaction.d.ts +19 -9
  117. package/dist/round-transaction.d.ts.map +1 -1
  118. package/dist/round-transaction.js +90 -22
  119. package/dist/round-transaction.js.map +1 -1
  120. package/dist/self-eval.d.ts +87 -9
  121. package/dist/self-eval.d.ts.map +1 -1
  122. package/dist/self-eval.js +396 -27
  123. package/dist/self-eval.js.map +1 -1
  124. package/dist/subgoal-state.d.ts +77 -0
  125. package/dist/subgoal-state.d.ts.map +1 -0
  126. package/dist/subgoal-state.js +198 -0
  127. package/dist/subgoal-state.js.map +1 -0
  128. package/dist/token-utils.d.ts +52 -19
  129. package/dist/token-utils.d.ts.map +1 -1
  130. package/dist/token-utils.js +83 -72
  131. package/dist/token-utils.js.map +1 -1
  132. package/dist/verification-gate.d.ts +14 -31
  133. package/dist/verification-gate.d.ts.map +1 -1
  134. package/dist/verification-gate.js +178 -496
  135. package/dist/verification-gate.js.map +1 -1
  136. package/dist/version.d.ts +1 -1
  137. package/dist/version.js +1 -1
  138. package/dist/workspace.d.ts +9 -0
  139. package/dist/workspace.d.ts.map +1 -1
  140. package/dist/workspace.js +17 -0
  141. package/dist/workspace.js.map +1 -1
  142. package/loop_policy.json +6 -30
  143. package/package.json +1 -1
  144. package/skills/perception/SKILL.md +243 -79
@@ -9,7 +9,6 @@ export declare enum Mode {
9
9
  LOOP_COMPILE = "loop_compile",
10
10
  FEEDBACK = "feedback"
11
11
  }
12
- import type { PresentedStateSnapshot } from "./canonical-state.js";
13
12
  export declare enum AgentStatus {
14
13
  OK = "ok",
15
14
  ERROR = "error",
@@ -22,27 +21,6 @@ export interface ExecutionFeedback {
22
21
  manual_fixes_needed: string;
23
22
  }
24
23
  export declare function makeExecutionFeedback(overrides?: Partial<ExecutionFeedback>): ExecutionFeedback;
25
- /** P4: Structured execution evidence reported by the agent after each round.
26
- * Gives LoopForge visibility into what actually happened — files changed,
27
- * test results, success criteria met, and a subjective progress estimate.
28
- * Enables the compiler to cross-validate agent claims and compute real progress. */
29
- export interface ExecutionEvidence {
30
- /** Files changed in this round. Empty if no files were modified. */
31
- files_changed: string[];
32
- /** Test results. null if no tests were run. */
33
- test_results: {
34
- passed: number;
35
- failed: number;
36
- skipped: number;
37
- } | null;
38
- /** Success criteria from the Loop Objective that were MET this round. */
39
- success_criteria_met: string[];
40
- /** Success criteria from the Loop Objective that REMAIN unmet. */
41
- success_criteria_remaining: string[];
42
- /** Agent's own estimate of overall progress (0.0 to 1.0). */
43
- progress_estimate: number;
44
- }
45
- export declare function makeExecutionEvidence(overrides?: Partial<ExecutionEvidence>): ExecutionEvidence;
46
24
  /** P5: A revision to a success criterion — the old form and the new form.
47
25
  * The agent proposes this when it discovers the original criterion was
48
26
  * wrong, unrealistic, or needs refinement. */
@@ -50,43 +28,6 @@ export interface CriterionRevision {
50
28
  old: string;
51
29
  new: string;
52
30
  }
53
- /** v3.3: Round Contract. v3.4 semantics: the field on a submission is a
54
- * PROPOSAL for the NEXT round — it becomes the ACTIVE contract (rendered
55
- * as the Current Task and checked for execution conformance) only after
56
- * the declaring round commits, and stays active until a committed eval
57
- * lists every done_when item in success_criteria_met (complete) or
58
- * reports outcome="blocked". While active it is restated unchanged each
59
- * round; on completion or block, the next contract is declared instead.
60
- * The ACTIVE contract is machine-derived from committed rounds
61
- * (round-contract.ts) — never read from last_round_result. Optional:
62
- * absent = no contract this round, all contract checks stay silent and
63
- * rendering is identical to a contract-less round.
64
- *
65
- * Every field is machine-checkable:
66
- * - done_when items are claimed satisfied by listing them in
67
- * execution_evidence.success_criteria_met (verified per-round claim
68
- * model); leaving them out while success is claimed is premature_boundary
69
- * against the ACTIVE contract.
70
- * - verification_plan names must reference configured, enabled
71
- * evidence.commands (round_unverifiable otherwise).
72
- * - scope lists the files/directories the round may touch; actual git
73
- * changes outside it trigger round_scope_drift against the ACTIVE
74
- * contract. */
75
- export interface RoundContract {
76
- /** Round focus, one line. Rendered as the Current Task's first line. */
77
- work_item?: string;
78
- /** Completion conditions: cr-XXXXXXXX criterion IDs or free text.
79
- * Claimed met = listed in success_criteria_met; still open = listed in
80
- * success_criteria_remaining. ≤ 20 items. */
81
- done_when: string[];
82
- /** Verification plan: names of configured, enabled evidence commands
83
- * (policy.evidence.commands[].name). ≤ 20 items. */
84
- verification_plan: string[];
85
- /** Files/directories this round may touch (workspace-relative paths,
86
- * forward or back slashes, "./" prefix and trailing slashes accepted).
87
- * Out-of-scope git changes = round_scope_drift. ≤ 50 items. */
88
- scope: string[];
89
- }
90
31
  /** Structured self-evaluation submitted at the round boundary.
91
32
  * The agent outputs this after completing each round.
92
33
  * Every field is consumed by at least one downstream function.
@@ -101,8 +42,8 @@ export interface SelfEvaluation {
101
42
  * computeConstraintRetirement (activity detection), vault lineage. */
102
43
  output_summary: string;
103
44
  /** Constraints the agent actually violated this round.
104
- * Feeds: checkLoopHealth (constraint_integrity),
105
- * buildRollingSummary (recurring_issues), computeConstraintRetirement. */
45
+ * Feeds: deriveRecurringFlags (the constraint_violation kind) and
46
+ * computeConstraintRetirement. */
106
47
  constraint_violations: string[];
107
48
  /** false ONLY when the entire task is complete. Tells the autonomous
108
49
  * runner to stop the loop. Not consumed by the compiler. */
@@ -132,7 +73,7 @@ export interface SelfEvaluation {
132
73
  /** P4: Structured evidence of what was executed this round.
133
74
  * Files changed, test results, criteria met/remaining, progress estimate.
134
75
  * Enables the compiler to validate claims and compute real progress. */
135
- execution_evidence?: ExecutionEvidence;
76
+ execution_report?: ExecutionReport;
136
77
  /** P5: Constraints that the agent now believes are wrong or irrelevant.
137
78
  * Removed from the active constraint set by the compiler.
138
79
  * Omit or leave empty if none. */
@@ -156,17 +97,12 @@ export interface SelfEvaluation {
156
97
  * The engine automatically writes these to the delegation journal.
157
98
  * Omit or leave empty if no delegations occurred. */
158
99
  worker_results?: WorkerResult[];
159
- /** v1.16: Agent's declared next action — what it plans to do in the
160
- * following round. Stored as loop state and rendered in the next prompt
161
- * so the agent's self-planning persists across rounds. Optional —
162
- * no next_action means the compiler generates the next task as before. */
163
- next_action?: string;
164
100
  /** v2.5: Why the agent is stopping. Only meaningful when
165
101
  * should_continue=false and success=false. Defaults to "gave_up"
166
102
  * (current behavior) when absent. "blocked" means work cannot proceed
167
103
  * under current constraints; "needs_human_input" requires intervention. */
168
104
  stop_reason?: "gave_up" | "blocked" | "needs_human_input";
169
- /** v2.12: Declared tri-state outcome. When absent, derived from success
105
+ /** v2.12: Declared outcome (four values). When absent, derived from success
170
106
  * (true → "success", false → "failed"). "partial" and "blocked" can only
171
107
  * be declared explicitly. A declared non-success outcome suppresses the
172
108
  * success-class verification checks even when success=true. */
@@ -194,13 +130,6 @@ export interface SelfEvaluation {
194
130
  * the round is rejected. Safe pre-work (investigation, dry-runs,
195
131
  * rollback evidence) never needs a gate. */
196
132
  gate_ids?: string[];
197
- /** v2.8: When the previous round's verification flagged intent_drift or
198
- * subgoal_drift, the agent explains why its actions diverged from its
199
- * stated plan. Populated from the self-eval block when the prompt
200
- * injected the field. Empty or absent when no drift was flagged.
201
- * Used by the enforcement gate R7 to distinguish intentional pivots
202
- * from unacknowledged drift. */
203
- drift_clarification?: string;
204
133
  /** Model's information needs for the next round's prompt.
205
134
  * Consumed by the Compiler — not durable across rounds. */
206
135
  prompt_requests?: PromptRequests;
@@ -209,7 +138,7 @@ export interface SelfEvaluation {
209
138
  * it completes or blocks). Becomes the ACTIVE contract only once this
210
139
  * round commits; it is then derived at compile time from committed
211
140
  * rounds — see round-contract.ts. Optional. */
212
- round_contract?: RoundContract;
141
+ round_contract?: RoundContractProposal;
213
142
  }
214
143
  /** v2.12: Tri-state round outcome. Declared via SelfEvaluation.outcome;
215
144
  * derived from `success` when absent. Shared by the dual gates, the stop
@@ -225,13 +154,15 @@ export interface LoopProjection {
225
154
  what: string;
226
155
  since_round: number;
227
156
  } | null;
228
- /** Suggested next steps: agent-declared intent vs compiler-derived
229
- * pending/blocked sub-goals. Non-authoritative. */
157
+ /** Suggested next steps, derived from the active contract, sub-goals, and
158
+ * open gates/recovery requirements. Non-authoritative. v3.8: the
159
+ * `agent_intent` source was deleted with `next_action` — the agent's own
160
+ * plan is no longer a projection input. */
230
161
  todo: Array<{
231
162
  id: string;
232
163
  item: string;
233
164
  reason: string;
234
- source: "derived" | "agent_intent";
165
+ source: "derived";
235
166
  priority: number;
236
167
  }>;
237
168
  /** Phase boundaries from milestone history. */
@@ -261,6 +192,12 @@ export interface LoopProjection {
261
192
  verified: string[];
262
193
  open_risks: string[];
263
194
  };
195
+ /** v3.8: Sub-goals a machine-verified contract item backs. The machine's
196
+ * separate statement about a `done` sub-goal — it never rewrites
197
+ * `SubGoal.status`. Derived in cognitive-facts.ts, exposed here so the
198
+ * projection carries the same verification view the prompt and state file
199
+ * do. */
200
+ verified_subgoals: VerifiedSubGoalFact[];
264
201
  }
265
202
  export declare function makeLoopProjection(overrides?: Partial<LoopProjection>): LoopProjection;
266
203
  /** v2.12: Structured high-risk action descriptor (internal — audit display
@@ -301,11 +238,11 @@ export declare function makeGateDecision(overrides?: Partial<GateDecision>): Gat
301
238
  * Compiler when assembling the next prompt. Transient — each round's
302
239
  * requests apply to that round only. */
303
240
  export interface PromptRequests {
304
- /** Items to emphasize. Matched against active state via Jaccard
305
- * similarity. Matching items are pulled into a "Critical Context"
306
- * section rendered before optional sections. No content is added —
307
- * only reordered. Max entries: policy-driven (L2: 5, L1: 3).
308
- * L0: ignored. */
241
+ /** Items to emphasize. Matched against active state by stable id or
242
+ * normalized-exact text (v3.8.1 — the Jaccard arm is gone). Matching items
243
+ * are pulled into a "Critical Context" section rendered before optional
244
+ * sections. No content is added — only reordered. An unmatched entry is
245
+ * dropped. Max entries: policy-driven (L2: 5, L1: 3). L0: ignored. */
309
246
  emphasize?: string[];
310
247
  /** Things the model is confused about. Rendered at the prompt top
311
248
  * as "Confusion Alerts" before the Objective section. Compiler
@@ -317,7 +254,7 @@ export interface PromptRequests {
317
254
  * rolling-window eviction. Triggered by three signals in priority order:
318
255
  *
319
256
  * 1. agent_declared — compression_checkpoint === true (agent marks phase complete)
320
- * 2. criteria_milestone — new success_criteria_met detected (semantic dedup)
257
+ * 2. criteria_milestone — a new met criterion_claim detected (semantic dedup)
321
258
  * 3. auto — safety net after N rounds without a milestone
322
259
  *
323
260
  * Built from raw round data in vault entries — no new persistent storage.
@@ -385,17 +322,23 @@ export interface LoopObjective {
385
322
  refinement_history?: string[];
386
323
  }
387
324
  /** v3.2: Derived per-criterion status for the progress dashboard — the
388
- * "goal → criteria → evidence" vertical view. Zero persistence: derived from
389
- * vault entries each round (met/remaining reports + Jaccard sub-goal links). */
325
+ * "goal → criteria → evidence" vertical view. Zero persistence: derived
326
+ * from committed rounds each round.
327
+ *
328
+ * v3.8 states: `claimed` (the agent claims it met), `remaining` (declared
329
+ * outstanding), `verified` (a verified contract item references it),
330
+ * `contradicted` / `insufficient` (machine evidence denies / cannot back
331
+ * the claim), `unknown` (never mentioned). */
390
332
  export interface CriterionStatus {
391
333
  /** Stable ID derived from the criterion text (cr-XXXXXXXX). */
392
334
  id: string;
393
335
  /** The criterion text as declared in the objective. */
394
336
  text: string;
395
- status: "met" | "remaining" | "unknown";
337
+ status: "unknown" | "claimed" | "remaining" | "insufficient" | "contradicted" | "verified";
396
338
  /** Round when the criterion was first reported met (machine-backed). */
397
339
  met_at_round?: number;
398
- /** Sub-goals whose description matches this criterion (Jaccard). */
340
+ /** Sub-goals an item referencing this criterion also names, via explicit
341
+ * `subgoal_refs` (v3.8.1 — never a text-similarity guess). */
399
342
  related_subgoal_ids: string[];
400
343
  }
401
344
  /** v3.2: A deterministic "lesson learned" — a constraint or verification
@@ -403,30 +346,32 @@ export interface CriterionStatus {
403
346
  * immunize the agent against repeating the same mistakes. Zero persistence:
404
347
  * derived from vault entries each round; presentation only — never feeds
405
348
  * the enforcement gate's decisions. */
406
- export interface Lesson {
407
- /** Constraint text or verification check name. */
408
- text: string;
349
+ /** v3.8.1: a repeated machine fact, keyed by what it is ABOUT.
350
+ *
351
+ * One derivation over the whole committed history replaces the three
352
+ * separate views of "what keeps going wrong" this release removed:
353
+ * `Lesson` (whole history, count >= 2), `rolling_summary.recurring_issues`
354
+ * (the last 5 rounds' raw violation texts, no threshold at all despite the
355
+ * name), and the L1/L2 prompt sections built on top of each. Callers FILTER
356
+ * this list — the state file renders the genuinely recurring set, the prompt
357
+ * renders the recent tail. */
358
+ export interface RecurringFlag {
359
+ /** Constraint text (for a violation) or the verification check id. */
360
+ subject: string;
409
361
  kind: "constraint_violation" | "verification_error" | "verification_warning";
410
- /** How many rounds this lesson occurred in. */
362
+ /** `VerificationFlag.ref` — the command id, `rci-`/`sg-`/`cr-` id or path
363
+ * the flag was about. Empty when the check recorded no subject. */
364
+ ref: string;
365
+ /** Occurrences across the whole committed history. */
411
366
  count: number;
412
- /** The rounds it occurred in, ascending. */
367
+ /** The distinct rounds it occurred in, ascending. */
413
368
  rounds: number[];
414
369
  }
415
370
  export declare function makeLoopObjective(overrides?: Partial<LoopObjective>): LoopObjective;
416
- export interface LoopHealth {
417
- goal_alignment: number;
418
- constraint_integrity: number;
419
- drift_detected: boolean;
420
- strategy_stability: boolean;
421
- task_continuity: number;
422
- escalation_recommended: string;
423
- }
424
- export declare function makeLoopHealth(overrides?: Partial<LoopHealth>): LoopHealth;
425
371
  export interface RollingSummary {
426
372
  /** v1.12: Unified key outcomes — merged from what_worked + key_lessons.
427
373
  * Format: "[R{round}] ✓/✗ ({technique}): {summary}" */
428
374
  key_outcomes: string[];
429
- recurring_issues: string[];
430
375
  rounds_sampled: number;
431
376
  generated_at_round: number;
432
377
  /** v1.7: Detected failure patterns — repeated failed rounds with
@@ -452,7 +397,6 @@ export interface SubGoalUpdate {
452
397
  /** Optional free-text note (≤ 300 chars). Lenient — never validated. */
453
398
  note?: string;
454
399
  }
455
- export declare function makeSubGoalUpdate(overrides?: Partial<SubGoalUpdate>): SubGoalUpdate;
456
400
  /** v2.2: A structured sub-goal tracked by the compiler across rounds.
457
401
  * Declared by the agent via emerged_subtasks (creation) and
458
402
  * subgoal_updates (explicit transitions); statuses are compiler-derived
@@ -461,7 +405,8 @@ export declare function makeSubGoalUpdate(overrides?: Partial<SubGoalUpdate>): S
461
405
  export interface SubGoal {
462
406
  /** Stable identifier derived from description hash (sg-XXXXXXXX). */
463
407
  id: string;
464
- /** Agent-declared description, deduplicated by similarity. */
408
+ /** Agent-declared description. Exact repeats within one declaration round
409
+ * keep only the first entry (v3.8.1 — no similarity dedup). */
465
410
  description: string;
466
411
  /** Compiler-derived status. */
467
412
  status: "pending" | "in_progress" | "done" | "blocked" | "canceled";
@@ -473,6 +418,9 @@ export interface SubGoal {
473
418
  completed_at_round?: number;
474
419
  /** Priority hint: 0 = highest. Derived from declaration order. */
475
420
  priority: number;
421
+ /** v3.8: The agent's note from the transition that set the current status.
422
+ * Lenient — it never affects validation, only what the agent reads back. */
423
+ status_note?: string;
476
424
  }
477
425
  export declare function makeSubGoal(overrides?: Partial<SubGoal>): SubGoal;
478
426
  /** v2.3: Per-constraint lifecycle metadata for the active constraint set.
@@ -481,8 +429,9 @@ export declare function makeSubGoal(overrides?: Partial<SubGoal>): SubGoal;
481
429
  * was removed — active constraints never auto-demote. */
482
430
  export interface ConstraintMeta {
483
431
  /** v2.11: Stable identifier derived from text hash (c-XXXXXXXX).
484
- * Enables exact ID-first matching by the agent and compiler.
485
- * Eliminates Jaccard false positives/negatives. */
432
+ * The only name an agent can use to refer to this constraint — v3.8.1
433
+ * deleted every similarity fallback, so stable ids and normalized-exact
434
+ * text are the whole matching surface. */
486
435
  id: string;
487
436
  /** Normalized constraint text (the key). */
488
437
  text: string;
@@ -493,13 +442,6 @@ export interface ConstraintMeta {
493
442
  source: "hard" | "plan" | "criteria" | "discovered";
494
443
  }
495
444
  export declare function makeConstraintMeta(overrides?: Partial<ConstraintMeta>): ConstraintMeta;
496
- export interface TaskAlignment {
497
- is_aligned: boolean;
498
- alignment_score: number;
499
- warning: string;
500
- escalation: string;
501
- }
502
- export declare function makeTaskAlignment(overrides?: Partial<TaskAlignment>): TaskAlignment;
503
445
  export interface LoopRoundResult {
504
446
  round: number;
505
447
  success: boolean;
@@ -516,7 +458,7 @@ export interface LoopRoundResult {
516
458
  * Set from SelfEvaluation.subgoal_updates during buildLoopRequest. */
517
459
  subgoal_updates?: SubGoalUpdate[];
518
460
  /** P4: Execution evidence from this round. */
519
- execution_evidence?: ExecutionEvidence;
461
+ execution_report?: ExecutionReport;
520
462
  /** P5: Constraints retracted this round. */
521
463
  retracted_constraints?: string[];
522
464
  /** P5: Success criteria revised this round. */
@@ -530,15 +472,10 @@ export interface LoopRoundResult {
530
472
  compression_checkpoint?: boolean;
531
473
  /** v1.10: Human-readable label for the checkpoint. */
532
474
  checkpoint_label?: string;
533
- /** v1.16: Agent's declared next action for the following round. */
534
- next_action?: string;
535
- /** v2.8: Agent's explanation for intent/subgoal drift detected in
536
- * the previous round. Carried forward from SelfEvaluation. */
537
- drift_clarification?: string;
538
475
  /** Model's information needs for the next round's prompt.
539
476
  * Carried forward from SelfEvaluation. Consumed by the Compiler. */
540
477
  prompt_requests?: PromptRequests;
541
- /** v2.12: Declared tri-state outcome. Carried forward from SelfEvaluation. */
478
+ /** v2.12: Declared outcome. Carried forward from SelfEvaluation. */
542
479
  outcome?: RoundOutcome;
543
480
  /** v2.12: Flat blocker description (outcome==="blocked" only). */
544
481
  blocker?: string;
@@ -566,7 +503,6 @@ export interface LoopCompileRequest {
566
503
  new_since_last_round: string;
567
504
  last_round_result: LoopRoundResult | null;
568
505
  force_level: string;
569
- health_check_interval: number;
570
506
  /** Optional context supplied explicitly by the embedding Agent. */
571
507
  external_context?: string;
572
508
  /** Maximum rounds for this loop. Used by the state file header to show
@@ -586,18 +522,40 @@ export interface LoopCompileRequest {
586
522
  }
587
523
  export declare function makeLoopCompileRequest(overrides?: Partial<LoopCompileRequest>): LoopCompileRequest;
588
524
  /** Immutable record of the exact prompt delivered for one round attempt. */
525
+ /** v3.8.1: the artifact schema version, next to the type it versions. The
526
+ * transaction envelope parser reads it, so the constant lives here rather
527
+ * than in the renderer. */
528
+ export declare const PROMPT_ARTIFACT_SCHEMA_VERSION: 2;
589
529
  export interface PromptArtifact {
590
- schemaVersion: 1;
530
+ /** v3.8.1: schema 2. Version 1 is a HARD break — a round whose artifact
531
+ * does not parse is not committed history, and `legacyTransactionRounds`
532
+ * reports the loss rather than letting it vanish. */
533
+ schemaVersion: typeof PROMPT_ARTIFACT_SCHEMA_VERSION;
534
+ /** Round identity: `loop:<loopId>:round:<n>`. */
591
535
  roundId: string;
536
+ /** The round number on its own, so a reader does not re-parse roundId. */
537
+ round: number;
592
538
  attempt: number;
593
539
  level: "l0" | "l1" | "l2";
594
540
  renderedPrompt: string;
595
541
  promptHash: string;
596
542
  stateHash: string;
597
- /** v3.2: What the rendered prompt actually presented (L1 only). Persisted
598
- * on the lineage entry as the diff baseline for L1 collapse. Absent for
599
- * L0/L2 compiles. */
600
- presentedState?: PresentedStateSnapshot;
543
+ /** Section ids actually rendered, in render order. */
544
+ sections: string[];
545
+ /** Section ids the deterministic budget rule dropped. */
546
+ droppedSections: string[];
547
+ /** True when the PROTECTED sections alone exceeded the budget. Recorded so
548
+ * an over-budget prompt is visible rather than silently over-long. */
549
+ protectedOverflow: boolean;
550
+ /** The ceiling this render was measured against: the level's configured
551
+ * budget (`lN_max_chars`) minus the fixed footer, which is appended after
552
+ * budgeting because it is never dropped. Measured over the SAME region as
553
+ * `renderedChars`. */
554
+ budget: number;
555
+ /** Characters the budgeted region produced: the fixed header, the confusion
556
+ * alerts and the rendered sections — everything except the footer. NOT the
557
+ * full prompt length; `renderedPrompt` adds the footer on top. */
558
+ renderedChars: number;
601
559
  }
602
560
  export interface LoopCompileResponse {
603
561
  status: AgentStatus;
@@ -612,8 +570,6 @@ export interface LoopCompileResponse {
612
570
  goal_id: string;
613
571
  goal_text_hash: string;
614
572
  loop_objective: LoopObjective | null;
615
- loop_health: LoopHealth | null;
616
- task_alignment: TaskAlignment | null;
617
573
  rolling_summary: RollingSummary | null;
618
574
  /** v2.2: Structured sub-goals tracked across rounds. Compiler-managed
619
575
  * lifecycle with derived status. Rendered as Sub-Goal Dashboard. */
@@ -622,17 +578,16 @@ export interface LoopCompileResponse {
622
578
  constraint_metadata?: ConstraintMeta[];
623
579
  /** v2.5: Current round's agent trust score [0, 1]. Derived from verification
624
580
  * flags: -0.15 per error, -0.03 per warn. Always 1.0 for round 1. */
625
- agent_trust_score?: number;
626
581
  /** v2.5: Trust scores from the last 10 rounds, newest last. Empty for
627
582
  * round 1. Reconstructed from vault entries — zero new persistence. */
628
- agent_trust_trend?: number[];
629
583
  /** v3.2: Derived per-criterion status (goal → criteria → evidence view).
630
584
  * Zero persistence — re-derived from vault entries each round. */
631
585
  criterion_statuses?: CriterionStatus[];
632
- /** v3.2: Deterministic lessons learned (repeated violations / repeated
633
- * verification failures). Presentation only — never feeds enforcement. */
634
- lessons?: Lesson[];
635
- suggested_next_task: string;
586
+ /** v3.8.1: repeated machine facts over the whole committed history, keyed
587
+ * by check id / constraint text and the id they were about. Presentation
588
+ * only — never feeds enforcement. Replaces the former Lessons list; callers
589
+ * filter it (state file: count >= 2, prompt: recent tail). */
590
+ recurring_flags?: RecurringFlag[];
636
591
  plan_source: string | null;
637
592
  warnings: string[];
638
593
  error: string;
@@ -677,7 +632,6 @@ export interface LoopForgeResponse {
677
632
  rolling_summary?: RollingSummary | null;
678
633
  sub_goals?: SubGoal[];
679
634
  criterion_statuses?: CriterionStatus[];
680
- suggested_next_task?: string;
681
635
  }
682
636
  export interface SessionState {
683
637
  task_id: string;
@@ -695,7 +649,11 @@ export interface AgentLoopResult {
695
649
  * `cancelled` is manual stop via loopforge_stop. */
696
650
  export type StopReason = "completed" | "failed" | "blocked" | "cancelled" | "max_rounds" | "stalled" | "enforcement_terminated"
697
651
  /** Loop was paused by user or signal. */
698
- | "paused";
652
+ | "paused"
653
+ /** v3.8: The agent stopped, but machine verification did not close the
654
+ * active contract (or the observations are insufficient to prove the task
655
+ * complete). Never reported as `completed`. */
656
+ | "incomplete";
699
657
  /** Result of round-boundary enforcement. Decides whether to accept the round,
700
658
  * reject it (force the agent to redo the SAME round), or terminate the loop.
701
659
  *
@@ -716,10 +674,10 @@ export interface EnforcementResult {
716
674
  * Used by callers to track consecutive rejections per-rule
717
675
  * so unrelated rejections don't accumulate toward the max. */
718
676
  check?: string;
719
- /** v2.12: True when the enforcement gate accepted the round via
720
- * drift_clarification waiver (R7). The caller uses this to track
721
- * clarification streaks independently of rejection streaks. */
722
- clarification_accepted?: boolean;
677
+ /** v3.8: The stop reason a `terminate` decision must map to. Absent means
678
+ * the historical `enforcement_terminated`; `incomplete` is set by the
679
+ * verification-debt row. */
680
+ stopReason?: StopReason;
723
681
  }
724
682
  export declare function makeEnforcementResult(overrides?: Partial<EnforcementResult>): EnforcementResult;
725
683
  /** Context supplied to an embedding-owned provider before compilation. */
@@ -754,6 +712,12 @@ export interface VerificationFlag {
754
712
  check: string;
755
713
  /** Human-readable description of the inconsistency found. */
756
714
  detail: string;
715
+ /** v3.8.1: the id this flag is ABOUT — a configured command id, an
716
+ * `rci-` / `sg-` / `cr-` id, or a workspace path. Optional: only checks with
717
+ * a concrete subject set it. Recurring-warning grouping keys on
718
+ * `(check, ref)` so it reports WHICH item keeps failing rather than
719
+ * re-parsing `detail` prose. */
720
+ ref?: string;
757
721
  }
758
722
  export declare function makeVerificationFlag(overrides?: Partial<VerificationFlag>): VerificationFlag;
759
723
  /** Result of cross-round self-evaluation verification.
@@ -768,7 +732,266 @@ export declare function makeVerificationFlag(overrides?: Partial<VerificationFla
768
732
  export interface VerificationResult {
769
733
  verdict: "trusted" | "suspect" | "contradicted";
770
734
  flags: VerificationFlag[];
735
+ /** v3.8.1: the round's success claim is MACHINE-backed — a passed
736
+ * after-phase command observed by the runtime (`deriveEvidenceStatus`).
737
+ * Carried as a fact so a consumer never re-derives it; the progress
738
+ * evaluator reads it as "this round is finishing, not churning". */
739
+ machineBackedSuccess: boolean;
771
740
  }
772
741
  export declare function makeVerificationResult(overrides?: Partial<VerificationResult>): VerificationResult;
742
+ /** v3.8: The agent's self-report for a round — renamed from ExecutionReport
743
+ * because these fields are claims, not evidence. The whole object is
744
+ * optional; a mistyped optional field is dropped with a warning and never
745
+ * rejects the round. */
746
+ export interface ExecutionReport {
747
+ /** Files the agent says it changed. Informational — compared against the
748
+ * git observation, never trusted as the observation. */
749
+ files_changed?: string[];
750
+ /** Test counts the agent reports. Informational. */
751
+ tests_reported?: {
752
+ passed: number;
753
+ failed: number;
754
+ skipped: number;
755
+ } | null;
756
+ /** Advisory claims about objective criteria. LENIENT: unknown/duplicate
757
+ * criterion ids and malformed outcomes are dropped with a warning. */
758
+ criterion_claims?: CriterionClaim[];
759
+ /** Claims about ACTIVE contract items. STRICT: an unknown/duplicate item id
760
+ * or an illegal outcome is a structural defect (contract_invalid). */
761
+ contract_item_claims?: ContractItemClaim[];
762
+ /** The agent's own progress estimate (0.0–1.0). Informational. */
763
+ progress_estimate?: number;
764
+ }
765
+ export declare function makeExecutionReport(overrides?: Partial<ExecutionReport>): ExecutionReport;
766
+ /** v3.8: An advisory claim about an objective criterion. Lenient by design —
767
+ * the criterion layer is advisory; the contract item layer is the machine
768
+ * verification skeleton. */
769
+ export interface CriterionClaim {
770
+ /** cr-XXXXXXXX (or the criterion text for plain-text matching). */
771
+ criterion_id: string;
772
+ outcome: "met" | "remaining";
773
+ }
774
+ /** v3.8: A claim about an ACTIVE contract item, cited by the derived
775
+ * rci-XXXXXXXX id the prompt rendered. */
776
+ export interface ContractItemClaim {
777
+ item_id: string;
778
+ outcome: "met" | "remaining";
779
+ }
780
+ /** v3.8: One declared contract item. `verify_with` must name configured,
781
+ * enabled, after-capable evidence commands — the declaration is strict.
782
+ *
783
+ * `subgoal_refs` lives HERE, not on the contract: a machine-verified item
784
+ * backs exactly the sub-goals it names, so "item A verifies SubGoal 1, item B
785
+ * verifies SubGoal 2" is expressible and `VerifiedSubGoalFact` attribution is
786
+ * per-item instead of "every verified item backs every sub-goal". */
787
+ export interface ContractItemProposal {
788
+ description: string;
789
+ /** cr-XXXXXXXX criterion ids this item is evidence for (or free text). */
790
+ criterion_refs: string[];
791
+ /** sg-XXXXXXXX sub-goals this item is evidence for. */
792
+ subgoal_refs: string[];
793
+ /** Evidence command ids (policy.evidence.commands[].name). */
794
+ verify_with: string[];
795
+ }
796
+ /** v3.8: A Round Contract proposal for the NEXT round. It becomes ACTIVE only
797
+ * after the declaring round commits. Identity (rc-/rci-) is derived from
798
+ * CONTENT ONLY — restating an unchanged contract keeps the same identity,
799
+ * unlike a SubGoal whose id includes its declaration round. */
800
+ export interface RoundContractProposal {
801
+ work_item?: string;
802
+ /** Files/directories the round may touch. Empty = no scope constraint. */
803
+ scope: string[];
804
+ items: ContractItemProposal[];
805
+ }
806
+ /** v3.8: The machine's record of what a contract bound at its declaration
807
+ * round. Stamped by the runtime when the declaring round COMMITS (policy is
808
+ * not part of the Vault, so the command configuration in force at
809
+ * declaration could not otherwise be recovered). It is machine-recomputed,
810
+ * never agent-supplied, and adds no second truth. */
811
+ export interface ContractBinding {
812
+ rc_id: string;
813
+ item_ids: string[];
814
+ config_hash_by_command: Record<string, string>;
815
+ }
816
+ /** v3.8: Runtime-derived contract item status. The agent may only claim
817
+ * `met` / `remaining`; the other three are machine-derived. */
818
+ export type ContractItemStatus = "pending" | "insufficient" | "contradicted" | "verified";
819
+ /** v3.8: The round-level verification posture. `trusted` means every claim in
820
+ * the round is machine-backed; `insufficient` means claims are unbacked but
821
+ * not contradicted; `contradicted` means machine facts deny a claim. */
822
+ export type RoundVerificationStatus = "trusted" | "insufficient" | "contradicted";
823
+ /** v3.8: Machine observation status. A configured provider always produces an
824
+ * observation — the failure modes are recorded, not filtered away.
825
+ *
826
+ * Who reports what: `timeout` and `unavailable` are the runtime's own words
827
+ * for "the provider exceeded its deadline" and "the provider yielded
828
+ * nothing" (the collector synthesizes both, so a provider cannot hide a
829
+ * failure by returning nothing). `aborted` is what a PROVIDER reports when
830
+ * its own capture was aborted — a command killed mid-flight, say. A
831
+ * collector deadline aborts the capture AS a timeout, so the round records
832
+ * the runtime's measured cause, not the provider's. */
833
+ export type ObservationStatus = "observed" | "passed" | "failed" | "timeout" | "unavailable" | "error" | "aborted";
834
+ /** v3.8: Common machine-observation fields. Observations are the factual
835
+ * record of what the machine saw; they are persisted with the round and are
836
+ * the only input that can create a `verified` fact. */
837
+ export interface MachineObservationBase {
838
+ schemaVersion: 1;
839
+ providerId: string;
840
+ kind: "git" | "command" | "custom";
841
+ phase: "before" | "after";
842
+ startedAt: number;
843
+ finishedAt: number;
844
+ status: ObservationStatus;
845
+ /** Files this observation reports (git: changed paths; command: resolved
846
+ * entrypoint files). */
847
+ files: string[];
848
+ }
849
+ export interface GitObservationData {
850
+ tracked: string[];
851
+ staged: string[];
852
+ untracked: string[];
853
+ /** path -> "<mode>:<sha256>" (or the literal "missing"). */
854
+ fingerprints: Record<string, string>;
855
+ head?: string;
856
+ }
857
+ export interface GitObservation extends MachineObservationBase {
858
+ kind: "git";
859
+ data: GitObservationData;
860
+ }
861
+ export interface CommandObservationData {
862
+ commandId: string;
863
+ argv: string[];
864
+ cwd: string;
865
+ /** sha256 of the normalized command configuration at capture time. */
866
+ configHash: string;
867
+ required: boolean;
868
+ exitCode: number | null;
869
+ signal: string | null;
870
+ durationMs: number;
871
+ /** Why a non-passed observation did not pass (e.g. "ENOENT", "cwd leaves
872
+ * the workspace"). Free text for the audit trail — never a verdict. */
873
+ failureDetail?: string;
874
+ /** sha256 over the FULL stdout stream — never the truncated excerpt. */
875
+ stdoutSha256: string;
876
+ /** sha256 over the FULL stderr stream. */
877
+ stderrSha256: string;
878
+ stdoutExcerpt: string;
879
+ stderrExcerpt: string;
880
+ truncated: boolean;
881
+ entrypointFiles: string[];
882
+ }
883
+ export interface CommandObservation extends MachineObservationBase {
884
+ kind: "command";
885
+ data: CommandObservationData;
886
+ }
887
+ export interface CustomObservation extends MachineObservationBase {
888
+ kind: "custom";
889
+ data: Record<string, unknown>;
890
+ }
891
+ export type MachineObservation = GitObservation | CommandObservation | CustomObservation;
892
+ /** v3.8: Static, policy-derived verification capability. A pure function of
893
+ * policy — no probing, no filesystem, no provider registry — so it can be
894
+ * hashed into stateHash and reproduced by replay/audit from committed facts.
895
+ * Provider REGISTRATION is code state and is deliberately excluded; it is
896
+ * reported as an unhashed readiness diagnostic instead. */
897
+ export interface ConfiguredCapability {
898
+ schemaVersion: 1;
899
+ providers: Array<{
900
+ providerId: string;
901
+ }>;
902
+ commands: Array<{
903
+ commandId: string;
904
+ enabled: boolean;
905
+ phase: "after" | "both";
906
+ required: boolean;
907
+ configHash: string;
908
+ }>;
909
+ /** policy.evidence.providers is non-empty. */
910
+ observationConfigured: boolean;
911
+ /** At least one enabled, after-capable command. */
912
+ contractVerificationAvailable: boolean;
913
+ }
914
+ /** v3.8: Live observation capability. Rendered only — never hashed, never
915
+ * persisted independently of the observations it is derived from. */
916
+ export interface ObservedCapability {
917
+ providers: Array<{
918
+ providerId: string;
919
+ status: ObservationStatus;
920
+ }>;
921
+ commands: Array<{
922
+ commandId: string;
923
+ status: ObservationStatus;
924
+ configHash: string;
925
+ }>;
926
+ }
927
+ /** v3.8: The single capability fact a prepared round returns — the union of
928
+ * the two halves, split so that only the POLICY half is hashable.
929
+ *
930
+ * `ConfiguredCapability` is a pure function of policy and feeds
931
+ * `stateHash`/`promptHash`; `ObservedCapability` carries live statuses and is
932
+ * rendered only. `provider.available` is provider-REGISTRY state (code, not
933
+ * policy) and therefore never enters the hash either — it is reported here and
934
+ * by `doctor`. Every surface that speaks about capability (MCP start / next /
935
+ * status, the warning list) calls this one function, so they cannot drift
936
+ * apart — and none of them carries a second copy of the fact. */
937
+ export interface EvidenceCapability {
938
+ schemaVersion: 1;
939
+ providers: Array<{
940
+ providerId: string;
941
+ /** A factory for this name is registered in this runtime. */
942
+ available: boolean;
943
+ status: ObservationStatus;
944
+ }>;
945
+ commands: Array<{
946
+ commandId: string;
947
+ enabled: boolean;
948
+ phase: "after" | "both";
949
+ configHash: string;
950
+ /** Enabled and after-capable — i.e. usable as a contract item's evidence. */
951
+ ready: boolean;
952
+ }>;
953
+ contractVerificationAvailable: boolean;
954
+ /** Human-readable capability gaps (the same text start/resume/status show). */
955
+ warnings: string[];
956
+ }
957
+ /** v3.8: A machine-verified sub-goal fact. DERIVED in cognitive-facts.ts,
958
+ * never persisted: it exists only while a committed contract item references
959
+ * the sub-goal AND that item is verified. It never writes SubGoal.status —
960
+ * `done` stays the agent's declaration. */
961
+ export interface VerifiedSubGoalFact {
962
+ subgoal_id: string;
963
+ contract_item_ids: string[];
964
+ verified_at_round: number;
965
+ }
966
+ /** v3.8: The STABLE error codes every tool answers with. A client can branch
967
+ * on these; the human sentence rides in `ToolError.message` and never doubles
968
+ * as the code.
969
+ *
970
+ * - `evaluation_invalid` / `contract_invalid` / `policy_invalid` — a payload
971
+ * or configuration defect; the same roundId may be retried.
972
+ * - `round_id_required` / `round_id_mismatch` — the anchor is missing or no
973
+ * longer names the current round.
974
+ * - `session_not_found` / `state_unavailable` — the named session or read
975
+ * model is not there.
976
+ * - `invalid_argument` — the request itself is malformed at the tool boundary.
977
+ * - `gate_disabled` / `loop_already_running` — a state condition, not a defect.
978
+ *
979
+ * Note: a `loopforge_next` submission whose roundId no longer matches is NOT
980
+ * `round_id_mismatch` — it returns the held prompt with a warning and
981
+ * `ok: true` so the agent can recover the response it missed. That recovery
982
+ * contract (v3.0.1) is deliberate; `round_id_mismatch` is for the places with
983
+ * no held prompt to return (the gate preflight). */
984
+ export type ToolErrorCode = "evaluation_invalid" | "contract_invalid" | "policy_invalid" | "session_not_found" | "round_id_required" | "round_id_mismatch" | "state_unavailable" | "invalid_argument" | "gate_disabled" | "loop_already_running";
985
+ /** v3.8: The structured error inside the uniform `{ok: false}` envelope. */
986
+ export interface ToolError {
987
+ code: ToolErrorCode;
988
+ /** Human-readable cause. Never the code. */
989
+ message: string;
990
+ /** Whether the fix is a corrected payload the agent may resend. */
991
+ retryable: boolean;
992
+ sessionId?: string;
993
+ roundId?: string;
994
+ details?: Record<string, unknown>;
995
+ }
773
996
  export declare function makeTaskId(taskDescription: string): string;
774
997
  //# sourceMappingURL=protocol.d.ts.map