instar 1.3.728 → 1.3.729

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 (69) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +85 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +11 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/FileClassifier.d.ts.map +1 -1
  8. package/dist/core/FileClassifier.js +11 -0
  9. package/dist/core/FileClassifier.js.map +1 -1
  10. package/dist/core/LocalSessionOwnershipStore.d.ts +5 -0
  11. package/dist/core/LocalSessionOwnershipStore.d.ts.map +1 -1
  12. package/dist/core/LocalSessionOwnershipStore.js +13 -0
  13. package/dist/core/LocalSessionOwnershipStore.js.map +1 -1
  14. package/dist/core/PostUpdateMigrator.d.ts +1 -0
  15. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  16. package/dist/core/PostUpdateMigrator.js +17 -0
  17. package/dist/core/PostUpdateMigrator.js.map +1 -1
  18. package/dist/core/SessionBuildContextStore.d.ts +20 -0
  19. package/dist/core/SessionBuildContextStore.d.ts.map +1 -1
  20. package/dist/core/SessionBuildContextStore.js +20 -3
  21. package/dist/core/SessionBuildContextStore.js.map +1 -1
  22. package/dist/core/SessionManager.d.ts +5 -0
  23. package/dist/core/SessionManager.d.ts.map +1 -1
  24. package/dist/core/SessionManager.js +3 -0
  25. package/dist/core/SessionManager.js.map +1 -1
  26. package/dist/core/SessionOwnershipRegistry.d.ts +16 -0
  27. package/dist/core/SessionOwnershipRegistry.d.ts.map +1 -1
  28. package/dist/core/SessionOwnershipRegistry.js +13 -0
  29. package/dist/core/SessionOwnershipRegistry.js.map +1 -1
  30. package/dist/core/StateManager.d.ts +20 -0
  31. package/dist/core/StateManager.d.ts.map +1 -1
  32. package/dist/core/StateManager.js +72 -4
  33. package/dist/core/StateManager.js.map +1 -1
  34. package/dist/core/WriteAdmission.d.ts +277 -0
  35. package/dist/core/WriteAdmission.d.ts.map +1 -0
  36. package/dist/core/WriteAdmission.js +514 -0
  37. package/dist/core/WriteAdmission.js.map +1 -0
  38. package/dist/core/WriteDomainRegistry.d.ts +132 -0
  39. package/dist/core/WriteDomainRegistry.d.ts.map +1 -0
  40. package/dist/core/WriteDomainRegistry.js +186 -0
  41. package/dist/core/WriteDomainRegistry.js.map +1 -0
  42. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  43. package/dist/core/devGatedFeatures.js +6 -0
  44. package/dist/core/devGatedFeatures.js.map +1 -1
  45. package/dist/core/types.d.ts +26 -0
  46. package/dist/core/types.d.ts.map +1 -1
  47. package/dist/core/types.js.map +1 -1
  48. package/dist/monitoring/guardManifest.d.ts.map +1 -1
  49. package/dist/monitoring/guardManifest.js +18 -0
  50. package/dist/monitoring/guardManifest.js.map +1 -1
  51. package/dist/scaffold/templates.d.ts.map +1 -1
  52. package/dist/scaffold/templates.js +2 -1
  53. package/dist/scaffold/templates.js.map +1 -1
  54. package/dist/server/AgentServer.d.ts +3 -0
  55. package/dist/server/AgentServer.d.ts.map +1 -1
  56. package/dist/server/AgentServer.js +1 -0
  57. package/dist/server/AgentServer.js.map +1 -1
  58. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  59. package/dist/server/CapabilityIndex.js +1 -0
  60. package/dist/server/CapabilityIndex.js.map +1 -1
  61. package/dist/server/routes.d.ts +6 -0
  62. package/dist/server/routes.d.ts.map +1 -1
  63. package/dist/server/routes.js +79 -0
  64. package/dist/server/routes.js.map +1 -1
  65. package/package.json +1 -1
  66. package/src/data/builtin-manifest.json +65 -65
  67. package/src/scaffold/templates.ts +2 -1
  68. package/upgrades/1.3.729.md +92 -0
  69. package/upgrades/side-effects/standby-write-reconciliation.md +62 -0
