@stigmer/runner 3.12.1 → 3.12.2

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 (62) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/execute-cursor/capture-flow.d.ts +5 -4
  3. package/dist/activities/execute-cursor/capture-flow.js +5 -4
  4. package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
  5. package/dist/activities/execute-cursor/cas-observations.d.ts +10 -4
  6. package/dist/activities/execute-cursor/cas-observations.js +10 -4
  7. package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
  8. package/dist/activities/execute-cursor/hook-script.js +39 -13
  9. package/dist/activities/execute-cursor/hook-script.js.map +1 -1
  10. package/dist/activities/execute-cursor/skill-resolver.d.ts +8 -0
  11. package/dist/activities/execute-cursor/skill-resolver.js +77 -26
  12. package/dist/activities/execute-cursor/skill-resolver.js.map +1 -1
  13. package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +3 -1
  14. package/dist/activities/execute-deep-agent/cas-capture-backend.js +3 -1
  15. package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -1
  16. package/dist/activities/execute-deep-agent/setup.js +8 -0
  17. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  18. package/dist/activities/execute-deep-agent/subagent-wiring.js +16 -9
  19. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  20. package/dist/activities/generate-session-subject.d.ts +80 -0
  21. package/dist/activities/generate-session-subject.js +283 -0
  22. package/dist/activities/generate-session-subject.js.map +1 -0
  23. package/dist/client/stigmer-client.d.ts +8 -0
  24. package/dist/client/stigmer-client.js +10 -0
  25. package/dist/client/stigmer-client.js.map +1 -1
  26. package/dist/middleware/approval-gate.d.ts +25 -10
  27. package/dist/middleware/approval-gate.js +33 -14
  28. package/dist/middleware/approval-gate.js.map +1 -1
  29. package/dist/middleware/otel-spans.d.ts +2 -1
  30. package/dist/middleware/otel-spans.js +2 -1
  31. package/dist/middleware/otel-spans.js.map +1 -1
  32. package/dist/runner-manager.js +3 -1
  33. package/dist/runner-manager.js.map +1 -1
  34. package/dist/runner.js +3 -1
  35. package/dist/runner.js.map +1 -1
  36. package/dist/shared/attachment-vision.js +9 -0
  37. package/dist/shared/attachment-vision.js.map +1 -1
  38. package/dist/shared/mcp-manager.js +8 -0
  39. package/dist/shared/mcp-manager.js.map +1 -1
  40. package/package.json +2 -2
  41. package/src/activities/__tests__/generate-session-subject.test.ts +348 -0
  42. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +60 -9
  43. package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +163 -7
  44. package/src/activities/execute-cursor/capture-flow.ts +5 -4
  45. package/src/activities/execute-cursor/cas-observations.ts +10 -4
  46. package/src/activities/execute-cursor/hook-script.ts +39 -13
  47. package/src/activities/execute-cursor/skill-resolver.ts +98 -31
  48. package/src/activities/execute-deep-agent/cas-capture-backend.ts +3 -1
  49. package/src/activities/execute-deep-agent/setup.ts +8 -0
  50. package/src/activities/execute-deep-agent/subagent-wiring.ts +16 -9
  51. package/src/activities/generate-session-subject.ts +370 -0
  52. package/src/client/stigmer-client.ts +11 -0
  53. package/src/middleware/__tests__/approval-gate.test.ts +130 -1
  54. package/src/middleware/approval-gate.ts +58 -24
  55. package/src/middleware/otel-spans.ts +2 -1
  56. package/src/runner-manager.ts +3 -0
  57. package/src/runner.ts +3 -0
  58. package/src/shared/__tests__/attachment-vision.test.ts +4 -0
  59. package/src/shared/__tests__/mcp-manager.test.ts +7 -2
  60. package/src/shared/attachment-vision.ts +9 -0
  61. package/src/shared/filereview/__tests__/capture.test.ts +48 -0
  62. package/src/shared/mcp-manager.ts +8 -0
@@ -703,6 +703,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
703
703
  { createCursorActivities },
704
704
  { createDeepAgentActivities },
705
705
  { createEnsureThreadActivities },
706
+ { createGenerateSessionSubjectActivities },
706
707
  { createClassifyToolApprovalsActivities },
707
708
  { createDiscoverMcpServerActivities },
708
709
  { createEvaluateExpressionsActivities },
@@ -721,6 +722,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
721
722
  import("./activities/execute-cursor/index.js"),
722
723
  import("./activities/execute-deep-agent/index.js"),
723
724
  import("./activities/ensure-thread.js"),
725
+ import("./activities/generate-session-subject.js"),
724
726
  import("./activities/classify-tool-approvals.js"),
