loopforge 1.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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/dist/adapter.d.ts +17 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +228 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/backends/fs.d.ts +31 -0
  8. package/dist/backends/fs.d.ts.map +1 -0
  9. package/dist/backends/fs.js +308 -0
  10. package/dist/backends/fs.js.map +1 -0
  11. package/dist/backends/interface.d.ts +42 -0
  12. package/dist/backends/interface.d.ts.map +1 -0
  13. package/dist/backends/interface.js +7 -0
  14. package/dist/backends/interface.js.map +1 -0
  15. package/dist/builder.d.ts +17 -0
  16. package/dist/builder.d.ts.map +1 -0
  17. package/dist/builder.js +205 -0
  18. package/dist/builder.js.map +1 -0
  19. package/dist/cli.d.ts +7 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +360 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/engine.d.ts +42 -0
  24. package/dist/engine.d.ts.map +1 -0
  25. package/dist/engine.js +595 -0
  26. package/dist/engine.js.map +1 -0
  27. package/dist/generate-schema.d.ts +12 -0
  28. package/dist/generate-schema.d.ts.map +1 -0
  29. package/dist/generate-schema.js +278 -0
  30. package/dist/generate-schema.js.map +1 -0
  31. package/dist/index.d.ts +27 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +30 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/loop-compiler.d.ts +37 -0
  36. package/dist/loop-compiler.d.ts.map +1 -0
  37. package/dist/loop-compiler.js +1232 -0
  38. package/dist/loop-compiler.js.map +1 -0
  39. package/dist/policy.d.ts +44 -0
  40. package/dist/policy.d.ts.map +1 -0
  41. package/dist/policy.js +111 -0
  42. package/dist/policy.js.map +1 -0
  43. package/dist/protocol.d.ts +167 -0
  44. package/dist/protocol.d.ts.map +1 -0
  45. package/dist/protocol.js +198 -0
  46. package/dist/protocol.js.map +1 -0
  47. package/dist/replay.d.ts +19 -0
  48. package/dist/replay.d.ts.map +1 -0
  49. package/dist/replay.js +198 -0
  50. package/dist/replay.js.map +1 -0
  51. package/dist/tests/adapter.test.d.ts +2 -0
  52. package/dist/tests/adapter.test.d.ts.map +1 -0
  53. package/dist/tests/adapter.test.js +104 -0
  54. package/dist/tests/adapter.test.js.map +1 -0
  55. package/dist/tests/builder.test.d.ts +2 -0
  56. package/dist/tests/builder.test.d.ts.map +1 -0
  57. package/dist/tests/builder.test.js +122 -0
  58. package/dist/tests/builder.test.js.map +1 -0
  59. package/dist/tests/engine.test.d.ts +2 -0
  60. package/dist/tests/engine.test.d.ts.map +1 -0
  61. package/dist/tests/engine.test.js +200 -0
  62. package/dist/tests/engine.test.js.map +1 -0
  63. package/dist/tests/generate-schema.test.d.ts +8 -0
  64. package/dist/tests/generate-schema.test.d.ts.map +1 -0
  65. package/dist/tests/generate-schema.test.js +196 -0
  66. package/dist/tests/generate-schema.test.js.map +1 -0
  67. package/dist/tests/loop-compiler.test.d.ts +2 -0
  68. package/dist/tests/loop-compiler.test.d.ts.map +1 -0
  69. package/dist/tests/loop-compiler.test.js +387 -0
  70. package/dist/tests/loop-compiler.test.js.map +1 -0
  71. package/dist/tests/policy.test.d.ts +2 -0
  72. package/dist/tests/policy.test.d.ts.map +1 -0
  73. package/dist/tests/policy.test.js +59 -0
  74. package/dist/tests/policy.test.js.map +1 -0
  75. package/dist/tests/protocol.test.d.ts +2 -0
  76. package/dist/tests/protocol.test.d.ts.map +1 -0
  77. package/dist/tests/protocol.test.js +63 -0
  78. package/dist/tests/protocol.test.js.map +1 -0
  79. package/dist/tests/replay.test.d.ts +2 -0
  80. package/dist/tests/replay.test.d.ts.map +1 -0
  81. package/dist/tests/replay.test.js +194 -0
  82. package/dist/tests/replay.test.js.map +1 -0
  83. package/loop_policy.json +44 -0
  84. package/package.json +58 -0
