instar 1.3.490 → 1.3.491
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/dashboard/index.html +30 -0
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +146 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/GuardPostureStore.d.ts +38 -0
- package/dist/core/GuardPostureStore.d.ts.map +1 -0
- package/dist/core/GuardPostureStore.js +87 -0
- package/dist/core/GuardPostureStore.js.map +1 -0
- package/dist/core/MachinePoolRegistry.d.ts +16 -0
- package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
- package/dist/core/MachinePoolRegistry.js +24 -1
- package/dist/core/MachinePoolRegistry.js.map +1 -1
- package/dist/core/PeerPresencePuller.d.ts +9 -0
- package/dist/core/PeerPresencePuller.d.ts.map +1 -1
- package/dist/core/PeerPresencePuller.js +1 -1
- package/dist/core/PeerPresencePuller.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +30 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +29 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/ActiveWorkSilenceSentinel.d.ts +8 -0
- package/dist/monitoring/ActiveWorkSilenceSentinel.d.ts.map +1 -1
- package/dist/monitoring/ActiveWorkSilenceSentinel.js +8 -0
- package/dist/monitoring/ActiveWorkSilenceSentinel.js.map +1 -1
- package/dist/monitoring/ContextWedgeSentinel.d.ts +8 -0
- package/dist/monitoring/ContextWedgeSentinel.d.ts.map +1 -1
- package/dist/monitoring/ContextWedgeSentinel.js +8 -0
- package/dist/monitoring/ContextWedgeSentinel.js.map +1 -1
- package/dist/monitoring/GuardPostureTripwire.d.ts +3 -27
- package/dist/monitoring/GuardPostureTripwire.d.ts.map +1 -1
- package/dist/monitoring/GuardPostureTripwire.js +8 -76
- package/dist/monitoring/GuardPostureTripwire.js.map +1 -1
- package/dist/monitoring/GuardRegistry.d.ts +48 -0
- package/dist/monitoring/GuardRegistry.d.ts.map +1 -0
- package/dist/monitoring/GuardRegistry.js +49 -0
- package/dist/monitoring/GuardRegistry.js.map +1 -0
- package/dist/monitoring/SessionReaper.d.ts +7 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +9 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/SessionWatchdog.d.ts +8 -0
- package/dist/monitoring/SessionWatchdog.d.ts.map +1 -1
- package/dist/monitoring/SessionWatchdog.js +8 -0
- package/dist/monitoring/SessionWatchdog.js.map +1 -1
- package/dist/monitoring/SocketDisconnectSentinel.d.ts +8 -0
- package/dist/monitoring/SocketDisconnectSentinel.d.ts.map +1 -1
- package/dist/monitoring/SocketDisconnectSentinel.js +8 -0
- package/dist/monitoring/SocketDisconnectSentinel.js.map +1 -1
- package/dist/monitoring/guardManifest.d.ts +67 -0
- package/dist/monitoring/guardManifest.d.ts.map +1 -0
- package/dist/monitoring/guardManifest.js +536 -0
- package/dist/monitoring/guardManifest.js.map +1 -0
- package/dist/monitoring/guardPosture.d.ts +77 -0
- package/dist/monitoring/guardPosture.d.ts.map +1 -0
- package/dist/monitoring/guardPosture.js +198 -0
- package/dist/monitoring/guardPosture.js.map +1 -0
- package/dist/monitoring/guardPostureView.d.ts +100 -0
- package/dist/monitoring/guardPostureView.d.ts.map +1 -0
- package/dist/monitoring/guardPostureView.js +294 -0
- package/dist/monitoring/guardPostureView.js.map +1 -0
- package/dist/monitoring/probes/GuardPostureProbe.d.ts +82 -0
- package/dist/monitoring/probes/GuardPostureProbe.d.ts.map +1 -0
- package/dist/monitoring/probes/GuardPostureProbe.js +384 -0
- package/dist/monitoring/probes/GuardPostureProbe.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +9 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts +10 -0
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +12 -0
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/server/AgentServer.d.ts +8 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +11 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/peerUrlGuard.d.ts +35 -0
- package/dist/server/peerUrlGuard.d.ts.map +1 -0
- package/dist/server/peerUrlGuard.js +93 -0
- package/dist/server/peerUrlGuard.js.map +1 -0
- package/dist/server/routes.d.ts +14 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +136 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +3 -2
- package/scripts/lint-guard-manifest.js +264 -0
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/state-coherence-registry.json +54 -18
- package/src/scaffold/templates.ts +9 -0
- package/upgrades/1.3.491.md +37 -0
- package/upgrades/side-effects/guard-posture-endpoint.md +101 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema-note": "Machine form of docs/specs/STATE-COHERENCE-REGISTRY.md (the approved census, census-date 2026-06-05). AUTHORED, NOT build-generated (committed-generated-manifest conflict-loop lesson, COHERENCE-JOURNAL-SPEC
|
|
2
|
+
"$schema-note": "Machine form of docs/specs/STATE-COHERENCE-REGISTRY.md (the approved census, census-date 2026-06-05). AUTHORED, NOT build-generated (committed-generated-manifest conflict-loop lesson, COHERENCE-JOURNAL-SPEC §3.6). One entry per durable state category the census enumerates. Consumed by scripts/lint-state-registry.js: every direct durable-write site targeting a state dir / .instar/ must match an entry's `paths` (or carry an inline `/* state-registry: <category> */` annotation). Fields: category (kebab-case id) | description | scope (machine-local | must-be-coherent | derived-cache | coherent-on-demand) | freshness (real-time | eventual | session-boundary | n/a) | conflictShape (single-writer | append-only | lww | n/a) | transport (git | peer-http | none | deferred) | paths (glob-ish hints) | grandfathered (census marked uncertainty, §4e). New state declares its class here at birth.",
|
|
3
3
|
"version": 1,
|
|
4
4
|
"censusDate": "2026-06-05",
|
|
5
5
|
"sourceDoc": "docs/specs/STATE-COHERENCE-REGISTRY.md",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"category": "pending-pulls",
|
|
21
|
-
"description": "Durable working-set pending-pull ledger - outstanding fetches whose producer was offline/unreachable/revoked/mid-run; re-fired on reappearance/run-stopped (WORKING-SET-HANDOFF-SPEC P2
|
|
21
|
+
"description": "Durable working-set pending-pull ledger - outstanding fetches whose producer was offline/unreachable/revoked/mid-run; re-fired on reappearance/run-stopped (WORKING-SET-HANDOFF-SPEC P2 §3.4). Machine-local: records describe THIS machine's outstanding fetches; single-writer serialized mutate() funnel.",
|
|
22
22
|
"scope": "machine-local",
|
|
23
23
|
"freshness": "live",
|
|
24
24
|
"conflictShape": "single-writer",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"category": "pull-opkeys",
|
|
33
|
-
"description": "Durable (topic,epoch) operation-key window for working-set pull dedupe - restart-proof at-most-once scheduling per move (WORKING-SET-HANDOFF-SPEC P2
|
|
33
|
+
"description": "Durable (topic,epoch) operation-key window for working-set pull dedupe - restart-proof at-most-once scheduling per move (WORKING-SET-HANDOFF-SPEC P2 §3.3). Machine-local, bounded window (200 keys), single-writer (the coordinator).",
|
|
34
34
|
"scope": "machine-local",
|
|
35
35
|
"freshness": "live",
|
|
36
36
|
"conflictShape": "single-writer",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"category": "visibility-guard",
|
|
45
|
-
"description": "Peer-visibility guard dedupe state - which improper revocations were already surfaced (keyed on revokedAt, cross-boot) + per-machine disappearance episodes for flap bounding (WORKING-SET-HANDOFF-SPEC P2
|
|
45
|
+
"description": "Peer-visibility guard dedupe state - which improper revocations were already surfaced (keyed on revokedAt, cross-boot) + per-machine disappearance episodes for flap bounding (WORKING-SET-HANDOFF-SPEC P2 §3.6). Machine-local notice hygiene, never authority.",
|
|
46
46
|
"scope": "machine-local",
|
|
47
47
|
"freshness": "live",
|
|
48
48
|
"conflictShape": "single-writer",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"category": "commitment-replicas",
|
|
69
|
-
"description": "Per-peer read-only replicas of other machines' commitment stores (COMMITMENTS-COHERENCE-SPEC P1.5
|
|
69
|
+
"description": "Per-peer read-only replicas of other machines' commitment stores (COMMITMENTS-COHERENCE-SPEC P1.5 §3.2). Derived cache - rebuilt by a full re-pull; written ONLY by the commitments-sync receive path; first-hop sender-bound; incarnation-fenced.",
|
|
70
70
|
"scope": "derived-cache",
|
|
71
71
|
"freshness": "eventual",
|
|
72
72
|
"conflictShape": "single-writer",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"category": "commitment-pending-mutations",
|
|
81
|
-
"description": "Durable owner-routed mutation intents awaiting an offline owner (COMMITMENTS-COHERENCE-SPEC P1.5
|
|
81
|
+
"description": "Durable owner-routed mutation intents awaiting an offline owner (COMMITMENTS-COHERENCE-SPEC P1.5 §3.4). Stores INTENT only - a FRESH signed envelope is re-issued at fire time; single-writer serialized funnel; per-(origin,id) and per-owner enqueue bounds; TTL 7d with one honest expiry notice.",
|
|
82
82
|
"scope": "machine-local",
|
|
83
83
|
"freshness": "live",
|
|
84
84
|
"conflictShape": "single-writer",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
"category": "commitment-opkeys",
|
|
93
|
-
"description": "Owner-side durable opKey replay window for commitment-mutate (COMMITMENTS-COHERENCE-SPEC P1.5
|
|
93
|
+
"description": "Owner-side durable opKey replay window for commitment-mutate (COMMITMENTS-COHERENCE-SPEC P1.5 §3.4) - the replay control beyond the 60s envelope nonce window; records verdicts, survives restarts, TTL >= pending-mutation TTL.",
|
|
94
94
|
"scope": "machine-local",
|
|
95
95
|
"freshness": "live",
|
|
96
96
|
"conflictShape": "single-writer",
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
"category": "job-definitions",
|
|
249
|
-
"description": "Declarative job definitions (cron / prompt / supervision). The coherent half of jobs.json plus markdown job specs; run state is machine-local (see job-run-state). Field split required before whole-file sync (census
|
|
249
|
+
"description": "Declarative job definitions (cron / prompt / supervision). The coherent half of jobs.json plus markdown job specs; run state is machine-local (see job-run-state). Field split required before whole-file sync (census §5).",
|
|
250
250
|
"scope": "must-be-coherent",
|
|
251
251
|
"freshness": "eventual",
|
|
252
252
|
"conflictShape": "lww",
|
|
@@ -344,7 +344,7 @@
|
|
|
344
344
|
},
|
|
345
345
|
{
|
|
346
346
|
"category": "fleet-config",
|
|
347
|
-
"description": "Fleet-wide config: feature flags, messaging[] config, monitoring tunables, multiMachine policy. SHARES config.json with machine-local fields (port, paths) -- split-required before whole-file sync (census
|
|
347
|
+
"description": "Fleet-wide config: feature flags, messaging[] config, monitoring tunables, multiMachine policy. SHARES config.json with machine-local fields (port, paths) -- split-required before whole-file sync (census §5).",
|
|
348
348
|
"scope": "must-be-coherent",
|
|
349
349
|
"freshness": "eventual",
|
|
350
350
|
"conflictShape": "lww",
|
|
@@ -561,7 +561,7 @@
|
|
|
561
561
|
},
|
|
562
562
|
{
|
|
563
563
|
"category": "audit-destructive-ops",
|
|
564
|
-
"description": "Destructive-ops audit stream (411M live -- needs rotation, census
|
|
564
|
+
"description": "Destructive-ops audit stream (411M live -- needs rotation, census §7). Append-only per-machine.",
|
|
565
565
|
"scope": "machine-local",
|
|
566
566
|
"freshness": "n/a",
|
|
567
567
|
"conflictShape": "append-only",
|
|
@@ -806,7 +806,7 @@
|
|
|
806
806
|
},
|
|
807
807
|
{
|
|
808
808
|
"category": "derived-semantic-memory",
|
|
809
|
-
"description": "semantic.db / memory.db / episodes -- rebuildable from evidence. (Live-disk: stale since Jun 1 -- investigate separately, census
|
|
809
|
+
"description": "semantic.db / memory.db / episodes -- rebuildable from evidence. (Live-disk: stale since Jun 1 -- investigate separately, census §1.6/§7.)",
|
|
810
810
|
"scope": "derived-cache",
|
|
811
811
|
"freshness": "eventual",
|
|
812
812
|
"conflictShape": "n/a",
|
|
@@ -909,7 +909,7 @@
|
|
|
909
909
|
},
|
|
910
910
|
{
|
|
911
911
|
"category": "uncertain-instructions-tracking",
|
|
912
|
-
"description": "state/instructions-tracking/ (59M, 15,180 UUID-keyed JSONL files). Census did not map an owner; volume says it matters. Owner + rotation + class needed (census
|
|
912
|
+
"description": "state/instructions-tracking/ (59M, 15,180 UUID-keyed JSONL files). Census did not map an owner; volume says it matters. Owner + rotation + class needed (census §4e).",
|
|
913
913
|
"scope": "machine-local",
|
|
914
914
|
"freshness": "eventual",
|
|
915
915
|
"conflictShape": "append-only",
|
|
@@ -921,7 +921,7 @@
|
|
|
921
921
|
},
|
|
922
922
|
{
|
|
923
923
|
"category": "uncertain-topic-intent-store",
|
|
924
|
-
"description": "TopicIntentStore. Code references it; on-disk location unverified (census
|
|
924
|
+
"description": "TopicIntentStore. Code references it; on-disk location unverified (census §4e).",
|
|
925
925
|
"scope": "derived-cache",
|
|
926
926
|
"freshness": "eventual",
|
|
927
927
|
"conflictShape": "n/a",
|
|
@@ -934,7 +934,7 @@
|
|
|
934
934
|
},
|
|
935
935
|
{
|
|
936
936
|
"category": "uncertain-shared-state-ledger",
|
|
937
|
-
"description": "shared-state.jsonl (SharedStateLedger). Nominally the git-synced cross-machine ledger -- is anything consuming it on real machines? May be the vestigial ancestor of the P1 journal (census
|
|
937
|
+
"description": "shared-state.jsonl (SharedStateLedger). Nominally the git-synced cross-machine ledger -- is anything consuming it on real machines? May be the vestigial ancestor of the P1 journal (census §4e).",
|
|
938
938
|
"scope": "must-be-coherent",
|
|
939
939
|
"freshness": "eventual",
|
|
940
940
|
"conflictShape": "append-only",
|
|
@@ -947,7 +947,7 @@
|
|
|
947
947
|
},
|
|
948
948
|
{
|
|
949
949
|
"category": "uncertain-correction-capture-backlog",
|
|
950
|
-
"description": "correction-capture-backlog.db vs correction-ledger.db: two stores, one sentinel -- which is canonical? (census
|
|
950
|
+
"description": "correction-capture-backlog.db vs correction-ledger.db: two stores, one sentinel -- which is canonical? (census §4e).",
|
|
951
951
|
"scope": "machine-local",
|
|
952
952
|
"freshness": "eventual",
|
|
953
953
|
"conflictShape": "append-only",
|
|
@@ -959,7 +959,7 @@
|
|
|
959
959
|
},
|
|
960
960
|
{
|
|
961
961
|
"category": "uncertain-project-round-worktrees",
|
|
962
|
-
"description": "ProjectRoundWorktrees / TaskFlow stores. Routes-managed; durable form unverified (census
|
|
962
|
+
"description": "ProjectRoundWorktrees / TaskFlow stores. Routes-managed; durable form unverified (census §4e).",
|
|
963
963
|
"scope": "machine-local",
|
|
964
964
|
"freshness": "eventual",
|
|
965
965
|
"conflictShape": "single-writer",
|
|
@@ -972,7 +972,7 @@
|
|
|
972
972
|
},
|
|
973
973
|
{
|
|
974
974
|
"category": "legacy-singletons",
|
|
975
|
-
"description": "Stale legacy singletons (anti-patterns.json, quick-facts.json, project-registry.json, May 20 vintage, no live writers found). Retire per census
|
|
975
|
+
"description": "Stale legacy singletons (anti-patterns.json, quick-facts.json, project-registry.json, May 20 vintage, no live writers found). Retire per census §7.",
|
|
976
976
|
"scope": "machine-local",
|
|
977
977
|
"freshness": "n/a",
|
|
978
978
|
"conflictShape": "single-writer",
|
|
@@ -998,7 +998,7 @@
|
|
|
998
998
|
},
|
|
999
999
|
{
|
|
1000
1000
|
"category": "stream-tickets",
|
|
1001
|
-
"description": "Pool Dashboard Streaming single-use bearer tickets (POOL-DASHBOARD-STREAM-SPEC
|
|
1001
|
+
"description": "Pool Dashboard Streaming single-use bearer tickets (POOL-DASHBOARD-STREAM-SPEC §2.3). Minted by the pool-stream-ticket mesh verb, consumed once on the /pool-stream WS upgrade. Persisted so a captured ticket cannot replay across a serving-machine restart (consumed-set survives). Machine-local; single-writer (the store's own funnel); TTL-bounded + GC'd.",
|
|
1002
1002
|
"scope": "machine-local",
|
|
1003
1003
|
"freshness": "live",
|
|
1004
1004
|
"conflictShape": "single-writer",
|
|
@@ -1007,6 +1007,42 @@
|
|
|
1007
1007
|
"state/stream-tickets.json"
|
|
1008
1008
|
],
|
|
1009
1009
|
"grandfathered": false
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"category": "guard-posture-snapshot",
|
|
1013
|
+
"description": "Boot-time guard posture snapshot written by the GuardPostureTripwire at every server boot; read by GET /guards for diverged-pending-restart derivation (GUARD-POSTURE-ENDPOINT-SPEC §2.2). Machine-local observability, never authority.",
|
|
1014
|
+
"scope": "machine-local",
|
|
1015
|
+
"freshness": "boot",
|
|
1016
|
+
"conflictShape": "single-writer",
|
|
1017
|
+
"transport": "none",
|
|
1018
|
+
"paths": [
|
|
1019
|
+
"state/guard-posture.json"
|
|
1020
|
+
],
|
|
1021
|
+
"grandfathered": false
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
"category": "guard-posture-peers",
|
|
1025
|
+
"description": "Durable last-known guard posture per peer machine with RECEIVER-side receipt time (GUARD-POSTURE-ENDPOINT-SPEC §2.3(c)) - survives local restarts so a dark peer's posture renders with its honest age. Written only at the heartbeat-ingestion chokepoint (registry-keyed identity). Machine-local observability, never authority.",
|
|
1026
|
+
"scope": "machine-local",
|
|
1027
|
+
"freshness": "live",
|
|
1028
|
+
"conflictShape": "single-writer",
|
|
1029
|
+
"transport": "none",
|
|
1030
|
+
"paths": [
|
|
1031
|
+
"state/guard-posture-peers.json"
|
|
1032
|
+
],
|
|
1033
|
+
"grandfathered": false
|
|
1034
|
+
},
|
|
1035
|
+
{
|
|
1036
|
+
"category": "guard-posture-episodes",
|
|
1037
|
+
"description": "GuardPostureProbe episode state - per-anomaly first/last-seen for the persist-across-ticks rule, flap windows, and the open-episode marker that keeps alerts to ONE aggregated Attention item per episode (GUARD-POSTURE-ENDPOINT-SPEC §2.4). Machine-local notice hygiene, never authority.",
|
|
1038
|
+
"scope": "machine-local",
|
|
1039
|
+
"freshness": "live",
|
|
1040
|
+
"conflictShape": "single-writer",
|
|
1041
|
+
"transport": "none",
|
|
1042
|
+
"paths": [
|
|
1043
|
+
"state/guard-posture-episodes.json"
|
|
1044
|
+
],
|
|
1045
|
+
"grandfathered": false
|
|
1010
1046
|
}
|
|
1011
1047
|
]
|
|
1012
1048
|
}
|
|
@@ -419,6 +419,15 @@ This routes feedback to the Instar maintainers automatically. Valid types: \`bug
|
|
|
419
419
|
- Also: when a session is autonomously shut down, you get a "your session was shut down — <reason>" notice (recovery-bounces and your own operator kills stay silent). Turn the notice off with \`{"monitoring": {"reapNotify": {"enabled": false}}}\`.
|
|
420
420
|
- Proactive: user asks "where did my session go?" / "why did X disappear?" / "did something get killed?" → GET /sessions/reap-log and explain the most recent reaped/skipped entries for that session.
|
|
421
421
|
|
|
422
|
+
### Guard Posture — which safety systems are genuinely on (\`GET /guards\`)
|
|
423
|
+
|
|
424
|
+
Every guard (monitoring sentinels, reapers, the scheduler, …) is graded by what can be VERIFIED, never by what the config wishes: \`on-confirmed\` / \`on-unverified\` / \`on-stale\` / \`on-dry-run\` / \`off\` (\`dark-default\` = ships-dark, quiet vs \`diverged-from-default\` = default-on but currently off — the load-shed signature) / \`diverged-pending-restart\` / \`errored\` / \`missing\` / \`off-runtime-divergent\`. Only the "off that shouldn't be off" and runtime-contradiction classes alert — a ships-dark feature that is off is normal, never noise.
|
|
425
|
+
- This machine: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/guards\`
|
|
426
|
+
- Every machine (heartbeat-fresh, or last-known posture with its age for a dark peer): \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/guards?scope=pool"\`
|
|
427
|
+
- **When to use** (PROACTIVE — this is the trigger): "are my guards on?" / "why didn't the watchdog/reaper fire on machine X?" / a post-incident sweep after ANY load-shed → read \`/guards?scope=pool\` and report the deviant rows instead of guessing from config memory. The Machines dashboard tab shows each machine's last-known posture with its age — even for a peer that is currently dark.
|
|
428
|
+
- **HAZARD — re-enabling a guard via \`PATCH /config\`**: send the guard's FULL config block (the merge is one-level-deep and a partial block erases sibling tuning); read the current block from the source machine first (\`GET /guards\` shows posture; the config block itself comes from that machine's config).
|
|
429
|
+
- Three complementary layers, one shared inventory: the Guard-Posture Tripwire covers enabled→disabled transitions at boot (\`logs/guard-posture.jsonl\`); \`/guards\` is the steady-state read; the GuardPostureProbe raises ONE aggregated Attention item when an anomaly persists across consecutive probes.
|
|
430
|
+
|
|
422
431
|
**Coherence Journal** — The durable "what happened where, and where are the files?" answer for a multi-machine agent. Every machine writes append-only event streams (topic placement + why it moved, session open/close/reap, autonomous runs + their artifact paths); the read API serves a merged view so you answer placement/artifact questions from local disk instead of grepping rotating logs on the right machine.
|
|
423
432
|
- Read it: \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/coherence/journal?topic=N&kind=topic-placement&limit=50"\` → \`{ entries: [...], streams: {...}, skippedCorrupt }\` (+ a partial-result flag when a read bound was hit). Filters: \`topic\`, \`kind\` (\`topic-placement\`|\`session-lifecycle\`|\`autonomous-run\`), \`machine\`, \`limit\`, \`cursor\`. Read-only; 503 when the journal is not enabled on this agent.
|
|
424
433
|
- TRUST NOTE: entries tagged \`source: "replica"\` are another machine's copied history — always a little stale (\`stalenessMs\` says how much). NEVER make a kill/spawn/move decision off journal data; it answers questions, the live systems decide.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: minor -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Implements `docs/specs/GUARD-POSTURE-ENDPOINT-SPEC.md` (converged 5 iterations, operator-approved 2026-06-12, topic 13481 — GAP-001: the Mac Mini's SessionReaper stayed disabled for a week because no API exposed a machine's guard posture).
|
|
9
|
+
|
|
10
|
+
- **`GET /guards`** (Bearer-auth, read-only, always-on — deliberately no config gate): the full guard inventory (shared extractor ∪ declared manifest, one definition shared with the boot tripwire) with verification-graded effective states: `on-confirmed` / `on-unverified` / `on-stale` (dead tick loop — `enabled:true, lastTickAt:0` can never read green again) / `on-dry-run` / `off{dark-default | diverged-from-default}` / `diverged-pending-restart` (disk edit not yet live) / `errored` / `missing` (expected runtime never registered) / `off-runtime-divergent` (runtime contradicts an on-config — the in-memory load-shed class). Strict closed-field projection (sensitive guard config values like `alertTopicId` can never leak; Tier-1 leak tests).
|
|
11
|
+
- **`GET /guards?scope=pool`**: every registered machine accounted for by name — a posture row or a classified failure row (`timeout | unreachable | unauthorized | route-missing | no-known-url | offline | url-rejected | error`), never a silent omission, never a 500. The Bearer token is only attached to https/allowlisted peer URLs (`src/server/peerUrlGuard.ts`, operator-extensible via `multiMachine.peerUrlAllowlist`); non-recursive; rate-limited.
|
|
12
|
+
- **Heartbeat piggyback + durability**: the capacity heartbeat carries a compact posture block, bound to the authenticated sender at ingestion, aged by the RECEIVER's clock, persisted durably (`GuardPostureStore`) and reloaded at boot — a dark peer's last-known posture renders with its real age on the **Machines tab** ("guards: N on (M confirmed) · ⚠ … · as of 2d ago").
|
|
13
|
+
- **GuardPostureProbe** (SystemReviewer family): persisting anomalies (deviant offs, runtime divergence, stale, missing, errored, flapping) raise ONE aggregated, episode-deduped Attention item; dark-default offs stay quiet; offline peers evaluated from durable last-known posture, never a doomed fan-out.
|
|
14
|
+
- **Runtime self-registration**: SessionReaper, JobScheduler, SessionWatchdog, SocketDisconnect/ActiveWorkSilence/ContextWedge sentinels (+ the wedge's autoRecovery sub-row) register cheap sync `guardStatus()` getters into a boot `GuardRegistry`, reconciled against the declared manifest (`src/monitoring/guardManifest.ts` + `NOT_A_GUARD` classifications).
|
|
15
|
+
- **CI ratchet**: `scripts/lint-guard-manifest.js` — every guard-shaped boot component must be classified in the manifest or `NOT_A_GUARD` with a real reason; ships with the complete backfill (a real finding: `WorktreeReaper` is dormant/unwired).
|
|
16
|
+
- **Agent awareness + migration parity**: `generateClaudeMd()` Guards block (including the `PATCH /config` full-block warning — the one-level-deep merge erases sibling tuning) + content-sniffed `migrateClaudeMd()` migration; `/guards` registered in CAPABILITY_INDEX.
|
|
17
|
+
- Remote guard FLIPPING is deliberately out of scope (authority expansion — tracked follow-up spec `GAP-001-remote-guard-flip`).
|
|
18
|
+
|
|
19
|
+
## What to Tell Your User
|
|
20
|
+
|
|
21
|
+
- "You can now see which safety systems are genuinely working on every machine — 'on in the settings' no longer counts as 'working'. The Machines tab shows each machine's guards with honest freshness, and I get one grouped alert if something that should be on stays off."
|
|
22
|
+
|
|
23
|
+
## Summary of New Capabilities
|
|
24
|
+
|
|
25
|
+
| Capability | How to Use |
|
|
26
|
+
|-----------|-----------|
|
|
27
|
+
| Honest guard posture, one machine | `GET /guards` (Bearer) — or ask the agent "are my guards on?" |
|
|
28
|
+
| Fleet-wide posture sweep | `GET /guards?scope=pool` — every machine accounted by name |
|
|
29
|
+
| Dark-peer last-known posture | Machines dashboard tab — posture line with real age |
|
|
30
|
+
| Persisting-anomaly alert | Automatic (GuardPostureProbe → one aggregated Attention item per episode) |
|
|
31
|
+
|
|
32
|
+
## Evidence
|
|
33
|
+
|
|
34
|
+
- Tier-1: `tests/unit/monitoring/guard-posture-view.test.ts` (29 — every precedence-table edge incl. the `lastTickAt:0 → on-stale` Mini pin + projection/leak allowlists), `guard-posture-snapshot.test.ts` (10 — one-disk-read pin, dev-gate resolution), `guard-posture-probe.test.ts` (18 — episode/flap/data-source rules), `peer-url-guard.test.ts` (7), `lint-guard-manifest.test.ts` (11), `PostUpdateMigrator-guardsCapabilitySection.test.ts`.
|
|
35
|
+
- Tier-2: `tests/integration/guards-route.test.ts` (15 — auth pins, classified peer failures over real ephemeral peer servers, token-never-attached on url-rejected, receiver-clock ingestion + durable reload).
|
|
36
|
+
- Tier-3: `tests/e2e/guards-endpoint-lifecycle.test.ts` (17 — feature-alive 200 with the runtime-enrichment floor, disk-flip → `diverged-pending-restart` over real files, HTTP-level leak pin, wired source guards on every server.ts registration).
|
|
37
|
+
- Side-effects artifact: `upgrades/side-effects/guard-posture-endpoint.md` (second-pass reviewed).
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Side-Effects Review — Guard-Posture Endpoint (GET /guards)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `guard-posture-endpoint`
|
|
4
|
+
**Date:** `2026-06-12`
|
|
5
|
+
**Author:** `echo (instar-dev agent)`
|
|
6
|
+
**Second-pass reviewer:** `required (feature has "guard" in its name + touches monitoring surface) — pending, appended below before ship`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Implements the approved converged spec `docs/specs/GUARD-POSTURE-ENDPOINT-SPEC.md`: a read-only, Bearer-authenticated `GET /guards` endpoint reporting every shipped guard's honest effective state (on-confirmed / on-unverified / on-stale / on-dry-run / off{dark-default, diverged-from-default} / diverged-pending-restart / errored / missing / off-runtime-divergent), a static guard manifest + runtime GuardRegistry reconciled at boot, a compact posture block riding the existing capacity heartbeat with durable last-known persistence, a pool-scope fan-out accounting for every registered machine, a GuardPostureProbe raising one episode-deduped Attention item for persisting anomalies, a repo-CI manifest lint with complete component backfill, and the CLAUDE.md template/migration + CAPABILITY_INDEX awareness updates. Files: `src/monitoring/guardPosture.ts` (shared extractor lifted from GuardPostureTripwire — single funnel), `guardManifest.ts`, `GuardRegistry.ts`, `guardPostureView.ts`, `probes/GuardPostureProbe.ts`, routes/boot wiring, heartbeat types/sender/receiver, `scripts/lint-guard-manifest.js`, scaffold template + PostUpdateMigrator, three test tiers.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- `GET /guards` route — **add** — read-only projection; no block/allow decisions on any flow.
|
|
15
|
+
- `GuardPostureProbe` — **add** — detector producing Attention-queue SIGNALS (episode-deduped); takes no action, re-enables nothing.
|
|
16
|
+
- `scope=pool` rate limit — **add** — transport-layer mechanics (anti-amplification), not a judgment decision.
|
|
17
|
+
- `peerUrlGuard` (https/allowlist before Bearer forward) — **add** — hard safety guard on credential egress; refusal is VISIBLE (`url-rejected` failure row), never silent.
|
|
18
|
+
- `GuardPostureTripwire` — **pass-through** — extraction logic moved to the shared module; behavior unchanged (its tests still pass unmodified).
|
|
19
|
+
- Heartbeat ingestion — **modify** — adds a posture block bound to the AUTHENTICATED sender; never a new accept/reject decision.
|
|
20
|
+
|
|
21
|
+
## 1. Over-block
|
|
22
|
+
|
|
23
|
+
No block/allow surface on message or agent-behavior flow. Two narrow rejection surfaces exist and are scoped:
|
|
24
|
+
- The peer-URL allowlist can refuse a LEGITIMATE peer URL if an operator uses an unusual tunnel domain → the peer renders as a named `url-rejected` failure row (visible, diagnosable), and the heartbeat path still carries its posture. Mitigation documented; allowlist is a shared helper so a domain fix lands once.
|
|
25
|
+
- The pool rate limit can briefly defer a rapid sweep — partial results semantics, never a 500.
|
|
26
|
+
|
|
27
|
+
## 2. Under-block
|
|
28
|
+
|
|
29
|
+
- Posture is self-attested telemetry: a compromised machine can report all-confirmed (spec §3(g) accepted; cross-check = deep read vs heartbeat disagreement, which the probe flags).
|
|
30
|
+
- `on-unverified` covers every non-instrumented guard — a crashed non-instrumented guard is indistinguishable from a healthy one (grey, honestly labeled; instrumentation grows over time; the E2E floor pins sessionReaper + scheduler enrichment so the headline guards can't regress to grey).
|
|
31
|
+
- Staleness detection only applies to guards declaring `expectedTickMs` — an event-driven guard with a dead event loop is not detected (stated scope line, spec §2.2).
|
|
32
|
+
|
|
33
|
+
## 3. Level-of-abstraction fit
|
|
34
|
+
|
|
35
|
+
Read surface sits at the route layer over pure derivation modules (`guardPostureView.ts`) — same layering as reap-log/TokenLedger (always-on read-only observability precedent). The extraction lives in ONE shared module consumed by both the tripwire and the endpoint (single-funnel; prevents inventory drift). The probe consumes the same inventory rather than re-deriving. No parallel-to-a-smarter-gate structure exists: nothing here blocks.
|
|
36
|
+
|
|
37
|
+
## 4. Signal vs authority compliance
|
|
38
|
+
|
|
39
|
+
**Reference:** docs/signal-vs-authority.md
|
|
40
|
+
|
|
41
|
+
- [x] No — this change produces signals (posture rows, probe Attention items) consumed by humans/agents; it holds no blocking authority over any flow.
|
|
42
|
+
|
|
43
|
+
The two block-shaped pieces fall in the doc's exempt classes: the rate limit is transport-layer mechanics ("idempotency/transport" class), and the peer-URL allowlist is a hard safety guard on credential egress ("safety guards on irreversible actions" class — sending a Bearer token to a hostile URL is irreversible) whose refusals are visible rows. The spec's §2.5 de-scope keeps the WRITE lever (real authority) out of this change entirely.
|
|
44
|
+
|
|
45
|
+
## 5. Interactions
|
|
46
|
+
|
|
47
|
+
- **Tripwire:** shares the extractor; tripwire behavior unchanged (tests pass unmodified). The endpoint READS the tripwire's boot snapshot (`state/guard-posture.json`) but never writes it — no write race (tripwire writes once at boot).
|
|
48
|
+
- **Heartbeat:** posture block is additive on `MachineCapacity`; older peers ignore unknown fields (verified shape is additive). Ingestion binds to authenticated sender identity — cannot shadow another machine's row (the merge-identity rule both fan-out and heartbeat already follow).
|
|
49
|
+
- **Attention queue:** probe emits through the existing budgeted funnel with a stable `healthKey` (episode dedup) — aggregated single item, P17-compliant; cannot topic-flood (the breaker is upstream of every attention emit).
|
|
50
|
+
- **Double-fire with tripwire:** tripwire alarms on boot TRANSITIONS; probe alarms on persisting STEADY-STATE anomalies. Distinct triggers, complementary by design (spec §2.6); both reference the same inventory so they can't disagree about what a guard is.
|
|
51
|
+
- **No shadowing:** `/guards` adds no middleware ahead of existing checks; Bearer middleware unchanged.
|
|
52
|
+
|
|
53
|
+
## 6. External surfaces
|
|
54
|
+
|
|
55
|
+
- New authenticated API surface (`GET /guards`) — operationally sensitive (attack-timing oracle); contained per spec §3: Bearer-only, never on exemption lists, never on /health//ping/signed-URL surfaces; pool fan-out forwards the token ONLY to https/allowlisted peer URLs. The `scope=pool` rate limit answers 429 when exceeded (transport mechanics); per-guard getter errors surface in-process messages only (never peer/TLS internals — those are enum-normalized in failure rows).
|
|
56
|
+
- Heartbeat payload grows by a few hundred bytes (bounded by manifest size); replicated to operator-paired machines only — accepted, contained exposure (spec §3(f)). The sender computes the block per 30s beat (one disk config read + in-memory inventory build, try/caught; a failed compute omits the block for that beat).
|
|
57
|
+
- TWO new durable machine-local state files (both registered in the State-Coherence Registry + annotated at their write sites, per second-pass review): `state/guard-posture-peers.json` (GuardPostureStore — durable last-known peer posture with receiver-side receipt time) and `state/guard-posture-episodes.json` (GuardPostureProbe episode state). The pre-existing tripwire snapshot `state/guard-posture.json` was registered alongside. The `guardPosture`/`guardPostureReceivedAt` fields are additive on the in-memory/API `MachineCapacity` view only — older readers ignore them.
|
|
58
|
+
- CLAUDE.md template grows a Guards block; existing agents receive it via content-sniffed `migrateClaudeMd()` (Migration Parity); includes the PATCH /config full-block warning (interim hazard containment for the de-scoped write lever).
|
|
59
|
+
- Dashboard Machines tab shows posture summary + age.
|
|
60
|
+
|
|
61
|
+
## 7. Rollback cost
|
|
62
|
+
|
|
63
|
+
Pure code change at the route/probe/dashboard layer: revert and ship a patch. Heartbeat block is additive — peers on the old version ignore it; durable record fields are ignored by old readers (no data migration needed either way). The CLAUDE.md template section requires a removal migration if rolled back (stated in spec §7 — Migration Parity cuts both ways). No agent state repair.
|
|
64
|
+
|
|
65
|
+
## Conclusion
|
|
66
|
+
|
|
67
|
+
The build implements a read-only observability surface whose design center is honesty layering (config-on ≠ working). The review confirms: no brittle logic holds blocking authority; both rejection surfaces are exempt-class with visible refusals; the heaviest risks are information-disclosure-shaped and carry shipping-dependency mitigations (projection allowlist + leak tests, URL allowlist before token forward, sender-bound ingestion). Clear to ship once all three test tiers are green and the second-pass reviewer concurs.
|
|
68
|
+
|
|
69
|
+
## Second-pass review (if required)
|
|
70
|
+
|
|
71
|
+
**Reviewer:** independent reviewer subagent (adversarial audit, 2026-06-12)
|
|
72
|
+
**Independent read of the artifact: concern raised → resolved → concur**
|
|
73
|
+
|
|
74
|
+
Initial verdict raised three concerns, all resolved before ship:
|
|
75
|
+
- *Unregistered durable state files* — `state/guard-posture-peers.json` and `state/guard-posture-episodes.json` were not in the State-Coherence Registry (the lint's documented variable-path blind spot). RESOLVED: both registered + inline `/* state-registry: ... */` annotations at the write sites; the pre-existing tripwire snapshot registered alongside.
|
|
76
|
+
- *§6 wording misdescribed durability* (claimed durable-machine-record fields; actually a separate store file). RESOLVED: §6 corrected to name both files and the in-memory-only capacity fields.
|
|
77
|
+
- *`deepReadPeer` implemented but unwired* (a silent scope reduction). RESOLVED: wired in server.ts — plain `GET /guards` against the peer, token only past the peerUrlGuard, online-peers-with-stale/missing-posture only.
|
|
78
|
+
|
|
79
|
+
Reviewer affirmation on the core questions: "No brittle logic holds blocking authority over message flow, session lifecycle, or dispatch — the only two rejection surfaces are exactly the exempt classes the artifact claims. All §3 shipping dependencies are genuinely implemented AND tested, not just claimed. Once the state-registry registration and the §6 wording fix land, I concur with shipping." Both landed; concurrence stands.
|
|
80
|
+
|
|
81
|
+
## Verification phase (LARGE build, 5 independent reviewers)
|
|
82
|
+
|
|
83
|
+
- **Spec-correctness**: all 8 acceptance criteria VERIFIED with code+test locations; precedence table matches §2.2 exactly. No findings.
|
|
84
|
+
- **Security**: IPv6 private ranges were over-blocked (safe direction) — now granted LAN trust (loopback/ULA/link-local) with boundary tests; redirect-safety rationale documented (Fetch strips Authorization cross-origin — deliberate). All ten threat-model rows verified implemented+tested.
|
|
85
|
+
- **Scalability**: REAL BUG fixed — store write-on-change compared `generatedAt` (always fresh → wrote every beat); now field-wise semantic comparison. Heartbeat posture compute now mtime-caches the resolved-config snapshot (was 2× structuredClone per 30s beat). 90-day TTL bounds the durable store; deep merge depth-capped at 64.
|
|
86
|
+
- **Test-quality**: added getter-invocation wiring spy, route-level one-read pin, async-getter-structurally-unusable pin (the sync-enforcement mechanism behind <100ms), staleness boundary at exactly 5×, dryRun override precedence, snapshot-unavailable+runtime-divergent combination.
|
|
87
|
+
- **Integration/regression**: no blockers; single-machine no-op verified; boot-order/TDZ verified safe. Fixes: first-failure logging for the heartbeat posture compute, explicit pool-not-wired return in deepReadPeer, defensive dashboard math on partial posture blocks.
|
|
88
|
+
|
|
89
|
+
## Evidence pointers
|
|
90
|
+
|
|
91
|
+
- `.instar/state/build/must-haves.md` (truths T1–T18), `threats.md` (STRIDE T-01…T-10), `plan.md`
|
|
92
|
+
- Tier-1: `tests/unit/monitoring/guard-posture-view.test.ts`, `guard-posture-snapshot.test.ts` (48+10 green at step 2)
|
|
93
|
+
- Spec: `docs/specs/GUARD-POSTURE-ENDPOINT-SPEC.md` (approved 2026-06-12, topic 13481)
|
|
94
|
+
|
|
95
|
+
## Addendum — agent-awareness migration collision fix
|
|
96
|
+
|
|
97
|
+
The pool-sessions-visibility CLAUDE.md migration's idempotency sniff was the bare string `scope=pool`; the new Guards section (which mentions `/guards?scope=pool`) would have permanently satisfied it, silently blocking that migration for any agent carrying the Guards block. Tightened to the route-qualified `sessions?scope=pool` with its test updated — found by the awareness-block test pass.
|
|
98
|
+
|
|
99
|
+
## Addendum — CI lint + ratchet compliance
|
|
100
|
+
|
|
101
|
+
`scripts/lint-guard-manifest.js` (+ unit test) wired into the composite lint chain; complete NOT_A_GUARD backfill (33 entries; one real finding: WorktreeReaper has no importer — dormant code, tracked). PrincipalGuard's reason reworded to dodge an llm-attribution-ratchet scanner false positive; the four new guard-path catch blocks carry @silent-fallback-ok justifications (no-silent-fallbacks ratchet stays at baseline).
|