725
727
  import("./activities/discover-mcp-server.js"),
726
728
  import("./activities/evaluate-expressions.js"),
@@ -741,6 +743,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
741
743
  ...createCursorActivities(config),
742
744
  ...createDeepAgentActivities(config),
743
745
  ...createEnsureThreadActivities(),
746
+ ...createGenerateSessionSubjectActivities(config),
744
747
  ...createClassifyToolApprovalsActivities(config),
745
748
  ...createDiscoverMcpServerActivities(config),
746
749
  ...createEvaluateExpressionsActivities(),
package/src/runner.ts CHANGED
@@ -407,6 +407,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
407
407
  { createCursorActivities },
408
408
  { createDeepAgentActivities },
409
409
  { createEnsureThreadActivities },
410
+ { createGenerateSessionSubjectActivities },
410
411
  { createClassifyToolApprovalsActivities },
411
412
  { createDiscoverMcpServerActivities },
412
413
  { createEvaluateExpressionsActivities },
@@ -425,6 +426,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
425
426
  import("./activities/execute-cursor/index.js"),
426
427
  import("./activities/execute-deep-agent/index.js"),
427
428
  import("./activities/ensure-thread.js"),
429
+ import("./activities/generate-session-subject.js"),
428
430
  import("./activities/classify-tool-approvals.js"),
429
431
  import("./activities/discover-mcp-server.js"),
430
432
  import("./activities/evaluate-expressions.js"),
@@ -445,6 +447,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
445
447
  ...createCursorActivities(config),
446
448
  ...createDeepAgentActivities(config),
447
449
  ...createEnsureThreadActivities(),
450
+ ...createGenerateSessionSubjectActivities(config),
448
451
  ...createClassifyToolApprovalsActivities(config),
449
452
  ...createDiscoverMcpServerActivities(config),
450
453
  ...createEvaluateExpressionsActivities(),
@@ -291,6 +291,10 @@ describe("VisionBudget — size and count budgets", () => {
291
291
  });
292
292
 
293
293
  it("ships the production constants agreed in T04 (raw bytes)", () => {
294
+ // Also the ADVERTISED == ENFORCED drift alarm (stigmer/stigmer#365):
295
+ // the registry document advertises these exact values in its
296
+ // `limits.vision` block, pinned by the cloud codec's own test. If this
297
+ // fails, the budget changed on one side only — update both together.
294
298
  expect(MAX_VISION_IMAGE_BYTES).toBe(3 * 1024 * 1024);
295
299
  expect(MAX_VISION_TOTAL_BYTES).toBe(4 * 1024 * 1024);
296
300
  expect(MAX_VISION_IMAGES).toBe(10);
@@ -66,7 +66,7 @@ describe("toMcpClientConfig", () => {
66
66
  });
67
67
  });
68
68
 
