instar 1.3.18 → 1.3.20

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 (101) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +104 -6
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/FencedLease.d.ts +126 -0
  5. package/dist/core/FencedLease.d.ts.map +1 -0
  6. package/dist/core/FencedLease.js +189 -0
  7. package/dist/core/FencedLease.js.map +1 -0
  8. package/dist/core/GitLeaseStore.d.ts +46 -0
  9. package/dist/core/GitLeaseStore.d.ts.map +1 -0
  10. package/dist/core/GitLeaseStore.js +79 -0
  11. package/dist/core/GitLeaseStore.js.map +1 -0
  12. package/dist/core/GitSync.d.ts +19 -0
  13. package/dist/core/GitSync.d.ts.map +1 -1
  14. package/dist/core/GitSync.js +77 -0
  15. package/dist/core/GitSync.js.map +1 -1
  16. package/dist/core/HandoffSentinel.d.ts +80 -0
  17. package/dist/core/HandoffSentinel.d.ts.map +1 -0
  18. package/dist/core/HandoffSentinel.js +141 -0
  19. package/dist/core/HandoffSentinel.js.map +1 -0
  20. package/dist/core/LeaseCoordinator.d.ts +141 -0
  21. package/dist/core/LeaseCoordinator.d.ts.map +1 -0
  22. package/dist/core/LeaseCoordinator.js +226 -0
  23. package/dist/core/LeaseCoordinator.js.map +1 -0
  24. package/dist/core/LiveTailBuffer.d.ts +64 -0
  25. package/dist/core/LiveTailBuffer.d.ts.map +1 -0
  26. package/dist/core/LiveTailBuffer.js +122 -0
  27. package/dist/core/LiveTailBuffer.js.map +1 -0
  28. package/dist/core/MultiMachineCoordinator.d.ts +49 -0
  29. package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
  30. package/dist/core/MultiMachineCoordinator.js +136 -0
  31. package/dist/core/MultiMachineCoordinator.js.map +1 -1
  32. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  33. package/dist/core/PostUpdateMigrator.js +24 -0
  34. package/dist/core/PostUpdateMigrator.js.map +1 -1
  35. package/dist/core/RegistrySyncDebouncer.d.ts +77 -0
  36. package/dist/core/RegistrySyncDebouncer.d.ts.map +1 -0
  37. package/dist/core/RegistrySyncDebouncer.js +131 -0
  38. package/dist/core/RegistrySyncDebouncer.js.map +1 -0
  39. package/dist/core/liveTailRedaction.d.ts +36 -0
  40. package/dist/core/liveTailRedaction.d.ts.map +1 -0
  41. package/dist/core/liveTailRedaction.js +57 -0
  42. package/dist/core/liveTailRedaction.js.map +1 -0
  43. package/dist/core/registryReplayGuard.d.ts +59 -0
  44. package/dist/core/registryReplayGuard.d.ts.map +1 -0
  45. package/dist/core/registryReplayGuard.js +86 -0
  46. package/dist/core/registryReplayGuard.js.map +1 -0
  47. package/dist/core/seamlessnessConfig.d.ts +79 -0
  48. package/dist/core/seamlessnessConfig.d.ts.map +1 -0
  49. package/dist/core/seamlessnessConfig.js +131 -0
  50. package/dist/core/seamlessnessConfig.js.map +1 -0
  51. package/dist/core/types.d.ts +117 -0
  52. package/dist/core/types.d.ts.map +1 -1
  53. package/dist/core/types.js.map +1 -1
  54. package/dist/core/wireRegistrySync.d.ts +32 -0
  55. package/dist/core/wireRegistrySync.d.ts.map +1 -0
  56. package/dist/core/wireRegistrySync.js +31 -0
  57. package/dist/core/wireRegistrySync.js.map +1 -0
  58. package/dist/feedback-factory/dispatch/dispatch.d.ts +47 -0
  59. package/dist/feedback-factory/dispatch/dispatch.d.ts.map +1 -0
  60. package/dist/feedback-factory/dispatch/dispatch.js +72 -0
  61. package/dist/feedback-factory/dispatch/dispatch.js.map +1 -0
  62. package/dist/feedback-factory/processor/reopen.d.ts +39 -0
  63. package/dist/feedback-factory/processor/reopen.d.ts.map +1 -0
  64. package/dist/feedback-factory/processor/reopen.js +41 -0
  65. package/dist/feedback-factory/processor/reopen.js.map +1 -0
  66. package/dist/messaging/FencedOutbox.d.ts +42 -0
  67. package/dist/messaging/FencedOutbox.d.ts.map +1 -0
  68. package/dist/messaging/FencedOutbox.js +60 -0
  69. package/dist/messaging/FencedOutbox.js.map +1 -0
  70. package/dist/messaging/MessageProcessingLedger.d.ts +105 -0
  71. package/dist/messaging/MessageProcessingLedger.d.ts.map +1 -0
  72. package/dist/messaging/MessageProcessingLedger.js +206 -0
  73. package/dist/messaging/MessageProcessingLedger.js.map +1 -0
  74. package/dist/messaging/TelegramAdapter.d.ts +18 -1
  75. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  76. package/dist/messaging/TelegramAdapter.js +50 -0
  77. package/dist/messaging/TelegramAdapter.js.map +1 -1
  78. package/dist/scaffold/templates.d.ts.map +1 -1
  79. package/dist/scaffold/templates.js +7 -0
  80. package/dist/scaffold/templates.js.map +1 -1
  81. package/dist/server/AgentServer.d.ts.map +1 -1
  82. package/dist/server/AgentServer.js +1 -0
  83. package/dist/server/AgentServer.js.map +1 -1
  84. package/dist/server/routes.d.ts +2 -0
  85. package/dist/server/routes.d.ts.map +1 -1
  86. package/dist/server/routes.js +6 -0
  87. package/dist/server/routes.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/data/builtin-manifest.json +64 -64
  90. package/src/scaffold/templates.ts +7 -0
  91. package/upgrades/1.3.19.md +23 -0
  92. package/upgrades/1.3.20.md +23 -0
  93. package/upgrades/side-effects/PR-BODY-cross-machine-seamlessness.md +63 -0
  94. package/upgrades/side-effects/cross-machine-seamlessness-g1-lease.md +71 -0
  95. package/upgrades/side-effects/cross-machine-seamlessness-g2-foundation.md +75 -0
  96. package/upgrades/side-effects/cross-machine-seamlessness-g3-telegram-contract.md +36 -0
  97. package/upgrades/side-effects/cross-machine-seamlessness-g3a-ledger-handoff.md +56 -0
  98. package/upgrades/side-effects/cross-machine-seamlessness-g3bc-livetail-outbox.md +51 -0
  99. package/upgrades/side-effects/cross-machine-seamlessness-p4-awareness-observability.md +54 -0
  100. package/upgrades/side-effects/feedback-factory-dispatch.md +31 -0
  101. package/upgrades/side-effects/feedback-factory-reopen.md +31 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wireRegistrySync.js","sourceRoot":"","sources":["../../src/core/wireRegistrySync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkBH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmC,EACnC,IAAuB;IAEvB,MAAM,MAAM,GAAG,CAAC,IAAa,EAAE,EAAW,EAAE,EAAE,CAC5C,IAAI,CAAC,iBAAiB,CAAC,cAAc,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE1F,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;IAE5C,OAAO;QACL,WAAW,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC;QAC/C,MAAM;YACJ,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACtC,WAAW,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * dispatch.ts — framework-agnostic port of the dispatch (guidance-out) logic.
