loopforge 3.9.2 → 4.0.7
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.
- package/README.md +236 -112
- package/dist/audit.d.ts +73 -15
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +131 -61
- package/dist/audit.js.map +1 -1
- package/dist/canonical-state.d.ts +152 -40
- package/dist/canonical-state.d.ts.map +1 -1
- package/dist/canonical-state.js +382 -206
- package/dist/canonical-state.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +41 -12
- package/dist/cli.js.map +1 -1
- package/dist/cognitive-governance.d.ts +0 -2
- package/dist/cognitive-governance.d.ts.map +1 -1
- package/dist/cognitive-governance.js +0 -4
- package/dist/cognitive-governance.js.map +1 -1
- package/dist/committed-round.d.ts +105 -141
- package/dist/committed-round.d.ts.map +1 -1
- package/dist/committed-round.js +249 -372
- package/dist/committed-round.js.map +1 -1
- package/dist/constraint-lifecycle.d.ts +73 -0
- package/dist/constraint-lifecycle.d.ts.map +1 -0
- package/dist/constraint-lifecycle.js +174 -0
- package/dist/constraint-lifecycle.js.map +1 -0
- package/dist/context-boundary.d.ts +83 -0
- package/dist/context-boundary.d.ts.map +1 -0
- package/dist/context-boundary.js +101 -0
- package/dist/context-boundary.js.map +1 -0
- package/dist/contract-items.d.ts +12 -8
- package/dist/contract-items.d.ts.map +1 -1
- package/dist/contract-items.js +31 -26
- package/dist/contract-items.js.map +1 -1
- package/dist/contract-requirement.d.ts +47 -0
- package/dist/contract-requirement.d.ts.map +1 -0
- package/dist/contract-requirement.js +51 -0
- package/dist/contract-requirement.js.map +1 -0
- package/dist/criterion-status.d.ts +35 -0
- package/dist/criterion-status.d.ts.map +1 -0
- package/dist/criterion-status.js +89 -0
- package/dist/criterion-status.js.map +1 -0
- package/dist/enforcement-gate.d.ts +32 -67
- package/dist/enforcement-gate.d.ts.map +1 -1
- package/dist/enforcement-gate.js +203 -439
- package/dist/enforcement-gate.js.map +1 -1
- package/dist/engine.d.ts +9 -103
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +28 -887
- package/dist/engine.js.map +1 -1
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +69 -0
- package/dist/errors.js.map +1 -0
- package/dist/evidence-claims.d.ts +33 -31
- package/dist/evidence-claims.d.ts.map +1 -1
- package/dist/evidence-claims.js +58 -72
- package/dist/evidence-claims.js.map +1 -1
- package/dist/evidence-posture-view.d.ts +19 -0
- package/dist/evidence-posture-view.d.ts.map +1 -0
- package/dist/evidence-posture-view.js +116 -0
- package/dist/evidence-posture-view.js.map +1 -0
- package/dist/evidence-posture.d.ts +73 -0
- package/dist/evidence-posture.d.ts.map +1 -0
- package/dist/evidence-posture.js +281 -0
- package/dist/evidence-posture.js.map +1 -0
- package/dist/evidence-provider.d.ts +55 -37
- package/dist/evidence-provider.d.ts.map +1 -1
- package/dist/evidence-provider.js +182 -332
- package/dist/evidence-provider.js.map +1 -1
- package/dist/explain.d.ts +167 -27
- package/dist/explain.d.ts.map +1 -1
- package/dist/explain.js +373 -58
- package/dist/explain.js.map +1 -1
- package/dist/field-accounting.d.ts.map +1 -1
- package/dist/field-accounting.js +3 -22
- package/dist/field-accounting.js.map +1 -1
- package/dist/generate-schema.js +13 -8
- package/dist/generate-schema.js.map +1 -1
- package/dist/git-boundary.d.ts +128 -0
- package/dist/git-boundary.d.ts.map +1 -0
- package/dist/git-boundary.js +625 -0
- package/dist/git-boundary.js.map +1 -0
- package/dist/git-facts.d.ts +22 -0
- package/dist/git-facts.d.ts.map +1 -0
- package/dist/git-facts.js +29 -0
- package/dist/git-facts.js.map +1 -0
- package/dist/git-motion.d.ts +37 -0
- package/dist/git-motion.d.ts.map +1 -0
- package/dist/git-motion.js +59 -0
- package/dist/git-motion.js.map +1 -0
- package/dist/history.d.ts +44 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +77 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +19 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +16 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +80 -14
- package/dist/init.js.map +1 -1
- package/dist/loop-compiler.d.ts +51 -19
- package/dist/loop-compiler.d.ts.map +1 -1
- package/dist/loop-compiler.js +423 -507
- package/dist/loop-compiler.js.map +1 -1
- package/dist/loop-store.d.ts +6 -5
- package/dist/loop-store.d.ts.map +1 -1
- package/dist/loop-store.js +153 -35
- package/dist/loop-store.js.map +1 -1
- package/dist/mcp/round-lifecycle.d.ts +285 -81
- package/dist/mcp/round-lifecycle.d.ts.map +1 -1
- package/dist/mcp/round-lifecycle.js +1629 -574
- package/dist/mcp/round-lifecycle.js.map +1 -1
- package/dist/mcp/server.d.ts +5 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +61 -19
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/session.d.ts +81 -39
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +963 -271
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/submission-boundary.d.ts +23 -31
- package/dist/mcp/submission-boundary.d.ts.map +1 -1
- package/dist/mcp/submission-boundary.js +242 -82
- package/dist/mcp/submission-boundary.js.map +1 -1
- package/dist/mcp/submission-handle.d.ts +66 -0
- package/dist/mcp/submission-handle.d.ts.map +1 -0
- package/dist/mcp/submission-handle.js +173 -0
- package/dist/mcp/submission-handle.js.map +1 -0
- package/dist/mcp/tools.d.ts +17 -7
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +763 -244
- package/dist/mcp/tools.js.map +1 -1
- package/dist/open-question.d.ts +7 -0
- package/dist/open-question.d.ts.map +1 -0
- package/dist/open-question.js +14 -0
- package/dist/open-question.js.map +1 -0
- package/dist/policy-metrics.d.ts +31 -21
- package/dist/policy-metrics.d.ts.map +1 -1
- package/dist/policy-metrics.js +117 -64
- package/dist/policy-metrics.js.map +1 -1
- package/dist/policy.d.ts +15 -40
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +13 -13
- package/dist/policy.js.map +1 -1
- package/dist/progress.d.ts +45 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +136 -0
- package/dist/progress.js.map +1 -0
- package/dist/prompt-assembler.d.ts +28 -9
- package/dist/prompt-assembler.d.ts.map +1 -1
- package/dist/prompt-assembler.js +592 -603
- package/dist/prompt-assembler.js.map +1 -1
- package/dist/prompt-coverage.d.ts +39 -0
- package/dist/prompt-coverage.d.ts.map +1 -0
- package/dist/prompt-coverage.js +80 -0
- package/dist/prompt-coverage.js.map +1 -0
- package/dist/prompt-freshness.d.ts +25 -0
- package/dist/prompt-freshness.d.ts.map +1 -0
- package/dist/prompt-freshness.js +88 -0
- package/dist/prompt-freshness.js.map +1 -0
- package/dist/prompt-policy.d.ts +14 -4
- package/dist/prompt-policy.d.ts.map +1 -1
- package/dist/prompt-policy.js +29 -10
- package/dist/prompt-policy.js.map +1 -1
- package/dist/protocol.d.ts +875 -419
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +73 -99
- package/dist/protocol.js.map +1 -1
- package/dist/recovery-guidance.d.ts +13 -0
- package/dist/recovery-guidance.d.ts.map +1 -0
- package/dist/recovery-guidance.js +15 -0
- package/dist/recovery-guidance.js.map +1 -0
- package/dist/recovery.d.ts +68 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +234 -0
- package/dist/recovery.js.map +1 -0
- package/dist/replay.d.ts +42 -8
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +311 -84
- package/dist/replay.js.map +1 -1
- package/dist/result-facts.d.ts +45 -0
- package/dist/result-facts.d.ts.map +1 -0
- package/dist/result-facts.js +86 -0
- package/dist/result-facts.js.map +1 -0
- package/dist/round-contract.d.ts +38 -8
- package/dist/round-contract.d.ts.map +1 -1
- package/dist/round-contract.js +71 -31
- package/dist/round-contract.js.map +1 -1
- package/dist/round-coordinator.d.ts +45 -91
- package/dist/round-coordinator.d.ts.map +1 -1
- package/dist/round-coordinator.js +254 -271
- package/dist/round-coordinator.js.map +1 -1
- package/dist/round-driver.d.ts +56 -16
- package/dist/round-driver.d.ts.map +1 -1
- package/dist/round-driver.js +225 -39
- package/dist/round-driver.js.map +1 -1
- package/dist/round-facts.d.ts +33 -52
- package/dist/round-facts.d.ts.map +1 -1
- package/dist/round-facts.js +54 -157
- package/dist/round-facts.js.map +1 -1
- package/dist/round-guidance.d.ts +56 -0
- package/dist/round-guidance.d.ts.map +1 -0
- package/dist/round-guidance.js +161 -0
- package/dist/round-guidance.js.map +1 -0
- package/dist/round-outcome.d.ts +21 -0
- package/dist/round-outcome.d.ts.map +1 -0
- package/dist/round-outcome.js +31 -0
- package/dist/round-outcome.js.map +1 -0
- package/dist/round-transaction.d.ts +168 -21
- package/dist/round-transaction.d.ts.map +1 -1
- package/dist/round-transaction.js +856 -39
- package/dist/round-transaction.js.map +1 -1
- package/dist/self-eval.d.ts +40 -60
- package/dist/self-eval.d.ts.map +1 -1
- package/dist/self-eval.js +455 -384
- package/dist/self-eval.js.map +1 -1
- package/dist/storage.d.ts +16 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +54 -4
- package/dist/storage.js.map +1 -1
- package/dist/subgoal-state.d.ts +2 -3
- package/dist/subgoal-state.d.ts.map +1 -1
- package/dist/subgoal-state.js +2 -3
- package/dist/subgoal-state.js.map +1 -1
- package/dist/submission-guidance.d.ts +43 -21
- package/dist/submission-guidance.d.ts.map +1 -1
- package/dist/submission-guidance.js +368 -262
- package/dist/submission-guidance.js.map +1 -1
- package/dist/submission-receipt.d.ts +16 -8
- package/dist/submission-receipt.d.ts.map +1 -1
- package/dist/submission-receipt.js +146 -51
- package/dist/submission-receipt.js.map +1 -1
- package/dist/token-utils.d.ts +47 -7
- package/dist/token-utils.d.ts.map +1 -1
- package/dist/token-utils.js +66 -15
- package/dist/token-utils.js.map +1 -1
- package/dist/transaction-identity.d.ts +9 -0
- package/dist/transaction-identity.d.ts.map +1 -0
- package/dist/transaction-identity.js +69 -0
- package/dist/transaction-identity.js.map +1 -0
- package/dist/verification-actions.d.ts +13 -0
- package/dist/verification-actions.d.ts.map +1 -0
- package/dist/verification-actions.js +44 -0
- package/dist/verification-actions.js.map +1 -0
- package/dist/verification-gate.d.ts +26 -46
- package/dist/verification-gate.d.ts.map +1 -1
- package/dist/verification-gate.js +218 -427
- package/dist/verification-gate.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/working-memory.d.ts +187 -0
- package/dist/working-memory.d.ts.map +1 -0
- package/dist/working-memory.js +767 -0
- package/dist/working-memory.js.map +1 -0
- package/dist/workspace-checkpoint.d.ts +88 -0
- package/dist/workspace-checkpoint.d.ts.map +1 -0
- package/dist/workspace-checkpoint.js +326 -0
- package/dist/workspace-checkpoint.js.map +1 -0
- package/dist/workspace-restore.d.ts +68 -0
- package/dist/workspace-restore.d.ts.map +1 -0
- package/dist/workspace-restore.js +604 -0
- package/dist/workspace-restore.js.map +1 -0
- package/dist/workspace.d.ts +0 -9
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +0 -17
- package/dist/workspace.js.map +1 -1
- package/loop_policy.json +5 -19
- package/package.json +2 -2
- package/skills/forge/SKILL.md +212 -0
- package/skills/forge/references/evidence-and-contracts.md +204 -0
- package/skills/forge/references/recovery-and-views.md +188 -0
- package/dist/cognitive-facts.d.ts +0 -30
- package/dist/cognitive-facts.d.ts.map +0 -1
- package/dist/cognitive-facts.js +0 -113
- package/dist/cognitive-facts.js.map +0 -1
- package/dist/loop-extras-parser.d.ts +0 -81
- package/dist/loop-extras-parser.d.ts.map +0 -1
- package/dist/loop-extras-parser.js +0 -213
- package/dist/loop-extras-parser.js.map +0 -1
- package/dist/loop-projection.d.ts +0 -6
- package/dist/loop-projection.d.ts.map +0 -1
- package/dist/loop-projection.js +0 -28
- package/dist/loop-projection.js.map +0 -1
- package/skills/perception/SKILL.md +0 -370
|
@@ -11,47 +11,58 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { deriveConfiguredCapability, getPolicy, } from "./policy.js";
|
|
13
13
|
import { deriveRoundFacts, NO_IN_FLIGHT_ROUND } from "./round-facts.js";
|
|
14
|
+
import { deriveCriterionStatuses } from "./criterion-status.js";
|
|
14
15
|
import { deriveSubGoals } from "./subgoal-state.js";
|
|
16
|
+
import { verificationActionFor } from "./verification-actions.js";
|
|
17
|
+
import { deriveContractRequirement } from "./contract-requirement.js";
|
|
15
18
|
/** Field order used by the prompt, guidance and receipts. Core fields first,
|
|
16
19
|
* then the execution report, then contract/sub-goal state, then the
|
|
17
20
|
* cognitive/report fields, then terminal fields. Deterministic by design. */
|
|
21
|
+
/** v4.0.3: THE four structural evaluation fields. The MCP input schema, the
|
|
22
|
+
* prompt template and field accounting read this one set. */
|
|
23
|
+
export const CORE_SELF_EVALUATION_FIELDS = new Set([
|
|
24
|
+
"outcome",
|
|
25
|
+
"output_summary",
|
|
26
|
+
"constraint_violations",
|
|
27
|
+
"should_continue",
|
|
28
|
+
]);
|
|
18
29
|
export const FIELD_ORDER = [
|
|
19
|
-
"
|
|
30
|
+
"outcome",
|
|
20
31
|
"output_summary",
|
|
21
32
|
"constraint_violations",
|
|
22
33
|
"should_continue",
|
|
23
34
|
"execution_report.files_changed",
|
|
24
|
-
"execution_report.
|
|
25
|
-
"
|
|
26
|
-
"execution_report.criterion_claims",
|
|
35
|
+
"execution_report.claims",
|
|
36
|
+
"objective_refinement",
|
|
27
37
|
"subgoal_updates",
|
|
28
38
|
"emerged_subtasks",
|
|
29
39
|
"discovered_constraints",
|
|
30
40
|
"wrong_assumptions",
|
|
31
|
-
"
|
|
41
|
+
"open_questions",
|
|
42
|
+
"resolved_open_question_ids",
|
|
32
43
|
"retracted_constraints",
|
|
33
|
-
"revised_success_criteria",
|
|
34
44
|
"round_contract",
|
|
35
45
|
"worker_results",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"checkpoint_label",
|
|
46
|
+
"subtask_boundary",
|
|
47
|
+
"subtask_boundary_label",
|
|
39
48
|
"retroactiveClaims",
|
|
40
49
|
"gate_ids",
|
|
41
|
-
"outcome",
|
|
42
50
|
"blocker",
|
|
43
|
-
"stop_reason",
|
|
44
51
|
"no_change_reason",
|
|
45
52
|
];
|
|
46
53
|
const GUIDES = [
|
|
47
54
|
{
|
|
48
|
-
path: "
|
|
49
|
-
purpose: "
|
|
50
|
-
when: "Every round.
|
|
55
|
+
path: "outcome",
|
|
56
|
+
purpose: "The ONE round conclusion.",
|
|
57
|
+
when: "Every round. success requires should_continue=false; blocked requires " +
|
|
58
|
+
"should_continue=false and a blocker; partial/failed may continue or stop.",
|
|
51
59
|
nature: "claim",
|
|
52
|
-
downstream: "Stop decision, success trajectory, verification posture
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
downstream: "Stop decision, success trajectory, verification posture, and every read " +
|
|
61
|
+
"surface. It is a claim; a machine observation is what backs it.",
|
|
62
|
+
toolDescription: "Required. success | partial | failed | blocked. success requires " +
|
|
63
|
+
"should_continue=false; blocked requires should_continue=false and a " +
|
|
64
|
+
"non-empty blocker. partial/failed may continue or stop. This is the ONE " +
|
|
65
|
+
"round conclusion.",
|
|
55
66
|
core: true,
|
|
56
67
|
},
|
|
57
68
|
{
|
|
@@ -59,13 +70,15 @@ const GUIDES = [
|
|
|
59
70
|
purpose: "What was actually done this round, not what was attempted.",
|
|
60
71
|
when: "Every round.",
|
|
61
72
|
nature: "report",
|
|
62
|
-
downstream: "
|
|
73
|
+
downstream: "Committed record, state file, audit/replay/explain, and backtrack " +
|
|
74
|
+
"failed-approach facts — never machine evidence or a current-prompt narrative.",
|
|
63
75
|
toolDescription: "Specific, actionable summary of what was DONE this round — not what was " +
|
|
64
76
|
"attempted. Do not restate the plan.",
|
|
65
77
|
core: true,
|
|
66
78
|
},
|
|
67
79
|
{
|
|
68
80
|
path: "constraint_violations",
|
|
81
|
+
array: true,
|
|
69
82
|
purpose: "Hard constraints actually violated this round.",
|
|
70
83
|
when: "Every round; empty when none were violated.",
|
|
71
84
|
nature: "report",
|
|
@@ -86,6 +99,7 @@ const GUIDES = [
|
|
|
86
99
|
},
|
|
87
100
|
{
|
|
88
101
|
path: "execution_report.files_changed",
|
|
102
|
+
array: true,
|
|
89
103
|
purpose: "The boundary net change: paths whose content or file type differs between " +
|
|
90
104
|
"round preparation and this submission, including deleted paths.",
|
|
91
105
|
when: "Every round that changed the workspace. A commit alone adds no entry when content is unchanged.",
|
|
@@ -98,42 +112,43 @@ const GUIDES = [
|
|
|
98
112
|
reportOnly: false,
|
|
99
113
|
},
|
|
100
114
|
{
|
|
101
|
-
path: "execution_report.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
toolDescription: "Self-reported test counts. Informational: the runtime never translates " +
|
|
107
|
-
"an exit code into a test count, and the receipt shows self-report and " +
|
|
108
|
-
"command observation separately.",
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
path: "execution_report.contract_item_claims",
|
|
112
|
-
purpose: "Claims about items of the ACTIVE Round Contract.",
|
|
113
|
-
when: "Only when an active contract is open; cite the rci-XXXXXXXX ids rendered in the prompt.",
|
|
115
|
+
path: "execution_report.claims",
|
|
116
|
+
array: true,
|
|
117
|
+
purpose: "Claims about objective criteria and ACTIVE contract items, in one channel.",
|
|
118
|
+
when: "When you want to declare which criteria or active contract items are met " +
|
|
119
|
+
"or still remaining; cite real cr-/rci- ids from this prompt.",
|
|
114
120
|
nature: "claim",
|
|
115
|
-
decision: "Claim
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"
|
|
121
|
+
decision: "Claim criteria or active contract items with their real cr-/rci- ids",
|
|
122
|
+
compact: true,
|
|
123
|
+
promptRank: 10,
|
|
124
|
+
downstream: "`cr-` advisory; `rci-` strict; only machine commands verify.",
|
|
125
|
+
toolDescription: "One claims channel. Each entry is { id, outcome } where id is a " +
|
|
126
|
+
"cr-XXXXXXXX objective criterion id or an rci-XXXXXXXX item id of the " +
|
|
127
|
+
"ACTIVE contract, and outcome is met | remaining. cr- claims are " +
|
|
128
|
+
"advisory (unknown/malformed entries are dropped); rci- claims are strict " +
|
|
129
|
+
"(unknown/duplicate ids are contract_invalid). A claim never verifies " +
|
|
130
|
+
"anything by itself — the runtime marks an item verified only when its " +
|
|
131
|
+
"bound commands are observed passing.",
|
|
121
132
|
},
|
|
122
133
|
{
|
|
123
|
-
path: "
|
|
124
|
-
purpose: "
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
path: "objective_refinement",
|
|
135
|
+
purpose: "The Agent's working version of the OVERALL starting objective — not the " +
|
|
136
|
+
"current round, not the contract.",
|
|
137
|
+
when: "Only when the overall objective genuinely evolved. Omit when unchanged; " +
|
|
138
|
+
"this is event-driven, not a per-round field.",
|
|
139
|
+
nature: "report",
|
|
140
|
+
decision: "Overall objective genuinely evolved (omit when unchanged)",
|
|
141
|
+
compact: true,
|
|
142
|
+
promptRank: 15,
|
|
143
|
+
downstream: "Updates the working objective text; never acceptance, criteria or constraints.",
|
|
144
|
+
toolDescription: "Optional, at most 1000 chars. A refined statement of the OVERALL " +
|
|
145
|
+
"starting objective when understanding genuinely changed. It never " +
|
|
146
|
+
"rewrites the operator acceptance, criteria or hard constraints, and it " +
|
|
147
|
+
"is not the round task or contract. Omit when the objective is unchanged.",
|
|
134
148
|
},
|
|
135
149
|
{
|
|
136
150
|
path: "subgoal_updates",
|
|
151
|
+
array: true,
|
|
137
152
|
purpose: "Explicit status transitions for existing sub-goals.",
|
|
138
153
|
when: "When an active sg-XXXXXXXX sub-goal starts, is blocked, completes, or is canceled.",
|
|
139
154
|
nature: "transition",
|
|
@@ -147,142 +162,171 @@ const GUIDES = [
|
|
|
147
162
|
},
|
|
148
163
|
{
|
|
149
164
|
path: "emerged_subtasks",
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
array: true,
|
|
166
|
+
purpose: "New execution-plan work that the active criteria/contract do not already cover.",
|
|
167
|
+
when: "Only when new work appears or an existing work item must be split. Zero " +
|
|
168
|
+
"is correct when the current criteria/contract already cover the round.",
|
|
152
169
|
nature: "transition",
|
|
153
170
|
decision: "A new sub-problem surfaced (plain text, never sg- ids)",
|
|
154
|
-
|
|
171
|
+
compact: true,
|
|
155
172
|
promptRank: 40,
|
|
156
173
|
downstream: "The only sub-goal creation channel; the runtime derives stable sg- ids.",
|
|
157
|
-
toolDescription: "
|
|
158
|
-
"
|
|
174
|
+
toolDescription: "New work that surfaced during execution and was not already covered by " +
|
|
175
|
+
"the active criteria or current contract. The ONLY sub-goal creation " +
|
|
176
|
+
"channel. Plain descriptions, never sg-XXXXXXXX ids. Do not restate the " +
|
|
177
|
+
"criteria as sub-goals; zero entries is a valid result.",
|
|
159
178
|
},
|
|
160
179
|
{
|
|
161
180
|
path: "discovered_constraints",
|
|
181
|
+
array: true,
|
|
162
182
|
purpose: "New constraints that later rounds must respect.",
|
|
163
183
|
when: "When this round discovered a limit that was not known before.",
|
|
164
184
|
nature: "report",
|
|
165
185
|
decision: "You discovered a limit later rounds must respect",
|
|
166
|
-
|
|
186
|
+
compact: true,
|
|
167
187
|
promptRank: 20,
|
|
168
|
-
downstream: "Merged into the active constraint set by the compiler
|
|
188
|
+
downstream: "Merged into the active constraint set by the compiler; entries over " +
|
|
189
|
+
"max_discovered_constraints_per_round are diagnosed and dropped at the " +
|
|
190
|
+
"submission boundary.",
|
|
169
191
|
toolDescription: "New constraints that must apply to later rounds. This is the ONLY " +
|
|
170
192
|
"promotion channel for a worker-discovered constraint: a worker result " +
|
|
171
193
|
"stays a report until the main agent states the constraint here.",
|
|
172
194
|
},
|
|
173
195
|
{
|
|
174
196
|
path: "wrong_assumptions",
|
|
197
|
+
array: true,
|
|
175
198
|
purpose: "Assumptions from earlier rounds that this round falsified.",
|
|
176
199
|
when: "When evidence proved an earlier assumption wrong; omit when none.",
|
|
177
200
|
nature: "report",
|
|
178
201
|
decision: "Evidence falsified an earlier assumption",
|
|
179
|
-
|
|
202
|
+
compact: true,
|
|
180
203
|
promptRank: 30,
|
|
181
|
-
downstream: "
|
|
204
|
+
downstream: "Bounded Working Memory (fresh prompts and the committed projection), " +
|
|
205
|
+
"recovery brief, replay and explain. Only committed reports reach the " +
|
|
206
|
+
"next prompt.",
|
|
182
207
|
toolDescription: "Assumptions from earlier rounds that turned out to be wrong. Record one " +
|
|
183
208
|
"only when this round actually falsified it; otherwise omit. This is not " +
|
|
184
209
|
"a reflection quota.",
|
|
185
210
|
},
|
|
186
211
|
{
|
|
187
|
-
path: "
|
|
188
|
-
|
|
189
|
-
|
|
212
|
+
path: "open_questions",
|
|
213
|
+
array: true,
|
|
214
|
+
purpose: "Unresolved questions that still affect later slices (a question list, " +
|
|
215
|
+
"not a todo list).",
|
|
216
|
+
when: "Only when a real open question affects how later work should proceed; " +
|
|
217
|
+
"omit when none.",
|
|
190
218
|
nature: "report",
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
219
|
+
reportOnly: true,
|
|
220
|
+
decision: "A question remains open that later slices must resolve",
|
|
221
|
+
compact: true,
|
|
222
|
+
promptRank: 35,
|
|
223
|
+
downstream: "Bounded Working Memory (fresh prompts and the committed projection), " +
|
|
224
|
+
"replay and explain. Strictly report-only: it never enters the " +
|
|
225
|
+
"verification gate, success, contract closure or machine evidence.",
|
|
226
|
+
toolDescription: "Optional. At most 3 unresolved questions, 300 chars each. Record only " +
|
|
227
|
+
"questions that still affect later slices — not a todo list, not a " +
|
|
228
|
+
"completion checklist, and not a substitute for a blocker or decision. " +
|
|
229
|
+
"Report-only: LoopForge never acts on these entries.",
|
|
194
230
|
},
|
|
195
231
|
{
|
|
196
|
-
path: "
|
|
197
|
-
|
|
198
|
-
|
|
232
|
+
path: "resolved_open_question_ids",
|
|
233
|
+
array: true,
|
|
234
|
+
purpose: "Open-question ids that this round resolved.",
|
|
235
|
+
when: "When a previously rendered open question is no longer unresolved.",
|
|
199
236
|
nature: "report",
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
237
|
+
reportOnly: true,
|
|
238
|
+
decision: "A rendered open question was resolved",
|
|
239
|
+
compact: true,
|
|
240
|
+
promptRank: 36,
|
|
241
|
+
downstream: "Working Memory removes the cited question; replay and explain retain the report.",
|
|
242
|
+
toolDescription: "Optional. Use only stable oq-... ids rendered beside open questions in " +
|
|
243
|
+
"Working Memory or the state file. Report-only; it never changes the " +
|
|
244
|
+
"verification gate or acceptance criteria.",
|
|
203
245
|
},
|
|
204
246
|
{
|
|
205
|
-
path: "
|
|
206
|
-
|
|
207
|
-
|
|
247
|
+
path: "retracted_constraints",
|
|
248
|
+
array: true,
|
|
249
|
+
purpose: "Existing constraints that are no longer correct or relevant.",
|
|
250
|
+
when: "When a prior constraint is proven wrong or obsolete.",
|
|
208
251
|
nature: "report",
|
|
209
|
-
downstream: "
|
|
210
|
-
|
|
211
|
-
"
|
|
252
|
+
downstream: "Only active Agent-discovered constraints (including recovery-preserved " +
|
|
253
|
+
"discoveries) are retractable, by c-XXXXXXXX id or normalized-exact text. " +
|
|
254
|
+
"Operator criteria/hard constraints and plan constraints are rejected. " +
|
|
255
|
+
"Unknown/inactive targets are no-ops with a diagnostic.",
|
|
256
|
+
toolDescription: "Optional. Active Agent-discovered constraints that are no longer valid, " +
|
|
257
|
+
"by c-XXXXXXXX id or exact text. Operator criteria/hard constraints and " +
|
|
258
|
+
"plan constraints cannot be retracted. Omit when none.",
|
|
212
259
|
},
|
|
213
260
|
{
|
|
214
261
|
path: "round_contract",
|
|
215
|
-
purpose: "
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
"
|
|
262
|
+
purpose: "THE contract channel: the NEXT round's bounded deliverable and its " +
|
|
263
|
+
"acceptance conditions.",
|
|
264
|
+
when: "When contract coverage requires a next-round contract, or when you want " +
|
|
265
|
+
"to start or replace a slice. With after-capable commands, a continuing " +
|
|
266
|
+
"round with a successor available must leave an active contract; omit to " +
|
|
267
|
+
"continue the current one. The final configured round has no successor.",
|
|
219
268
|
nature: "proposal",
|
|
220
|
-
decision: "
|
|
269
|
+
decision: "The Agent decides the next slice; LoopForge only validates the declaration",
|
|
221
270
|
downstream: "Becomes active only after this round commits; item ids rci-XXXXXXXX are " +
|
|
222
|
-
"derived by the runtime."
|
|
223
|
-
|
|
224
|
-
"
|
|
225
|
-
|
|
226
|
-
"
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"
|
|
271
|
+
"derived by the runtime. `scope` is a report-only intent statement and " +
|
|
272
|
+
"never rejects or blocks a round. `supersedes` closes the named ACTIVE " +
|
|
273
|
+
"contract as `superseded` and activates this proposal next round.",
|
|
274
|
+
toolDescription: "THE contract channel for the NEXT round. work_item is the bounded " +
|
|
275
|
+
"deliverable this slice produces (an outcome, not an activity) and is " +
|
|
276
|
+
"required for a new proposal. items are acceptance conditions; each item " +
|
|
277
|
+
"binds its own verify_with commands and may cite cr- ids in " +
|
|
278
|
+
"criterion_refs. scope is an OPTIONAL, report-only declaration of " +
|
|
279
|
+
"intended files — it is not enforced and is not part of the rc- id. " +
|
|
280
|
+
"While a contract is open, omit this field to continue it unchanged. To " +
|
|
281
|
+
"replace the active slice, add supersedes { contract_id, reason? } with " +
|
|
282
|
+
"the active rc- id and different acceptance items. If the active " +
|
|
283
|
+
"contract closes this round and a successor is available, a successor " +
|
|
284
|
+
"is REQUIRED. The final configured round has no successor consumer. " +
|
|
285
|
+
"DECLARATION IS STRICT: a missing work_item, an item with no bound " +
|
|
286
|
+
"command, an unknown/disabled command, a malformed reference, an " +
|
|
287
|
+
"unknown field, or a count over the limits returns contract_invalid.",
|
|
230
288
|
},
|
|
231
289
|
{
|
|
232
290
|
path: "worker_results",
|
|
291
|
+
array: true,
|
|
233
292
|
purpose: "Results of sub-agent / worker delegations.",
|
|
234
293
|
when: "Only when work was actually delegated.",
|
|
235
294
|
nature: "report",
|
|
236
295
|
decision: "You delegated work",
|
|
237
|
-
|
|
296
|
+
compact: true,
|
|
238
297
|
promptRank: 50,
|
|
239
|
-
downstream: "Saved
|
|
240
|
-
"
|
|
298
|
+
downstream: "Saved inside the committed transaction as an audit report. A worker " +
|
|
299
|
+
"finding is not auto-promoted.",
|
|
241
300
|
toolDescription: "Optional. Results of sub-agent / Worker delegations this round. Each " +
|
|
242
301
|
"entry must declare an outcome. Entries without a valid outcome are " +
|
|
243
|
-
"dropped with a diagnostic.
|
|
244
|
-
"
|
|
245
|
-
"discovered_constraints.",
|
|
302
|
+
"dropped with a diagnostic. To make a worker finding a global " +
|
|
303
|
+
"constraint, submit it in top-level discovered_constraints.",
|
|
246
304
|
reportOnly: true,
|
|
247
305
|
},
|
|
248
306
|
{
|
|
249
|
-
path: "
|
|
250
|
-
purpose: "Information needs for the next round's prompt.",
|
|
251
|
-
when: "When you know what context the next round will need.",
|
|
252
|
-
nature: "control",
|
|
253
|
-
decision: "You know what the next prompt needs",
|
|
254
|
-
promptLevels: ["l1", "l2"],
|
|
255
|
-
promptRank: 70,
|
|
256
|
-
downstream: "Matched exactly against state items; applied to the next prompt only " +
|
|
257
|
-
"(L0 ignores it). Unmatched entries have no effect.",
|
|
258
|
-
toolDescription: "Optional. Information needs for the NEXT prompt. emphasize entries are " +
|
|
259
|
-
"matched by stable id or normalized-exact text; a paraphrase matches " +
|
|
260
|
-
"nothing. confusion_points are echoed at the top. L0 retry prompts ignore " +
|
|
261
|
-
"both arms. This never becomes long-term knowledge.",
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
path: "compression_checkpoint",
|
|
307
|
+
path: "subtask_boundary",
|
|
265
308
|
purpose: "Mark a meaningful work boundary.",
|
|
266
|
-
when: "At a
|
|
309
|
+
when: "At a subtask boundary that warrants an L2 rehydration.",
|
|
267
310
|
nature: "report",
|
|
268
|
-
decision: "This round reached a real phase boundary; pair with
|
|
269
|
-
|
|
311
|
+
decision: "This round reached a real phase boundary; pair with subtask_boundary_label",
|
|
312
|
+
compact: true,
|
|
270
313
|
promptRank: 60,
|
|
271
|
-
downstream: "
|
|
272
|
-
toolDescription: "Optional. true at a subtask boundary to
|
|
273
|
-
"
|
|
314
|
+
downstream: "Forces an L2 rehydration boundary. It creates no milestone or phase narrative.",
|
|
315
|
+
toolDescription: "Optional. true at a subtask boundary to force an L2 rehydration boundary. " +
|
|
316
|
+
"Pair with subtask_boundary_label.",
|
|
274
317
|
},
|
|
275
318
|
{
|
|
276
|
-
path: "
|
|
277
|
-
purpose: "A human-readable label for the
|
|
278
|
-
when: "Only together with
|
|
319
|
+
path: "subtask_boundary_label",
|
|
320
|
+
purpose: "A human-readable label for the subtask boundary.",
|
|
321
|
+
when: "Only together with subtask_boundary=true.",
|
|
279
322
|
nature: "report",
|
|
280
|
-
downstream: "
|
|
281
|
-
toolDescription: "Optional. Short label for the
|
|
282
|
-
"'core-model-complete'). Meaningful only when
|
|
323
|
+
downstream: "Stored on the committed report; it does not create a later prompt heading.",
|
|
324
|
+
toolDescription: "Optional. Short label for the subtask boundary (for example " +
|
|
325
|
+
"'core-model-complete'). Meaningful only when subtask_boundary=true.",
|
|
283
326
|
},
|
|
284
327
|
{
|
|
285
328
|
path: "retroactiveClaims",
|
|
329
|
+
array: true,
|
|
286
330
|
purpose: "A claim that an earlier round satisfied a criterion.",
|
|
287
331
|
when: "When you can point at an earlier round's evidence.",
|
|
288
332
|
nature: "claim",
|
|
@@ -293,6 +337,7 @@ const GUIDES = [
|
|
|
293
337
|
},
|
|
294
338
|
{
|
|
295
339
|
path: "gate_ids",
|
|
340
|
+
array: true,
|
|
296
341
|
purpose: "Approved gate ids this round's work depended on.",
|
|
297
342
|
when: "Only when policy.gate.enabled is true and an approval was actually obtained.",
|
|
298
343
|
nature: "control",
|
|
@@ -301,34 +346,16 @@ const GUIDES = [
|
|
|
301
346
|
"Enforced only when policy.gate.enabled: a cited, unapproved gate rejects " +
|
|
302
347
|
"the round. Without the gate layer this is saved but has no effect.",
|
|
303
348
|
},
|
|
304
|
-
{
|
|
305
|
-
path: "outcome",
|
|
306
|
-
purpose: "The declared round outcome.",
|
|
307
|
-
when: "When the round is partial, failed, or blocked (success is derivable).",
|
|
308
|
-
nature: "claim",
|
|
309
|
-
downstream: "Wins over `success` for the stop decision and success-class checks.",
|
|
310
|
-
toolDescription: "Optional. success | partial | failed | blocked. When absent, derived " +
|
|
311
|
-
"from success. A declared non-success outcome suppresses the " +
|
|
312
|
-
"success-class checks even when success=true.",
|
|
313
|
-
},
|
|
314
349
|
{
|
|
315
350
|
path: "blocker",
|
|
316
351
|
purpose: "A concrete description of what blocks the work.",
|
|
317
|
-
when: "Required when outcome=blocked;
|
|
352
|
+
when: "Required when outcome=blocked; ignored (with a diagnostic) otherwise.",
|
|
318
353
|
nature: "report",
|
|
319
|
-
downstream: "Stop
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
"
|
|
323
|
-
|
|
324
|
-
{
|
|
325
|
-
path: "stop_reason",
|
|
326
|
-
purpose: "Why the agent is stopping.",
|
|
327
|
-
when: "Only when should_continue=false and success=false.",
|
|
328
|
-
nature: "control",
|
|
329
|
-
downstream: "blocked/needs_human_input stop without claiming success; gave_up is the default stop behavior.",
|
|
330
|
-
toolDescription: "Optional. Why the agent is stopping: gave_up | blocked | needs_human_input. " +
|
|
331
|
-
"Only meaningful when should_continue=false and success=false.",
|
|
354
|
+
downstream: "Stop reason, blocked-contract closure, and gate classification when enabled. " +
|
|
355
|
+
"When work needs human input, say so here with outcome=blocked.",
|
|
356
|
+
toolDescription: "Required when outcome=blocked (trim non-empty, at most 500 chars). State " +
|
|
357
|
+
"what cannot proceed and why. When another outcome is declared it is " +
|
|
358
|
+
"dropped with a diagnostic and never rejects the round.",
|
|
332
359
|
},
|
|
333
360
|
{
|
|
334
361
|
path: "no_change_reason",
|
|
@@ -343,13 +370,31 @@ const GUIDES = [
|
|
|
343
370
|
},
|
|
344
371
|
];
|
|
345
372
|
const GUIDE_BY_PATH = new Map(GUIDES.map((guide) => [guide.path, guide]));
|
|
373
|
+
/** v4.0.3: array-valued evaluation paths, derived from the SAME field
|
|
374
|
+
* metadata the prompt, MCP schema and receipts read. Field accounting uses
|
|
375
|
+
* this set instead of a second hardcoded list. */
|
|
376
|
+
export const ARRAY_SELF_EVALUATION_FIELDS = new Set(GUIDES.filter((guide) => guide.array === true).map((guide) => guide.path));
|
|
346
377
|
/** Fields that existed in earlier releases and are now unknown. A diagnostic
|
|
347
378
|
* for one of these names explains the removal instead of silently dropping. */
|
|
348
379
|
const RETIRED_FIELDS = {
|
|
349
380
|
progress_estimate: "removed in 3.9.0 — progress is machine-derived; remove this field",
|
|
350
381
|
progress_at_boundary: "removed in 3.9.0 — milestones render a round range, not a percentage",
|
|
351
|
-
success_criteria_remaining: "removed in 3.8 — report criterion claims under execution_report.
|
|
382
|
+
success_criteria_remaining: "removed in 3.8 — report criterion claims under execution_report.claims",
|
|
352
383
|
next_action: "removed in 3.8 — the agent plans; LoopForge does not accept a next-action field",
|
|
384
|
+
revised_success_criteria: "removed in 3.9.6 — operator acceptance is immutable; report a conflict in " +
|
|
385
|
+
"wrong_assumptions or stop with outcome=blocked/needs_human_input",
|
|
386
|
+
prompt_requests: "removed in 4.0.1 — the next prompt is compiled from committed facts; " +
|
|
387
|
+
"there is no per-round prompt-steering channel",
|
|
388
|
+
success: "removed in 4.0.6 — use `outcome` (success | partial | failed | blocked)",
|
|
389
|
+
agent_stop_reason: "removed in 4.0.6 — use outcome=blocked with `blocker`; stop with " +
|
|
390
|
+
"outcome=failed and should_continue=false",
|
|
391
|
+
contract_transition: "removed in 4.0.6 — use round_contract.supersedes { contract_id, reason? }",
|
|
392
|
+
tests_reported: "removed in 4.0.6 — command observations are the test fact; do not report counts",
|
|
393
|
+
criterion_claims: "removed in 4.0.6 — use execution_report.claims with cr- ids",
|
|
394
|
+
contract_item_claims: "removed in 4.0.6 — use execution_report.claims with rci- ids",
|
|
395
|
+
"execution_report.tests_reported": "removed in 4.0.6 — command observations are the test fact; remove tests_reported",
|
|
396
|
+
"execution_report.criterion_claims": "removed in 4.0.6 — move these claims into execution_report.claims with cr- ids",
|
|
397
|
+
"execution_report.contract_item_claims": "removed in 4.0.6 — move these claims into execution_report.claims with rci- ids",
|
|
353
398
|
};
|
|
354
399
|
export function fieldGuide(path) {
|
|
355
400
|
return GUIDE_BY_PATH.get(path);
|
|
@@ -375,24 +420,21 @@ function firstActiveSubGoal(subGoals) {
|
|
|
375
420
|
* never invents an sg-/rci- reference. */
|
|
376
421
|
export function fieldExample(path, ctx) {
|
|
377
422
|
switch (path) {
|
|
378
|
-
case "
|
|
423
|
+
case "outcome": return "partial";
|
|
379
424
|
case "output_summary": return "<what was done and how it was verified>";
|
|
380
425
|
case "constraint_violations": return [];
|
|
381
426
|
case "should_continue": return true;
|
|
382
427
|
case "execution_report.files_changed":
|
|
383
428
|
return ["<path whose content or type differs from round start>"];
|
|
384
|
-
case "execution_report.
|
|
385
|
-
return { passed: 0, failed: 0, skipped: 0 };
|
|
386
|
-
case "execution_report.contract_item_claims": {
|
|
429
|
+
case "execution_report.claims": {
|
|
387
430
|
const item = firstActiveItem(ctx.activeContract);
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
case "execution_report.criterion_claims": {
|
|
431
|
+
if (item)
|
|
432
|
+
return [{ id: item.id, outcome: "met" }];
|
|
391
433
|
const criterion = ctx.criteria?.[0];
|
|
392
|
-
return criterion
|
|
393
|
-
? [{ criterion_id: criterion.id, outcome: "met" }]
|
|
394
|
-
: null;
|
|
434
|
+
return criterion ? [{ id: criterion.id, outcome: "met" }] : null;
|
|
395
435
|
}
|
|
436
|
+
case "objective_refinement":
|
|
437
|
+
return "<the overall objective as it now stands>";
|
|
396
438
|
case "subgoal_updates": {
|
|
397
439
|
const subGoal = firstActiveSubGoal(ctx.activeSubGoals);
|
|
398
440
|
return subGoal ? [{ id: subGoal.id, status: "done" }] : null;
|
|
@@ -403,58 +445,47 @@ export function fieldExample(path, ctx) {
|
|
|
403
445
|
return ["<a constraint later rounds must respect>"];
|
|
404
446
|
case "wrong_assumptions":
|
|
405
447
|
return ["<an assumption from an earlier round that was falsified>"];
|
|
406
|
-
case "
|
|
407
|
-
return "<
|
|
448
|
+
case "open_questions":
|
|
449
|
+
return ["<an unresolved question that still affects later slices>"];
|
|
450
|
+
case "resolved_open_question_ids":
|
|
451
|
+
return ["oq-<stable id rendered for a question>"];
|
|
408
452
|
case "retracted_constraints":
|
|
409
453
|
return ["<constraint text or c-XXXXXXXX id that is no longer valid>"];
|
|
410
|
-
case "revised_success_criteria":
|
|
411
|
-
return [{ old: "<old criterion>", new: "<new criterion>" }];
|
|
412
454
|
case "round_contract": {
|
|
413
455
|
if (!ctx.contractVerificationAvailable || ctx.commands.length === 0)
|
|
414
456
|
return null;
|
|
415
457
|
return {
|
|
416
|
-
work_item: "<
|
|
458
|
+
work_item: "<bounded deliverable this slice produces>",
|
|
417
459
|
items: [{
|
|
418
|
-
description: "<machine-checkable
|
|
460
|
+
description: "<machine-checkable acceptance condition>",
|
|
419
461
|
criterion_refs: [],
|
|
420
|
-
subgoal_refs: [],
|
|
421
462
|
verify_with: [ctx.commands[0]],
|
|
422
463
|
}],
|
|
423
|
-
scope: ["<workspace-relative file or directory>"],
|
|
424
464
|
};
|
|
425
465
|
}
|
|
426
466
|
case "worker_results":
|
|
427
467
|
return [{
|
|
428
468
|
agentId: "<worker id>",
|
|
429
|
-
subAgentType: "general-purpose",
|
|
430
469
|
subTask: "<self-contained subtask you delegated>",
|
|
431
470
|
resultSummary: "<what the worker reported>",
|
|
432
471
|
outcome: "success",
|
|
433
|
-
discoveredConstraints: [],
|
|
434
472
|
}];
|
|
435
|
-
case "
|
|
436
|
-
|
|
437
|
-
emphasize: ["<exact constraint text or stable id>"],
|
|
438
|
-
confusion_points: ["<what is unclear about the current state>"],
|
|
439
|
-
};
|
|
440
|
-
case "compression_checkpoint": return false;
|
|
441
|
-
case "checkpoint_label": return "<short phase label>";
|
|
473
|
+
case "subtask_boundary": return false;
|
|
474
|
+
case "subtask_boundary_label": return "<short phase label>";
|
|
442
475
|
case "retroactiveClaims":
|
|
443
476
|
return [{ round: 1, claim: "<what that earlier round satisfied>" }];
|
|
444
477
|
case "gate_ids":
|
|
445
478
|
return ["<approved gateId from loopforge_gate_check>"];
|
|
446
|
-
case "outcome": return "partial";
|
|
447
479
|
case "blocker": return "<what cannot proceed and why>";
|
|
448
|
-
case "stop_reason": return "blocked";
|
|
449
480
|
case "no_change_reason": return "<why no workspace change was needed>";
|
|
450
481
|
default: return null;
|
|
451
482
|
}
|
|
452
483
|
}
|
|
453
|
-
/** Semantic applicability —
|
|
454
|
-
* the two baseline execution-report fields are always
|
|
455
|
-
* depend on facts the runtime can actually observe.
|
|
456
|
-
* (delegation, a
|
|
457
|
-
* conditional opportunities, not render-time facts. */
|
|
484
|
+
/** Semantic applicability — the ONE rule, deliberately independent of prompt
|
|
485
|
+
* level. Core fields and the two baseline execution-report fields are always
|
|
486
|
+
* applicable; the rest depend on facts the runtime can actually observe.
|
|
487
|
+
* Future events (delegation, a subtask boundary, a falsified assumption)
|
|
488
|
+
* remain conditional opportunities, not render-time facts. */
|
|
458
489
|
export function isFieldApplicable(path, facts) {
|
|
459
490
|
const guide = GUIDE_BY_PATH.get(path);
|
|
460
491
|
if (!guide)
|
|
@@ -463,21 +494,18 @@ export function isFieldApplicable(path, facts) {
|
|
|
463
494
|
return true;
|
|
464
495
|
switch (path) {
|
|
465
496
|
case "execution_report.files_changed":
|
|
466
|
-
case "execution_report.tests_reported":
|
|
467
497
|
return true;
|
|
468
|
-
case "execution_report.
|
|
469
|
-
return facts.activeContract !== null;
|
|
470
|
-
case "
|
|
471
|
-
return
|
|
498
|
+
case "execution_report.claims":
|
|
499
|
+
return facts.activeContract !== null || (facts.criteria ?? []).length > 0;
|
|
500
|
+
case "objective_refinement":
|
|
501
|
+
return true;
|
|
472
502
|
case "subgoal_updates":
|
|
473
503
|
return firstActiveSubGoal(facts.subGoals) !== null;
|
|
474
504
|
case "round_contract":
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
return facts.
|
|
479
|
-
facts.contractVerificationAvailable &&
|
|
480
|
-
facts.commands.length > 0;
|
|
505
|
+
// v4.0.6: the contract channel is usable whenever a contract can be
|
|
506
|
+
// verified. The dedicated contract block decides REQUIRED vs continue vs
|
|
507
|
+
// redirect for the current facts.
|
|
508
|
+
return facts.contractVerificationAvailable && facts.commands.length > 0;
|
|
481
509
|
case "gate_ids":
|
|
482
510
|
return facts.gateEnabled;
|
|
483
511
|
case "no_change_reason":
|
|
@@ -486,13 +514,14 @@ export function isFieldApplicable(path, facts) {
|
|
|
486
514
|
return true;
|
|
487
515
|
}
|
|
488
516
|
}
|
|
489
|
-
/**
|
|
490
|
-
*
|
|
517
|
+
/** Compact-checklist membership: the explicit `compact` marker plus semantic
|
|
518
|
+
* applicability. The level is deliberately absent — L0/L1/L2 offer the same
|
|
519
|
+
* evaluation fields; only state density changes. Dedicated renderer fields
|
|
520
|
+
* (`round_contract`, `subgoal_updates`) are never compact members, so they
|
|
521
|
+
* cannot duplicate their own blocks. */
|
|
491
522
|
export function isFieldPrompted(path, facts) {
|
|
492
523
|
const guide = GUIDE_BY_PATH.get(path);
|
|
493
|
-
if (!guide?.
|
|
494
|
-
return false;
|
|
495
|
-
if (!guide.promptLevels.includes(facts.level))
|
|
524
|
+
if (!guide?.compact)
|
|
496
525
|
return false;
|
|
497
526
|
return isFieldApplicable(path, facts);
|
|
498
527
|
}
|
|
@@ -508,10 +537,23 @@ function statusOfItem(itemId, statuses) {
|
|
|
508
537
|
}
|
|
509
538
|
function renderContractGuidance(ctx) {
|
|
510
539
|
const contract = ctx.activeContract;
|
|
540
|
+
const hasCommand = ctx.contractVerificationAvailable && ctx.commands.length > 0;
|
|
541
|
+
// v4.0.6: coverage guidance uses the SAME shared rule as the submission
|
|
542
|
+
// boundary and the post-evidence gate. `proposalPresent:false` describes
|
|
543
|
+
// this prompt (no next-round proposal has been committed yet).
|
|
544
|
+
const requirement = deriveContractRequirement({
|
|
545
|
+
shouldContinue: true,
|
|
546
|
+
blocked: false,
|
|
547
|
+
proposalPresent: false,
|
|
548
|
+
activeContract: contract,
|
|
549
|
+
closure: ctx.itemStatuses?.closure ?? "open",
|
|
550
|
+
contractCapability: hasCommand,
|
|
551
|
+
successorRoundAvailable: ctx.maxRounds === undefined || ctx.round < ctx.maxRounds,
|
|
552
|
+
});
|
|
511
553
|
if (contract) {
|
|
512
554
|
const lines = [
|
|
513
|
-
"Active Round Contract —
|
|
514
|
-
`- ${contract.work_item
|
|
555
|
+
"Active Round Contract — it governs this round:",
|
|
556
|
+
`- Deliverable: ${contract.work_item ?? "(not named; legacy contract)"} (${contract.id})`,
|
|
515
557
|
];
|
|
516
558
|
const shown = contract.items.slice(0, 5);
|
|
517
559
|
for (const item of shown) {
|
|
@@ -522,37 +564,52 @@ function renderContractGuidance(ctx) {
|
|
|
522
564
|
if (contract.items.length > shown.length) {
|
|
523
565
|
lines.push(` - … and ${contract.items.length - shown.length} more in the Current Task.`);
|
|
524
566
|
}
|
|
525
|
-
const claimDecision = GUIDE_BY_PATH.get("execution_report.
|
|
526
|
-
?? "Claim
|
|
527
|
-
lines.push(`${claimDecision} via \`execution_report.
|
|
567
|
+
const claimDecision = GUIDE_BY_PATH.get("execution_report.claims")?.decision
|
|
568
|
+
?? "Claim criteria or active contract items with their real cr-/rci- ids";
|
|
569
|
+
lines.push(`${claimDecision} via \`execution_report.claims\`.`, "A claim alone leaves an item insufficient; its bound command must be observed", "passing. Omit `round_contract` to CONTINUE this contract unchanged — a", "different proposal without `supersedes` is rejected as contract_premature.", "To replace this slice, add `round_contract.supersedes` with", `{ contract_id: "${contract.id}" } and DIFFERENT acceptance items in the`, "same proposal. The old contract closes as superseded, its unverified items", "remain in the audit record, the workspace is not restored, and this round", "cannot be completed.", "`scope` is your declared intent — a report, not permission. It is not", "enforced and it is not part of the rc- id.");
|
|
570
|
+
if (requirement.reason === "no_contract_capability") {
|
|
571
|
+
lines.push("No enabled after-capable command is configured now, so this contract's", "items cannot be machine-verified this round and no successor is required.");
|
|
572
|
+
}
|
|
573
|
+
else if (requirement.reason === "no_successor_round") {
|
|
574
|
+
lines.push("This is the final configured round. Do not submit a successor " +
|
|
575
|
+
"round_contract; there is no next round to consume it.");
|
|
576
|
+
}
|
|
577
|
+
else if (requirement.reason === "active_contract_closed") {
|
|
578
|
+
lines.push("This contract is already closed. If you continue, a successor", "`round_contract` is REQUIRED for the next round.");
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
lines.push("If this round closes the contract (every item verified) and you continue,", "a successor `round_contract` is REQUIRED for the next round.");
|
|
582
|
+
}
|
|
528
583
|
return lines;
|
|
529
584
|
}
|
|
530
|
-
if (
|
|
585
|
+
if (requirement.reason === "no_contract_capability") {
|
|
531
586
|
return [
|
|
532
|
-
"No enabled after-capable evidence command is configured
|
|
533
|
-
"
|
|
587
|
+
"No enabled after-capable evidence command is configured — no contract is possible.",
|
|
588
|
+
"If the OVERALL starting objective genuinely evolved, submit `objective_refinement`.",
|
|
589
|
+
];
|
|
590
|
+
}
|
|
591
|
+
if (requirement.reason === "no_successor_round") {
|
|
592
|
+
return [
|
|
593
|
+
"This is the final configured round. Do not submit `round_contract`;",
|
|
594
|
+
"there is no successor round to consume a proposal.",
|
|
534
595
|
];
|
|
535
596
|
}
|
|
536
597
|
const commands = ctx.commands.slice(0, 3).join(", ");
|
|
537
|
-
const
|
|
538
|
-
|
|
598
|
+
const example = fieldExample("round_contract", {
|
|
599
|
+
activeContract: null,
|
|
600
|
+
activeSubGoals: ctx.subGoals,
|
|
601
|
+
commands: [...ctx.commands],
|
|
602
|
+
contractVerificationAvailable: true,
|
|
603
|
+
criteria: ctx.criteria,
|
|
604
|
+
});
|
|
539
605
|
return [
|
|
540
|
-
|
|
606
|
+
"No active Round Contract. If you continue, one is REQUIRED for the next",
|
|
607
|
+
"round. You decide the slice and acceptance conditions; LoopForge validates",
|
|
608
|
+
"structure, references and command bindings. Legal shape:",
|
|
541
609
|
"```json",
|
|
542
|
-
JSON.stringify({
|
|
543
|
-
round_contract: {
|
|
544
|
-
work_item: "<next slice, one line>",
|
|
545
|
-
items: [{
|
|
546
|
-
description: "<machine-checkable outcome>",
|
|
547
|
-
criterion_refs: [],
|
|
548
|
-
subgoal_refs: [],
|
|
549
|
-
verify_with: [ctx.commands[0]],
|
|
550
|
-
}],
|
|
551
|
-
scope: ["<workspace-relative path>"],
|
|
552
|
-
},
|
|
553
|
-
}, null, 1),
|
|
610
|
+
JSON.stringify({ round_contract: example }, null, 1),
|
|
554
611
|
"```",
|
|
555
|
-
`Usable commands: ${commands}
|
|
612
|
+
`Usable commands: ${commands}.`,
|
|
556
613
|
];
|
|
557
614
|
}
|
|
558
615
|
function renderSubGoalGuidance(ctx) {
|
|
@@ -593,7 +650,6 @@ function criteriaDetailLines(criteria) {
|
|
|
593
650
|
* per-field shapes remain in `submission_guidance`. */
|
|
594
651
|
function renderCompactTriggers(ctx) {
|
|
595
652
|
const facts = {
|
|
596
|
-
level: ctx.level,
|
|
597
653
|
activeContract: ctx.activeContract,
|
|
598
654
|
itemStatuses: ctx.itemStatuses,
|
|
599
655
|
subGoals: ctx.subGoals,
|
|
@@ -615,37 +671,71 @@ function renderCompactTriggers(ctx) {
|
|
|
615
671
|
if (!guide?.decision)
|
|
616
672
|
continue;
|
|
617
673
|
lines.push(`- ${guide.decision} → \`${path}\` → ${guide.downstream}`);
|
|
618
|
-
if (path === "execution_report.
|
|
674
|
+
if (path === "execution_report.claims") {
|
|
619
675
|
lines.push(...criteriaDetailLines(ctx.criteria ?? []));
|
|
620
676
|
}
|
|
621
677
|
}
|
|
622
678
|
return lines;
|
|
623
679
|
}
|
|
624
|
-
|
|
680
|
+
/** Verification flags name the concrete evaluation field, which is often the
|
|
681
|
+
* dotted path the Agent must fill. Normalize the legacy short names before
|
|
682
|
+
* the guidance lookup so the prompt always names the real field. */
|
|
683
|
+
const FLAG_FIELD_PATHS = {
|
|
684
|
+
files_changed: "execution_report.files_changed",
|
|
685
|
+
claims: "execution_report.claims",
|
|
686
|
+
criterion_claims: "execution_report.claims",
|
|
687
|
+
contract_item_claims: "execution_report.claims",
|
|
688
|
+
};
|
|
689
|
+
function flagFieldPath(field) {
|
|
690
|
+
return FLAG_FIELD_PATHS[field] ?? field;
|
|
691
|
+
}
|
|
692
|
+
function renderFlagGuidance(flags, criteria = [], level = "l1") {
|
|
625
693
|
if (flags.length === 0)
|
|
626
694
|
return [];
|
|
627
|
-
const fields = [
|
|
695
|
+
const fields = [
|
|
696
|
+
...new Set(flags.map((flag) => flagFieldPath(flag.field)).filter(Boolean)),
|
|
697
|
+
];
|
|
628
698
|
const lines = [
|
|
629
|
-
"
|
|
699
|
+
"Previous machine findings name these fields:",
|
|
630
700
|
...fields.slice(0, 8).map((field) => {
|
|
631
701
|
const guide = GUIDE_BY_PATH.get(field);
|
|
632
702
|
return `- \`${field}\`${guide ? ` — ${guide.purpose}` : ""}`;
|
|
633
703
|
}),
|
|
634
704
|
];
|
|
635
|
-
|
|
705
|
+
// L0's Verification Gate deliberately stays compact and carries no action
|
|
706
|
+
// continuation. The evaluation block is the Agent's composition surface,
|
|
707
|
+
// so the concrete action belongs here. L1/L2 already render it once in the
|
|
708
|
+
// gate; do not duplicate it.
|
|
709
|
+
if (level === "l0") {
|
|
710
|
+
const actions = new Map();
|
|
711
|
+
for (const flag of flags) {
|
|
712
|
+
if (flag.severity === "info" || actions.has(flag.check))
|
|
713
|
+
continue;
|
|
714
|
+
actions.set(flag.check, {
|
|
715
|
+
label: flag.severity === "error" ? "Fix" : "Action",
|
|
716
|
+
action: verificationActionFor(flag.check),
|
|
717
|
+
});
|
|
718
|
+
if (actions.size >= 3)
|
|
719
|
+
break;
|
|
720
|
+
}
|
|
721
|
+
for (const [check, entry] of actions) {
|
|
722
|
+
lines.push(` → ${entry.label}: ${entry.action} [${check}]`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
const criterionFinding = flags.some((flag) => flag.field === "execution_report.claims" ||
|
|
636
726
|
flag.field === "criterion_claims" ||
|
|
637
727
|
flag.check === "criteria_claims_unverified" ||
|
|
638
728
|
flag.check === "success_with_remaining_criteria");
|
|
639
729
|
if (criterionFinding && criteria.length > 0) {
|
|
640
730
|
lines.push(...criteriaDetailLines(criteria));
|
|
641
731
|
}
|
|
642
|
-
lines.push("Correct the relevant field(s) in the
|
|
732
|
+
lines.push("Correct the relevant field(s) in this round if the finding still applies.", "If this attempt falsified an earlier assumption, record it in", "`wrong_assumptions`; otherwise omit it.");
|
|
643
733
|
return lines;
|
|
644
734
|
}
|
|
645
735
|
/** Render the evaluation block appended to every prompt. */
|
|
646
736
|
export function renderSelfEvalBlock(ctx) {
|
|
647
737
|
const base = {
|
|
648
|
-
|
|
738
|
+
outcome: "partial",
|
|
649
739
|
output_summary: "<what was done and how it was verified>",
|
|
650
740
|
constraint_violations: [],
|
|
651
741
|
should_continue: true,
|
|
@@ -667,26 +757,25 @@ export function renderSelfEvalBlock(ctx) {
|
|
|
667
757
|
"```json",
|
|
668
758
|
JSON.stringify(base, null, 2),
|
|
669
759
|
"```",
|
|
670
|
-
"Add the execution report when
|
|
760
|
+
"Add the execution report when files changed or you claim items:",
|
|
671
761
|
"```json",
|
|
672
762
|
JSON.stringify({
|
|
673
763
|
execution_report: {
|
|
674
764
|
files_changed: fieldExample("execution_report.files_changed", reportCtx),
|
|
675
|
-
|
|
765
|
+
claims: fieldExample("execution_report.claims", reportCtx) ?? [],
|
|
676
766
|
},
|
|
677
767
|
}, null, 1),
|
|
678
768
|
"```",
|
|
679
|
-
"`files_changed` is the net
|
|
680
|
-
"
|
|
681
|
-
"is unchanged. Do not list gitignored paths merely to look complete.",
|
|
769
|
+
"`files_changed` is the net change from round start, including deletions.",
|
|
770
|
+
"A commit alone adds nothing; gitignored paths are outside the machine boundary.",
|
|
682
771
|
];
|
|
683
772
|
lines.push(...renderCompactTriggers(ctx));
|
|
684
773
|
lines.push(...renderContractGuidance(ctx));
|
|
685
774
|
lines.push(...renderSubGoalGuidance(ctx));
|
|
686
775
|
if (ctx.recovery || ctx.verificationFlags.length > 0) {
|
|
687
|
-
lines.push(...renderFlagGuidance(ctx.verificationFlags, ctx.criteria ?? []));
|
|
776
|
+
lines.push(...renderFlagGuidance(ctx.verificationFlags, ctx.criteria ?? [], ctx.level));
|
|
688
777
|
}
|
|
689
|
-
lines.push("Never invent an id
|
|
778
|
+
lines.push("Never invent an id; use only ids rendered here or in `submission_guidance`", "and omit the field when an id is absent.");
|
|
690
779
|
return lines.join("\n");
|
|
691
780
|
}
|
|
692
781
|
function activeSubGoals(subGoals) {
|
|
@@ -701,29 +790,31 @@ export function deriveSubmissionGuidance(session, options) {
|
|
|
701
790
|
const commandNames = capability.commands
|
|
702
791
|
.filter((command) => command.enabled)
|
|
703
792
|
.map((command) => command.commandId);
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
currentRound: session.currentRound,
|
|
713
|
-
rounds: options.rounds,
|
|
714
|
-
});
|
|
793
|
+
// Never invent a prompt level. If no held artifact is observable, the
|
|
794
|
+
// level is unknown; the prompt itself is derived from current facts.
|
|
795
|
+
const level = session.roundSnapshot?.promptArtifact?.level ?? null;
|
|
796
|
+
const subGoals = deriveSubGoals({
|
|
797
|
+
loopId: session.loopId,
|
|
798
|
+
currentRound: session.currentRound,
|
|
799
|
+
rounds: options.rounds,
|
|
800
|
+
});
|
|
715
801
|
const facts = deriveRoundFacts({
|
|
716
802
|
rounds: options.rounds,
|
|
717
803
|
currentRound: session.currentRound,
|
|
718
804
|
inFlight: NO_IN_FLIGHT_ROUND,
|
|
719
|
-
subGoals,
|
|
720
805
|
commands: commandsPolicy,
|
|
721
806
|
});
|
|
722
807
|
const activeContract = facts.activeContract;
|
|
723
808
|
const itemStatuses = facts.itemStatuses;
|
|
724
|
-
const criteria =
|
|
809
|
+
const criteria = options.objective
|
|
810
|
+
? deriveCriterionStatuses({
|
|
811
|
+
rounds: options.rounds,
|
|
812
|
+
currentRound: session.currentRound,
|
|
813
|
+
objective: options.objective,
|
|
814
|
+
criterionFacts: facts.criterionFacts,
|
|
815
|
+
})
|
|
816
|
+
: [];
|
|
725
817
|
const guidanceFacts = {
|
|
726
|
-
level,
|
|
727
818
|
activeContract,
|
|
728
819
|
itemStatuses,
|
|
729
820
|
subGoals,
|
|
@@ -739,16 +830,36 @@ export function deriveSubmissionGuidance(session, options) {
|
|
|
739
830
|
contractVerificationAvailable: capability.contractVerificationAvailable,
|
|
740
831
|
criteria,
|
|
741
832
|
};
|
|
742
|
-
const artifact = session.roundSnapshot?.promptArtifact
|
|
743
|
-
session.lastCompileResponse?.prompt_artifact;
|
|
744
|
-
const roundId = session.roundSnapshot?.roundId ??
|
|
745
|
-
`loop:${session.loopId}:round:${session.currentRound}`;
|
|
833
|
+
const artifact = session.roundSnapshot?.promptArtifact;
|
|
746
834
|
return {
|
|
747
|
-
|
|
835
|
+
contract_requirement: (() => {
|
|
836
|
+
const requirement = deriveContractRequirement({
|
|
837
|
+
shouldContinue: true,
|
|
838
|
+
blocked: false,
|
|
839
|
+
proposalPresent: false,
|
|
840
|
+
activeContract,
|
|
841
|
+
closure: itemStatuses.closure,
|
|
842
|
+
contractCapability: capability.contractVerificationAvailable,
|
|
843
|
+
successorRoundAvailable: session.maxRounds === undefined || session.currentRound < session.maxRounds,
|
|
844
|
+
});
|
|
845
|
+
return {
|
|
846
|
+
required_on_continue: requirement.required,
|
|
847
|
+
successor_required_if_closed: activeContract !== null && capability.contractVerificationAvailable &&
|
|
848
|
+
session.currentRound < (session.maxRounds ?? Number.POSITIVE_INFINITY),
|
|
849
|
+
reason: requirement.reason === "active_contract_closed" ||
|
|
850
|
+
requirement.reason === "active_contract_continues" ||
|
|
851
|
+
requirement.reason === "no_contract_capability" ||
|
|
852
|
+
requirement.reason === "no_successor_round"
|
|
853
|
+
? requirement.reason
|
|
854
|
+
: "no_active_contract",
|
|
855
|
+
active_contract_id: activeContract?.id ?? null,
|
|
856
|
+
};
|
|
857
|
+
})(),
|
|
748
858
|
active_contract: activeContract
|
|
749
859
|
? {
|
|
750
860
|
id: activeContract.id,
|
|
751
861
|
...(activeContract.work_item ? { work_item: activeContract.work_item } : {}),
|
|
862
|
+
scope: [...activeContract.scope],
|
|
752
863
|
declared_at_round: activeContract.declared_at_round,
|
|
753
864
|
items: activeContract.items.map((item) => ({
|
|
754
865
|
id: item.id,
|
|
@@ -770,13 +881,7 @@ export function deriveSubmissionGuidance(session, options) {
|
|
|
770
881
|
text: criterion.text,
|
|
771
882
|
status: criterion.status,
|
|
772
883
|
})),
|
|
773
|
-
recovery: options.recovery ??
|
|
774
|
-
? {
|
|
775
|
-
required: true,
|
|
776
|
-
restore_point: Math.max(1, session.currentRound - 1),
|
|
777
|
-
target_head: session.backtrackTargetGitHead,
|
|
778
|
-
}
|
|
779
|
-
: null),
|
|
884
|
+
recovery: options.recovery ?? null,
|
|
780
885
|
prompt: {
|
|
781
886
|
level,
|
|
782
887
|
dropped_sections: [...(artifact?.droppedSections ?? [])],
|
|
@@ -798,6 +903,7 @@ export function deriveSubmissionGuidance(session, options) {
|
|
|
798
903
|
check: flag.check,
|
|
799
904
|
severity: flag.severity,
|
|
800
905
|
detail: flag.detail,
|
|
906
|
+
...(flag.ref ? { ref: flag.ref } : {}),
|
|
801
907
|
})),
|
|
802
908
|
};
|
|
803
909
|
}
|