instar 1.3.748 → 1.3.749
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 +136 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/core/HttpLeaseTransport.d.ts +22 -0
- package/dist/core/HttpLeaseTransport.d.ts.map +1 -1
- package/dist/core/HttpLeaseTransport.js +37 -3
- package/dist/core/HttpLeaseTransport.js.map +1 -1
- package/dist/core/LeaseCoordinator.d.ts +22 -0
- package/dist/core/LeaseCoordinator.d.ts.map +1 -1
- package/dist/core/LeaseCoordinator.js +11 -0
- package/dist/core/LeaseCoordinator.js.map +1 -1
- package/dist/core/MachinePoolRegistry.d.ts +11 -0
- package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
- package/dist/core/MachinePoolRegistry.js +29 -1
- package/dist/core/MachinePoolRegistry.js.map +1 -1
- package/dist/core/PeerPresencePuller.d.ts +26 -1
- package/dist/core/PeerPresencePuller.d.ts.map +1 -1
- package/dist/core/PeerPresencePuller.js +15 -1
- package/dist/core/PeerPresencePuller.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +16 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/machineCoherenceAdvert.d.ts +108 -0
- package/dist/core/machineCoherenceAdvert.d.ts.map +1 -0
- package/dist/core/machineCoherenceAdvert.js +160 -0
- package/dist/core/machineCoherenceAdvert.js.map +1 -0
- package/dist/core/machineCoherenceManifest.d.ts +133 -0
- package/dist/core/machineCoherenceManifest.d.ts.map +1 -0
- package/dist/core/machineCoherenceManifest.js +293 -0
- package/dist/core/machineCoherenceManifest.js.map +1 -0
- package/dist/core/types.d.ts +21 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/MachineCoherenceSentinel.d.ts +240 -0
- package/dist/monitoring/MachineCoherenceSentinel.d.ts.map +1 -0
- package/dist/monitoring/MachineCoherenceSentinel.js +336 -0
- package/dist/monitoring/MachineCoherenceSentinel.js.map +1 -0
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +25 -0
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/monitoring/machineCoherenceEpisode.d.ts +152 -0
- package/dist/monitoring/machineCoherenceEpisode.d.ts.map +1 -0
- package/dist/monitoring/machineCoherenceEpisode.js +92 -0
- package/dist/monitoring/machineCoherenceEpisode.js.map +1 -0
- package/dist/monitoring/machineCoherenceEpisodeManager.d.ts +210 -0
- package/dist/monitoring/machineCoherenceEpisodeManager.d.ts.map +1 -0
- package/dist/monitoring/machineCoherenceEpisodeManager.js +724 -0
- package/dist/monitoring/machineCoherenceEpisodeManager.js.map +1 -0
- package/dist/monitoring/machineCoherenceEvaluate.d.ts +129 -0
- package/dist/monitoring/machineCoherenceEvaluate.d.ts.map +1 -0
- package/dist/monitoring/machineCoherenceEvaluate.js +183 -0
- package/dist/monitoring/machineCoherenceEvaluate.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +6 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -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 +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +12 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +6 -0
- package/upgrades/1.3.749.md +35 -0
- package/upgrades/side-effects/machine-coherence-guard.md +229 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MachineCoherenceSentinel — the machine-coherence guard's evaluator core
|
|
3
|
+
* (machine-coherence-guard §3.3/§3.4; roadmap 4.1, F4/P0-1).
|
|
4
|
+
*
|
|
5
|
+
* A pure-core, tick-driven, signal-only sentinel in the `checkPoolFlagCoherence`
|
|
6
|
+
* shape: it compares, across every ONLINE machine in the pool, the §3.2 advert
|
|
7
|
+
* dimensions (version / resolved flags / protocol / manifest generation) and —
|
|
8
|
+
* when the pool diverges — will raise ONE deduped, episode-scoped attention item
|
|
9
|
+
* from exactly ONE elected machine. It never blocks, equalizes, or restarts
|
|
10
|
+
* anything.
|
|
11
|
+
*
|
|
12
|
+
* INCREMENT STATUS (C₁ is landing in sub-units — see the side-effects artifact):
|
|
13
|
+
* - LANDED here: config resolution (spec §7 keys, code-side defaults,
|
|
14
|
+
* `enabled` OMITTED from ConfigDefaults → resolveDevAgentGate, the #1001
|
|
15
|
+
* anti-mechanism), the tick loop's early no-op gates (single-machine strict
|
|
16
|
+
* no-op BEFORE any state is touched), the per-tick peer-classification pass
|
|
17
|
+
* (composing the pure C₀ helpers), the §3.4 election over live candidates,
|
|
18
|
+
* the M11 comparison-universe honesty accounting, and the §6 status
|
|
19
|
+
* snapshot shape.
|
|
20
|
+
* - NOT YET here (Session B): dimension comparison + confirmation counters
|
|
21
|
+
* (R2-L3 consecutive rule, M6 update-wave suppression, N8 warm-up
|
|
22
|
+
* accounting beyond the tick gate), the §4 episode state machine + the ONE
|
|
23
|
+
* attention item + §4.2.1 fix flow, the alarm-marker attach into
|
|
24
|
+
* refreshPool's advert, jsonl transitions, and the status route.
|
|
25
|
+
*
|
|
26
|
+
* Fail toward silence (§3.3): any evaluator error → no emit this tick, an
|
|
27
|
+
* error counter on the status snapshot. A guard that can flood on its own
|
|
28
|
+
* malfunction re-creates the disease it treats.
|
|
29
|
+
*
|
|
30
|
+
* Supervision tier (N6): Tier 0 — fully deterministic; no LLM call anywhere.
|
|
31
|
+
* Signal-vs-authority: PURE SIGNAL (dev-gated dark; dry-run first even on dev).
|
|
32
|
+
*/
|
|
33
|
+
import type { MachineCapacity } from '../core/types.js';
|
|
34
|
+
import { type SkewRow } from './machineCoherenceEvaluate.js';
|
|
35
|
+
import { type EpisodeEffect } from './machineCoherenceEpisodeManager.js';
|
|
36
|
+
/** Resolved config (spec §7 — every knob carries its shipped default in code). */
|
|
37
|
+
export interface MachineCoherenceResolvedConfig {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
dryRun: boolean;
|
|
40
|
+
flagConfirmTicks: number;
|
|
41
|
+
versionSkewGraceMs: number;
|
|
42
|
+
resolveTicks: number;
|
|
43
|
+
escalateAfterMs: number;
|
|
44
|
+
advertStaleMs: number;
|
|
45
|
+
warmupTicks: number;
|
|
46
|
+
reopenWindowMs: number;
|
|
47
|
+
maxEpisodeItemsPerDay: number;
|
|
48
|
+
suspendedEpisodeExpiryMs: number;
|
|
49
|
+
raiserTakeoverTicks: number;
|
|
50
|
+
flappingLatchReopens: number;
|
|
51
|
+
episodeAppendBudget: number;
|
|
52
|
+
episodeAppendWindowMs: number;
|
|
53
|
+
fixVerifyTicks: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the guard's config from the full agent config object. `enabled` is
|
|
57
|
+
* DELIBERATELY absent from ConfigDefaults — resolveDevAgentGate decides (LIVE
|
|
58
|
+
* on a development agent, DARK on the fleet; an explicit value always wins —
|
|
59
|
+
* the #1001 anti-mechanism). `dryRun` defaults TRUE even on dev (dry-run
|
|
60
|
+
* FIRST: evaluator runs, counters record would-raise, NO item).
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveMachineCoherenceConfig(config: Record<string, unknown>): MachineCoherenceResolvedConfig;
|
|
63
|
+
/** The guard's own posture, derived from resolved config (feeds candidacy). */
|
|
64
|
+
export declare function selfPostureOf(cfg: Pick<MachineCoherenceResolvedConfig, 'enabled' | 'dryRun'>): 'live' | 'dry-run' | 'dark';
|
|
65
|
+
export interface MachineCoherenceSentinelDeps {
|
|
66
|
+
/** The pool view (self + peers) — `machinePoolRegistry.getCapacities()`. */
|
|
67
|
+
listCapacities: () => MachineCapacity[];
|
|
68
|
+
/** This machine's id (null before pool identity is established). */
|
|
69
|
+
selfMachineId: () => string | null;
|
|
70
|
+
/** The serving-lease holder's machine id, or null when unknown/none. */
|
|
71
|
+
leaseHolderMachineId: () => string | null;
|
|
72
|
+
/** Wall clock — injectable for tests. */
|
|
73
|
+
now?: () => number;
|
|
74
|
+
/** The per-agent state root (`<agent>/.instar`). When provided, the sentinel
|
|
75
|
+
* owns a durable EpisodeManager (§4 episode machinery); when absent (pure
|
|
76
|
+
* unit tests), the sentinel runs classification + confirmation only. */
|
|
77
|
+
stateDir?: () => string | null;
|
|
78
|
+
/** machineId → operator-facing nickname (registry display label). */
|
|
79
|
+
nicknameOf?: (machineId: string) => string;
|
|
80
|
+
}
|
|
81
|
+
/** The §6 status snapshot (the future `GET /pool/machine-coherence` body core). */
|
|
82
|
+
export interface MachineCoherenceStatus {
|
|
83
|
+
enabled: boolean;
|
|
84
|
+
dryRun: boolean;
|
|
85
|
+
lastTickAt: string | null;
|
|
86
|
+
machinesRegisteredOnline: number;
|
|
87
|
+
machinesCompared: number;
|
|
88
|
+
peerClassifications: {
|
|
89
|
+
compared: number;
|
|
90
|
+
unknown: number;
|
|
91
|
+
advertStale: number;
|
|
92
|
+
advertRejected: number;
|
|
93
|
+
};
|
|
94
|
+
raiser: {
|
|
95
|
+
machineId: string | null;
|
|
96
|
+
isSelf: boolean;
|
|
97
|
+
candidates: string[];
|
|
98
|
+
};
|
|
99
|
+
/** The open episode (§4), or null when none / the durable machinery is unwired.
|
|
100
|
+
* `pendingFix` carries the §4.2.1 proposal awaiting operator approval (or null). */
|
|
101
|
+
openEpisode: {
|
|
102
|
+
episodeId: string;
|
|
103
|
+
rows: number;
|
|
104
|
+
suspended: boolean;
|
|
105
|
+
itemRaisedAt: string | null;
|
|
106
|
+
pendingFix: {
|
|
107
|
+
state: import('./machineCoherenceEpisode.js').PendingFixState;
|
|
108
|
+
key: string;
|
|
109
|
+
targetMachineId: string;
|
|
110
|
+
targetValue: string;
|
|
111
|
+
proposalHash: string;
|
|
112
|
+
} | null;
|
|
113
|
+
} | null;
|
|
114
|
+
/** Episode lifecycle counters (§4.5) — present only when the machinery is wired. */
|
|
115
|
+
episodeCounters?: import('./machineCoherenceEpisodeManager.js').EpisodeManagerCounters;
|
|
116
|
+
/**
|
|
117
|
+
* `skewsConfirmed` is CUMULATIVE (a counter of confirmation transitions, not a
|
|
118
|
+
* live gauge). `confirmedRows`/`pendingRows` are the live gauges — how many
|
|
119
|
+
* distinct skew rows are currently confirmed vs still accruing consecutive
|
|
120
|
+
* ticks. `errors` is fail-toward-silence tick errors.
|
|
121
|
+
*/
|
|
122
|
+
counters: {
|
|
123
|
+
ticks: number;
|
|
124
|
+
skewsConfirmed: number;
|
|
125
|
+
confirmedRows: number;
|
|
126
|
+
pendingRows: number;
|
|
127
|
+
errors: number;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export declare class MachineCoherenceSentinel {
|
|
131
|
+
private readonly deps;
|
|
132
|
+
private readonly cfg;
|
|
133
|
+
private lastTickAtMs;
|
|
134
|
+
private ticks;
|
|
135
|
+
private errors;
|
|
136
|
+
/** Post-boot warm-up accounting (N8): ticks completed since construction. */
|
|
137
|
+
private ticksSinceBoot;
|
|
138
|
+
private lastClassified;
|
|
139
|
+
private lastRegisteredOnline;
|
|
140
|
+
private lastRaiser;
|
|
141
|
+
private lastCandidates;
|
|
142
|
+
/** §3.3 confirmation engine: per-row consecutive-tick + grace-clock state. */
|
|
143
|
+
private rowState;
|
|
144
|
+
/** The row identities present LAST tick (R2-L3 consecutive detection). */
|
|
145
|
+
private lastTickRowIds;
|
|
146
|
+
/** Cumulative count of confirmation transitions (never decremented). */
|
|
147
|
+
private skewsConfirmed;
|
|
148
|
+
/** The §4 episode machinery (constructed only when a stateDir is provided). */
|
|
149
|
+
private episode?;
|
|
150
|
+
/** Effects the last tick produced, awaiting execution by the caller (server). */
|
|
151
|
+
private pendingEffects;
|
|
152
|
+
constructor(deps: MachineCoherenceSentinelDeps, cfg: MachineCoherenceResolvedConfig);
|
|
153
|
+
/**
|
|
154
|
+
* Drain the effects the last reconcile produced (raise/append/resolve). The
|
|
155
|
+
* caller (server) executes them against the telegram adapter, keeping the
|
|
156
|
+
* sentinel Tier-0 and its tick synchronous. Empty on a dark/no-episode agent.
|
|
157
|
+
*/
|
|
158
|
+
drainPendingEffects(): EpisodeEffect[];
|
|
159
|
+
/** Passthrough for the conversational reply path (b3): the durable "leave it" ack. */
|
|
160
|
+
setOperatorAck(ack: boolean): void;
|
|
161
|
+
/**
|
|
162
|
+
* Operator "fix it" approval passthrough (§4.2.1-i). The caller (conversational
|
|
163
|
+
* reply path) has verified the sender is the topic's VERIFIED operator (Know
|
|
164
|
+
* Your Principal) and passes `verifiedOperator`; `proposalHash` is the display-
|
|
165
|
+
* integrity authority. Returns the transition + any effects (an `execute-fix`
|
|
166
|
+
* for the divergent==raiser case) the caller executes immediately. A dark/
|
|
167
|
+
* unwired guard is a no-op refusal.
|
|
168
|
+
*/
|
|
169
|
+
approveFix(args: {
|
|
170
|
+
proposalHash: string;
|
|
171
|
+
verifiedOperator: boolean;
|
|
172
|
+
now?: number;
|
|
173
|
+
}): {
|
|
174
|
+
result: {
|
|
175
|
+
ok: boolean;
|
|
176
|
+
reason?: string;
|
|
177
|
+
state?: string;
|
|
178
|
+
};
|
|
179
|
+
effects: EpisodeEffect[];
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Whether this tick is still inside the N8 post-boot warm-up window:
|
|
183
|
+
* `MachinePoolRegistry` is in-memory, so a local restart wipes every peer's
|
|
184
|
+
* advert until the next 30s pull — for `warmupTicks` after boot,
|
|
185
|
+
* `unknown`/`advert-stale` classifications must count toward NOTHING (no
|
|
186
|
+
* confirmation progress, no version-class grace clock). The classification
|
|
187
|
+
* itself still runs (the status snapshot stays honest); the CONSUMERS of
|
|
188
|
+
* warm-up (confirmation counters, Session B) read this flag.
|
|
189
|
+
*/
|
|
190
|
+
inWarmup(): boolean;
|
|
191
|
+
/**
|
|
192
|
+
* One evaluator tick (rides the existing 30s peerPresenceTick — no timer of
|
|
193
|
+
* its own). Runs only when the guard resolves live or dry-run; the caller
|
|
194
|
+
* owns the gate (a dark guard never constructs/ticks the sentinel). Fails
|
|
195
|
+
* toward silence: any error increments the error counter and emits nothing.
|
|
196
|
+
*/
|
|
197
|
+
tick(): void;
|
|
198
|
+
/**
|
|
199
|
+
* §3.3 confirmation engine (R2-L3 consecutive rule + M6 update-wave
|
|
200
|
+
* suppression). Runs over the CURRENTLY-`compared` machines (self included —
|
|
201
|
+
* self records its own advert every beat), turns the raw per-tick divergences
|
|
202
|
+
* into confirmed rows, and never raises anything (the episode/alarm machinery
|
|
203
|
+
* is Session B). Pure state transitions; the caller owns fail-toward-silence.
|
|
204
|
+
*
|
|
205
|
+
* The consecutive rule (R2-L3): a row's confirmation counts ONLY ticks in which
|
|
206
|
+
* the row's identity (which encodes every participant's clamped value) is
|
|
207
|
+
* present. Because a participant dropping out (offline / unknown / advert-stale)
|
|
208
|
+
* either vanishes the identity or changes it, the old identity leaves
|
|
209
|
+
* `currentIds`, its counter is dropped, and a re-appearance starts fresh at 1 —
|
|
210
|
+
* one flapping reading can never accumulate toward confirmation.
|
|
211
|
+
*
|
|
212
|
+
* M6 update-wave suppression: FLAG rows are suppressed while ANY version skew
|
|
213
|
+
* exists among the compared machines (a differing version OR an open patch-only
|
|
214
|
+
* grace window — an update that changes a flag's resolved default would else
|
|
215
|
+
* alarm HIGH mid-wave and auto-resolve). Once every version agrees, residual
|
|
216
|
+
* flag skew confirms normally.
|
|
217
|
+
*/
|
|
218
|
+
private updateConfirmation;
|
|
219
|
+
/** The currently-confirmed skew rows (C₁b-ii — Session B's episode machinery
|
|
220
|
+
* consumes these; the status route exposes their count). Pure read. */
|
|
221
|
+
confirmedSkewRows(): SkewRow[];
|
|
222
|
+
/** The rows still accruing consecutive ticks (divergent, not yet confirmed). */
|
|
223
|
+
pendingSkewRows(): SkewRow[];
|
|
224
|
+
/**
|
|
225
|
+
* The GuardRegistry runtime getter (GUARD-POSTURE-ENDPOINT-SPEC §2.1): a
|
|
226
|
+
* synchronous in-memory read the /guards endpoint snapshots per request.
|
|
227
|
+
* `expectRuntime:true` on the GUARD_MANIFEST entry requires the C₁b server-boot
|
|
228
|
+
* wiring to register THIS at boot. `enabled`/`dryRun` come from the resolved
|
|
229
|
+
* config; `lastTickAt` drives the on-stale grading (a constructed-but-never-
|
|
230
|
+
* ticking guard reads stale, never "on"). Pure — never mutates.
|
|
231
|
+
*/
|
|
232
|
+
guardStatus(): {
|
|
233
|
+
enabled: boolean;
|
|
234
|
+
dryRun: boolean;
|
|
235
|
+
lastTickAt: number;
|
|
236
|
+
};
|
|
237
|
+
/** The §6 status snapshot (pure read — never mutates). */
|
|
238
|
+
status(): MachineCoherenceStatus;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=MachineCoherenceSentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MachineCoherenceSentinel.d.ts","sourceRoot":"","sources":["../../src/monitoring/MachineCoherenceSentinel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MachineCoherenceSentinel — the machine-coherence guard's evaluator core
|
|
3
|
+
* (machine-coherence-guard §3.3/§3.4; roadmap 4.1, F4/P0-1).
|
|
4
|
+
*
|
|
5
|
+
* A pure-core, tick-driven, signal-only sentinel in the `checkPoolFlagCoherence`
|
|
6
|
+
* shape: it compares, across every ONLINE machine in the pool, the §3.2 advert
|
|
7
|
+
* dimensions (version / resolved flags / protocol / manifest generation) and —
|
|
8
|
+
* when the pool diverges — will raise ONE deduped, episode-scoped attention item
|
|
9
|
+
* from exactly ONE elected machine. It never blocks, equalizes, or restarts
|
|
10
|
+
* anything.
|
|
11
|
+
*
|
|
12
|
+
* INCREMENT STATUS (C₁ is landing in sub-units — see the side-effects artifact):
|
|
13
|
+
* - LANDED here: config resolution (spec §7 keys, code-side defaults,
|
|
14
|
+
* `enabled` OMITTED from ConfigDefaults → resolveDevAgentGate, the #1001
|
|
15
|
+
* anti-mechanism), the tick loop's early no-op gates (single-machine strict
|
|
16
|
+
* no-op BEFORE any state is touched), the per-tick peer-classification pass
|
|
17
|
+
* (composing the pure C₀ helpers), the §3.4 election over live candidates,
|
|
18
|
+
* the M11 comparison-universe honesty accounting, and the §6 status
|
|
19
|
+
* snapshot shape.
|
|
20
|
+
* - NOT YET here (Session B): dimension comparison + confirmation counters
|
|
21
|
+
* (R2-L3 consecutive rule, M6 update-wave suppression, N8 warm-up
|
|
22
|
+
* accounting beyond the tick gate), the §4 episode state machine + the ONE
|
|
23
|
+
* attention item + §4.2.1 fix flow, the alarm-marker attach into
|
|
24
|
+
* refreshPool's advert, jsonl transitions, and the status route.
|
|
25
|
+
*
|
|
26
|
+
* Fail toward silence (§3.3): any evaluator error → no emit this tick, an
|
|
27
|
+
* error counter on the status snapshot. A guard that can flood on its own
|
|
28
|
+
* malfunction re-creates the disease it treats.
|
|
29
|
+
*
|
|
30
|
+
* Supervision tier (N6): Tier 0 — fully deterministic; no LLM call anywhere.
|
|
31
|
+
* Signal-vs-authority: PURE SIGNAL (dev-gated dark; dry-run first even on dev).
|
|
32
|
+
*/
|
|
33
|
+
import { resolveDevAgentGate } from '../core/devAgentGate.js';
|
|
34
|
+
import { getByPath } from '../core/machineCoherenceManifest.js';
|
|
35
|
+
import { classifyPeer, computeDivergentRows, electRaiser, } from './machineCoherenceEvaluate.js';
|
|
36
|
+
import { MachineCoherenceEpisodeManager } from './machineCoherenceEpisodeManager.js';
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the guard's config from the full agent config object. `enabled` is
|
|
39
|
+
* DELIBERATELY absent from ConfigDefaults — resolveDevAgentGate decides (LIVE
|
|
40
|
+
* on a development agent, DARK on the fleet; an explicit value always wins —
|
|
41
|
+
* the #1001 anti-mechanism). `dryRun` defaults TRUE even on dev (dry-run
|
|
42
|
+
* FIRST: evaluator runs, counters record would-raise, NO item).
|
|
43
|
+
*/
|
|
44
|
+
export function resolveMachineCoherenceConfig(config) {
|
|
45
|
+
const block = (getByPath(config, 'monitoring.machineCoherence') ?? {});
|
|
46
|
+
const num = (key, fallback) => {
|
|
47
|
+
const v = block[key];
|
|
48
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : fallback;
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
enabled: resolveDevAgentGate(typeof block.enabled === 'boolean' ? block.enabled : undefined, config),
|
|
52
|
+
dryRun: typeof block.dryRun === 'boolean' ? block.dryRun : true,
|
|
53
|
+
flagConfirmTicks: num('flagConfirmTicks', 2),
|
|
54
|
+
versionSkewGraceMs: num('versionSkewGraceMs', 2_700_000), // 45 min
|
|
55
|
+
resolveTicks: num('resolveTicks', 3),
|
|
56
|
+
escalateAfterMs: num('escalateAfterMs', 86_400_000), // 24 h
|
|
57
|
+
advertStaleMs: num('advertStaleMs', 300_000), // 5 min (M5)
|
|
58
|
+
warmupTicks: num('warmupTicks', 4), // N8
|
|
59
|
+
reopenWindowMs: num('reopenWindowMs', 3_600_000), // 60 min (M2)
|
|
60
|
+
maxEpisodeItemsPerDay: num('maxEpisodeItemsPerDay', 3), // M2
|
|
61
|
+
suspendedEpisodeExpiryMs: num('suspendedEpisodeExpiryMs', 604_800_000), // 7 d (M1)
|
|
62
|
+
raiserTakeoverTicks: num('raiserTakeoverTicks', 10), // C1/R2-M1
|
|
63
|
+
flappingLatchReopens: num('flappingLatchReopens', 3), // R2-N4
|
|
64
|
+
episodeAppendBudget: num('episodeAppendBudget', 6), // R3-M5
|
|
65
|
+
episodeAppendWindowMs: num('episodeAppendWindowMs', 21_600_000), // 6 h (R3-M5)
|
|
66
|
+
fixVerifyTicks: num('fixVerifyTicks', 10), // R2-M3-v
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** The guard's own posture, derived from resolved config (feeds candidacy). */
|
|
70
|
+
export function selfPostureOf(cfg) {
|
|
71
|
+
return cfg.enabled ? (cfg.dryRun ? 'dry-run' : 'live') : 'dark';
|
|
72
|
+
}
|
|
73
|
+
export class MachineCoherenceSentinel {
|
|
74
|
+
deps;
|
|
75
|
+
cfg;
|
|
76
|
+
lastTickAtMs = 0;
|
|
77
|
+
ticks = 0;
|
|
78
|
+
errors = 0;
|
|
79
|
+
/** Post-boot warm-up accounting (N8): ticks completed since construction. */
|
|
80
|
+
ticksSinceBoot = 0;
|
|
81
|
+
lastClassified = [];
|
|
82
|
+
lastRegisteredOnline = 0;
|
|
83
|
+
lastRaiser = null;
|
|
84
|
+
lastCandidates = [];
|
|
85
|
+
/** §3.3 confirmation engine: per-row consecutive-tick + grace-clock state. */
|
|
86
|
+
rowState = new Map();
|
|
87
|
+
/** The row identities present LAST tick (R2-L3 consecutive detection). */
|
|
88
|
+
lastTickRowIds = new Set();
|
|
89
|
+
/** Cumulative count of confirmation transitions (never decremented). */
|
|
90
|
+
skewsConfirmed = 0;
|
|
91
|
+
/** The §4 episode machinery (constructed only when a stateDir is provided). */
|
|
92
|
+
episode;
|
|
93
|
+
/** Effects the last tick produced, awaiting execution by the caller (server). */
|
|
94
|
+
pendingEffects = [];
|
|
95
|
+
constructor(deps, cfg) {
|
|
96
|
+
this.deps = deps;
|
|
97
|
+
this.cfg = cfg;
|
|
98
|
+
const dir = this.deps.stateDir?.() ?? null;
|
|
99
|
+
if (dir)
|
|
100
|
+
this.episode = new MachineCoherenceEpisodeManager(dir, cfg);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Drain the effects the last reconcile produced (raise/append/resolve). The
|
|
104
|
+
* caller (server) executes them against the telegram adapter, keeping the
|
|
105
|
+
* sentinel Tier-0 and its tick synchronous. Empty on a dark/no-episode agent.
|
|
106
|
+
*/
|
|
107
|
+
drainPendingEffects() {
|
|
108
|
+
const out = this.pendingEffects;
|
|
109
|
+
this.pendingEffects = [];
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
/** Passthrough for the conversational reply path (b3): the durable "leave it" ack. */
|
|
113
|
+
setOperatorAck(ack) {
|
|
114
|
+
this.episode?.setOperatorAck(ack);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Operator "fix it" approval passthrough (§4.2.1-i). The caller (conversational
|
|
118
|
+
* reply path) has verified the sender is the topic's VERIFIED operator (Know
|
|
119
|
+
* Your Principal) and passes `verifiedOperator`; `proposalHash` is the display-
|
|
120
|
+
* integrity authority. Returns the transition + any effects (an `execute-fix`
|
|
121
|
+
* for the divergent==raiser case) the caller executes immediately. A dark/
|
|
122
|
+
* unwired guard is a no-op refusal.
|
|
123
|
+
*/
|
|
124
|
+
approveFix(args) {
|
|
125
|
+
if (!this.episode)
|
|
126
|
+
return { result: { ok: false, reason: 'guard-not-active' }, effects: [] };
|
|
127
|
+
return this.episode.approveFix({ proposalHash: args.proposalHash, verifiedOperator: args.verifiedOperator, now: args.now ?? (this.deps.now ?? Date.now)() });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether this tick is still inside the N8 post-boot warm-up window:
|
|
131
|
+
* `MachinePoolRegistry` is in-memory, so a local restart wipes every peer's
|
|
132
|
+
* advert until the next 30s pull — for `warmupTicks` after boot,
|
|
133
|
+
* `unknown`/`advert-stale` classifications must count toward NOTHING (no
|
|
134
|
+
* confirmation progress, no version-class grace clock). The classification
|
|
135
|
+
* itself still runs (the status snapshot stays honest); the CONSUMERS of
|
|
136
|
+
* warm-up (confirmation counters, Session B) read this flag.
|
|
137
|
+
*/
|
|
138
|
+
inWarmup() {
|
|
139
|
+
return this.ticksSinceBoot < this.cfg.warmupTicks;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* One evaluator tick (rides the existing 30s peerPresenceTick — no timer of
|
|
143
|
+
* its own). Runs only when the guard resolves live or dry-run; the caller
|
|
144
|
+
* owns the gate (a dark guard never constructs/ticks the sentinel). Fails
|
|
145
|
+
* toward silence: any error increments the error counter and emits nothing.
|
|
146
|
+
*/
|
|
147
|
+
tick() {
|
|
148
|
+
this.ticks += 1;
|
|
149
|
+
this.ticksSinceBoot += 1;
|
|
150
|
+
const nowMs = (this.deps.now ?? Date.now)();
|
|
151
|
+
this.lastTickAtMs = nowMs;
|
|
152
|
+
try {
|
|
153
|
+
const self = this.deps.selfMachineId();
|
|
154
|
+
const online = this.deps.listCapacities().filter((c) => c.online);
|
|
155
|
+
this.lastRegisteredOnline = online.length;
|
|
156
|
+
// Single-machine strict no-op (§3.3): the comparison set is {self} —
|
|
157
|
+
// short-circuit at fewer than 2 members BEFORE any state is touched.
|
|
158
|
+
if (online.length < 2 || self === null) {
|
|
159
|
+
this.lastClassified = [];
|
|
160
|
+
this.lastRaiser = null;
|
|
161
|
+
this.lastCandidates = [];
|
|
162
|
+
// Below 2 comparable members → no divergence is possible; the whole
|
|
163
|
+
// confirmation engine resets (R2-L3: every row's participants dropped).
|
|
164
|
+
this.rowState.clear();
|
|
165
|
+
this.lastTickRowIds = new Set();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Per-machine classification (M11 universe honesty: every ONLINE machine
|
|
169
|
+
// is accounted — one that cannot be compared classifies `unknown`/
|
|
170
|
+
// `advert-stale`/`advert-rejected`, surfaced, never silently coherent).
|
|
171
|
+
this.lastClassified = online.map((c) => classifyPeer(c, nowMs, this.cfg.advertStaleMs));
|
|
172
|
+
// §3.4 election: candidates are the machines whose guard posture reads
|
|
173
|
+
// 'live'. Self's posture is known LOCALLY (resolved config — authoritative
|
|
174
|
+
// over our own possibly-stale advert echo); peers' via their adverts.
|
|
175
|
+
const selfLive = selfPostureOf(this.cfg) === 'live';
|
|
176
|
+
const candidates = this.lastClassified
|
|
177
|
+
.filter((p) => (p.machineId === self ? selfLive : p.advert?.guard === 'live'))
|
|
178
|
+
.map((p) => p.machineId);
|
|
179
|
+
this.lastCandidates = candidates;
|
|
180
|
+
this.lastRaiser = electRaiser(candidates, this.deps.leaseHolderMachineId());
|
|
181
|
+
// ── §3.3 dimension comparison + confirmation counters (R2-L3, M6) ──
|
|
182
|
+
this.updateConfirmation(nowMs);
|
|
183
|
+
// ── §4 episode reconcile (when the durable machinery is wired) ──
|
|
184
|
+
if (this.episode && !this.inWarmup()) {
|
|
185
|
+
const online = new Set(this.lastClassified.map((p) => p.machineId));
|
|
186
|
+
const compared = new Set(this.lastClassified.filter((p) => p.cls === 'compared').map((p) => p.machineId));
|
|
187
|
+
const nick = this.deps.nicknameOf ?? ((m) => m);
|
|
188
|
+
const effects = this.episode.reconcile({
|
|
189
|
+
confirmedRows: this.confirmedSkewRows(),
|
|
190
|
+
comparedMachineIds: compared,
|
|
191
|
+
onlineMachineIds: online,
|
|
192
|
+
selfMachineId: self,
|
|
193
|
+
raiserMachineId: this.lastRaiser,
|
|
194
|
+
leaseHolderMachineId: this.deps.leaseHolderMachineId(),
|
|
195
|
+
nicknameOf: nick,
|
|
196
|
+
now: nowMs,
|
|
197
|
+
});
|
|
198
|
+
const expiries = this.episode.expireIfStale(nowMs, nick);
|
|
199
|
+
this.pendingEffects.push(...effects, ...expiries);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Fail toward silence (§3.3): no emit, a visible error counter. The
|
|
204
|
+
// confirmation state is LEFT INTACT on an error tick (a transient pool-read
|
|
205
|
+
// fault must not fabricate a participant-drop reset); the next clean tick
|
|
206
|
+
// recomputes over fresh data.
|
|
207
|
+
this.errors += 1;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* §3.3 confirmation engine (R2-L3 consecutive rule + M6 update-wave
|
|
212
|
+
* suppression). Runs over the CURRENTLY-`compared` machines (self included —
|
|
213
|
+
* self records its own advert every beat), turns the raw per-tick divergences
|
|
214
|
+
* into confirmed rows, and never raises anything (the episode/alarm machinery
|
|
215
|
+
* is Session B). Pure state transitions; the caller owns fail-toward-silence.
|
|
216
|
+
*
|
|
217
|
+
* The consecutive rule (R2-L3): a row's confirmation counts ONLY ticks in which
|
|
218
|
+
* the row's identity (which encodes every participant's clamped value) is
|
|
219
|
+
* present. Because a participant dropping out (offline / unknown / advert-stale)
|
|
220
|
+
* either vanishes the identity or changes it, the old identity leaves
|
|
221
|
+
* `currentIds`, its counter is dropped, and a re-appearance starts fresh at 1 —
|
|
222
|
+
* one flapping reading can never accumulate toward confirmation.
|
|
223
|
+
*
|
|
224
|
+
* M6 update-wave suppression: FLAG rows are suppressed while ANY version skew
|
|
225
|
+
* exists among the compared machines (a differing version OR an open patch-only
|
|
226
|
+
* grace window — an update that changes a flag's resolved default would else
|
|
227
|
+
* alarm HIGH mid-wave and auto-resolve). Once every version agrees, residual
|
|
228
|
+
* flag skew confirms normally.
|
|
229
|
+
*/
|
|
230
|
+
updateConfirmation(nowMs) {
|
|
231
|
+
const compared = this.lastClassified
|
|
232
|
+
.filter((p) => p.cls === 'compared' && !!p.advert)
|
|
233
|
+
.map((p) => ({ machineId: p.machineId, advert: p.advert }));
|
|
234
|
+
let rows = computeDivergentRows(compared);
|
|
235
|
+
// M6: suppress FLAG rows while a version skew (differing version or open
|
|
236
|
+
// grace) is present among the compared machines.
|
|
237
|
+
const hasVersionSkew = new Set(compared.map((c) => c.advert.instarVersion)).size > 1;
|
|
238
|
+
if (hasVersionSkew)
|
|
239
|
+
rows = rows.filter((r) => r.dimension !== 'flag');
|
|
240
|
+
const currentIds = new Set(rows.map((r) => r.identity));
|
|
241
|
+
// Increment consecutive counters for rows present this tick; a row whose
|
|
242
|
+
// identity was NOT present last tick (re)starts at 1 with a fresh grace clock.
|
|
243
|
+
for (const r of rows) {
|
|
244
|
+
const existing = this.rowState.get(r.identity);
|
|
245
|
+
if (existing && this.lastTickRowIds.has(r.identity)) {
|
|
246
|
+
existing.consecutiveTicks += 1;
|
|
247
|
+
existing.row = r; // refresh the row snapshot (nicknames etc. are not in the identity)
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.rowState.set(r.identity, { dimension: r.dimension, row: r, consecutiveTicks: 1, firstSeenAtMs: nowMs, confirmed: false });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Drop rows that vanished this tick (R2-L3 reset — a participant left the set,
|
|
254
|
+
// the pair equalized, or M6 suppressed a flag row): their counter is gone.
|
|
255
|
+
for (const id of [...this.rowState.keys()]) {
|
|
256
|
+
if (!currentIds.has(id))
|
|
257
|
+
this.rowState.delete(id);
|
|
258
|
+
}
|
|
259
|
+
// Confirmation predicate per dimension.
|
|
260
|
+
for (const st of this.rowState.values()) {
|
|
261
|
+
if (st.confirmed)
|
|
262
|
+
continue;
|
|
263
|
+
const doConfirm = st.dimension === 'version' && st.row.versionSeverity === 'patch-only'
|
|
264
|
+
// Patch-only version skew: confirmed after versionSkewGraceMs of
|
|
265
|
+
// CONTINUOUS skew (a normal rolling update would else cry wolf).
|
|
266
|
+
? nowMs - st.firstSeenAtMs >= this.cfg.versionSkewGraceMs
|
|
267
|
+
// flag / major-minor version / manifest-class / protocol: N consecutive ticks.
|
|
268
|
+
: st.consecutiveTicks >= this.cfg.flagConfirmTicks;
|
|
269
|
+
if (doConfirm) {
|
|
270
|
+
st.confirmed = true;
|
|
271
|
+
this.skewsConfirmed += 1;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
this.lastTickRowIds = currentIds;
|
|
275
|
+
}
|
|
276
|
+
/** The currently-confirmed skew rows (C₁b-ii — Session B's episode machinery
|
|
277
|
+
* consumes these; the status route exposes their count). Pure read. */
|
|
278
|
+
confirmedSkewRows() {
|
|
279
|
+
return [...this.rowState.values()].filter((s) => s.confirmed).map((s) => s.row);
|
|
280
|
+
}
|
|
281
|
+
/** The rows still accruing consecutive ticks (divergent, not yet confirmed). */
|
|
282
|
+
pendingSkewRows() {
|
|
283
|
+
return [...this.rowState.values()].filter((s) => !s.confirmed).map((s) => s.row);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* The GuardRegistry runtime getter (GUARD-POSTURE-ENDPOINT-SPEC §2.1): a
|
|
287
|
+
* synchronous in-memory read the /guards endpoint snapshots per request.
|
|
288
|
+
* `expectRuntime:true` on the GUARD_MANIFEST entry requires the C₁b server-boot
|
|
289
|
+
* wiring to register THIS at boot. `enabled`/`dryRun` come from the resolved
|
|
290
|
+
* config; `lastTickAt` drives the on-stale grading (a constructed-but-never-
|
|
291
|
+
* ticking guard reads stale, never "on"). Pure — never mutates.
|
|
292
|
+
*/
|
|
293
|
+
guardStatus() {
|
|
294
|
+
return { enabled: this.cfg.enabled, dryRun: this.cfg.dryRun, lastTickAt: this.lastTickAtMs };
|
|
295
|
+
}
|
|
296
|
+
/** The §6 status snapshot (pure read — never mutates). */
|
|
297
|
+
status() {
|
|
298
|
+
const counts = { compared: 0, unknown: 0, advertStale: 0, advertRejected: 0 };
|
|
299
|
+
for (const p of this.lastClassified) {
|
|
300
|
+
if (p.cls === 'compared')
|
|
301
|
+
counts.compared += 1;
|
|
302
|
+
else if (p.cls === 'unknown')
|
|
303
|
+
counts.unknown += 1;
|
|
304
|
+
else if (p.cls === 'advert-stale')
|
|
305
|
+
counts.advertStale += 1;
|
|
306
|
+
else
|
|
307
|
+
counts.advertRejected += 1;
|
|
308
|
+
}
|
|
309
|
+
const self = this.deps.selfMachineId();
|
|
310
|
+
// Self is always comparable (§3.3): a below-2 pool reports compared=1.
|
|
311
|
+
const machinesCompared = this.lastClassified.length === 0 ? (self !== null ? 1 : 0) : counts.compared;
|
|
312
|
+
return {
|
|
313
|
+
enabled: this.cfg.enabled,
|
|
314
|
+
dryRun: this.cfg.dryRun,
|
|
315
|
+
lastTickAt: this.lastTickAtMs ? new Date(this.lastTickAtMs).toISOString() : null,
|
|
316
|
+
machinesRegisteredOnline: this.lastRegisteredOnline,
|
|
317
|
+
machinesCompared,
|
|
318
|
+
peerClassifications: counts,
|
|
319
|
+
raiser: {
|
|
320
|
+
machineId: this.lastRaiser,
|
|
321
|
+
isSelf: this.lastRaiser !== null && this.lastRaiser === self,
|
|
322
|
+
candidates: [...this.lastCandidates],
|
|
323
|
+
},
|
|
324
|
+
openEpisode: this.episode?.status().openEpisode ?? null,
|
|
325
|
+
episodeCounters: this.episode?.status().counters,
|
|
326
|
+
counters: {
|
|
327
|
+
ticks: this.ticks,
|
|
328
|
+
skewsConfirmed: this.skewsConfirmed,
|
|
329
|
+
confirmedRows: this.confirmedSkewRows().length,
|
|
330
|
+
pendingRows: this.pendingSkewRows().length,
|
|
331
|
+
errors: this.errors,
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=MachineCoherenceSentinel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MachineCoherenceSentinel.js","sourceRoot":"","sources":["../../src/monitoring/MachineCoherenceSentinel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardManifest.d.ts","sourceRoot":"","sources":["../../src/monitoring/guardManifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,SAAS,CAAC;IAChB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;qFAEiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;wEACoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB;;;;2DAIuD;IACvD,aAAa,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB;4EACwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;wFACoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;qFACiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;oFAEgF;IAChF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,
|
|
1
|
+
{"version":3,"file":"guardManifest.d.ts","sourceRoot":"","sources":["../../src/monitoring/guardManifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,SAAS,CAAC;IAChB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;qFAEiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;wEACoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB;;;;2DAIuD;IACvD,aAAa,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB;4EACwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;wFACoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;qFACiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;oFAEgF;IAChF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,EAg1B9C,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,cAAc,EAiFvC,CAAC;AAEX,qFAAqF;AACrF,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAI/D;AAED,wBAAgB,kBAAkB,IAAI,GAAG,CAAC,MAAM,CAAC,CAIhD;AAED,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,CAAC,CAEjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,GAAE,SAAS,kBAAkB,EAAmB,GACvD,MAAM,EAAE,CAgBV"}
|
|
@@ -386,6 +386,31 @@ export const GUARD_MANIFEST = [
|
|
|
386
386
|
component: 'AgentWorktreeReaper',
|
|
387
387
|
description: 'Reclaims merged+clean+unused agent worktrees.',
|
|
388
388
|
},
|
|
389
|
+
{
|
|
390
|
+
// Machine-coherence guard (machine-coherence-guard §6/§7, roadmap 4.1
|
|
391
|
+
// F4/P0-1). `enabled` is deliberately OMITTED from ConfigDefaults — the
|
|
392
|
+
// runtime resolves it through the developmentAgent dark-feature gate (dark
|
|
393
|
+
// on the fleet, live on a dev agent; dry-run first). defaultEnabled:false
|
|
394
|
+
// reflects the fleet default. expectRuntime:true — increment C₁b-i adds the
|
|
395
|
+
// server-boot construction + guardRegistry.register('monitoring.machineCoherence.enabled')
|
|
396
|
+
// callsite on the peerPresenceTick path, registered ONLY when the gate
|
|
397
|
+
// resolves enabled. The `missing` classification requires configEnabled===true
|
|
398
|
+
// (guardPostureView §precedence), so a dark fleet agent (gate → false) never
|
|
399
|
+
// constructs, never registers, and is never falsely graded `missing` — the
|
|
400
|
+
// ws13Reconcile/holdForStability expectRuntime:true precedent.
|
|
401
|
+
// NOT loadBearing (Frontloaded Decision D6): signal-only, no critical path
|
|
402
|
+
// consumes it yet, and loadBearing:true would raise G3 gap alarms on every
|
|
403
|
+
// fleet agent where the guard is deliberately dark.
|
|
404
|
+
key: 'monitoring.machineCoherence.enabled',
|
|
405
|
+
kind: 'config',
|
|
406
|
+
configPath: 'monitoring.machineCoherence.enabled',
|
|
407
|
+
defaultEnabled: false,
|
|
408
|
+
expectedTickMs: 30_000,
|
|
409
|
+
process: 'server',
|
|
410
|
+
expectRuntime: true,
|
|
411
|
+
component: 'MachineCoherenceSentinel',
|
|
412
|
+
description: 'Machine-coherence guard evaluator: compares version/resolved-flag/protocol/manifest across the agent\'s own ONLINE machines (the F4 skew class) and will raise ONE episode-scoped attention item from exactly ONE elected machine. Signal-only; MUTATES NOTHING.',
|
|
413
|
+
},
|
|
389
414
|
{
|
|
390
415
|
// `enabled` is deliberately OMITTED from ConfigDefaults — the runtime resolves
|
|
391
416
|
// it through the developmentAgent dark-feature gate (dark on the fleet, live on
|