69
- it("maps HTTP servers to streamable_http transport", () => {
69
+ it("maps HTTP servers to streamable_http transport with reconnect enabled", () => {
70
70
  const servers = [
71
71
  makeServer({
72
72
  slug: "github",
@@ -80,10 +80,14 @@ describe("toMcpClientConfig", () => {
80
80
  transport: "http",
81
81
  url: "https://api.github.com/mcp",
82
82
  headers: { Authorization: "Bearer tok" },
83
+ // oss#316: severed remote connections (e.g. the hosted bridge
84
+ // restarting mid-execution) re-initialize instead of stranding the
85
+ // agent on a dead session.
86
+ reconnect: { enabled: true, maxAttempts: 3, delayMs: 1_000 },
83
87
  });
84
88
  });
85
89
 
86
- it("maps SSE servers to streamable_http transport", () => {
90
+ it("maps SSE servers to streamable_http transport with reconnect enabled", () => {
87
91
  const servers = [
88
92
  makeServer({
89
93
  slug: "sse-server",
@@ -96,6 +100,7 @@ describe("toMcpClientConfig", () => {
96
100
  transport: "http",
97
101
  url: "https://sse.example.com/mcp",
98
102
  headers: undefined,
103
+ reconnect: { enabled: true, maxAttempts: 3, delayMs: 1_000 },
99
104
  });
100
105
  });
101
106
 
@@ -32,6 +32,15 @@
32
32
 
33
33
  // ---------------------------------------------------------------------------
34
34
  // Budget constants (owner decision, 2026-08-09; project T04)
35
+ //
36
+ // ADVERTISED == ENFORCED (stigmer/stigmer#365): the model registry document
37
+ // advertises these values in its `limits.vision` block (rendered by the
38
+ // cloud's ModelRegistryDocumentCodec, mirrored verbatim by the OSS server)
39
+ // so clients can warn BEFORE an upload this budget would degrade. Both sides
40
+ // pin the literal values in tests — attachment-vision.test.ts here, the
41
+ // codec test there — so changing either side alone fails its own suite.
42
+ // Update both together; deploy the runner first if the budget ever shrinks
43
+ // (never advertise more than the runner accepts).
35
44
  // ---------------------------------------------------------------------------
36
45
 
37
46
  /**
@@ -946,6 +946,54 @@ describe("capture orchestration — CAS-only non-git workspace (Slice 2a)", () =
946
946
  await expect(readFile(join(ws, "drop.txt"), "utf-8")).rejects.toThrow();
947
947
  });
948
948
 
949
+ it("authors a DELETE from {before, after:null} and reconciles it both ways (issue #303)", async () => {
950
+ // The delete flow end-to-end at this seam: the harness captured the
951
+ // pre-delete bytes and the file is gone from disk (the tool ran). The
952
+ // candidate must carry a DELETE with the before blob; an approved DELETE
953
+ // stays deleted, a rejected DELETE is restored byte-exact from the blob.
954
+ const status = newStatus();
955
+ const storage = makeStorage();
956
+ const readBlob = reconcilerReadBlob(storage);
957
+ const enc = (s: string) => new TextEncoder().encode(s);
958
+
959
+ const baseline = await captureBaselineToLedger({
960
+ status, gitRoot: ws, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
961
+ harnessId: HARNESS, gitWorkspace: false,
962
+ });
963
+ await captureCandidateToLedger({
964
+ status, gitRoot: ws, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
965
+ baselineTree: baseline, harnessId: HARNESS, gitWorkspace: false, storage,
966
+ casCaptures: [
967
+ { path: "gone-approved.txt", before: enc("A"), after: null, captureClass: FileCaptureClass.NON_GIT_CAS },
968
+ { path: "gone-rejected.txt", before: enc("B"), after: null, captureClass: FileCaptureClass.NON_GIT_CAS },
969
+ ],
970
+ });
971
+
972
+ const cand = candidateChanges(status);
973
+ expect(cand.map((c) => c.kind)).toEqual([FileChangeKind.DELETE, FileChangeKind.DELETE]);
974
+ // A DELETE names its path on the BEFORE side only, with the restorable blob.
975
+ expect(cand.map((c) => c.pathBefore)).toEqual(["gone-approved.txt", "gone-rejected.txt"]);
976
+ expect(cand.map((c) => c.pathAfter)).toEqual(["", ""]);
977
+ expect(cand[0].before?.body.case).toBe("ref");
978
+ expect(cand[0].after).toBeUndefined();
979
+
980
+ const changeSet = decidedChangeSet(status, {
981
+ "gone-approved.txt": FileDecisionAction.APPROVE,
982
+ "gone-rejected.txt": FileDecisionAction.REJECT,
983
+ });
984
+ const result = await applyCaptureDecisions({
985
+ status, gitRoot: ws, executionId: EXEC_ID, changeSet, harnessId: HARNESS,
986
+ gitWorkspace: false, storage, readBlob,
987
+ });
988
+
989
+ expect(result.failed).toBe(false);
990
+ expect(result.approvedPaths).toEqual(["gone-approved.txt"]);
991
+ expect(result.rejectedPaths).toEqual(["gone-rejected.txt"]);
992
+ // Approved DELETE: the file stays gone. Rejected DELETE: restored byte-exact.
993
+ await expect(readFile(join(ws, "gone-approved.txt"), "utf-8")).rejects.toThrow();
994
+ expect(await readFile(join(ws, "gone-rejected.txt"), "utf-8")).toBe("B");
995
+ });
996
+
949
997
  it("is not a capture turn when neither a git ref nor a CAS manifest exists", async () => {
950
998
  const status = newStatus();
951
999
  const storage = makeStorage();
@@ -73,6 +73,14 @@ export function toMcpClientConfig(
73
73
  transport: "http",
74
74
  url: server.url,
75
75
  headers: server.headers,
76
+ // Re-establish severed connections (oss#316): when a remote MCP
77
+ // server restarts mid-execution — the hosted bridge's sessions are
78
+ // in-memory, so a deploy orphans every live one — the adapter's
79
+ // onclose hook re-runs initialize, minting a fresh session for
80
+ // subsequent calls instead of stranding the agent on a dead one.
81
+ // Covers transport-close only; a session lost with no stream open
82
+ // still surfaces as a JSON-RPC session-not-found on the next call.
83
+ reconnect: { enabled: true, maxAttempts: 3, delayMs: 1_000 },
76
84
  };
77
85
  }
78
86
  }