loopforge 2.11.0 → 3.0.0
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 +145 -128
- package/dist/canonical-event-writer.d.ts +20 -0
- package/dist/canonical-event-writer.d.ts.map +1 -0
- package/dist/canonical-event-writer.js +131 -0
- package/dist/canonical-event-writer.js.map +1 -0
- package/dist/canonical-state.d.ts +20 -16
- package/dist/canonical-state.d.ts.map +1 -1
- package/dist/canonical-state.js +170 -61
- package/dist/canonical-state.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -10
- package/dist/cli.js.map +1 -1
- package/dist/cognitive-governance.d.ts +48 -0
- package/dist/cognitive-governance.d.ts.map +1 -0
- package/dist/cognitive-governance.js +226 -0
- package/dist/cognitive-governance.js.map +1 -0
- package/dist/compiler-subgoals.d.ts +7 -0
- package/dist/compiler-subgoals.d.ts.map +1 -0
- package/dist/compiler-subgoals.js +93 -0
- package/dist/compiler-subgoals.js.map +1 -0
- package/dist/derive-id.d.ts +12 -0
- package/dist/derive-id.d.ts.map +1 -0
- package/dist/derive-id.js +31 -0
- package/dist/derive-id.js.map +1 -0
- package/dist/evidence-provider.d.ts +23 -21
- package/dist/evidence-provider.d.ts.map +1 -1
- package/dist/evidence-provider.js +34 -74
- package/dist/evidence-provider.js.map +1 -1
- package/dist/generate-schema.js +90 -2
- package/dist/generate-schema.js.map +1 -1
- package/dist/index.d.ts +22 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -16
- package/dist/index.js.map +1 -1
- package/dist/loop-compiler.d.ts +1 -1
- package/dist/loop-compiler.d.ts.map +1 -1
- package/dist/loop-compiler.js +250 -337
- package/dist/loop-compiler.js.map +1 -1
- package/dist/loop-extras-parser.d.ts +2 -2
- package/dist/loop-extras-parser.d.ts.map +1 -1
- package/dist/loop-extras-parser.js +2 -2
- package/dist/loop-extras-parser.js.map +1 -1
- package/dist/loop-store.d.ts +20 -58
- package/dist/loop-store.d.ts.map +1 -1
- package/dist/loop-store.js +232 -309
- package/dist/loop-store.js.map +1 -1
- package/dist/mcp/server.d.ts +3 -3
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +83 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/session-projection.d.ts +5 -0
- package/dist/mcp/session-projection.d.ts.map +1 -0
- package/dist/mcp/session-projection.js +18 -0
- package/dist/mcp/session-projection.js.map +1 -0
- package/dist/mcp/session-queue.d.ts +3 -0
- package/dist/mcp/session-queue.d.ts.map +1 -0
- package/dist/mcp/session-queue.js +18 -0
- package/dist/mcp/session-queue.js.map +1 -0
- package/dist/mcp/session-types.d.ts +72 -0
- package/dist/mcp/session-types.d.ts.map +1 -0
- package/dist/mcp/session-types.js +2 -0
- package/dist/mcp/session-types.js.map +1 -0
- package/dist/mcp/session.d.ts +49 -93
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +544 -245
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/tools.d.ts +26 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +399 -274
- package/dist/mcp/tools.js.map +1 -1
- package/dist/policy-metrics.d.ts +17 -1
- package/dist/policy-metrics.d.ts.map +1 -1
- package/dist/policy-metrics.js +164 -1
- package/dist/policy-metrics.js.map +1 -1
- package/dist/policy.d.ts +34 -18
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +113 -18
- package/dist/policy.js.map +1 -1
- package/dist/prompt-assembler.d.ts +5 -3
- package/dist/prompt-assembler.d.ts.map +1 -1
- package/dist/prompt-assembler.js +126 -77
- package/dist/prompt-assembler.js.map +1 -1
- package/dist/prompt-policy.d.ts +8 -1
- package/dist/prompt-policy.d.ts.map +1 -1
- package/dist/prompt-policy.js +26 -8
- package/dist/prompt-policy.js.map +1 -1
- package/dist/protocol.d.ts +232 -192
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +15 -100
- package/dist/protocol.js.map +1 -1
- package/dist/replay.d.ts +11 -3
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +51 -14
- package/dist/replay.js.map +1 -1
- package/dist/round-commit-store.d.ts +12 -0
- package/dist/round-commit-store.d.ts.map +1 -0
- package/dist/round-commit-store.js +13 -0
- package/dist/round-commit-store.js.map +1 -0
- package/dist/round-coordinator.d.ts +25 -18
- package/dist/round-coordinator.d.ts.map +1 -1
- package/dist/round-coordinator.js +83 -71
- package/dist/round-coordinator.js.map +1 -1
- package/dist/round-driver.d.ts +14 -10
- package/dist/round-driver.d.ts.map +1 -1
- package/dist/round-driver.js +9 -13
- package/dist/round-driver.js.map +1 -1
- package/dist/round-gate.d.ts +31 -0
- package/dist/round-gate.d.ts.map +1 -0
- package/dist/round-gate.js +259 -0
- package/dist/round-gate.js.map +1 -0
- package/dist/round-recovery.d.ts +17 -0
- package/dist/round-recovery.d.ts.map +1 -0
- package/dist/round-recovery.js +117 -0
- package/dist/round-recovery.js.map +1 -0
- package/dist/round-report.d.ts +16 -0
- package/dist/round-report.d.ts.map +1 -0
- package/dist/round-report.js +401 -0
- package/dist/round-report.js.map +1 -0
- package/dist/round-transaction.d.ts +19 -12
- package/dist/round-transaction.d.ts.map +1 -1
- package/dist/round-transaction.js +102 -88
- package/dist/round-transaction.js.map +1 -1
- package/dist/runtime-services.d.ts +59 -0
- package/dist/runtime-services.d.ts.map +1 -0
- package/dist/runtime-services.js +460 -0
- package/dist/runtime-services.js.map +1 -0
- package/dist/storage.d.ts +3 -9
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +6 -17
- package/dist/storage.js.map +1 -1
- package/dist/token-utils.d.ts +9 -8
- package/dist/token-utils.d.ts.map +1 -1
- package/dist/token-utils.js +50 -10
- package/dist/token-utils.js.map +1 -1
- package/dist/vault-format.d.ts +4 -0
- package/dist/vault-format.d.ts.map +1 -0
- package/dist/vault-format.js +4 -0
- package/dist/vault-format.js.map +1 -0
- package/dist/vault-types.d.ts +24 -0
- package/dist/vault-types.d.ts.map +1 -0
- package/dist/vault-types.js +2 -0
- package/dist/vault-types.js.map +1 -0
- package/loop_policy.json +10 -12
- package/loopforge-policy.json +340 -0
- package/package.json +12 -6
- package/skills/perception/SKILL.md +199 -164
- package/dist/backends/interface.d.ts +0 -39
- package/dist/backends/interface.d.ts.map +0 -1
- package/dist/backends/interface.js +0 -6
- package/dist/backends/interface.js.map +0 -1
- package/dist/enforcement-gate.d.ts +0 -71
- package/dist/enforcement-gate.d.ts.map +0 -1
- package/dist/enforcement-gate.js +0 -744
- package/dist/enforcement-gate.js.map +0 -1
- package/dist/engine.d.ts +0 -59
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -596
- package/dist/engine.js.map +0 -1
- package/dist/self-eval.d.ts +0 -23
- package/dist/self-eval.d.ts.map +0 -1
- package/dist/self-eval.js +0 -181
- package/dist/self-eval.js.map +0 -1
- package/dist/verification-gate.d.ts +0 -56
- package/dist/verification-gate.d.ts.map +0 -1
- package/dist/verification-gate.js +0 -563
- package/dist/verification-gate.js.map +0 -1
package/dist/policy.js
CHANGED
|
@@ -2,14 +2,32 @@
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
4
4
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
5
|
+
const REMOVED_POLICY_KEYS = new Set([
|
|
6
|
+
"engine.backtrack_auto_restore",
|
|
7
|
+
]);
|
|
8
|
+
const DEPRECATED_POLICY_KEYS = new Set([
|
|
9
|
+
"constraints.retire_window",
|
|
10
|
+
"engine.round_event_flush_interval",
|
|
11
|
+
"evolution.progress_stall_threshold",
|
|
12
|
+
"evolution.progress_stall_rounds",
|
|
13
|
+
"evolution.progress_mismatch_threshold",
|
|
14
|
+
"evolution.subgoal_auto_in_progress_threshold",
|
|
15
|
+
"evolution.subgoal_stale_rounds",
|
|
16
|
+
"state_file.max_checkpoints",
|
|
17
|
+
"state_file.max_summary_rounds",
|
|
18
|
+
]);
|
|
5
19
|
export const DEFAULT_POLICY = {
|
|
6
|
-
version: "
|
|
7
|
-
constraints: {
|
|
20
|
+
version: "stable",
|
|
21
|
+
constraints: {},
|
|
8
22
|
summary: { window: 5, health_check_interval: 1, milestone_interval: 20, max_milestones: 10, enable_loop_synthesis: true },
|
|
9
|
-
engine: {
|
|
23
|
+
engine: { max_circuit_breaker: 3, max_rounds: 100, enforcement_escalation_enabled: true, backtrack_enabled: true, backtrack_max_depth: 3, backtrack_preserve_discoveries: true, drift_clarification_max_streak: 3, max_rejections: 3 },
|
|
10
24
|
prompt: {
|
|
11
25
|
injection_mode: "adaptive",
|
|
12
26
|
full_refresh_interval: 0,
|
|
27
|
+
adaptive_refresh: true,
|
|
28
|
+
max_l1_streak: 6,
|
|
29
|
+
stale_round_threshold: 3,
|
|
30
|
+
min_meaningful_sections: 4,
|
|
13
31
|
l0_max_chars: 3000,
|
|
14
32
|
l1_max_chars: 7000,
|
|
15
33
|
l2_max_chars: 18000,
|
|
@@ -23,25 +41,21 @@ export const DEFAULT_POLICY = {
|
|
|
23
41
|
max_emphasize_l1: 3,
|
|
24
42
|
max_expand_l1: 1,
|
|
25
43
|
max_confusion_points: 3,
|
|
26
|
-
base_prompt_version: "
|
|
44
|
+
base_prompt_version: "stable",
|
|
27
45
|
},
|
|
28
46
|
backend: { root_dir: ".loopforge" },
|
|
29
47
|
evolution: {
|
|
30
48
|
max_discovered_constraints_per_round: 5,
|
|
31
49
|
max_active_constraints: 15,
|
|
32
50
|
max_objective_versions: 10,
|
|
33
|
-
|
|
34
|
-
progress_stall_rounds: 2,
|
|
35
|
-
progress_mismatch_threshold: 0.3,
|
|
51
|
+
failed_pattern_match_threshold: 0.6,
|
|
36
52
|
intent_drift_threshold: 0.15,
|
|
37
53
|
criteria_dedup_threshold: 0.45,
|
|
38
54
|
subgoal_dedup_threshold: 0.6,
|
|
39
55
|
subgoal_match_threshold: 0.5,
|
|
40
|
-
subgoal_auto_in_progress_threshold: 0.4,
|
|
41
56
|
subgoal_auto_complete_threshold: 0.4,
|
|
42
57
|
constraint_match_threshold: 0.5,
|
|
43
58
|
subgoal_drift_alignment_threshold: 0.3,
|
|
44
|
-
subgoal_stale_rounds: 10,
|
|
45
59
|
max_subgoals_in_prompt: 10,
|
|
46
60
|
max_done_subgoals_in_prompt: 5,
|
|
47
61
|
constraint_inactive_rounds: 15,
|
|
@@ -51,8 +65,6 @@ export const DEFAULT_POLICY = {
|
|
|
51
65
|
state_file: {
|
|
52
66
|
enabled: true,
|
|
53
67
|
directory: ".loopforge/state",
|
|
54
|
-
max_checkpoints: 5,
|
|
55
|
-
max_summary_rounds: 5,
|
|
56
68
|
},
|
|
57
69
|
evidence: { providers: ["git"], timeout_ms: 120_000, commands: [] },
|
|
58
70
|
mcp: {
|
|
@@ -60,6 +72,85 @@ export const DEFAULT_POLICY = {
|
|
|
60
72
|
session_lease_renew_interval_ms: 10_000,
|
|
61
73
|
},
|
|
62
74
|
};
|
|
75
|
+
let lastPolicyDiagnostics = [];
|
|
76
|
+
function policyKind(value) {
|
|
77
|
+
if (Array.isArray(value))
|
|
78
|
+
return "array";
|
|
79
|
+
if (value === null)
|
|
80
|
+
return "null";
|
|
81
|
+
return typeof value;
|
|
82
|
+
}
|
|
83
|
+
function collectPolicyDiagnostics(value, defaults, path, diagnostics) {
|
|
84
|
+
if (value === null || value === undefined)
|
|
85
|
+
return;
|
|
86
|
+
if (typeof defaults !== "object" || defaults === null || Array.isArray(defaults)) {
|
|
87
|
+
if (policyKind(value) !== policyKind(defaults)) {
|
|
88
|
+
diagnostics.push({
|
|
89
|
+
severity: "error",
|
|
90
|
+
kind: "type",
|
|
91
|
+
path,
|
|
92
|
+
message: `Expected ${policyKind(defaults)}, received ${policyKind(value)}.`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
98
|
+
diagnostics.push({
|
|
99
|
+
severity: "error",
|
|
100
|
+
kind: "type",
|
|
101
|
+
path,
|
|
102
|
+
message: `Expected object, received ${policyKind(value)}.`,
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const defaultRecord = defaults;
|
|
107
|
+
const valueRecord = value;
|
|
108
|
+
for (const key of Object.keys(valueRecord)) {
|
|
109
|
+
const childPath = path ? `${path}.${key}` : key;
|
|
110
|
+
if (REMOVED_POLICY_KEYS.has(childPath)) {
|
|
111
|
+
diagnostics.push({
|
|
112
|
+
severity: "error",
|
|
113
|
+
kind: "removed",
|
|
114
|
+
path: childPath,
|
|
115
|
+
message: "This policy key is removed and has never performed automatic workspace changes.",
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (DEPRECATED_POLICY_KEYS.has(childPath)) {
|
|
120
|
+
diagnostics.push({
|
|
121
|
+
severity: "warning",
|
|
122
|
+
kind: "deprecated",
|
|
123
|
+
path: childPath,
|
|
124
|
+
message: "This policy key is deprecated and has no effect in the stable runtime.",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (!(key in defaultRecord)) {
|
|
128
|
+
const kind = REMOVED_POLICY_KEYS.has(childPath)
|
|
129
|
+
? "removed"
|
|
130
|
+
: DEPRECATED_POLICY_KEYS.has(childPath) ? "deprecated" : "unknown";
|
|
131
|
+
diagnostics.push({
|
|
132
|
+
severity: kind === "removed" ? "error" : "warning",
|
|
133
|
+
kind,
|
|
134
|
+
path: childPath,
|
|
135
|
+
message: kind === "removed"
|
|
136
|
+
? "This policy key is removed and has never performed automatic workspace changes."
|
|
137
|
+
: kind === "deprecated"
|
|
138
|
+
? "This policy key is deprecated and has no effect in the stable runtime."
|
|
139
|
+
: "Unknown policy key; it will be ignored.",
|
|
140
|
+
});
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
collectPolicyDiagnostics(valueRecord[key], defaultRecord[key], childPath, diagnostics);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function diagnosePolicyDocument(value) {
|
|
147
|
+
const diagnostics = [];
|
|
148
|
+
collectPolicyDiagnostics(value, DEFAULT_POLICY, "", diagnostics);
|
|
149
|
+
return diagnostics;
|
|
150
|
+
}
|
|
151
|
+
export function getPolicyDiagnostics() {
|
|
152
|
+
return lastPolicyDiagnostics.map((diagnostic) => ({ ...diagnostic }));
|
|
153
|
+
}
|
|
63
154
|
/** Write a full default `loop_policy.json` to the target directory.
|
|
64
155
|
*
|
|
65
156
|
* The written file contains every configurable key and its default value
|
|
@@ -86,28 +177,32 @@ function deepMerge(defaults, overrides) {
|
|
|
86
177
|
typeof incoming === "object" && !Array.isArray(incoming)) {
|
|
87
178
|
result[key] = deepMerge(current, incoming);
|
|
88
179
|
}
|
|
89
|
-
else if (key in result) {
|
|
180
|
+
else if (key in result && policyKind(current) === policyKind(incoming)) {
|
|
90
181
|
result[key] = incoming;
|
|
91
182
|
}
|
|
92
|
-
else {
|
|
93
|
-
// Warn on unknown keys — a typo like "max_round" instead of
|
|
94
|
-
// "max_rounds" would otherwise be silently ignored.
|
|
95
|
-
console.warn(`loopforge: ignoring unknown policy key "${key}". Check loop_policy.json for typos.`);
|
|
96
|
-
}
|
|
97
183
|
}
|
|
98
184
|
return result;
|
|
99
185
|
}
|
|
100
186
|
export function loadPolicy(path) {
|
|
187
|
+
lastPolicyDiagnostics = [];
|
|
101
188
|
const candidates = [path, "loop_policy.json"].filter(Boolean);
|
|
102
189
|
for (const candidate of candidates) {
|
|
103
190
|
try {
|
|
104
191
|
const raw = JSON.parse(readFileSync(resolve(candidate), "utf8"));
|
|
105
192
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
193
|
+
lastPolicyDiagnostics = diagnosePolicyDocument(raw);
|
|
106
194
|
return deepMerge(DEFAULT_POLICY, raw);
|
|
107
195
|
}
|
|
108
196
|
}
|
|
109
197
|
catch {
|
|
110
|
-
|
|
198
|
+
if (existsSync(resolve(candidate))) {
|
|
199
|
+
lastPolicyDiagnostics = [{
|
|
200
|
+
severity: "error",
|
|
201
|
+
kind: "parse",
|
|
202
|
+
path: candidate,
|
|
203
|
+
message: "Policy file is not valid JSON; defaults are active.",
|
|
204
|
+
}];
|
|
205
|
+
}
|
|
111
206
|
}
|
|
112
207
|
}
|
|
113
208
|
return structuredClone(DEFAULT_POLICY);
|
package/dist/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import type { CanonicalLoopState } from "./canonical-state.js";
|
|
8
8
|
import type { PromptArtifact, PromptRequests } from "./protocol.js";
|
|
9
9
|
import type { PromptLevel, PromptLevelReason } from "./prompt-policy.js";
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const BASE_PROMPT_VERSION = "
|
|
10
|
+
export declare const PROMPT_ARTIFACT_FORMAT: "loopforge.prompt";
|
|
11
|
+
export declare const BASE_PROMPT_VERSION = "stable";
|
|
12
12
|
export type InjectionMode = "adaptive" | "full" | "pointer";
|
|
13
13
|
export interface PromptBudgets {
|
|
14
14
|
l0: number;
|
|
@@ -23,8 +23,10 @@ export interface PromptAssemblyInput {
|
|
|
23
23
|
mode?: InjectionMode;
|
|
24
24
|
budgets?: Partial<PromptBudgets>;
|
|
25
25
|
attempt?: number;
|
|
26
|
-
|
|
26
|
+
roundReportBlock?: string;
|
|
27
27
|
fullStateMarkdown?: string;
|
|
28
|
+
/** Previous Agent suggestion. Display-only; never part of canonical state. */
|
|
29
|
+
agentIntent?: string;
|
|
28
30
|
/** v2.9: Model's information needs for this prompt. L0: ignored. */
|
|
29
31
|
promptRequests?: PromptRequests;
|
|
30
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-assembler.d.ts","sourceRoot":"","sources":["../src/prompt-assembler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"prompt-assembler.d.ts","sourceRoot":"","sources":["../src/prompt-assembler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAI5B,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAClE,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AA4sBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CA2KjF"}
|
package/dist/prompt-assembler.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* are never truncated; budgets are soft and overflow is recorded.
|
|
6
6
|
*/
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
|
+
import { deriveItemId } from "./derive-id.js";
|
|
8
9
|
import { hashCanonicalState } from "./canonical-state.js";
|
|
9
10
|
import { jaccardSimilarity } from "./token-utils.js";
|
|
10
11
|
import { getPolicy } from "./policy.js";
|
|
11
|
-
export const
|
|
12
|
-
export const BASE_PROMPT_VERSION = "
|
|
12
|
+
export const PROMPT_ARTIFACT_FORMAT = "loopforge.prompt";
|
|
13
|
+
export const BASE_PROMPT_VERSION = "stable";
|
|
13
14
|
export const DEFAULT_PROMPT_BUDGETS = {
|
|
14
15
|
l0: 3000,
|
|
15
16
|
l1: 7000,
|
|
@@ -23,10 +24,6 @@ function bullets(values, prefix = "- ") {
|
|
|
23
24
|
}
|
|
24
25
|
/** v2.11: Derive a stable item ID from text content.
|
|
25
26
|
* Same hash strategy as computeGoalTextHash in loop-compiler.ts. */
|
|
26
|
-
function deriveItemId(text) {
|
|
27
|
-
const normalized = text.trim().replace(/\s+/g, " ").toLowerCase();
|
|
28
|
-
return createHash("sha256").update(normalized).digest("hex").slice(0, 8);
|
|
29
|
-
}
|
|
30
27
|
/** v2.11: Render a bullet list with ID prefixes for constraints/criteria.
|
|
31
28
|
* Each item gets a [prefix-XXXXXXXX] tag. Items that already look like IDs
|
|
32
29
|
* are rendered as-is. When constraint_id_enabled is false, renders plain bullets. */
|
|
@@ -69,12 +66,41 @@ level) {
|
|
|
69
66
|
text: section("Objective", state.objective),
|
|
70
67
|
mandatory: true,
|
|
71
68
|
},
|
|
72
|
-
{
|
|
73
|
-
id: "current_task",
|
|
74
|
-
text: section("Current Task", state.currentTask),
|
|
75
|
-
mandatory: true,
|
|
76
|
-
},
|
|
77
69
|
];
|
|
70
|
+
const phase = state.phaseHistory.at(-1);
|
|
71
|
+
if (phase) {
|
|
72
|
+
sections.push({
|
|
73
|
+
id: "current_phase",
|
|
74
|
+
text: section("Current Phase", `${phase.label} (${phase.status})\n${phase.outcome}`),
|
|
75
|
+
mandatory: false,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const focus = state.currentFocus || state.objective;
|
|
79
|
+
if (focus.trim()) {
|
|
80
|
+
sections.push({
|
|
81
|
+
id: "current_focus",
|
|
82
|
+
text: section("Current Focus", focus),
|
|
83
|
+
mandatory: true,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (state.todoProjection) {
|
|
87
|
+
sections.push({
|
|
88
|
+
id: "todo_projection",
|
|
89
|
+
text: section("Active Todo Projection", `${state.todoProjection.action}\nCompletion: ${state.todoProjection.completionSignal}`),
|
|
90
|
+
mandatory: false,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
sections.push({
|
|
94
|
+
id: "verification",
|
|
95
|
+
text: section("Verification Gate", verificationText(state) || "No verification contradiction is currently open."),
|
|
96
|
+
mandatory: true,
|
|
97
|
+
});
|
|
98
|
+
if (state.activeGate) {
|
|
99
|
+
const body = state.activeGate.kind === "user"
|
|
100
|
+
? [`Owner: user`, `Question: ${state.activeGate.question}`, `Blocked scope: ${state.activeGate.blockedScope.join("; ")}`, `Safe work: ${state.activeGate.allowedWork.join("; ")}`].join("\n")
|
|
101
|
+
: [`Owner: agent`, `Problem: ${state.activeGate.problem}`, `Required evidence: ${state.activeGate.requiredEvidence.join("; ")}`, `Resolution: ${state.activeGate.suggestedResolution}`].join("\n");
|
|
102
|
+
sections.push({ id: "active_gate", text: section("Active Gate", body), mandatory: true });
|
|
103
|
+
}
|
|
78
104
|
if (state.hardConstraints.length > 0) {
|
|
79
105
|
// v2.11: L0 uses plain bullets (tight budget); L1/L2 show constraint IDs
|
|
80
106
|
const body = level === "l0"
|
|
@@ -86,13 +112,6 @@ level) {
|
|
|
86
112
|
mandatory: true,
|
|
87
113
|
});
|
|
88
114
|
}
|
|
89
|
-
if (state.verificationFlags.length > 0) {
|
|
90
|
-
sections.push({
|
|
91
|
-
id: "verification",
|
|
92
|
-
text: section("Verification Gate", verificationText(state)),
|
|
93
|
-
mandatory: true,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
115
|
return sections;
|
|
97
116
|
}
|
|
98
117
|
function l0Sections(state) {
|
|
@@ -119,6 +138,14 @@ function l0Sections(state) {
|
|
|
119
138
|
}
|
|
120
139
|
function l1Sections(state) {
|
|
121
140
|
const sections = commonMandatorySections(state, "l1");
|
|
141
|
+
const openRegression = state.regressionObligations.filter((obligation) => obligation.status !== "satisfied");
|
|
142
|
+
if (openRegression.length > 0) {
|
|
143
|
+
sections.push({
|
|
144
|
+
id: "regression_obligations",
|
|
145
|
+
text: section("Regression Obligations", bullets(openRegression.map((item) => `[${item.status}] ${item.description}`))),
|
|
146
|
+
mandatory: true,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
122
149
|
const active = activeNonHardConstraints(state);
|
|
123
150
|
if (state.changesSinceLastRound.length > 0) {
|
|
124
151
|
sections.push({
|
|
@@ -145,7 +172,14 @@ function l1Sections(state) {
|
|
|
145
172
|
sections.push({
|
|
146
173
|
id: "blockers",
|
|
147
174
|
text: section("Blockers", bullets(state.blockers)),
|
|
148
|
-
mandatory:
|
|
175
|
+
mandatory: true,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (state.handoff.verifiedFacts.length > 0) {
|
|
179
|
+
sections.push({
|
|
180
|
+
id: "verified_facts",
|
|
181
|
+
text: section("Latest Verified Facts", bulletsWithIds(state.handoff.verifiedFacts, "cr")),
|
|
182
|
+
mandatory: true,
|
|
149
183
|
});
|
|
150
184
|
}
|
|
151
185
|
// v2.2: Sub-Goal Dashboard (compact — L1)
|
|
@@ -186,10 +220,10 @@ function l1Sections(state) {
|
|
|
186
220
|
mandatory: false,
|
|
187
221
|
});
|
|
188
222
|
}
|
|
189
|
-
if (state.
|
|
223
|
+
if (state.suggestedNextAction) {
|
|
190
224
|
sections.push({
|
|
191
|
-
id: "
|
|
192
|
-
text: section("Next Action", state.
|
|
225
|
+
id: "agent_intent",
|
|
226
|
+
text: section("Suggested Next Action", state.suggestedNextAction),
|
|
193
227
|
mandatory: false,
|
|
194
228
|
});
|
|
195
229
|
}
|
|
@@ -197,6 +231,14 @@ function l1Sections(state) {
|
|
|
197
231
|
}
|
|
198
232
|
function l2Sections(state, fullStateMarkdown) {
|
|
199
233
|
const sections = commonMandatorySections(state, "l2");
|
|
234
|
+
const openRegression = state.regressionObligations.filter((obligation) => obligation.status !== "satisfied");
|
|
235
|
+
if (openRegression.length > 0) {
|
|
236
|
+
sections.push({
|
|
237
|
+
id: "regression_obligations",
|
|
238
|
+
text: section("Regression Obligations", bullets(openRegression.map((item) => `[${item.status}] ${item.description}`))),
|
|
239
|
+
mandatory: true,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
200
242
|
const fullState = fullStateMarkdown?.trim();
|
|
201
243
|
if (fullState) {
|
|
202
244
|
sections.push({
|
|
@@ -213,6 +255,7 @@ function l2Sections(state, fullStateMarkdown) {
|
|
|
213
255
|
["changes", "Changes Since Last Round", state.changesSinceLastRound, null],
|
|
214
256
|
["remaining", "Remaining", state.remainingCriteria, "cr"],
|
|
215
257
|
["blockers", "Blockers", state.blockers, null],
|
|
258
|
+
["verified_facts", "Latest Verified Facts", state.handoff.verifiedFacts, "cr"],
|
|
216
259
|
["discoveries", "Discoveries", state.discoveries, null],
|
|
217
260
|
["rolling_outcomes", "Cross-Round Outcomes", state.rollingOutcomes, null],
|
|
218
261
|
["recurring_issues", "Recurring Issues", state.recurringIssues, null],
|
|
@@ -223,28 +266,25 @@ function l2Sections(state, fullStateMarkdown) {
|
|
|
223
266
|
const body = idPrefix
|
|
224
267
|
? bulletsWithIds(values, idPrefix)
|
|
225
268
|
: bullets(values);
|
|
226
|
-
sections.push({
|
|
269
|
+
sections.push({
|
|
270
|
+
id,
|
|
271
|
+
text: section(title, body),
|
|
272
|
+
mandatory: id === "blockers" || id === "verified_facts",
|
|
273
|
+
});
|
|
227
274
|
}
|
|
228
275
|
}
|
|
229
|
-
if (state.
|
|
230
|
-
const
|
|
231
|
-
.map((
|
|
232
|
-
const
|
|
233
|
-
?
|
|
234
|
-
:
|
|
235
|
-
|
|
236
|
-
`**${kindIcon} ${m.label}** (Rounds ${m.round_range.start}–${m.round_range.end}, ${(m.progress_at_boundary * 100).toFixed(0)}%)`,
|
|
237
|
-
` Outcome: ${m.outcome}`,
|
|
238
|
-
];
|
|
239
|
-
if (m.resolved_constraints.length > 0) {
|
|
240
|
-
lines.push(` Resolved: ${m.resolved_constraints.slice(0, 3).join("; ")}`);
|
|
241
|
-
}
|
|
242
|
-
return lines.join("\n");
|
|
276
|
+
if (state.phaseHistory.length > 0) {
|
|
277
|
+
const phaseText = state.phaseHistory
|
|
278
|
+
.map((phase) => {
|
|
279
|
+
const range = phase.closedAtRound
|
|
280
|
+
? `R${phase.enteredAtRound}-R${phase.closedAtRound}`
|
|
281
|
+
: `R${phase.enteredAtRound}-current`;
|
|
282
|
+
return `**${phase.label}** (${range}, ${phase.status})\n Outcome: ${phase.outcome}`;
|
|
243
283
|
})
|
|
244
284
|
.join("\n\n");
|
|
245
285
|
sections.push({
|
|
246
|
-
id: "
|
|
247
|
-
text: section("Phase History",
|
|
286
|
+
id: "phase_history",
|
|
287
|
+
text: section("Phase History", phaseText),
|
|
248
288
|
mandatory: false,
|
|
249
289
|
});
|
|
250
290
|
}
|
|
@@ -299,10 +339,10 @@ function l2Sections(state, fullStateMarkdown) {
|
|
|
299
339
|
mandatory: false,
|
|
300
340
|
});
|
|
301
341
|
}
|
|
302
|
-
if (state.
|
|
342
|
+
if (state.suggestedNextAction) {
|
|
303
343
|
sections.push({
|
|
304
|
-
id: "
|
|
305
|
-
text: section("Next Action", state.
|
|
344
|
+
id: "agent_intent",
|
|
345
|
+
text: section("Suggested Next Action", state.suggestedNextAction),
|
|
306
346
|
mandatory: false,
|
|
307
347
|
});
|
|
308
348
|
}
|
|
@@ -400,20 +440,26 @@ function l2Sections(state, fullStateMarkdown) {
|
|
|
400
440
|
return sections;
|
|
401
441
|
}
|
|
402
442
|
function selectSections(input) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (input.
|
|
409
|
-
|
|
410
|
-
|
|
443
|
+
const sections = input.mode === "full"
|
|
444
|
+
? l2Sections(input.state, input.fullStateMarkdown)
|
|
445
|
+
: input.level === "l0" ? l0Sections(input.state)
|
|
446
|
+
: input.level === "l1" ? l1Sections(input.state)
|
|
447
|
+
: l2Sections(input.state, input.fullStateMarkdown);
|
|
448
|
+
if (input.agentIntent?.trim()) {
|
|
449
|
+
sections.push({
|
|
450
|
+
id: "agent_intent",
|
|
451
|
+
text: section("Agent Intent (non-authoritative)", `${input.agentIntent.trim()}\nRuntime-derived Focus, Todo and Suggested Next Action take precedence.`),
|
|
452
|
+
mandatory: false,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
return sections;
|
|
411
456
|
}
|
|
412
457
|
function renderWithinBudget(sections, fixedText, budget) {
|
|
413
458
|
const mandatory = sections.filter((item) => item.mandatory);
|
|
414
459
|
const optional = sections.filter((item) => !item.mandatory);
|
|
415
460
|
let rendered = fixedText + mandatory.map((item) => item.text).join("");
|
|
416
461
|
const included = mandatory.filter((item) => item.text).map((item) => item.id);
|
|
462
|
+
const omitted = [];
|
|
417
463
|
for (const item of optional) {
|
|
418
464
|
if (!item.text)
|
|
419
465
|
continue;
|
|
@@ -421,8 +467,11 @@ function renderWithinBudget(sections, fixedText, budget) {
|
|
|
421
467
|
rendered += item.text;
|
|
422
468
|
included.push(item.id);
|
|
423
469
|
}
|
|
470
|
+
else {
|
|
471
|
+
omitted.push(item.id);
|
|
472
|
+
}
|
|
424
473
|
}
|
|
425
|
-
return { rendered, included };
|
|
474
|
+
return { rendered, included, omitted };
|
|
426
475
|
}
|
|
427
476
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
428
477
|
// v2.9: Prompt Requests — model-expressed information needs
|
|
@@ -532,20 +581,14 @@ function renderCriticalContext(emphasized, state) {
|
|
|
532
581
|
function renderExpandedSection(sectionName, state) {
|
|
533
582
|
switch (sectionName) {
|
|
534
583
|
case "milestones": {
|
|
535
|
-
if (state.
|
|
584
|
+
if (state.phaseHistory.length === 0)
|
|
536
585
|
return "";
|
|
537
|
-
const text = state.
|
|
538
|
-
.map((
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
];
|
|
544
|
-
if (m.carried_constraints.length > 0)
|
|
545
|
-
lines.push(` Carried: ${m.carried_constraints.slice(0, 3).join("; ")}`);
|
|
546
|
-
if (m.resolved_constraints.length > 0)
|
|
547
|
-
lines.push(` Resolved: ${m.resolved_constraints.slice(0, 3).join("; ")}`);
|
|
548
|
-
return lines.join("\n");
|
|
586
|
+
const text = state.phaseHistory
|
|
587
|
+
.map((phase) => {
|
|
588
|
+
const range = phase.closedAtRound
|
|
589
|
+
? `R${phase.enteredAtRound}-R${phase.closedAtRound}`
|
|
590
|
+
: `R${phase.enteredAtRound}-current`;
|
|
591
|
+
return `**${phase.label}** (${range}, ${phase.status})\n Outcome: ${phase.outcome}`;
|
|
549
592
|
})
|
|
550
593
|
.join("\n\n");
|
|
551
594
|
return section("Expanded Phase History", text);
|
|
@@ -643,6 +686,7 @@ export function assemblePromptArtifact(input) {
|
|
|
643
686
|
// than relying on potentially-compacted conversation history.
|
|
644
687
|
const fullContextReasons = new Set([
|
|
645
688
|
"first_round", "plan_boundary", "checkpoint_boundary", "goal_changed",
|
|
689
|
+
"constraint_changed",
|
|
646
690
|
"missing_previous_state", "verification_contradicted",
|
|
647
691
|
"rejection_rehydrate", "recovery_boundary", "state_drift",
|
|
648
692
|
"periodic_refresh",
|
|
@@ -676,8 +720,9 @@ export function assemblePromptArtifact(input) {
|
|
|
676
720
|
const pointer = stateFilePath
|
|
677
721
|
? section("Full State", stateFilePath)
|
|
678
722
|
: "";
|
|
679
|
-
const
|
|
680
|
-
|
|
723
|
+
const reportBlock = input.roundReportBlock ?? "";
|
|
724
|
+
const evaluation = reportBlock.trim()
|
|
725
|
+
? `${reportBlock.trim()}\n`
|
|
681
726
|
: "";
|
|
682
727
|
const howToRespond = [
|
|
683
728
|
"## How to Complete This Round",
|
|
@@ -685,24 +730,20 @@ export function assemblePromptArtifact(input) {
|
|
|
685
730
|
"1. Execute the task described above. Do NOT generate another prompt or plan — act.",
|
|
686
731
|
"2. When finished, call the MCP tool **`loopforge_next`** with these parameters:",
|
|
687
732
|
" - `sessionId`: the session ID from `loopforge_start`.",
|
|
688
|
-
" - `
|
|
733
|
+
" - `report`: a canonical `RoundReport` object (see schema below).",
|
|
689
734
|
"",
|
|
690
735
|
"### Evaluation Rules",
|
|
691
736
|
"",
|
|
692
|
-
"- `success
|
|
693
|
-
"
|
|
694
|
-
"-
|
|
695
|
-
"
|
|
696
|
-
"- `constraint_violations`: Be honest. List every constraint you actually violated.",
|
|
697
|
-
"- `execution_evidence.files_changed`: List files you modified — used for verification.",
|
|
698
|
-
"- `execution_evidence.test_results`: Report actual test runner output.",
|
|
699
|
-
"- `progress_estimate`: A number 0.0–1.0 reflecting overall task completion.",
|
|
737
|
+
"- Use `outcome=success` only when all criteria have runtime-verified evidence; use `continuation=stop` only when you are requesting no further round.",
|
|
738
|
+
"- `violations`: list every constraint actually violated.",
|
|
739
|
+
"- Put claims in `evidence.claims` and reference configured providers or commands through `evidenceRefs`; provenance is runtime-owned.",
|
|
740
|
+
"- Do not estimate progress. LoopForge derives it from verified claims and remaining criteria.",
|
|
700
741
|
"",
|
|
701
742
|
"### If the Prompt Says \"REJECTED\"",
|
|
702
743
|
"",
|
|
703
744
|
"- Re-execute the **same round**. Do NOT advance the round counter.",
|
|
704
745
|
"- Read the Required Fix section, address every issue, then submit again.",
|
|
705
|
-
"- Use `loopforge_next` with a corrected
|
|
746
|
+
"- Use `loopforge_next` with a corrected report.",
|
|
706
747
|
"",
|
|
707
748
|
evaluation,
|
|
708
749
|
].join("\n");
|
|
@@ -761,7 +802,7 @@ export function assemblePromptArtifact(input) {
|
|
|
761
802
|
];
|
|
762
803
|
const promptHash = createHash("sha256").update(renderedPrompt).digest("hex");
|
|
763
804
|
return {
|
|
764
|
-
|
|
805
|
+
format: PROMPT_ARTIFACT_FORMAT,
|
|
765
806
|
roundId: `loop:${input.state.loopId}:round:${input.state.round}`,
|
|
766
807
|
attempt,
|
|
767
808
|
level: input.level,
|
|
@@ -771,9 +812,17 @@ export function assemblePromptArtifact(input) {
|
|
|
771
812
|
stateHash,
|
|
772
813
|
basePromptVersion: BASE_PROMPT_VERSION,
|
|
773
814
|
includedSections,
|
|
815
|
+
omittedSections: selected.omitted,
|
|
774
816
|
budgetChars: budget,
|
|
775
817
|
charCount: renderedPrompt.length,
|
|
776
818
|
budgetExceeded: renderedPrompt.length > budget,
|
|
819
|
+
// lastL2Round / lastMeaningfulProgressRound / stateAgeRounds are NOT
|
|
820
|
+
// assembled here: the assembler has no vault history and can only guess,
|
|
821
|
+
// so the values were always immediately overwritten by the compiler's
|
|
822
|
+
// vault-derived backfill. They stay undefined at this layer.
|
|
823
|
+
phaseId: input.state.phaseHistory.at(-1)?.id,
|
|
824
|
+
focusId: input.state.todoProjection?.sourceId,
|
|
825
|
+
todoId: input.state.todoProjection?.id,
|
|
777
826
|
generatedAt: Date.now(),
|
|
778
827
|
};
|
|
779
828
|
}
|