instar 1.3.365 → 1.3.367
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/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +200 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +18 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/IntentTestHarness.d.ts +27 -0
- package/dist/core/IntentTestHarness.d.ts.map +1 -1
- package/dist/core/IntentTestHarness.js +91 -0
- package/dist/core/IntentTestHarness.js.map +1 -1
- package/dist/core/MeshRpc.d.ts +8 -0
- package/dist/core/MeshRpc.d.ts.map +1 -1
- package/dist/core/MeshRpc.js +6 -1
- package/dist/core/MeshRpc.js.map +1 -1
- package/dist/core/PeerPresencePuller.d.ts +6 -0
- package/dist/core/PeerPresencePuller.d.ts.map +1 -1
- package/dist/core/PeerPresencePuller.js +5 -0
- package/dist/core/PeerPresencePuller.js.map +1 -1
- package/dist/core/PeerVisibilityGuard.d.ts +83 -0
- package/dist/core/PeerVisibilityGuard.d.ts.map +1 -0
- package/dist/core/PeerVisibilityGuard.js +204 -0
- package/dist/core/PeerVisibilityGuard.js.map +1 -0
- package/dist/core/PendingPullLedger.d.ts +129 -0
- package/dist/core/PendingPullLedger.d.ts.map +1 -0
- package/dist/core/PendingPullLedger.js +239 -0
- package/dist/core/PendingPullLedger.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +20 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/WorkingSetManifest.d.ts +2 -0
- package/dist/core/WorkingSetManifest.d.ts.map +1 -1
- package/dist/core/WorkingSetManifest.js +13 -1
- package/dist/core/WorkingSetManifest.js.map +1 -1
- package/dist/core/WorkingSetPull.d.ts +157 -0
- package/dist/core/WorkingSetPull.d.ts.map +1 -0
- package/dist/core/WorkingSetPull.js +546 -0
- package/dist/core/WorkingSetPull.js.map +1 -0
- package/dist/core/WorkingSetPullCoordinator.d.ts +134 -0
- package/dist/core/WorkingSetPullCoordinator.d.ts.map +1 -0
- package/dist/core/WorkingSetPullCoordinator.js +306 -0
- package/dist/core/WorkingSetPullCoordinator.js.map +1 -0
- package/dist/core/types.d.ts +43 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/redteam/ScenarioPack.d.ts +30 -3
- package/dist/redteam/ScenarioPack.d.ts.map +1 -1
- package/dist/redteam/ScenarioPack.js +46 -1
- package/dist/redteam/ScenarioPack.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +3 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +5 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +47 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/data/state-coherence-registry.json +48 -12
- package/src/scaffold/templates.ts +4 -0
- package/upgrades/{1.3.365.md → 1.3.366.md} +35 -0
- package/upgrades/1.3.367.md +134 -0
- package/upgrades/side-effects/intent-llm-judge.md +94 -0
- package/upgrades/side-effects/working-set-ci-absorb.md +29 -0
- package/upgrades/side-effects/working-set-parity-absorb.md +35 -0
- package/upgrades/side-effects/working-set-pull-p22a.md +121 -0
- package/upgrades/side-effects/working-set-trigger-p22b.md +115 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PeerVisibilityGuard — P2.2 rider (WORKING-SET-HANDOFF-SPEC §3.6): improper
|
|
3
|
+
* revocations and silently-missing peers must surface LOUDLY.
|
|
4
|
+
*
|
|
5
|
+
* Earned 2026-06-06: the Mini was revoked with NO `revokedBy`/`revokeReason`
|
|
6
|
+
* (a write that bypassed `revokeMachine()`), making it invisible to the mesh
|
|
7
|
+
* for ~10 hours while it held a topic's entire overnight working set.
|
|
8
|
+
*
|
|
9
|
+
* Two detections, both HYGIENE SIGNALS (they detect sloppy state, not
|
|
10
|
+
* malicious action — populated fields are NOT authenticated and must never
|
|
11
|
+
* be read as "this revocation is legitimate"):
|
|
12
|
+
*
|
|
13
|
+
* 1. `detectImproperRevocations(registry)` — a PURE helper (deliberately NOT
|
|
14
|
+
* inside `loadRegistry()`, a hot dependency-free read called 41+ times
|
|
15
|
+
* per boot): an entry with `revokedAt` set but `revokedBy`/`revokeReason`
|
|
16
|
+
* missing. The consumer surfaces findings via the agent-health attention
|
|
17
|
+
* lane, deduped ACROSS boots keyed on the entry's `revokedAt` (a
|
|
18
|
+
* crash-loop cannot re-spam it).
|
|
19
|
+
*
|
|
20
|
+
* 2. Peer-disappearance notice — pool transitions from N≥2 online to fewer
|
|
21
|
+
* and stays past a 30-min grace → ONE agent-health notice naming the
|
|
22
|
+
* machine + last known reason, and — when pending-pulls reference it —
|
|
23
|
+
* the stranded topic working sets. Coalesced per machine per episode;
|
|
24
|
+
* FLAP-BOUNDED: 3 episodes for one machine in 24h collapses to a single
|
|
25
|
+
* "machine X is flapping" notice (Bounded Notification Surface). Clears
|
|
26
|
+
* silently on stable re-peer.
|
|
27
|
+
*/
|
|
28
|
+
import fs from 'node:fs';
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
export const DEFAULT_DISAPPEARANCE_GRACE_MS = 30 * 60 * 1000;
|
|
31
|
+
export const FLAP_EPISODE_LIMIT = 3;
|
|
32
|
+
export const FLAP_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
33
|
+
/**
|
|
34
|
+
* PURE: entries revoked without authorship/reason — the §3.6 hygiene signal.
|
|
35
|
+
* Never inside loadRegistry(); the consumer (boot/refresh path) calls this.
|
|
36
|
+
*/
|
|
37
|
+
export function detectImproperRevocations(registry) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const [machineId, entry] of Object.entries(registry.machines ?? {})) {
|
|
40
|
+
const e = entry;
|
|
41
|
+
if (!e.revokedAt)
|
|
42
|
+
continue;
|
|
43
|
+
const missing = [];
|
|
44
|
+
if (!e.revokedBy)
|
|
45
|
+
missing.push('revokedBy');
|
|
46
|
+
if (!e.revokeReason)
|
|
47
|
+
missing.push('revokeReason');
|
|
48
|
+
if (missing.length) {
|
|
49
|
+
out.push({
|
|
50
|
+
machineId,
|
|
51
|
+
...(e.nickname ? { nickname: e.nickname } : {}),
|
|
52
|
+
revokedAt: e.revokedAt,
|
|
53
|
+
missing,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
export class PeerVisibilityGuard {
|
|
60
|
+
d;
|
|
61
|
+
stateFile;
|
|
62
|
+
state = null;
|
|
63
|
+
/** In-memory per-episode tracking (a notice fires once per episode). */
|
|
64
|
+
missing = new Map();
|
|
65
|
+
constructor(config) {
|
|
66
|
+
this.d = config;
|
|
67
|
+
this.stateFile = path.join(config.stateDir, 'state', 'coherence-journal', 'visibility-guard.json');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* §3.6.1 — call on boot + registry refresh with the loaded registry.
|
|
71
|
+
* Surfaces each improper revocation ONCE across boots (keyed on revokedAt).
|
|
72
|
+
*/
|
|
73
|
+
checkRevocations(registry) {
|
|
74
|
+
const found = detectImproperRevocations(registry);
|
|
75
|
+
const st = this.loadState();
|
|
76
|
+
const fresh = found.filter((f) => !st.surfacedRevocations.includes(f.revokedAt));
|
|
77
|
+
for (const f of fresh) {
|
|
78
|
+
st.surfacedRevocations.push(f.revokedAt);
|
|
79
|
+
this.safeNotify({
|
|
80
|
+
kind: 'improper-revocation',
|
|
81
|
+
machineId: f.machineId,
|
|
82
|
+
title: `Machine ${f.nickname ?? f.machineId} was revoked without ${f.missing.join('/')}`,
|
|
83
|
+
body: `${f.nickname ?? f.machineId} is marked revoked (at ${f.revokedAt}) but the revocation ` +
|
|
84
|
+
`carries no ${f.missing.join(' or ')} — it did not go through revokeMachine(). ` +
|
|
85
|
+
`HYGIENE SIGNAL ONLY: this detects a sloppy revocation, not a malicious one (and a ` +
|
|
86
|
+
`populated field would not prove legitimacy either). If this machine should be in the ` +
|
|
87
|
+
`pool, un-revoke it; its working sets are unreachable until then.`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (fresh.length)
|
|
91
|
+
this.persist(st);
|
|
92
|
+
return found;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* §3.6.2 — call on a presence cadence with the CURRENT online view.
|
|
96
|
+
* `expected` = machines that should be online (active, not revoked, not
|
|
97
|
+
* self); `online` = machines recorded this pass.
|
|
98
|
+
*/
|
|
99
|
+
async checkDisappearances(expected, online) {
|
|
100
|
+
const nowMs = (this.d.now?.() ?? new Date()).getTime();
|
|
101
|
+
const grace = this.d.graceMs ?? DEFAULT_DISAPPEARANCE_GRACE_MS;
|
|
102
|
+
const st = this.loadState();
|
|
103
|
+
let dirty = false;
|
|
104
|
+
for (const machineId of expected) {
|
|
105
|
+
if (machineId === this.d.selfMachineId)
|
|
106
|
+
continue;
|
|
107
|
+
if (online.has(machineId)) {
|
|
108
|
+
// Stable re-peer → episode closes SILENTLY (§3.6.2).
|
|
109
|
+
if (this.missing.delete(machineId))
|
|
110
|
+
this.d.logger?.(`peer ${machineId} re-peered`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
let tracker = this.missing.get(machineId);
|
|
114
|
+
if (!tracker) {
|
|
115
|
+
tracker = { missingSinceMs: nowMs, noticed: false };
|
|
116
|
+
this.missing.set(machineId, tracker);
|
|
117
|
+
}
|
|
118
|
+
if (tracker.noticed || nowMs - tracker.missingSinceMs < grace)
|
|
119
|
+
continue;
|
|
120
|
+
// Episode confirmed past grace — flap accounting first.
|
|
121
|
+
const episodes = (st.episodes[machineId] ?? []).filter((iso) => nowMs - new Date(iso).getTime() < FLAP_WINDOW_MS);
|
|
122
|
+
episodes.push(new Date(nowMs).toISOString());
|
|
123
|
+
st.episodes[machineId] = episodes;
|
|
124
|
+
dirty = true;
|
|
125
|
+
tracker.noticed = true;
|
|
126
|
+
if (episodes.length > FLAP_EPISODE_LIMIT) {
|
|
127
|
+
if (!st.flapNotified[machineId]) {
|
|
128
|
+
st.flapNotified[machineId] = true;
|
|
129
|
+
this.safeNotify({
|
|
130
|
+
kind: 'peer-flapping',
|
|
131
|
+
machineId,
|
|
132
|
+
title: `Machine ${machineId} is flapping`,
|
|
133
|
+
body: `${machineId} has dropped off the mesh ${episodes.length} times in 24h. ` +
|
|
134
|
+
`Collapsing to this single notice — no further per-episode messages until ` +
|
|
135
|
+
`it stabilizes (Bounded Notification Surface).`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Flap-notified machines that stabilized under the limit get re-armed.
|
|
141
|
+
if (st.flapNotified[machineId] && episodes.length <= FLAP_EPISODE_LIMIT) {
|
|
142
|
+
delete st.flapNotified[machineId];
|
|
143
|
+
}
|
|
144
|
+
let stranded = [];
|
|
145
|
+
try {
|
|
146
|
+
stranded = (await this.d.strandedTopicsFor?.(machineId)) ?? [];
|
|
147
|
+
}
|
|
148
|
+
catch { /* @silent-fallback-ok: the stranded-topics enrichment is best-effort; the disappearance notice itself must still fire (WORKING-SET-HANDOFF-SPEC §3.6) */
|
|
149
|
+
}
|
|
150
|
+
const strandedLine = stranded.length
|
|
151
|
+
? ` Topic working set(s) stranded on it: ${stranded.join(', ')} — recover by bringing it back / un-revoking; the pending fetch re-fires automatically on its return.`
|
|
152
|
+
: '';
|
|
153
|
+
this.safeNotify({
|
|
154
|
+
kind: 'peer-missing',
|
|
155
|
+
machineId,
|
|
156
|
+
title: `Machine ${machineId} has been unreachable for 30+ minutes`,
|
|
157
|
+
body: `${machineId} should be in the pool but has not answered the presence pull past the ` +
|
|
158
|
+
`grace window.${strandedLine}`,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (dirty)
|
|
162
|
+
this.persist(st);
|
|
163
|
+
}
|
|
164
|
+
// ---- durable dedupe state -------------------------------------------------
|
|
165
|
+
loadState() {
|
|
166
|
+
if (this.state)
|
|
167
|
+
return this.state;
|
|
168
|
+
try {
|
|
169
|
+
const parsed = JSON.parse(fs.readFileSync(this.stateFile, 'utf-8'));
|
|
170
|
+
if (parsed?.version === 1) {
|
|
171
|
+
this.state = {
|
|
172
|
+
version: 1,
|
|
173
|
+
surfacedRevocations: Array.isArray(parsed.surfacedRevocations) ? parsed.surfacedRevocations : [],
|
|
174
|
+
episodes: parsed.episodes && typeof parsed.episodes === 'object' ? parsed.episodes : {},
|
|
175
|
+
flapNotified: parsed.flapNotified && typeof parsed.flapNotified === 'object' ? parsed.flapNotified : {},
|
|
176
|
+
};
|
|
177
|
+
return this.state;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch { /* @silent-fallback-ok: absent/corrupt guard state only weakens notice dedupe (worst case one repeat notice) — never a failure (WORKING-SET-HANDOFF-SPEC §3.6) */
|
|
181
|
+
}
|
|
182
|
+
this.state = { version: 1, surfacedRevocations: [], episodes: {}, flapNotified: {} };
|
|
183
|
+
return this.state;
|
|
184
|
+
}
|
|
185
|
+
persist(st) {
|
|
186
|
+
try {
|
|
187
|
+
fs.mkdirSync(path.dirname(this.stateFile), { recursive: true });
|
|
188
|
+
const tmp = `${this.stateFile}.tmp-${process.pid}`;
|
|
189
|
+
fs.writeFileSync(tmp, JSON.stringify(st, null, 2));
|
|
190
|
+
fs.renameSync(tmp, this.stateFile);
|
|
191
|
+
}
|
|
192
|
+
catch (e) { /* @silent-fallback-ok: a failed dedupe persist risks one repeat notice after restart, never a lost detection (WORKING-SET-HANDOFF-SPEC §3.6) */
|
|
193
|
+
this.d.logger?.(`guard state persist failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
safeNotify(notice) {
|
|
197
|
+
try {
|
|
198
|
+
this.d.notify(notice);
|
|
199
|
+
}
|
|
200
|
+
catch { /* @silent-fallback-ok: a notify-consumer failure must never break the guard's detection loop (WORKING-SET-HANDOFF-SPEC §3.6) */
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=PeerVisibilityGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PeerVisibilityGuard.js","sourceRoot":"","sources":["../../src/core/PeerVisibilityGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AASlD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAyB;IACjE,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,GAAG,KAA6B,CAAC;QACxC,IAAI,CAAC,CAAC,CAAC,SAAS;YAAE,SAAS;QAC3B,MAAM,OAAO,GAAqC,EAAE,CAAC;QACrD,IAAI,CAAC,CAAC,CAAC,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC;gBACP,SAAS;gBACT,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAqCD,MAAM,OAAO,mBAAmB;IACb,CAAC,CAA4B;IAC7B,SAAS,CAAS;IAC3B,KAAK,GAA2B,IAAI,CAAC;IAC7C,wEAAwE;IAChE,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEpD,YAAY,MAAiC;QAC3C,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,CAAC,CAAC;IACrG,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,QAAyB;QACxC,MAAM,KAAK,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACjF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,CAAC;gBACd,IAAI,EAAE,qBAAqB;gBAC3B,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,KAAK,EAAE,WAAW,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,wBAAwB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBACxF,IAAI,EACF,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,0BAA0B,CAAC,CAAC,SAAS,uBAAuB;oBACxF,cAAc,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,4CAA4C;oBAChF,oFAAoF;oBACpF,uFAAuF;oBACvF,kEAAkE;aACrE,CAAC,CAAC;QACL,CAAC;QACD,IAAI,KAAK,CAAC,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB,CAAC,QAAkB,EAAE,MAAmB;QAC/D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,8BAA8B,CAAC;QAC/D,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAG,KAAK,CAAC;QAElB,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;YACjC,IAAI,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa;gBAAE,SAAS;YACjD,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1B,qDAAqD;gBACrD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;oBAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,SAAS,YAAY,CAAC,CAAC;gBACnF,SAAS;YACX,CAAC;YACD,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;gBACpD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,CAAC,cAAc,GAAG,KAAK;gBAAE,SAAS;YAExE,wDAAwD;YACxD,MAAM,QAAQ,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CACpD,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,cAAc,CAC1D,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7C,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;YAClC,KAAK,GAAG,IAAI,CAAC;YACb,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YAEvB,IAAI,QAAQ,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;oBAClC,IAAI,CAAC,UAAU,CAAC;wBACd,IAAI,EAAE,eAAe;wBACrB,SAAS;wBACT,KAAK,EAAE,WAAW,SAAS,cAAc;wBACzC,IAAI,EACF,GAAG,SAAS,6BAA6B,QAAQ,CAAC,MAAM,iBAAiB;4BACzE,2EAA2E;4BAC3E,+CAA+C;qBAClD,CAAC,CAAC;gBACL,CAAC;gBACD,SAAS;YACX,CAAC;YACD,uEAAuE;YACvE,IAAI,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;gBACxE,OAAO,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YAED,IAAI,QAAQ,GAAa,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;YACjE,CAAC;YAAC,MAAM,CAAC,CAAC,yJAAyJ;YACnK,CAAC;YACD,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM;gBAClC,CAAC,CAAC,yCAAyC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,uGAAuG;gBACrK,CAAC,CAAC,EAAE,CAAC;YACP,IAAI,CAAC,UAAU,CAAC;gBACd,IAAI,EAAE,cAAc;gBACpB,SAAS;gBACT,KAAK,EAAE,WAAW,SAAS,uCAAuC;gBAClE,IAAI,EACF,GAAG,SAAS,yEAAyE;oBACrF,gBAAgB,YAAY,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,8EAA8E;IAEtE,SAAS;QACf,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAoB,CAAC;YACvF,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,GAAG;oBACX,OAAO,EAAE,CAAC;oBACV,mBAAmB,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE;oBAChG,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;oBACvF,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;iBACxG,CAAC;gBACF,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,iKAAiK;QAC3K,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,mBAAmB,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QACrF,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEO,OAAO,CAAC,EAAmB;QACjC,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;YACnD,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACnD,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAC,gJAAgJ;YAC5J,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,+BAA+B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,MAAmB;QACpC,IAAI,CAAC;YACH,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC,CAAC,gIAAgI;QAC1I,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PendingPullLedger — P2.2 of multi-machine coherence: the durable record of
|
|
3
|
+
* working-set pulls that could not complete because the producer was
|
|
4
|
+
* offline / unreachable / revoked / mid-run. The EXO case, solved: the
|
|
5
|
+
* request survives restarts and re-fires the moment the peer returns.
|
|
6
|
+
*
|
|
7
|
+
* Spec: docs/specs/WORKING-SET-HANDOFF-SPEC.md §3.4.
|
|
8
|
+
*
|
|
9
|
+
* SINGLE-WRITER DISCIPLINE (the topic-flood-#3 lesson, applied at birth):
|
|
10
|
+
* SIX mutators can overlap on one tick (onAccepted scheduler, reappearance
|
|
11
|
+
* re-arm, run-stopped re-arm, attempt/breaker update, reflex route, TTL
|
|
12
|
+
* sweep). ALL mutations route through ONE serialized `mutate(fn)` funnel —
|
|
13
|
+
* an in-process async queue, so read-modify-write never interleaves — with
|
|
14
|
+
* temp-file + atomic-rename persistence.
|
|
15
|
+
*
|
|
16
|
+
* PARSE-FAILURE POSTURE (the flood's second root): a corrupt/unparseable
|
|
17
|
+
* ledger is NEVER read as "no pending pulls" — the file is quarantined
|
|
18
|
+
* aside (`.corrupt-<ts>`), ONE notice fires through the injected
|
|
19
|
+
* `onCorrupt` seam ("pending-pull ledger unreadable — stranded-recovery
|
|
20
|
+
* records may be lost"), and a fresh ledger starts.
|
|
21
|
+
*
|
|
22
|
+
* Store path: `state/coherence-journal/pending-pulls.json` — registered in
|
|
23
|
+
* the State-Coherence Registry (machine-local; the records describe THIS
|
|
24
|
+
* machine's outstanding fetches).
|
|
25
|
+
*/
|
|
26
|
+
export declare const PENDING_PULLS_FILENAME = "pending-pulls.json";
|
|
27
|
+
export declare const DEFAULT_PENDING_PULL_TTL_DAYS = 7;
|
|
28
|
+
/** Per-record attempt cap — the (peer,topic,epoch) breaker (§3.4). */
|
|
29
|
+
export declare const DEFAULT_ATTEMPT_CAP = 6;
|
|
30
|
+
export type PendingPullReason = 'peer-offline' | 'peer-unreachable' | 'peer-revoked' | 'live-source' | 'busy-exhausted';
|
|
31
|
+
export interface PendingPullRecord {
|
|
32
|
+
topic: number;
|
|
33
|
+
epoch: number;
|
|
34
|
+
nominee: string;
|
|
35
|
+
reason: PendingPullReason;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
attempts: number;
|
|
38
|
+
lastAttemptAt: string | null;
|
|
39
|
+
}
|
|
40
|
+
export interface PendingPullLedgerConfig {
|
|
41
|
+
/** Absolute path to the agent's `.instar/` directory. */
|
|
42
|
+
stateDir: string;
|
|
43
|
+
ttlDays?: number;
|
|
44
|
+
attemptCap?: number;
|
|
45
|
+
now?: () => Date;
|
|
46
|
+
/**
|
|
47
|
+
* Fired ONCE per corrupt-quarantine episode (agent-health lane upstream).
|
|
48
|
+
* Never throws into the ledger.
|
|
49
|
+
*/
|
|
50
|
+
onCorrupt?: (quarantinedPath: string) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Fired once per record on TTL expiry — "topic T's working set on
|
|
53
|
+
* <machine> was never recovered" (§3.4). Never throws into the ledger.
|
|
54
|
+
*/
|
|
55
|
+
onExpired?: (record: PendingPullRecord) => void;
|
|
56
|
+
logger?: (msg: string) => void;
|
|
57
|
+
}
|
|
58
|
+
export declare class PendingPullLedger {
|
|
59
|
+
private readonly file;
|
|
60
|
+
private readonly ttlMs;
|
|
61
|
+
private readonly attemptCap;
|
|
62
|
+
private readonly now;
|
|
63
|
+
private readonly onCorrupt?;
|
|
64
|
+
private readonly onExpired?;
|
|
65
|
+
private readonly logger;
|
|
66
|
+
/** The serialized mutate() funnel — read-modify-write never interleaves. */
|
|
67
|
+
private queue;
|
|
68
|
+
/** In-memory truth between mutations (loaded once, kept current). */
|
|
69
|
+
private records;
|
|
70
|
+
private corruptNotified;
|
|
71
|
+
constructor(config: PendingPullLedgerConfig);
|
|
72
|
+
/**
|
|
73
|
+
* File (or refresh) a pending pull. Idempotent on (topic, epoch, nominee):
|
|
74
|
+
* an existing record keeps its createdAt/attempts; only `reason` refreshes.
|
|
75
|
+
*/
|
|
76
|
+
file_(rec: {
|
|
77
|
+
topic: number;
|
|
78
|
+
epoch: number;
|
|
79
|
+
nominee: string;
|
|
80
|
+
reason: PendingPullReason;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Record a GENUINE failed attempt (offline / unreachable / refused /
|
|
84
|
+
* verify-failed). `busy` responses MUST NOT come through here — busy is
|
|
85
|
+
* retry-without-penalty (§3.2); a throttled drain must never exhaust the
|
|
86
|
+
* very records it exists to recover.
|
|
87
|
+
*/
|
|
88
|
+
recordAttempt(topic: number, epoch: number, nominee: string): Promise<void>;
|
|
89
|
+
/** A completed pull clears its record. */
|
|
90
|
+
clear(topic: number, epoch: number, nominee: string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Supersession (§3.4): a newer epoch for the topic clears ALL records for
|
|
93
|
+
* that topic with `epoch < newEpoch`, across all nominees — a partial clear
|
|
94
|
+
* must never strand a sibling record.
|
|
95
|
+
*/
|
|
96
|
+
supersede(topic: number, newEpoch: number): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* TTL sweep: expire records older than ttlDays — each surfaced ONCE via
|
|
99
|
+
* onExpired ("never recovered"), then removed. Run on a slow cadence by the
|
|
100
|
+
* caller (it is one of the six mutators, so it rides the funnel too).
|
|
101
|
+
* Returns the expired records.
|
|
102
|
+
*/
|
|
103
|
+
sweepExpired(): Promise<PendingPullRecord[]>;
|
|
104
|
+
/**
|
|
105
|
+
* The records eligible to re-fire for a returning peer — the staggered
|
|
106
|
+
* drain reads this (most-recent-epoch-first; the drain itself enforces
|
|
107
|
+
* rearmConcurrency). Records at/over the attempt cap are excluded (the
|
|
108
|
+
* breaker; a NEW epoch files a NEW record, so an old exhausted breaker
|
|
109
|
+
* never suppresses a fresh, warranted pull).
|
|
110
|
+
*/
|
|
111
|
+
pendingForPeer(nominee: string): Promise<PendingPullRecord[]>;
|
|
112
|
+
/** All records for a topic (the run-stopped re-arm + reflex route read this). */
|
|
113
|
+
pendingForTopic(topic: number): Promise<PendingPullRecord[]>;
|
|
114
|
+
/** Every record, including breaker-exhausted ones (observability). */
|
|
115
|
+
all(): Promise<PendingPullRecord[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Serialize a read-modify-write. The fn receives the current records array
|
|
118
|
+
* (mutable) and returns the next one; persistence is temp-file + atomic
|
|
119
|
+
* rename. Errors persist nothing and propagate to THIS caller only — the
|
|
120
|
+
* queue itself never wedges.
|
|
121
|
+
*/
|
|
122
|
+
private mutate;
|
|
123
|
+
private read;
|
|
124
|
+
/** Load from memory or disk. Corrupt disk → quarantine + notice + fresh. */
|
|
125
|
+
private readUnqueued;
|
|
126
|
+
private quarantineCorrupt;
|
|
127
|
+
private persist;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=PendingPullLedger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PendingPullLedger.d.ts","sourceRoot":"","sources":["../../src/core/PendingPullLedger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAWD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAiC;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAE/C,4EAA4E;IAC5E,OAAO,CAAC,KAAK,CAAuC;IACpD,qEAAqE;IACrE,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,eAAe,CAAS;gBAEpB,MAAM,EAAE,uBAAuB;IAY3C;;;OAGG;IACG,KAAK,CAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7G;;;;;OAKG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjF,0CAA0C;IACpC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzE;;;;OAIG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAqBlD;;;;;;OAMG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAOnE,iFAAiF;IAC3E,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAKlE,sEAAsE;IAChE,GAAG,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAMzC;;;;;OAKG;IACH,OAAO,CAAC,MAAM;YAeA,IAAI;IAOlB,4EAA4E;IAC5E,OAAO,CAAC,YAAY;IA8BpB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,OAAO;CAQhB"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PendingPullLedger — P2.2 of multi-machine coherence: the durable record of
|
|
3
|
+
* working-set pulls that could not complete because the producer was
|
|
4
|
+
* offline / unreachable / revoked / mid-run. The EXO case, solved: the
|
|
5
|
+
* request survives restarts and re-fires the moment the peer returns.
|
|
6
|
+
*
|
|
7
|
+
* Spec: docs/specs/WORKING-SET-HANDOFF-SPEC.md §3.4.
|
|
8
|
+
*
|
|
9
|
+
* SINGLE-WRITER DISCIPLINE (the topic-flood-#3 lesson, applied at birth):
|
|
10
|
+
* SIX mutators can overlap on one tick (onAccepted scheduler, reappearance
|
|
11
|
+
* re-arm, run-stopped re-arm, attempt/breaker update, reflex route, TTL
|
|
12
|
+
* sweep). ALL mutations route through ONE serialized `mutate(fn)` funnel —
|
|
13
|
+
* an in-process async queue, so read-modify-write never interleaves — with
|
|
14
|
+
* temp-file + atomic-rename persistence.
|
|
15
|
+
*
|
|
16
|
+
* PARSE-FAILURE POSTURE (the flood's second root): a corrupt/unparseable
|
|
17
|
+
* ledger is NEVER read as "no pending pulls" — the file is quarantined
|
|
18
|
+
* aside (`.corrupt-<ts>`), ONE notice fires through the injected
|
|
19
|
+
* `onCorrupt` seam ("pending-pull ledger unreadable — stranded-recovery
|
|
20
|
+
* records may be lost"), and a fresh ledger starts.
|
|
21
|
+
*
|
|
22
|
+
* Store path: `state/coherence-journal/pending-pulls.json` — registered in
|
|
23
|
+
* the State-Coherence Registry (machine-local; the records describe THIS
|
|
24
|
+
* machine's outstanding fetches).
|
|
25
|
+
*/
|
|
26
|
+
import fs from 'node:fs';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
export const PENDING_PULLS_FILENAME = 'pending-pulls.json';
|
|
29
|
+
export const DEFAULT_PENDING_PULL_TTL_DAYS = 7;
|
|
30
|
+
/** Per-record attempt cap — the (peer,topic,epoch) breaker (§3.4). */
|
|
31
|
+
export const DEFAULT_ATTEMPT_CAP = 6;
|
|
32
|
+
function recordKey(r) {
|
|
33
|
+
return `${r.topic}:${r.epoch}:${r.nominee}`;
|
|
34
|
+
}
|
|
35
|
+
export class PendingPullLedger {
|
|
36
|
+
file;
|
|
37
|
+
ttlMs;
|
|
38
|
+
attemptCap;
|
|
39
|
+
now;
|
|
40
|
+
onCorrupt;
|
|
41
|
+
onExpired;
|
|
42
|
+
logger;
|
|
43
|
+
/** The serialized mutate() funnel — read-modify-write never interleaves. */
|
|
44
|
+
queue = Promise.resolve();
|
|
45
|
+
/** In-memory truth between mutations (loaded once, kept current). */
|
|
46
|
+
records = null;
|
|
47
|
+
corruptNotified = false;
|
|
48
|
+
constructor(config) {
|
|
49
|
+
this.file = path.join(config.stateDir, 'state', 'coherence-journal', PENDING_PULLS_FILENAME);
|
|
50
|
+
this.ttlMs = (config.ttlDays ?? DEFAULT_PENDING_PULL_TTL_DAYS) * 24 * 60 * 60 * 1000;
|
|
51
|
+
this.attemptCap = config.attemptCap ?? DEFAULT_ATTEMPT_CAP;
|
|
52
|
+
this.now = config.now ?? (() => new Date());
|
|
53
|
+
this.onCorrupt = config.onCorrupt;
|
|
54
|
+
this.onExpired = config.onExpired;
|
|
55
|
+
this.logger = config.logger ?? (() => { });
|
|
56
|
+
}
|
|
57
|
+
// ---- public API (every mutation rides the funnel) ------------------------
|
|
58
|
+
/**
|
|
59
|
+
* File (or refresh) a pending pull. Idempotent on (topic, epoch, nominee):
|
|
60
|
+
* an existing record keeps its createdAt/attempts; only `reason` refreshes.
|
|
61
|
+
*/
|
|
62
|
+
async file_(rec) {
|
|
63
|
+
await this.mutate((records) => {
|
|
64
|
+
const key = recordKey(rec);
|
|
65
|
+
const existing = records.find((r) => recordKey(r) === key);
|
|
66
|
+
if (existing) {
|
|
67
|
+
existing.reason = rec.reason;
|
|
68
|
+
return records;
|
|
69
|
+
}
|
|
70
|
+
records.push({
|
|
71
|
+
...rec,
|
|
72
|
+
createdAt: this.now().toISOString(),
|
|
73
|
+
attempts: 0,
|
|
74
|
+
lastAttemptAt: null,
|
|
75
|
+
});
|
|
76
|
+
return records;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Record a GENUINE failed attempt (offline / unreachable / refused /
|
|
81
|
+
* verify-failed). `busy` responses MUST NOT come through here — busy is
|
|
82
|
+
* retry-without-penalty (§3.2); a throttled drain must never exhaust the
|
|
83
|
+
* very records it exists to recover.
|
|
84
|
+
*/
|
|
85
|
+
async recordAttempt(topic, epoch, nominee) {
|
|
86
|
+
await this.mutate((records) => {
|
|
87
|
+
const r = records.find((x) => x.topic === topic && x.epoch === epoch && x.nominee === nominee);
|
|
88
|
+
if (r) {
|
|
89
|
+
r.attempts += 1;
|
|
90
|
+
r.lastAttemptAt = this.now().toISOString();
|
|
91
|
+
}
|
|
92
|
+
return records;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** A completed pull clears its record. */
|
|
96
|
+
async clear(topic, epoch, nominee) {
|
|
97
|
+
await this.mutate((records) => records.filter((r) => !(r.topic === topic && r.epoch === epoch && r.nominee === nominee)));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Supersession (§3.4): a newer epoch for the topic clears ALL records for
|
|
101
|
+
* that topic with `epoch < newEpoch`, across all nominees — a partial clear
|
|
102
|
+
* must never strand a sibling record.
|
|
103
|
+
*/
|
|
104
|
+
async supersede(topic, newEpoch) {
|
|
105
|
+
await this.mutate((records) => records.filter((r) => !(r.topic === topic && r.epoch < newEpoch)));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* TTL sweep: expire records older than ttlDays — each surfaced ONCE via
|
|
109
|
+
* onExpired ("never recovered"), then removed. Run on a slow cadence by the
|
|
110
|
+
* caller (it is one of the six mutators, so it rides the funnel too).
|
|
111
|
+
* Returns the expired records.
|
|
112
|
+
*/
|
|
113
|
+
async sweepExpired() {
|
|
114
|
+
const expired = [];
|
|
115
|
+
await this.mutate((records) => {
|
|
116
|
+
const nowMs = this.now().getTime();
|
|
117
|
+
const kept = [];
|
|
118
|
+
for (const r of records) {
|
|
119
|
+
const age = nowMs - new Date(r.createdAt).getTime();
|
|
120
|
+
if (age > this.ttlMs)
|
|
121
|
+
expired.push(r);
|
|
122
|
+
else
|
|
123
|
+
kept.push(r);
|
|
124
|
+
}
|
|
125
|
+
for (const r of expired) {
|
|
126
|
+
try {
|
|
127
|
+
this.onExpired?.(r);
|
|
128
|
+
}
|
|
129
|
+
catch { /* @silent-fallback-ok: an expiry-notice consumer failure must never block the sweep itself (WORKING-SET-HANDOFF-SPEC §3.4) */
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return kept;
|
|
133
|
+
});
|
|
134
|
+
return expired;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The records eligible to re-fire for a returning peer — the staggered
|
|
138
|
+
* drain reads this (most-recent-epoch-first; the drain itself enforces
|
|
139
|
+
* rearmConcurrency). Records at/over the attempt cap are excluded (the
|
|
140
|
+
* breaker; a NEW epoch files a NEW record, so an old exhausted breaker
|
|
141
|
+
* never suppresses a fresh, warranted pull).
|
|
142
|
+
*/
|
|
143
|
+
async pendingForPeer(nominee) {
|
|
144
|
+
const records = await this.read();
|
|
145
|
+
return records
|
|
146
|
+
.filter((r) => r.nominee === nominee && r.attempts < this.attemptCap)
|
|
147
|
+
.sort((a, b) => b.epoch - a.epoch);
|
|
148
|
+
}
|
|
149
|
+
/** All records for a topic (the run-stopped re-arm + reflex route read this). */
|
|
150
|
+
async pendingForTopic(topic) {
|
|
151
|
+
const records = await this.read();
|
|
152
|
+
return records.filter((r) => r.topic === topic && r.attempts < this.attemptCap);
|
|
153
|
+
}
|
|
154
|
+
/** Every record, including breaker-exhausted ones (observability). */
|
|
155
|
+
async all() {
|
|
156
|
+
return [...(await this.read())];
|
|
157
|
+
}
|
|
158
|
+
// ---- the funnel -----------------------------------------------------------
|
|
159
|
+
/**
|
|
160
|
+
* Serialize a read-modify-write. The fn receives the current records array
|
|
161
|
+
* (mutable) and returns the next one; persistence is temp-file + atomic
|
|
162
|
+
* rename. Errors persist nothing and propagate to THIS caller only — the
|
|
163
|
+
* queue itself never wedges.
|
|
164
|
+
*/
|
|
165
|
+
mutate(fn) {
|
|
166
|
+
const run = this.queue.then(async () => {
|
|
167
|
+
const before = await this.readUnqueued();
|
|
168
|
+
const next = fn(before);
|
|
169
|
+
this.persist(next);
|
|
170
|
+
this.records = next;
|
|
171
|
+
return next;
|
|
172
|
+
});
|
|
173
|
+
// The queue continues even when one mutation throws (error isolated to caller).
|
|
174
|
+
this.queue = run.catch(() => { });
|
|
175
|
+
return run;
|
|
176
|
+
}
|
|
177
|
+
async read() {
|
|
178
|
+
// Reads ride the funnel too — a read mid-mutation would see torn state.
|
|
179
|
+
const run = this.queue.then(() => this.readUnqueued());
|
|
180
|
+
this.queue = run.catch(() => { });
|
|
181
|
+
return run;
|
|
182
|
+
}
|
|
183
|
+
/** Load from memory or disk. Corrupt disk → quarantine + notice + fresh. */
|
|
184
|
+
readUnqueued() {
|
|
185
|
+
if (this.records)
|
|
186
|
+
return this.records;
|
|
187
|
+
let raw;
|
|
188
|
+
try {
|
|
189
|
+
raw = fs.readFileSync(this.file, 'utf-8');
|
|
190
|
+
}
|
|
191
|
+
catch { /* @silent-fallback-ok: ledger absent = genuinely empty (first boot) — distinct from corrupt, which quarantines below (WORKING-SET-HANDOFF-SPEC §3.4) */
|
|
192
|
+
this.records = [];
|
|
193
|
+
return this.records;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const parsed = JSON.parse(raw);
|
|
197
|
+
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.records)) {
|
|
198
|
+
throw new Error('shape mismatch');
|
|
199
|
+
}
|
|
200
|
+
this.records = parsed.records.filter((r) => typeof r?.topic === 'number' &&
|
|
201
|
+
typeof r?.epoch === 'number' &&
|
|
202
|
+
typeof r?.nominee === 'string' &&
|
|
203
|
+
typeof r?.attempts === 'number');
|
|
204
|
+
return this.records;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// NEVER read corrupt as empty-silently: quarantine + one notice + fresh.
|
|
208
|
+
this.quarantineCorrupt();
|
|
209
|
+
this.records = [];
|
|
210
|
+
return this.records;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
quarantineCorrupt() {
|
|
214
|
+
const quarantined = `${this.file}.corrupt-${this.now().getTime()}`;
|
|
215
|
+
try {
|
|
216
|
+
fs.renameSync(this.file, quarantined);
|
|
217
|
+
}
|
|
218
|
+
catch { /* @silent-fallback-ok: quarantine rename can lose a race with another process; the notice below still fires once (WORKING-SET-HANDOFF-SPEC §3.4) */
|
|
219
|
+
}
|
|
220
|
+
this.logger(`pending-pull ledger unreadable — quarantined to ${path.basename(quarantined)}`);
|
|
221
|
+
if (!this.corruptNotified) {
|
|
222
|
+
this.corruptNotified = true;
|
|
223
|
+
try {
|
|
224
|
+
this.onCorrupt?.(quarantined);
|
|
225
|
+
}
|
|
226
|
+
catch { /* @silent-fallback-ok: a corrupt-notice consumer failure must never block ledger recovery (WORKING-SET-HANDOFF-SPEC §3.4) */
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
persist(records) {
|
|
231
|
+
const dir = path.dirname(this.file);
|
|
232
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
233
|
+
const tmp = `${this.file}.tmp-${process.pid}`;
|
|
234
|
+
const body = { version: 1, records };
|
|
235
|
+
fs.writeFileSync(tmp, JSON.stringify(body, null, 2));
|
|
236
|
+
fs.renameSync(tmp, this.file);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=PendingPullLedger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PendingPullLedger.js","sourceRoot":"","sources":["../../src/core/PendingPullLedger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
|