@@ -0,0 +1,387 @@
1
+ /** Tests for loop compiler core: gates, advisories, L0/L1/L2 compilation. */
2
+ import { describe, it, beforeEach } from "node:test";
3
+ import assert from "node:assert/strict";
4
+ import { decideLevel, compileLoop, computeGoalTextHash, deriveGoalId, alignTask, compileL2, } from "../loop-compiler.js";
5
+ import { makeLoopCompileRequest, makeLoopRoundResult, makeLoopObjective, } from "../protocol.js";
6
+ import { resetPolicy } from "../policy.js";
7
+ describe("Loop Compiler — Goal Identity", () => {
8
+ it("computeGoalTextHash produces a 12-char hex string", () => {
9
+ const hash = computeGoalTextHash("Audit ERC20 token");
10
+ assert.equal(hash.length, 12);
11
+ assert.ok(/^[a-f0-9]{12}$/.test(hash));
12
+ });
13
+ it("computeGoalTextHash is deterministic", () => {
14
+ assert.equal(computeGoalTextHash("Audit ERC20 token"), computeGoalTextHash("Audit ERC20 token"));
15
+ });
16
+ it("computeGoalTextHash normalises whitespace", () => {
17
+ const h1 = computeGoalTextHash("Audit ERC20 token");
18
+ const h2 = computeGoalTextHash("Audit ERC20 token");
19
+ assert.equal(h1, h2);
20
+ });
21
+ it("deriveGoalId uses explicit goal_id when provided", () => {
22
+ assert.equal(deriveGoalId("loop-1", "Audit ERC20", "audit-erc20"), "audit-erc20");
23
+ });
24
+ it("deriveGoalId falls back to derived id", () => {
25
+ const id = deriveGoalId("loop-1", "Audit ERC20 token");
26
+ assert.ok(id.startsWith("loop-1:"));
27
+ });
28
+ });
29
+ describe("Loop Compiler — Decide Level (4-gate router)", () => {
30
+ beforeEach(() => resetPolicy());
31
+ it("returns l2 for round 1 (Gate 2: first call)", () => {
32
+ const req = makeLoopCompileRequest({ round: 1, task: "Audit ERC20" });
33
+ assert.equal(decideLevel(req, null), "l2");
34
+ });
35
+ it("returns l2 when plan_source is provided (Gate 2)", () => {
36
+ const req = makeLoopCompileRequest({
37
+ round: 5,
38
+ task: "Audit ERC20",
39
+ plan_source: "spec.md",
40
+ });
41
+ assert.equal(decideLevel(req, null), "l2");
42
+ });
43
+ it("returns l2 when no previous round found", () => {
44
+ const req = makeLoopCompileRequest({ round: 3, task: "Audit ERC20" });
45
+ assert.equal(decideLevel(req, null), "l2");
46
+ });
47
+ it("returns l2 when goal_id changed (Gate 3)", () => {
48
+ const req = makeLoopCompileRequest({
49
+ round: 2,
50
+ loop_id: "test",
51
+ goal_id: "new-audit",
52
+ task: "Audit new contract",
53
+ });
54
+ const vaultContext = {
55
+ results: [
56
+ {
57
+ loop_lineage: {
58
+ loop_id: "test",
59
+ round: 1,
60
+ goal_id: "old-audit",
61
+ },
62
+ },
63
+ ],
64
+ };
65
+ // goal_id "new-audit" doesn't match prev "old-audit"
66
+ // But wait: deriveGoalId uses explicit goal_id first, and prev.goal_id is "old-audit"
67
+ // deriveGoalId("test", "Audit new contract", "new-audit") = "new-audit"
68
+ // prev.goal_id = "old-audit" → mismatch → L2
69
+ assert.equal(decideLevel(req, vaultContext), "l2");
70
+ });
71
+ it("returns l1 when new constraints added (Gate 4)", () => {
72
+ const req = makeLoopCompileRequest({
73
+ round: 2,
74
+ loop_id: "test",
75
+ goal_id: "audit",
76
+ task: "Audit ERC20",
77
+ constraints_from_plan: ["check flash loans"],
78
+ });
79
+ const vaultContext = {
80
+ results: [
81
+ {
82
+ loop_lineage: {
83
+ loop_id: "test",
84
+ round: 1,
85
+ goal_id: "audit",
86
+ },
87
+ },
88
+ ],
89
+ };
90
+ assert.equal(decideLevel(req, vaultContext), "l1");
91
+ });
92
+ it("returns l1 when last round failed (Gate 4)", () => {
93
+ const req = makeLoopCompileRequest({
94
+ round: 2,
95
+ loop_id: "test",
96
+ goal_id: "audit",
97
+ task: "Audit ERC20",
98
+ last_round_result: makeLoopRoundResult({ success: false }),
99
+ });
100
+ const vaultContext = {
101
+ results: [
102
+ {
103
+ loop_lineage: {
104
+ loop_id: "test",
105
+ round: 1,
106
+ goal_id: "audit",
107
+ },
108
+ },
109
+ ],
110
+ };
111
+ assert.equal(decideLevel(req, vaultContext), "l1");
112
+ });
113
+ it("returns l1 with repair signal (Gate 4)", () => {
114
+ const req = makeLoopCompileRequest({
115
+ round: 2,
116
+ loop_id: "test",
117
+ goal_id: "audit",
118
+ task: "Audit ERC20",
119
+ new_since_last_round: "fix the approve race condition bug",
120
+ });
121
+ const vaultContext = {
122
+ results: [
123
+ {
124
+ loop_lineage: {
125
+ loop_id: "test",
126
+ round: 1,
127
+ goal_id: "audit",
128
+ },
129
+ },
130
+ ],
131
+ };
132
+ assert.equal(decideLevel(req, vaultContext), "l1");
133
+ });
134
+ it("returns l0 when nothing triggered (Gate 4: fast path)", () => {
135
+ const req = makeLoopCompileRequest({
136
+ round: 2,
137
+ loop_id: "test",
138
+ goal_id: "audit",
139
+ task: "Audit ERC20",
140
+ });
141
+ const vaultContext = {
142
+ results: [
143
+ {
144
+ loop_lineage: {
145
+ loop_id: "test",
146
+ round: 1,
147
+ goal_id: "audit",
148
+ },
149
+ },
150
+ ],
151
+ };
152
+ assert.equal(decideLevel(req, vaultContext), "l0");
153
+ });
154
+ it("respects force_level override (Gate 1)", () => {
155
+ const req = makeLoopCompileRequest({
156
+ round: 3,
157
+ loop_id: "test",
158
+ goal_id: "audit",
159
+ task: "Audit ERC20",
160
+ force_level: "l0",
161
+ });
162
+ const vaultContext = {
163
+ results: [
164
+ {
165
+ loop_lineage: {
166
+ loop_id: "test",
167
+ round: 2,
168
+ goal_id: "audit",
169
+ },
170
+ },
171
+ ],
172
+ };
173
+ assert.equal(decideLevel(req, vaultContext), "l0");
174
+ });
175
+ it("force_level never overrides round 1 (Gate 1 exception)", () => {
176
+ const req = makeLoopCompileRequest({
177
+ round: 1,
178
+ task: "Audit ERC20",
179
+ force_level: "l0",
180
+ });
181
+ assert.equal(decideLevel(req, null), "l2");
182
+ });
183
+ it("force_level never overrides plan_source (Gate 1 exception)", () => {
184
+ const req = makeLoopCompileRequest({
185
+ round: 3,
186
+ task: "Audit ERC20",
187
+ plan_source: "plan.md",
188
+ force_level: "l0",
189
+ });
190
+ assert.equal(decideLevel(req, null), "l2");
191
+ });
192
+ });
193
+ describe("Loop Compiler — L0 Fast Path", () => {
194
+ it("reuses cached prompt from previous round", () => {
195
+ const req = makeLoopCompileRequest({
196
+ round: 2,
197
+ loop_id: "test",
198
+ goal_id: "audit",
199
+ task: "Continue audit",
200
+ });
201
+ const vaultContext = {
202
+ results: [
203
+ {
204
+ loop_lineage: {
205
+ loop_id: "test",
206
+ round: 1,
207
+ goal_id: "audit",
208
+ constraints_active: ["check ownership"],
209
+ },
210
+ full_prompt: "## Round 1 Prompt\n\nAudit the contract.",
211
+ },
212
+ ],
213
+ };
214
+ const response = compileLoop(req, vaultContext);
215
+ assert.equal(response.recompile_level, "l0");
216
+ assert.ok(response.prompt.includes("Round 1 Prompt"));
217
+ assert.equal(response.technique_used, "cached");
218
+ assert.deepEqual(response.constraints_active, ["check ownership"]);
219
+ });
220
+ });
221
+ describe("Loop Compiler — L1 Patch Path", () => {
222
+ it("patches prompt with new constraints", () => {
223
+ const req = makeLoopCompileRequest({
224
+ round: 2,
225
+ loop_id: "test",
226
+ goal_id: "audit",
227
+ task: "Check approve race condition",
228
+ constraints_from_plan: ["check flash loans"],
229
+ new_since_last_round: "fix the approve race",
230
+ });
231
+ const vaultContext = {
232
+ results: [
233
+ {
234
+ loop_lineage: {
235
+ loop_id: "test",
236
+ round: 1,
237
+ goal_id: "audit",
238
+ constraints_active: ["check ownership"],
239
+ },
240
+ },
241
+ ],
242
+ };
243
+ const response = compileLoop(req, vaultContext);
244
+ assert.equal(response.recompile_level, "l1");
245
+ assert.ok(response.prompt.includes("L1 Patch"));
246
+ assert.ok(response.prompt.includes("check flash loans"));
247
+ assert.ok(response.prompt.includes("check ownership"));
248
+ assert.equal(response.technique_used, "patch");
249
+ });
250
+ });
251
+ describe("Loop Compiler — L2 Full Recompile", () => {
252
+ it("generates full meta-instruction prompt", () => {
253
+ const req = makeLoopCompileRequest({
254
+ round: 1,
255
+ loop_id: "audit-erc20",
256
+ goal_id: "audit-erc20",
257
+ task: "Audit ERC20 token for security vulnerabilities",
258
+ domain: "solidity-security",
259
+ });
260
+ const response = compileL2(req, null);
261
+ assert.equal(response.recompile_level, "l2");
262
+ assert.ok(response.prompt.includes("L2 Compile"));
263
+ assert.ok(response.prompt.includes("Loop Identity"));
264
+ assert.ok(response.prompt.includes("Generation Instructions"));
265
+ assert.notEqual(response.technique_used, "");
266
+ assert.notEqual(response.goal_text_hash, "");
267
+ assert.equal(response.round, 1);
268
+ assert.equal(response.loop_id, "audit-erc20");
269
+ });
270
+ it("includes loop objective at round 1", () => {
271
+ const req = makeLoopCompileRequest({
272
+ round: 1,
273
+ loop_id: "test",
274
+ task: "Audit ERC20 token",
275
+ loop_objective: makeLoopObjective({
276
+ objective: "Find all vulnerabilities",
277
+ success_criteria: ["All tests pass"],
278
+ hard_constraints: ["No external deps"],
279
+ loop_id: "test",
280
+ }),
281
+ });
282
+ const response = compileL2(req, null);
283
+ assert.ok(response.prompt.includes("Loop Objective (Anchor)"));
284
+ assert.ok(response.prompt.includes("Find all vulnerabilities"));
285
+ assert.ok(response.loop_objective !== null);
286
+ });
287
+ it("auto-generates loop objective at round 1 when none provided", () => {
288
+ const req = makeLoopCompileRequest({
289
+ round: 1,
290
+ loop_id: "test",
291
+ task: "Test the API endpoints for security issues",
292
+ });
293
+ const response = compileL2(req, null);
294
+ assert.ok(response.loop_objective !== null);
295
+ assert.ok(response.loop_objective.objective.length > 0);
296
+ });
297
+ });
298
+ describe("Loop Compiler — Task Alignment (advisory)", () => {
299
+ it("returns default alignment when no loop objective", () => {
300
+ const req = makeLoopCompileRequest({ loop_id: "test", task: "Audit" });
301
+ const result = alignTask("Proposed task", req, null);
302
+ assert.equal(result.is_aligned, true);
303
+ assert.equal(result.escalation, "none");
304
+ });
305
+ it("warns when proposed task drifts from objective", () => {
306
+ const req = makeLoopCompileRequest({
307
+ loop_id: "test",
308
+ task: "Audit ERC20",
309
+ loop_objective: makeLoopObjective({
310
+ objective: "Audit ERC20 token for all security vulnerabilities",
311
+ success_criteria: ["Find all critical vulnerabilities"],
312
+ hard_constraints: ["No external dependencies"],
313
+ }),
314
+ });
315
+ const result = alignTask("Write a frontend UI for the token dashboard", req, null);
316
+ assert.equal(result.escalation, "block");
317
+ assert.equal(result.is_aligned, false);
318
+ });
319
+ });
320
+ describe("Loop Compiler — Compile Loop (top-level)", () => {
321
+ it("returns complete response with advisories", () => {
322
+ const req = makeLoopCompileRequest({
323
+ round: 1,
324
+ loop_id: "test",
325
+ task: "Test the API",
326
+ next_task_proposal: "Test the database",
327
+ loop_objective: makeLoopObjective({
328
+ objective: "Test all APIs",
329
+ success_criteria: ["All tests pass"],
330
+ hard_constraints: [],
331
+ }),
332
+ });
333
+ const response = compileLoop(req, null);
334
+ assert.equal(response.status, "ok");
335
+ assert.equal(response.recompile_level, "l2");
336
+ assert.notEqual(response.goal_text_hash.length, 0);
337
+ assert.ok(response.task_alignment !== null);
338
+ });
339
+ });
340
+ describe("Loop Compiler — Cross-Round Scenarios", () => {
341
+ it("L0→L1 escalation: goal_id stable, new constraints added", () => {
342
+ const vaultContext = {
343
+ results: [
344
+ {
345
+ loop_lineage: {
346
+ loop_id: "audit",
347
+ round: 1,
348
+ goal_id: "audit",
349
+ constraints_active: ["check ownership"],
350
+ },
351
+ },
352
+ ],
353
+ };
354
+ // Round 2: same semantic task → deriveGoalId will match
355
+ const req = makeLoopCompileRequest({
356
+ round: 2,
357
+ loop_id: "audit",
358
+ goal_id: "audit",
359
+ task: "Audit ERC20 token for security vulnerabilities",
360
+ constraints_from_plan: ["check flash loans"],
361
+ });
362
+ const level = decideLevel(req, vaultContext);
363
+ assert.equal(level, "l1");
364
+ });
365
+ it("L0 stability: multiple rounds with same goal_id, no failures", () => {
366
+ const vaultContext = {
367
+ results: [
368
+ {
369
+ loop_lineage: {
370
+ loop_id: "audit",
371
+ round: 2,
372
+ goal_id: "audit",
373
+ },
374
+ },
375
+ ],
376
+ };
377
+ const req = makeLoopCompileRequest({
378
+ round: 3,
379
+ loop_id: "audit",
380
+ goal_id: "audit",
381
+ task: "Audit ERC20",
382
+ });
383
+ const level = decideLevel(req, vaultContext);
384
+ assert.equal(level, "l0");
385
+ });
386
+ });
387
+ //# sourceMappingURL=loop-compiler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-compiler.test.js","sourceRoot":"","sources":["../../src/tests/loop-compiler.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.test.d.ts","sourceRoot":"","sources":["../../src/tests/policy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ /** Tests for policy loading and singleton. */
2
+ import { describe, it, beforeEach } from "node:test";
3
+ import assert from "node:assert/strict";
4
+ import { loadPolicy, getPolicy, resetPolicy, DEFAULT_POLICY, } from "../policy.js";
5
+ describe("Policy — Defaults", () => {
6
+ beforeEach(() => resetPolicy());
7
+ it("DEFAULT_POLICY has correct constraint values", () => {
8
+ assert.equal(DEFAULT_POLICY.constraints.retire_window, 3);
9
+ assert.equal(DEFAULT_POLICY.constraints.max_active, 12);
10
+ });
11
+ it("DEFAULT_POLICY has correct summary values", () => {
12
+ assert.equal(DEFAULT_POLICY.summary.window, 5);
13
+ assert.equal(DEFAULT_POLICY.summary.health_check_interval, 1);
14
+ });
15
+ it("DEFAULT_POLICY has correct engine values", () => {
16
+ assert.equal(DEFAULT_POLICY.engine.feedback_flush_interval, 5);
17
+ assert.equal(DEFAULT_POLICY.engine.max_circuit_breaker, 3);
18
+ });
19
+ it("DEFAULT_POLICY fallback_chain is complete", () => {
20
+ const chain = DEFAULT_POLICY.technique.fallback_chain;
21
+ assert.equal(chain["zero-shot"], "few-shot");
22
+ assert.equal(chain["few-shot"], "zero-shot-cot");
23
+ assert.equal(chain["tree-of-thought"], "tree-of-thought");
24
+ });
25
+ it("DEFAULT_POLICY routing_table has 6 entries", () => {
26
+ const rt = DEFAULT_POLICY.technique.routing_table;
27
+ assert.equal(Object.keys(rt).length, 6);
28
+ assert.equal(rt["continuous_high"], "few-shot-cot");
29
+ assert.equal(rt["independent_high"], "tree-of-thought");
30
+ });
31
+ it("DEFAULT_POLICY recompile_triggers has L1 and L2 lists", () => {
32
+ assert.ok(DEFAULT_POLICY.recompile_triggers.l1.includes("new_constraints"));
33
+ assert.ok(DEFAULT_POLICY.recompile_triggers.l2.includes("goal_id_changed"));
34
+ });
35
+ it("getPolicy returns DEFAULT_POLICY when no file found", () => {
36
+ resetPolicy();
37
+ const policy = getPolicy("nonexistent_policy.json");
38
+ assert.equal(policy.constraints.retire_window, 3);
39
+ });
40
+ it("getPolicy is a singleton within a session", () => {
41
+ resetPolicy();
42
+ const p1 = getPolicy();
43
+ const p2 = getPolicy();
44
+ assert.strictEqual(p1, p2);
45
+ });
46
+ it("resetPolicy clears the singleton", () => {
47
+ resetPolicy();
48
+ const p1 = getPolicy();
49
+ resetPolicy();
50
+ const p2 = getPolicy();
51
+ assert.notStrictEqual(p1, p2);
52
+ });
53
+ it("loadPolicy returns defaults when given invalid path", () => {
54
+ const policy = loadPolicy("/nonexistent/path.json");
55
+ assert.equal(policy.constraints.retire_window, 3);
56
+ assert.equal(policy.version, "1");
57
+ });
58
+ });
59
+ //# sourceMappingURL=policy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.test.js","sourceRoot":"","sources":["../../src/tests/policy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=protocol.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../../src/tests/protocol.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ /** Tests for protocol type factories and serialisation. */
2
+ import { describe, it } from "node:test";
3
+ import assert from "node:assert/strict";
4
+ import { Mode, AgentStatus, Technique, makeAnalysis, makeVaultConfig, makeLoopCompileRequest, makeLoopCompileResponse, makeTaskId, } from "../protocol.js";
5
+ describe("Protocol — Enums", () => {
6
+ it("Mode has 4 values", () => {
7
+ assert.equal(Object.values(Mode).length, 4);
8
+ assert.equal(Mode.LOOP_COMPILE, "loop_compile");
9
+ assert.equal(Mode.FEEDBACK, "feedback");
10
+ assert.equal(Mode.REVIEW, "review");
11
+ assert.equal(Mode.BUILD, "build");
12
+ });
13
+ it("AgentStatus has 3 values", () => {
14
+ assert.equal(AgentStatus.OK, "ok");
15
+ assert.equal(AgentStatus.ERROR, "error");
16
+ assert.equal(AgentStatus.STALLED, "stalled");
17
+ });
18
+ it("Technique has 7 values", () => {
19
+ assert.equal(Technique.ZERO_SHOT, "zero-shot");
20
+ assert.equal(Technique.TREE_OF_THOUGHT, "tree-of-thought");
21
+ });
22
+ });
23
+ describe("Protocol — Factory functions", () => {
24
+ it("makeAnalysis returns sensible defaults", () => {
25
+ const a = makeAnalysis();
26
+ assert.equal(a.technique, "zero-shot");
27
+ assert.equal(a.was_rotated, false);
28
+ assert.equal(a.independence, "independent");
29
+ assert.equal(a.cognitive_load, "low");
30
+ });
31
+ it("makeAnalysis accepts overrides", () => {
32
+ const a = makeAnalysis({ technique: "few-shot", was_rotated: true });
33
+ assert.equal(a.technique, "few-shot");
34
+ assert.equal(a.was_rotated, true);
35
+ });
36
+ it("makeVaultConfig returns sensible defaults", () => {
37
+ const vc = makeVaultConfig();
38
+ assert.equal(vc.project_vault, ".promptcraft/prompt_vault.json");
39
+ assert.equal(vc.skills_dir, "skills");
40
+ assert.equal(vc.no_global, false);
41
+ });
42
+ it("makeLoopCompileRequest returns sensible defaults", () => {
43
+ const req = makeLoopCompileRequest();
44
+ assert.equal(req.mode, "loop_compile");
45
+ assert.equal(req.round, 1);
46
+ assert.equal(req.force_level, "auto");
47
+ assert.equal(req.health_check_interval, 1);
48
+ assert.equal(req.loop_objective, null);
49
+ assert.deepEqual(req.constraints_from_plan, []);
50
+ });
51
+ it("makeLoopCompileResponse returns sensible defaults", () => {
52
+ const resp = makeLoopCompileResponse();
53
+ assert.equal(resp.status, "ok");
54
+ assert.equal(resp.recompile_level, "l2");
55
+ assert.equal(resp.round, 0);
56
+ assert.deepEqual(resp.warnings, []);
57
+ });
58
+ it("makeTaskId derives kebab-case from description", () => {
59
+ assert.equal(makeTaskId("Audit ERC20 token"), "audit-erc20-token");
60
+ assert.equal(makeTaskId(""), "unnamed-task");
61
+ });
62
+ });
63
+ //# sourceMappingURL=protocol.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../../src/tests/protocol.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=replay.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.test.d.ts","sourceRoot":"","sources":["../../src/tests/replay.test.ts"],"names":[],"mappings":""}