3
+ *
4
+ * Ports the pure logic of `the-portal/pages/api/instar/dispatches/index.ts` out of
5
+ * the Next.js handler: the dispatch type/priority vocab, the semver comparison used
6
+ * for version-compat filtering (an agent only receives a dispatch whose
7
+ * [minVersion, maxVersion] window includes the agent's version), the list query
8
+ * filter (since/type/version), and the create-dedup title normalization. The HTTP
9
+ * wiring + storage are excluded (the app-placement decision); this is the reusable
10
+ * core. Reference is TypeScript, so equivalence is by faithful transcription +
11
+ * exhaustive both-sides-of-boundary tests (not a cross-runtime parity harness).
12
+ */
13
+ export declare const DISPATCH_TYPES: readonly ["strategy", "behavioral", "lesson", "configuration", "security", "action"];
14
+ export type DispatchType = typeof DISPATCH_TYPES[number];
15
+ export declare const DISPATCH_PRIORITIES: readonly ["low", "normal", "high", "critical"];
16
+ export type DispatchPriority = typeof DISPATCH_PRIORITIES[number];
17
+ export declare const SEMVER_RE: RegExp;
18
+ export declare function isValidDispatchType(type: unknown): type is DispatchType;
19
+ export declare function isValidDispatchPriority(p: unknown): p is DispatchPriority;
20
+ /** Port of parseVersion: leading major.minor.patch → [n,n,n]; [0,0,0] if unparseable. */
21
+ export declare function parseVersion(v: string): [number, number, number];
22
+ /** Port of isVersionGte: version >= min (major.minor.patch, equal counts as gte). */
23
+ export declare function isVersionGte(version: string, min: string): boolean;
24
+ /** Port of isVersionLte: version <= max (equal counts as lte). */
25
+ export declare function isVersionLte(version: string, max: string): boolean;
26
+ export interface DispatchRecord {
27
+ dispatchId: string;
28
+ type: string;
29
+ title: string;
30
+ content?: string;
31
+ priority?: string;
32
+ minVersion?: string | null;
33
+ maxVersion?: string | null;
34
+ active?: boolean;
35
+ createdAt?: string;
36
+ [k: string]: unknown;
37
+ }
38
+ /**
39
+ * Port of handleList's version-compat filter: a dispatch is included only if the
40
+ * agent's version is within its [minVersion, maxVersion] window. Mirrors the
41
+ * reference — applied only when the agent sent a valid-semver version; otherwise
42
+ * all candidates pass (the caller gates on SEMVER_RE before calling).
43
+ */
44
+ export declare function filterDispatchesForVersion(dispatches: DispatchRecord[], version: string): DispatchRecord[];
45
+ /** Port of the create-path title normalization used for dedup: trim + cap at 500 chars. */
46
+ export declare function normalizeDispatchTitle(title: string): string;
47
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/feedback-factory/dispatch/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,cAAc,sFAAuF,CAAC;AACnH,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AACzD,eAAO,MAAM,mBAAmB,gDAAiD,CAAC;AAClF,MAAM,MAAM,gBAAgB,GAAG,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,SAAS,QAA8B,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,YAAY,CAEvE;AACD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,gBAAgB,CAEzE;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAIhE;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQlE;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQlE;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAM1G;AAED,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * dispatch.ts — framework-agnostic port of the dispatch (guidance-out) logic.
3
+ *
4
+ * Ports the pure logic of `the-portal/pages/api/instar/dispatches/index.ts` out of
5
+ * the Next.js handler: the dispatch type/priority vocab, the semver comparison used
6
+ * for version-compat filtering (an agent only receives a dispatch whose
7
+ * [minVersion, maxVersion] window includes the agent's version), the list query
8
+ * filter (since/type/version), and the create-dedup title normalization. The HTTP
9
+ * wiring + storage are excluded (the app-placement decision); this is the reusable
10
+ * core. Reference is TypeScript, so equivalence is by faithful transcription +
11
+ * exhaustive both-sides-of-boundary tests (not a cross-runtime parity harness).
12
+ */
13
+ export const DISPATCH_TYPES = ['strategy', 'behavioral', 'lesson', 'configuration', 'security', 'action'];
14
+ export const DISPATCH_PRIORITIES = ['low', 'normal', 'high', 'critical'];
15
+ export const SEMVER_RE = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
16
+ export function isValidDispatchType(type) {
17
+ return typeof type === 'string' && DISPATCH_TYPES.includes(type);
18
+ }
19
+ export function isValidDispatchPriority(p) {
20
+ return typeof p === 'string' && DISPATCH_PRIORITIES.includes(p);
21
+ }
22
+ /** Port of parseVersion: leading major.minor.patch → [n,n,n]; [0,0,0] if unparseable. */
23
+ export function parseVersion(v) {
24
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
25
+ if (!match)
26
+ return [0, 0, 0];
27
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
28
+ }
29
+ /** Port of isVersionGte: version >= min (major.minor.patch, equal counts as gte). */
30
+ export function isVersionGte(version, min) {
31
+ const v = parseVersion(version);
32
+ const m = parseVersion(min);
33
+ for (let i = 0; i < 3; i++) {
34
+ if (v[i] > m[i])
35
+ return true;
36
+ if (v[i] < m[i])
37
+ return false;
38
+ }
39
+ return true; // equal
40
+ }
41
+ /** Port of isVersionLte: version <= max (equal counts as lte). */
42
+ export function isVersionLte(version, max) {
43
+ const v = parseVersion(version);
44
+ const m = parseVersion(max);
45
+ for (let i = 0; i < 3; i++) {
46
+ if (v[i] < m[i])
47
+ return true;
48
+ if (v[i] > m[i])
49
+ return false;
50
+ }
51
+ return true; // equal
52
+ }
53
+ /**
54
+ * Port of handleList's version-compat filter: a dispatch is included only if the
55
+ * agent's version is within its [minVersion, maxVersion] window. Mirrors the
56
+ * reference — applied only when the agent sent a valid-semver version; otherwise
57
+ * all candidates pass (the caller gates on SEMVER_RE before calling).
58
+ */
59
+ export function filterDispatchesForVersion(dispatches, version) {
60
+ return dispatches.filter((d) => {
61
+ if (d.minVersion && !isVersionGte(version, d.minVersion))
62
+ return false;
63
+ if (d.maxVersion && !isVersionLte(version, d.maxVersion))
64
+ return false;
65
+ return true;
66
+ });
67
+ }
68
+ /** Port of the create-path title normalization used for dedup: trim + cap at 500 chars. */
69
+ export function normalizeDispatchTitle(title) {
70
+ return title.trim().slice(0, 500);
71
+ }
72
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../src/feedback-factory/dispatch/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * reopen.ts — TS port of the auto-reopen-on-regression decision.
3
+ *
4
+ * Ports the decision embedded in cmd_apply_clusters (the-portal/.claude/scripts/
5
+ * feedback-processor.py, the regression branch ~:1543) out of the DB-write code
6
+ * into a pure function. When the clustering driver (cluster.ts) merges a new
7
+ * report into a cluster that was already fixed/resolved/deferred (a "possible
8
+ * regression" note), the cluster is auto-reopened. This computes the reopen
9
+ * outcome from the cluster's prior status:
10
+ *
11
+ * - deferred → AGED-REOPEN → status 'new', annotate actionTaken, no recurrence bump
12
+ * - otherwise → REGRESSION → status 'investigating', annotate researchNotes, bump recurrenceCount
13
+ *
14
+ * The DB writes (the prisma update with `{ increment: 1 }` etc.) stay in the
15
+ * adapter; this is the pure decision + the audit-note text. `now` is injected.
16
+ * Reference is interleaved with DB I/O, so equivalence is by faithful
17
+ * transcription + exhaustive unit tests (no clean isolated reference function to
18
+ * run a cross-runtime harness against).
19
+ */
20
+ import type { Cluster } from './types.js';
21
+ export interface ReopenDecision {
22
+ /** New lifecycle status to set on the reopened cluster. */
23
+ newStatus: 'new' | 'investigating';
24
+ /** Whether to bump recurrenceCount (chronic-regression accounting; NOT for aged-reopen). */
25
+ bumpRecurrence: boolean;
26
+ /** Which cluster field the audit note is appended to. */
27
+ annotateField: 'actionTaken' | 'researchNotes';
28
+ /** The note tag. */
29
+ noteTag: 'AGED-REOPEN' | 'REGRESSION';
30
+ /** The audit note appended to the chosen field. */
31
+ note: string;
32
+ }
33
+ /**
34
+ * Compute the auto-reopen outcome for a cluster being merged into on a regression.
35
+ * `wasStatus` is the cluster's status before reopen; `feedbackId` is the incoming
36
+ * report; `now` is the injected ISO timestamp (reference uses new Date().toISOString()).
37
+ */
38
+ export declare function computeReopen(cluster: Cluster, feedbackId: string, now: string): ReopenDecision;
39
+ //# sourceMappingURL=reopen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reopen.d.ts","sourceRoot":"","sources":["../../../src/feedback-factory/processor/reopen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,SAAS,EAAE,KAAK,GAAG,eAAe,CAAC;IACnC,4FAA4F;IAC5F,cAAc,EAAE,OAAO,CAAC;IACxB,yDAAyD;IACzD,aAAa,EAAE,aAAa,GAAG,eAAe,CAAC;IAC/C,oBAAoB;IACpB,OAAO,EAAE,aAAa,GAAG,YAAY,CAAC;IACtC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB/F"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * reopen.ts — TS port of the auto-reopen-on-regression decision.
3
+ *
4
+ * Ports the decision embedded in cmd_apply_clusters (the-portal/.claude/scripts/
5
+ * feedback-processor.py, the regression branch ~:1543) out of the DB-write code
6
+ * into a pure function. When the clustering driver (cluster.ts) merges a new
7
+ * report into a cluster that was already fixed/resolved/deferred (a "possible
8
+ * regression" note), the cluster is auto-reopened. This computes the reopen
9
+ * outcome from the cluster's prior status:
10
+ *
11
+ * - deferred → AGED-REOPEN → status 'new', annotate actionTaken, no recurrence bump
12
+ * - otherwise → REGRESSION → status 'investigating', annotate researchNotes, bump recurrenceCount
13
+ *
14
+ * The DB writes (the prisma update with `{ increment: 1 }` etc.) stay in the
15
+ * adapter; this is the pure decision + the audit-note text. `now` is injected.
16
+ * Reference is interleaved with DB I/O, so equivalence is by faithful
17
+ * transcription + exhaustive unit tests (no clean isolated reference function to
18
+ * run a cross-runtime harness against).
19
+ */
20
+ /**
21
+ * Compute the auto-reopen outcome for a cluster being merged into on a regression.
22
+ * `wasStatus` is the cluster's status before reopen; `feedbackId` is the incoming
23
+ * report; `now` is the injected ISO timestamp (reference uses new Date().toISOString()).
24
+ */
25
+ export function computeReopen(cluster, feedbackId, now) {
26
+ const wasStatus = cluster.status ?? null;
27
+ const isAged = wasStatus === 'deferred';
28
+ const newStatus = isAged ? 'new' : 'investigating';
29
+ const noteTag = isAged ? 'AGED-REOPEN' : 'REGRESSION';
30
+ const fixedInVersion = cluster.fixedInVersion || 'n/a';
31
+ // Verbatim from the reference's regressionNote template.
32
+ const note = `[${noteTag} ${now}] New report matched cluster previously marked '${wasStatus}' (fixedInVersion=${fixedInVersion}). Auto-reopened to '${newStatus}' for review. Report: ${feedbackId}`;
33
+ return {
34
+ newStatus,
35
+ bumpRecurrence: !isAged,
36
+ annotateField: isAged ? 'actionTaken' : 'researchNotes',
37
+ noteTag,
38
+ note,
39
+ };
40
+ }
41
+ //# sourceMappingURL=reopen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reopen.js","sourceRoot":"","sources":["../../../src/feedback-factory/processor/reopen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAiBH;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,UAAkB,EAAE,GAAW;IAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,KAAK,UAAU,CAAC;IACxC,MAAM,SAAS,GAA4B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC;IAC5E,MAAM,OAAO,GAAiC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IACpF,MAAM,cAAc,GAAI,OAAO,CAAC,cAAyB,IAAI,KAAK,CAAC;IAEnE,yDAAyD;IACzD,MAAM,IAAI,GAAG,IAAI,OAAO,IAAI,GAAG,mDAAmD,SAAS,qBAAqB,cAAc,wBAAwB,SAAS,yBAAyB,UAAU,EAAE,CAAC;IAErM,OAAO;QACL,SAAS;QACT,cAAc,EAAE,CAAC,MAAM;QACvB,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe;QACvD,OAAO;QACP,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * FencedOutbox — fencing-token-gated outbound reply path (spec §8 G3a).
3
+ *
4
+ * "No duplicate replies" is enforced here STRUCTURALLY, not by assuming a single
5
+ * consumer. A reply is sent only while this machine holds the lease at the epoch
6
+ * the reply was stamped under; a fenced (stale-epoch) machine's in-flight reply
7
+ * is SUPPRESSED at the send path. The reply is committed to the message ledger
8
+ * with a deterministic idempotency key (hash(dedupeKey + replyIndex)) so any
9
+ * machine re-running the same event reproduces it identically — and the ledger
10
+ * recognizes an already-committed reply and refuses to re-send.
11
+ *
12
+ * On a channel with native outbound dedup the idempotency key makes a re-send a
13
+ * no-op; on a channel without it (Telegram), the dual-medium reply_committed
14
+ * marker (propagated by the sync layer) is what prevents a failover re-send.
15
+ */
16
+ import { MessageProcessingLedger } from './MessageProcessingLedger.js';
17
+ export interface FencedOutboxDeps {
18
+ ledger: MessageProcessingLedger;
19
+ /** The current effective fencing epoch. */
20
+ currentEpoch: () => number;
21
+ /** Whether this machine structurally holds the lease right now. */
22
+ holdsLease: () => boolean;
23
+ logger?: (msg: string) => void;
24
+ }
25
+ export interface SendOutcome {
26
+ sent: boolean;
27
+ suppressed: boolean;
28
+ reason: 'sent' | 'already-replied' | 'fenced-no-lease' | 'fenced-stale-epoch' | 'send-failed';
29
+ idempotencyKey: string;
30
+ }
31
+ export declare class FencedOutbox {
32
+ private readonly d;
33
+ constructor(deps: FencedOutboxDeps);
34
+ private log;
35
+ /**
36
+ * Send a reply for `dedupeKey`, stamped under `stampedEpoch` (the epoch the
37
+ * turn began processing under). Returns the outcome. The actual platform send
38
+ * is `sendFn`; it is invoked ONLY after the fencing checks pass.
39
+ */
40
+ send(dedupeKey: string, replyIndex: number, stampedEpoch: number, sendFn: () => Promise<void>): Promise<SendOutcome>;
41
+ }
42
+ //# sourceMappingURL=FencedOutbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FencedOutbox.d.ts","sourceRoot":"","sources":["../../src/messaging/FencedOutbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,uBAAuB,EAA8B,MAAM,8BAA8B,CAAC;AAEnG,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,uBAAuB,CAAC;IAChC,2CAA2C;IAC3C,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,mEAAmE;IACnE,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,aAAa,CAAC;IAC9F,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAmB;gBAEzB,IAAI,EAAE,gBAAgB;IAIlC,OAAO,CAAC,GAAG;IAIX;;;;OAIG;IACG,IAAI,CACR,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC1B,OAAO,CAAC,WAAW,CAAC;CAgCxB"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * FencedOutbox — fencing-token-gated outbound reply path (spec §8 G3a).
3
+ *
4
+ * "No duplicate replies" is enforced here STRUCTURALLY, not by assuming a single
5
+ * consumer. A reply is sent only while this machine holds the lease at the epoch
6
+ * the reply was stamped under; a fenced (stale-epoch) machine's in-flight reply
7
+ * is SUPPRESSED at the send path. The reply is committed to the message ledger
8
+ * with a deterministic idempotency key (hash(dedupeKey + replyIndex)) so any
9
+ * machine re-running the same event reproduces it identically — and the ledger
10
+ * recognizes an already-committed reply and refuses to re-send.
11
+ *
12
+ * On a channel with native outbound dedup the idempotency key makes a re-send a
13
+ * no-op; on a channel without it (Telegram), the dual-medium reply_committed
14
+ * marker (propagated by the sync layer) is what prevents a failover re-send.
15
+ */
16
+ import { computeReplyIdempotencyKey } from './MessageProcessingLedger.js';
17
+ export class FencedOutbox {
18
+ d;
19
+ constructor(deps) {
20
+ this.d = deps;
21
+ }
22
+ log(m) {
23
+ this.d.logger?.(`[outbox] ${m}`);
24
+ }
25
+ /**
26
+ * Send a reply for `dedupeKey`, stamped under `stampedEpoch` (the epoch the
27
+ * turn began processing under). Returns the outcome. The actual platform send
28
+ * is `sendFn`; it is invoked ONLY after the fencing checks pass.
29
+ */
30
+ async send(dedupeKey, replyIndex, stampedEpoch, sendFn) {
31
+ const idempotencyKey = computeReplyIdempotencyKey(dedupeKey, replyIndex);
32
+ // Idempotency: if a reply was already committed (locally or via a remote
33
+ // dual-medium marker), do not send again.
34
+ if (this.d.ledger.isActedOn(dedupeKey)) {
35
+ this.log(`already replied to ${dedupeKey} — suppressing`);
36
+ return { sent: false, suppressed: true, reason: 'already-replied', idempotencyKey };
37
+ }
38
+ // Fencing: only the current lease holder, at the stamped epoch, may send.
39
+ if (!this.d.holdsLease()) {
40
+ this.log(`fenced (no lease) — suppressing reply to ${dedupeKey}`);
41
+ return { sent: false, suppressed: true, reason: 'fenced-no-lease', idempotencyKey };
42
+ }
43
+ const epoch = this.d.currentEpoch();
44
+ if (epoch !== stampedEpoch) {
45
+ this.log(`fenced (stale epoch ${stampedEpoch} != current ${epoch}) — suppressing reply to ${dedupeKey}`);
46
+ return { sent: false, suppressed: true, reason: 'fenced-stale-epoch', idempotencyKey };
47
+ }
48
+ try {
49
+ await sendFn();
50
+ }
51
+ catch (err) {
52
+ this.log(`send failed for ${dedupeKey}: ${err instanceof Error ? err.message : String(err)}`);
53
+ return { sent: false, suppressed: false, reason: 'send-failed', idempotencyKey };
54
+ }
55
+ // Commit the reply marker (durable, synchronous) BEFORE advancing the cursor.
56
+ this.d.ledger.commitReply(dedupeKey, idempotencyKey, stampedEpoch);
57
+ return { sent: true, suppressed: false, reason: 'sent', idempotencyKey };
58
+ }
59
+ }
60
+ //# sourceMappingURL=FencedOutbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FencedOutbox.js","sourceRoot":"","sources":["../../src/messaging/FencedOutbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA2B,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAkBnG,MAAM,OAAO,YAAY;IACN,CAAC,CAAmB;IAErC,YAAY,IAAsB;QAChC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAChB,CAAC;IAEO,GAAG,CAAC,CAAS;QACnB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CACR,SAAiB,EACjB,UAAkB,EAClB,YAAoB,EACpB,MAA2B;QAE3B,MAAM,cAAc,GAAG,0BAA0B,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAEzE,yEAAyE;QACzE,0CAA0C;QAC1C,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,sBAAsB,SAAS,gBAAgB,CAAC,CAAC;YAC1D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC;QACtF,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,4CAA4C,SAAS,EAAE,CAAC,CAAC;YAClE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC;QACtF,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;QACpC,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,uBAAuB,YAAY,eAAe,KAAK,4BAA4B,SAAS,EAAE,CAAC,CAAC;YACzG,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC;QACzF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,EAAE,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,mBAAmB,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9F,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;QACnF,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QACnE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC3E,CAAC;CACF"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * MessageProcessingLedger — the no-loss / no-duplicate-reply guarantee (spec §8 G3a).
3
+ *
4
+ * A durable, SQLite-backed record of each inbound message's lifecycle:
5
+ * received → processing → reply_committed → cursor_advanced
6
+ * keyed by the adapter's `dedupeKey(rawEvent)` (Telegram update_id, Slack
7
+ * event_id/client_msg_id). Rules:
8
+ *
9
+ * - An event whose dedupeKey is already reply_committed/cursor_advanced is
10
+ * NEVER acted on again — a redelivery (Telegram retry, Slack reconnect, or a
11
+ * transfer-window overlap during a handoff) is recognized and dropped. This
12
+ * is what makes "no duplicate replies" structural, not merely "only one
13
+ * consumer".
14
+ * - The ingress cursor advances ONLY on durable completion (cursor_advanced),
15
+ * so a crash before completion replays the event (at-least-once) and the
16
+ * ledger makes the replay a no-op-or-resume (exactly-once effect).
17
+ * - Each transition is flushed to local SQLite synchronously on commit (WAL +
18
+ * NORMAL), so a same-machine crash-restart never double-acts.
19
+ * - A stuck `processing` entry past maxProcessingMs (old holder fenced
20
+ * mid-turn) is re-runnable by the current holder from its stored input.
21
+ *
22
+ * Substrate is SQLite (the proven PendingRelayStore/CommitmentTracker path) —
23
+ * NOT a new ad-hoc JSON file and NOT a git-synced blob. Schema self-initializes
24
+ * on first access (no PostUpdateMigrator step needed). Per-agent-id isolation.
25
+ */
26
+ export type LedgerState = 'received' | 'processing' | 'reply_committed' | 'cursor_advanced';
27
+ export interface LedgerEntry {
28
+ dedupeKey: string;
29
+ platform: string;
30
+ topic: string | null;
31
+ state: LedgerState;
32
+ receivedAt: string;
33
+ processingStartedAt: string | null;
34
+ replyCommittedAt: string | null;
35
+ cursorAdvancedAt: string | null;
36
+ replyIdempotencyKey: string | null;
37
+ replyEpoch: number | null;
38
+ inputSnapshot: string | null;
39
+ attempts: number;
40
+ }
41
+ export declare function resolveMessageLedgerPath(stateDir: string, agentId: string): string;
42
+ /**
43
+ * Deterministic outbound idempotency key — any machine re-running the same
44
+ * inbound event reproduces it identically (spec §8 G3a). Used so a failover
45
+ * re-send is recognized as the same reply.
46
+ */
47
+ export declare function computeReplyIdempotencyKey(dedupeKey: string, replyIndex: number): string;
48
+ export declare class MessageProcessingLedger {
49
+ private readonly db;
50
+ readonly path: string;
51
+ private constructor();
52
+ static open(agentId: string, stateDir: string): MessageProcessingLedger;
53
+ /** Open an in-memory ledger (tests). */
54
+ static openMemory(): MessageProcessingLedger;
55
+ /**
56
+ * Record an inbound event. Idempotent on dedupeKey (INSERT OR IGNORE).
57
+ * Returns whether this is the first time we've seen it + the current state.
58
+ * A caller seeing firstSeen:false with an acted-on state must DROP the event.
59
+ */
60
+ record(dedupeKey: string, opts: {
61
+ platform: string;
62
+ topic?: string | null;
63
+ input?: string;
64
+ }): {
65
+ firstSeen: boolean;
66
+ state: LedgerState;
67
+ };
68
+ /** Has this event already been acted on (reply committed or cursor advanced)? */
69
+ isActedOn(dedupeKey: string): boolean;
70
+ /**
71
+ * Claim an event for processing under the given fencing epoch. Returns false
72
+ * if it has already been acted on (drop). A stuck 'processing' entry can be
73
+ * re-claimed (the old holder was fenced); attempts is incremented.
74
+ */
75
+ beginProcessing(dedupeKey: string, epoch: number): boolean;
76
+ /**
77
+ * Commit that a reply was sent. Records the deterministic idempotency key and
78
+ * the fencing epoch it was committed under. Idempotent — committing twice is
79
+ * a no-op (the marker already exists).
80
+ */
81
+ commitReply(dedupeKey: string, replyIdempotencyKey: string, epoch: number): void;
82
+ /** Advance the ingress cursor — only call after durable reply commit. */
83
+ advanceCursor(dedupeKey: string): void;
84
+ /**
85
+ * Apply a reply_committed marker propagated from another machine (dual-medium
86
+ * marker, spec §8 G3a): if we have the entry and it's not yet acted on, mark
87
+ * it committed so a failover does not re-send. Creates the entry if unknown
88
+ * (the other machine saw it first).
89
+ */
90
+ applyRemoteReplyMarker(dedupeKey: string, opts: {
91
+ platform: string;
92
+ replyIdempotencyKey: string;
93
+ epoch: number;
94
+ topic?: string | null;
95
+ }): void;
96
+ /**
97
+ * Entries stuck in 'processing' past maxProcessingMs — eligible for re-run by
98
+ * the current lease holder from their stored input (spec §8 G3a). The old
99
+ * holder's abandoned output is discarded (the new holder re-executes).
100
+ */
101
+ reclaimStuck(maxProcessingMs: number, nowMs?: number): LedgerEntry[];
102
+ get(dedupeKey: string): LedgerEntry | null;
103
+ close(): void;
104
+ }
105
+ //# sourceMappingURL=MessageProcessingLedger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageProcessingLedger.d.ts","sourceRoot":"","sources":["../../src/messaging/MessageProcessingLedger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE5F,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoBD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAExF;AAED,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAuB;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,uBAAuB;IAYvE,wCAAwC;IACxC,MAAM,CAAC,UAAU,IAAI,uBAAuB;IAO5C;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAC5F,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,WAAW,CAAC;KACpB;IAYD,iFAAiF;IACjF,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKrC;;;;OAIG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAc1D;;;;OAIG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAUhF,yEAAyE;IACzE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAStC;;;;;OAKG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAe9I;;;;OAIG;IACH,YAAY,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,GAAE,MAAmB,GAAG,WAAW,EAAE;IAahF,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAK1C,KAAK,IAAI,IAAI;CAGd"}