@@ -0,0 +1,514 @@
1
+ /**
2
+ * WriteAdmission — ONE synchronous, in-memory decision point that classifies
3
+ * every write into a domain (machine-local / session-scoped / topic-scoped /
4
+ * cluster-shared) and admits or TYPED-refuses it, replacing the blanket
5
+ * lease-boolean standby guard with ownership-scoped write admission.
6
+ *
7
+ * Spec: docs/specs/standby-write-reconciliation.md (§3.2 decision table,
8
+ * §3.4 typed-refusal contract, §5 fail directions, §6 observability).
9
+ *
10
+ * Hard properties (invariant I2): the admission path is synchronous and
11
+ * in-memory ONLY — no fs, no network, no LLM, no await. It reads (a) the
12
+ * lease view the coordinator already maintains in memory (via injected
13
+ * `isReadOnly`), (b) the ownership index (boot-warmed + onCommit-updated,
14
+ * never `registry.read()`), (c) the domain registry. Refusal log rows are
15
+ * BUFFERED in memory and flushed off the admission path (a timer), so even
16
+ * observability never puts fs on the decision path.
17
+ *
18
+ * Authority ladder (§7): the layer only gains refusal authority at
19
+ * `dryRun:false` AND after the wave-2 write-surface inventory is complete
20
+ * (WRITE_SURFACE_INVENTORY_COMPLETE — the §9.14 ladder gate). Until then it
21
+ * evaluates + logs would-verdicts while the LEGACY blanket guard keeps
22
+ * enforcing (§9.6).
23
+ */
24
+ import path from 'node:path';
25
+ import { monitorEventLoopDelay } from 'node:perf_hooks';
26
+ import { JsonlStore } from './storage/JsonlStore.js';
27
+ import { WRITE_SURFACE_INVENTORY_COMPLETE, } from './WriteDomainRegistry.js';
28
+ /** Legacy message preserved for log-scraping continuity (§7 migration parity). */
29
+ export function legacyReadOnlyMessage(operation) {
30
+ return `StateManager is read-only (this machine is on standby). Blocked: ${operation}`;
31
+ }
32
+ /** Thrown at the store seam for a refused write. Callers that today
33
+ * catch-and-log the string keep working — the legacy message is preserved. */
34
+ export class WriteRefusedError extends Error {
35
+ refusal;
36
+ constructor(refusal, operation) {
37
+ super(`${legacyReadOnlyMessage(operation)} [write-refused:${refusal.code}]`);
38
+ this.name = 'WriteRefusedError';
39
+ this.refusal = refusal;
40
+ }
41
+ }
42
+ const KNOWN_STATUSES = new Set([
43
+ 'placing', 'active', 'transferring', 'released',
44
+ ]);
45
+ /**
46
+ * The ownership index (§3.2, decided — was OQ1): owned by WriteAdmission,
47
+ * warmed by ONE synchronous `store.all()` scan at construction, updated via
48
+ * the `onCommit` hook at each substrate's own commit point. `admitWrite`
49
+ * NEVER calls `registry.read()` — negative answers come from memory.
50
+ */
51
+ export class OwnershipIndex {
52
+ entries = new Map();
53
+ warmed = false;
54
+ _lastCasTransitionAt = null;
55
+ /** Ingest validation (round-2 L1): `ownerMachineId` must be a string and
56
+ * `status` a known FSM status — REGARDLESS of which store path surfaced the
57
+ * record (the warm-scan `all()` validates weaker than `loadOne`). A record
58
+ * failing ingest classifies malformed ⇒ fail-closed `ownership-unresolved`
59
+ * for that scope — never `not-owner` with `owner: null`. */
60
+ ingest(record, opts) {
61
+ if (!record || typeof record !== 'object')
62
+ return; // unkeyable — nothing to poison
63
+ const r = record;
64
+ if (typeof r.sessionKey !== 'string' || !r.sessionKey)
65
+ return; // unkeyable
66
+ if (typeof r.ownerMachineId !== 'string' || !KNOWN_STATUSES.has(String(r.status))) {
67
+ this.entries.set(r.sessionKey, 'malformed');
68
+ }
69
+ else {
70
+ this.entries.set(r.sessionKey, { owner: r.ownerMachineId, status: r.status });
71
+ }
72
+ if (opts?.fromCommit)
73
+ this._lastCasTransitionAt = new Date().toISOString();
74
+ }
75
+ /** Boot warm — ONE synchronous scan result, off the request path. */
76
+ warmFrom(records) {
77
+ for (const r of records)
78
+ this.ingest(r);
79
+ this.warmed = true;
80
+ }
81
+ lookup(sessionKey) {
82
+ if (!this.warmed)
83
+ return { state: 'unwarmed' };
84
+ const e = this.entries.get(sessionKey);
85
+ if (e === undefined)
86
+ return { state: 'none' };
87
+ if (e === 'malformed')
88
+ return { state: 'malformed' };
89
+ return { state: 'record', owner: e.owner, status: e.status };
90
+ }
91
+ get isWarmed() {
92
+ return this.warmed;
93
+ }
94
+ stats() {
95
+ return { entries: this.entries.size, lastCasTransitionAt: this._lastCasTransitionAt };
96
+ }
97
+ /** Test-parity helper: the full keyed view (never on the admission path). */
98
+ snapshot() {
99
+ return new Map(this.entries);
100
+ }
101
+ }
102
+ const DOMAINS = ['machine-local', 'session-scoped', 'topic-scoped', 'cluster-shared'];
103
+ const AGGREGATE_WINDOW_MS = 10 * 60 * 1000;
104
+ const LOG_BUFFER_MAX = 1000;
105
+ const RECENT_REFUSALS_MAX = 50;
106
+ const STARVED_WINDOW_THRESHOLD_MS = 1000;
107
+ export class WriteAdmission {
108
+ d;
109
+ index;
110
+ counters = new Map();
111
+ recentRefusals = [];
112
+ aggregate = new Map();
113
+ logBuffer = [];
114
+ logStore = null;
115
+ flushTimer = null;
116
+ histogram = null;
117
+ gaugeTimer = null;
118
+ starvedWindows = [];
119
+ lastGauge = { p50: 0, p99: 0, max: 0 };
120
+ constructor(deps, ownershipStore) {
121
+ this.d = deps;
122
+ for (const dom of DOMAINS)
123
+ this.counters.set(dom, { admitted: 0, refused: 0, wouldRefuse: 0, wouldAdmitChanged: 0 });
124
+ if (deps.logDir) {
125
+ this.logStore = new JsonlStore(path.join(deps.logDir, 'write-admission.jsonl'), {
126
+ maxBytes: 8 * 1024 * 1024, // bounded + rotated (§6)
127
+ keepSegments: 2,
128
+ });
129
+ }
130
+ this.index = new OwnershipIndex();
131
+ // Hook-then-warm (§3.2.2 ordering): register the interface-level onCommit
132
+ // hook BEFORE the warm scan. The constructor is synchronous, so no commit
133
+ // can interleave between hook registration and the scan — the index can
134
+ // never miss a transition the local store saw.
135
+ if (ownershipStore) {
136
+ ownershipStore.onCommit = (rec) => this.onOwnershipCommit(rec);
137
+ }
138
+ // Boot warm: ONE synchronous store.all() scan AT CONSTRUCTION (§3.2.1) —
139
+ // deliberately off the request path. A store without all() (or none at
140
+ // all, e.g. pool-dark installs) warms empty: no peers' custody ⇒ scoped
141
+ // verdicts collapse via the pool-inactive clause anyway.
142
+ let records = [];
143
+ try {
144
+ records = ownershipStore?.all?.() ?? [];
145
+ }
146
+ catch (err) {
147
+ // Loud, never silent: an unreadable warm scan leaves the index warmed-
148
+ // empty (fail toward today's verdicts via the decision table's
149
+ // absent arms) and the failure is visible on the status surface.
150
+ this.log({ seam: 'boot', event: 'warm-scan-failed', error: err instanceof Error ? err.message : String(err) });
151
+ }
152
+ this.index.warmFrom(records);
153
+ // §6 event-loop-lag gauge (~zero cost) — the P2-6 attribution instrument.
154
+ if (!deps.disableTimers) {
155
+ this.histogram = monitorEventLoopDelay({ resolution: 20 });
156
+ this.histogram.enable();
157
+ this.gaugeTimer = setInterval(() => this.sampleGauge(), 5000);
158
+ this.gaugeTimer.unref?.();
159
+ this.flushTimer = setInterval(() => this.flushLog(), 2000);
160
+ this.flushTimer.unref?.();
161
+ }
162
+ }
163
+ /** The onCommit hook target (§3.2.2) — wire on BOTH shipped substrates. */
164
+ onOwnershipCommit(record) {
165
+ this.index.ingest(record, { fromCommit: true });
166
+ }
167
+ /** legacy = layer constructed but... never (construction implies enabled);
168
+ * dry-run = evaluating + logging, legacy guard enforcing;
169
+ * live = refusal authority (dryRun:false AND inventory complete — §9.14). */
170
+ mode() {
171
+ const inventoryComplete = this.d.inventoryComplete ?? WRITE_SURFACE_INVENTORY_COMPLETE;
172
+ return !this.d.dryRun && inventoryComplete ? 'live' : 'dry-run';
173
+ }
174
+ get isLive() {
175
+ return this.mode() === 'live';
176
+ }
177
+ get dryRun() {
178
+ return this.d.dryRun;
179
+ }
180
+ // ── The §3.2 decision table ────────────────────────────────────────────
181
+ /**
182
+ * Pure, synchronous, in-memory verdict (I2). Reads only the injected
183
+ * in-memory lease view, the ownership index, and the registry entry.
184
+ */
185
+ evaluate(domain, scope, entry) {
186
+ switch (domain) {
187
+ case 'machine-local':
188
+ return { admit: true };
189
+ case 'cluster-shared':
190
+ return this.d.isReadOnly()
191
+ ? { admit: false, refusal: this.refusal('lease-required', domain, scope, null) }
192
+ : { admit: true };
193
+ case 'session-scoped':
194
+ case 'topic-scoped': {
195
+ // Pool INACTIVE (§3.2, was S5): scoped domains collapse to the legacy
196
+ // lease boolean — byte-identical to today's standby behavior.
197
+ if (!this.d.isPoolActive()) {
198
+ return this.d.isReadOnly()
199
+ ? { admit: false, refusal: this.refusal('read-only-standby', domain, scope, null) }
200
+ : { admit: true };
201
+ }
202
+ // Keying (§3.1): one index, two key derivations.
203
+ let topicKey = null;
204
+ if (scope?.topicId !== undefined && scope.topicId !== null) {
205
+ topicKey = String(scope.topicId);
206
+ }
207
+ else if (domain === 'session-scoped' && scope?.sessionId) {
208
+ let bound = null;
209
+ // The binding resolver is an in-memory map read by contract; treat a
210
+ // resolver throw as a binding miss (fail toward delivery — §5).
211
+ try {
212
+ bound = this.d.resolveTopicForSession?.(scope.sessionId) ?? null;
213
+ }
214
+ catch {
215
+ /* @silent-fallback-ok — §5 "binding unresolved" row: a resolver failure IS the
216
+ in-memory-map miss case and fails toward DELIVERY (unbound ⇒ admit,
217
+ machine-local-by-construction); refusing here would gate serving an inbound
218
+ message on a standby — the exact M2 regression the table forbids. */
219
+ bound = null;
220
+ }
221
+ topicKey = bound === null || bound === undefined ? null : String(bound);
222
+ }
223
+ if (topicKey === null) {
224
+ if (domain === 'session-scoped') {
225
+ // UNBOUND arm: machine-local-by-construction ⇒ ADMIT (M2).
226
+ return { admit: true };
227
+ }
228
+ // topic-scoped writes carry their topic id by definition (§3.2 n/a
229
+ // arm); a missing id resolves like the absent arm: legacy boolean.
230
+ return this.legacyBooleanVerdict(domain, scope);
231
+ }
232
+ const lk = this.index.lookup(topicKey);
233
+ if (lk.state === 'unwarmed' || lk.state === 'malformed') {
234
+ // Fail closed on GENUINE ambiguity only (I5).
235
+ return { admit: false, refusal: this.refusal('ownership-unresolved', domain, scope, null) };
236
+ }
237
+ if (lk.state === 'none' || lk.status === 'released') {
238
+ if (domain === 'session-scoped')
239
+ return { admit: true }; // today-equivalent (the carve-out)
240
+ // topic-scoped absent/released ⇒ legacy lease boolean (§9.18) unless
241
+ // the entry declares an I9-audited absent-window story.
242
+ if ((entry?.kind === 'kv' || entry?.kind === 'route') && entry.absentWindowStory) {
243
+ return { admit: true };
244
+ }
245
+ return this.legacyBooleanVerdict(domain, scope);
246
+ }
247
+ // Record in placing / active / transferring: admit iff the FSM's
248
+ // single named owner is this machine (§9.11 — ownerOf semantics).
249
+ if (this.d.thisMachineId !== null && lk.owner === this.d.thisMachineId) {
250
+ return { admit: true };
251
+ }
252
+ return { admit: false, refusal: this.refusal('not-owner', domain, scope, lk.owner) };
253
+ }
254
+ }
255
+ }
256
+ legacyBooleanVerdict(domain, scope) {
257
+ return this.d.isReadOnly()
258
+ ? { admit: false, refusal: this.refusal('read-only-standby', domain, scope, null) }
259
+ : { admit: true };
260
+ }
261
+ refusal(code, domain, scope, ownerId) {
262
+ const now = this.d.now?.() ?? Date.now();
263
+ const ownerNick = ownerId ? this.d.nicknameOf?.(ownerId) ?? null : null;
264
+ let hint;
265
+ switch (code) {
266
+ case 'not-owner':
267
+ hint = `This write belongs to ${ownerNick ? `'${ownerNick}'` : `machine ${ownerId}`} — re-send it there. (Advisory only: moving the topic is a consent-gated operator decision, not a step to auto-follow.)`;
268
+ break;
269
+ case 'lease-required':
270
+ hint = 'This is cluster-shared state; only the serving-lease holder writes it. Re-send to the lease holder.';
271
+ break;
272
+ case 'ownership-unresolved':
273
+ hint = 'Ownership for this scope could not be resolved right now — retry shortly.';
274
+ break;
275
+ case 'read-only-standby':
276
+ hint = 'This machine is on standby for this write; the serving machine handles it.';
277
+ break;
278
+ case 'admission-error':
279
+ hint = 'The write-admission layer failed while evaluating this write; refused fail-closed. Retry shortly.';
280
+ break;
281
+ }
282
+ let leaseHolder = null;
283
+ try {
284
+ leaseHolder = this.d.leaseHolder?.() ?? null;
285
+ }
286
+ catch {
287
+ /* @silent-fallback-ok — I7: the refusal body's lease-holder decoration is best-effort
288
+ LOCAL knowledge; a reader failure only omits the advisory field, never changes the
289
+ verdict, and the refusal must never hang or throw on decoration. */
290
+ leaseHolder = null;
291
+ }
292
+ return {
293
+ error: 'write-refused',
294
+ code,
295
+ domain,
296
+ ...(scope ? { scope } : {}),
297
+ thisMachine: { machineId: this.d.thisMachineId, nickname: this.d.selfNickname?.() ?? null },
298
+ owner: ownerId ? { machineId: ownerId, nickname: ownerNick } : null,
299
+ leaseHolder,
300
+ asOf: new Date(now).toISOString(),
301
+ retryable: true,
302
+ hint,
303
+ };
304
+ }
305
+ // ── Store seam (§3.3) ──────────────────────────────────────────────────
306
+ /**
307
+ * Verdict for StateManager.guardWrite. Returns:
308
+ * - 'admit' — pass (live authority admitted the write)
309
+ * - 'refuse' — throw the carried WriteRefusedError (live authority refused)
310
+ * - 'legacy' — dry-run/ladder-gated: caller runs today's legacy verdict
311
+ * A throw ANYWHERE inside is caught by the caller ⇒ legacy verdict (§5).
312
+ */
313
+ guardStoreWrite(op, opts) {
314
+ const { domain, entry } = this.d.registry.domainForOp(op, opts?.key);
315
+ const verdict = this.evaluate(domain, opts?.scope, entry);
316
+ const surface = opts?.key ? `${op}:${opts.key}` : op;
317
+ if (this.isLive) {
318
+ this.record('store', surface, domain, verdict, opts?.scope);
319
+ if (verdict.admit)
320
+ return { enforce: 'admit' };
321
+ return { enforce: 'refuse', refusal: verdict.refusal };
322
+ }
323
+ // Dry-run: compute today's LEGACY verdict and log divergences — the
324
+ // graduation evidence (§6): wouldRefuse-but-today-succeeds = false
325
+ // positive to fix; wouldAdmit-but-today-throws = the fix landing.
326
+ const legacyThrows = this.d.isReadOnly() && !(opts?.legacySessionScoped && this.d.isPoolActive());
327
+ this.recordDryRun('store', surface, domain, verdict, legacyThrows, opts?.scope);
328
+ return { enforce: 'legacy' };
329
+ }
330
+ // ── Route seam (§3.4/§3.5) ─────────────────────────────────────────────
331
+ /**
332
+ * Verdict for a mutating HTTP route. Returns:
333
+ * - 'proceed' — route continues into today's exact flow
334
+ * - 'refuse' — respond 409 + Retry-After with the typed body
335
+ * An unwired route (no registry entry) always proceeds (I8). An admission-
336
+ * layer throw splits by domain (§9.16): machine-local PROCEEDS (fail toward
337
+ * delivery), scoped/cluster-shared REFUSE typed `admission-error` (fail
338
+ * closed). Both directions are logged + join the §6 aggregate.
339
+ */
340
+ guardRouteWrite(method, routePath, scope) {
341
+ let entry = null;
342
+ try {
343
+ entry = this.d.registry.entryForRoute(method, routePath);
344
+ if (!entry)
345
+ return { action: 'proceed' };
346
+ const verdict = this.evaluate(entry.domain, scope, entry);
347
+ const surface = `${method.toUpperCase()} ${entry.pathPrefix}`;
348
+ if (this.isLive) {
349
+ this.record('route', surface, entry.domain, verdict, scope);
350
+ if (verdict.admit)
351
+ return { action: 'proceed' };
352
+ return { action: 'refuse', refusal: verdict.refusal, status: 409, retryAfterSeconds: 5 };
353
+ }
354
+ const legacyThrows = false; // routes never consulted the legacy guard (§1.2)
355
+ this.recordDryRun('route', surface, entry.domain, verdict, legacyThrows, scope);
356
+ return { action: 'proceed' };
357
+ }
358
+ catch (err) {
359
+ const domain = entry?.domain ?? 'cluster-shared';
360
+ const surface = `${method.toUpperCase()} ${entry?.pathPrefix ?? routePath}`;
361
+ const direction = domain === 'machine-local' ? 'fail-open-proceed' : 'fail-closed-refuse';
362
+ this.log({
363
+ seam: 'route', surface, domain, verdict: 'admission-error', direction,
364
+ error: err instanceof Error ? err.message : String(err),
365
+ });
366
+ this.bumpAggregate(surface, 'admission-error', direction);
367
+ if (domain === 'machine-local' || !this.isLive)
368
+ return { action: 'proceed' };
369
+ return {
370
+ action: 'refuse',
371
+ refusal: this.refusal('admission-error', domain, scope, null),
372
+ status: 409,
373
+ retryAfterSeconds: 5,
374
+ };
375
+ }
376
+ }
377
+ // ── Observability (§6) ─────────────────────────────────────────────────
378
+ record(seam, surface, domain, verdict, scope) {
379
+ const c = this.counters.get(domain);
380
+ if (verdict.admit) {
381
+ c.admitted++;
382
+ return;
383
+ }
384
+ c.refused++;
385
+ const { hint: _hint, ...bodyMinusHint } = verdict.refusal;
386
+ this.recentRefusals.push({ ...bodyMinusHint, seam, surface });
387
+ if (this.recentRefusals.length > RECENT_REFUSALS_MAX)
388
+ this.recentRefusals.shift();
389
+ this.log({ seam, surface, domain, scope, verdict: 'refused', code: verdict.refusal.code, owner: verdict.refusal.owner?.machineId ?? null, leaseHolder: verdict.refusal.leaseHolder });
390
+ this.bumpAggregate(surface, verdict.refusal.code, 'refused');
391
+ }
392
+ recordDryRun(seam, surface, domain, verdict, legacyThrows, scope) {
393
+ const c = this.counters.get(domain);
394
+ if (!verdict.admit && !legacyThrows) {
395
+ c.wouldRefuse++;
396
+ this.log({ seam, surface, domain, scope, verdict: 'would-refuse', code: verdict.refusal.code, owner: verdict.refusal.owner?.machineId ?? null });
397
+ }
398
+ else if (verdict.admit && legacyThrows) {
399
+ c.wouldAdmitChanged++;
400
+ this.log({ seam, surface, domain, scope, verdict: 'would-admit' });
401
+ }
402
+ else if (verdict.admit) {
403
+ c.admitted++; // agreement rows are counted, not logged (bounded log)
404
+ }
405
+ else {
406
+ c.refused++; // both refuse — today's behavior, count only
407
+ }
408
+ }
409
+ bumpAggregate(surface, code, direction) {
410
+ const key = `${surface}|${code}|${direction}`;
411
+ const now = this.d.now?.() ?? Date.now();
412
+ let a = this.aggregate.get(key);
413
+ if (!a || now - a.windowStart > AGGREGATE_WINDOW_MS) {
414
+ a = { count: 0, windowStart: now, raised: false };
415
+ this.aggregate.set(key, a);
416
+ }
417
+ a.count++;
418
+ const threshold = this.d.refusalAggregateThreshold ?? 5;
419
+ if (a.count >= threshold && !a.raised) {
420
+ a.raised = true; // ONE deduped item per window — never per-event (§6)
421
+ try {
422
+ this.d.raiseAttention?.({
423
+ id: `agent:write-admission-${key.replace(/[^A-Za-z0-9:_-]+/g, '-').toLowerCase()}`,
424
+ title: `Write-admission: ${a.count}+ ${code} on ${surface}`,
425
+ body: `${a.count} ${code} verdicts (${direction}) for ${surface} within ${Math.round(AGGREGATE_WINDOW_MS / 60000)} min. A caller may be looping on refusals, or a guard may be broken — see GET /write-admission and logs/write-admission.jsonl.`,
426
+ });
427
+ }
428
+ catch {
429
+ /* @silent-fallback-ok — the aggregate alert is observability; a failing attention
430
+ surface must never break (or recurse into) the admission path. The refusal rows
431
+ remain in the JSONL log, so the evidence is not lost. */
432
+ }
433
+ }
434
+ }
435
+ /** Admission-layer throw at the STORE seam (§5): the caller fell back to the
436
+ * legacy verdict; record it so a broken guard is never log-only-invisible. */
437
+ noteStoreSeamError(op, err) {
438
+ this.log({ seam: 'store', surface: op, verdict: 'admission-error', direction: 'fail-legacy', error: err instanceof Error ? err.message : String(err) });
439
+ this.bumpAggregate(op, 'admission-error', 'fail-legacy');
440
+ }
441
+ log(row) {
442
+ if (!this.logStore)
443
+ return;
444
+ if (this.logBuffer.length >= LOG_BUFFER_MAX)
445
+ this.logBuffer.shift();
446
+ this.logBuffer.push(JSON.stringify({ ts: new Date(this.d.now?.() ?? Date.now()).toISOString(), ...row }));
447
+ if (this.d.disableTimers)
448
+ this.flushLog(); // test seam: synchronous visibility
449
+ }
450
+ /** Flush buffered rows to logs/write-admission.jsonl — OFF the admission
451
+ * path (I2: even observability never puts fs on the decision path).
452
+ * Routed through JsonlStore (Bounded Accumulation: bounded + rotated). */
453
+ flushLog() {
454
+ if (!this.logStore || this.logBuffer.length === 0)
455
+ return;
456
+ const rows = this.logBuffer.splice(0, this.logBuffer.length);
457
+ try {
458
+ for (const r of rows)
459
+ this.logStore.append(r);
460
+ }
461
+ catch (err) {
462
+ // Loud once per flush failure: observability loss must not be silent,
463
+ // but must also never throw into the admission path.
464
+ console.warn(`[write-admission] log flush failed: ${err instanceof Error ? err.message : String(err)}`);
465
+ }
466
+ }
467
+ sampleGauge() {
468
+ if (!this.histogram)
469
+ return;
470
+ const h = this.histogram;
471
+ // monitorEventLoopDelay reports nanoseconds.
472
+ this.lastGauge = {
473
+ p50: Math.round(h.percentile(50) / 1e6),
474
+ p99: Math.round(h.percentile(99) / 1e6),
475
+ max: Math.round(h.max / 1e6),
476
+ };
477
+ if (this.lastGauge.max >= STARVED_WINDOW_THRESHOLD_MS) {
478
+ this.starvedWindows.push(this.d.now?.() ?? Date.now());
479
+ }
480
+ const dayAgo = (this.d.now?.() ?? Date.now()) - 24 * 60 * 60 * 1000;
481
+ this.starvedWindows = this.starvedWindows.filter((t) => t >= dayAgo);
482
+ h.reset();
483
+ }
484
+ eventLoopStats() {
485
+ return { ...this.lastGauge, starvedWindows24h: this.starvedWindows.length };
486
+ }
487
+ /** The GET /write-admission body (§6). */
488
+ status() {
489
+ return {
490
+ enabled: true,
491
+ dryRun: this.d.dryRun,
492
+ mode: this.mode(),
493
+ inventoryComplete: this.d.inventoryComplete ?? WRITE_SURFACE_INVENTORY_COMPLETE,
494
+ domains: DOMAINS.map((domain) => ({ domain, ...this.counters.get(domain) })),
495
+ recentRefusals: [...this.recentRefusals],
496
+ refusedClassifications: this.d.registry.refusedClassifications.map((r) => ({ reason: r.reason })),
497
+ ownershipIndex: this.index.stats(),
498
+ eventLoop: this.eventLoopStats(),
499
+ };
500
+ }
501
+ /** Tear down timers/histogram (tests + shutdown). */
502
+ stop() {
503
+ if (this.flushTimer)
504
+ clearInterval(this.flushTimer);
505
+ if (this.gaugeTimer)
506
+ clearInterval(this.gaugeTimer);
507
+ this.flushTimer = null;
508
+ this.gaugeTimer = null;
509
+ this.flushLog();
510
+ this.histogram?.disable();
511
+ this.histogram = null;
512
+ }
513
+ }
514
+ //# sourceMappingURL=WriteAdmission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WriteAdmission.js","sourceRoot":"","sources":["../../src/core/WriteAdmission.ts"],"names":[],"mappings":"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"}