instar 1.3.364 → 1.3.366

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.
@@ -0,0 +1,89 @@
1
+ # Side-Effects Review — Working-Set Manifest (P2.1 of multi-machine coherence)
2
+
3
+ **Version / slug:** `working-set-manifest-p21`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required (pure read-only module + reader method; no actuation, no routes, no persistence)`
7
+
8
+ ## Summary of the change
9
+
10
+ P2.1 of the converged WORKING-SET-HANDOFF-SPEC: the pure, on-demand computation
11
+ of "what files make up topic T's workspace on THIS machine". Two pieces:
12
+
13
+ 1. `src/core/WorkingSetManifest.ts` — `computeWorkingSet()`: candidates from the
14
+ filesystem convention (`autonomous/<topic>.*`, bounded readdir) + the topic's
15
+ own-stream journal `artifactPaths`; every candidate compute-time jailed
16
+ (realpath containment + final-component symlink refusal), hashed, scanned for
17
+ credential shapes (reusing the versioned `redactForLiveTail` enum), capped
18
+ (per-file / headline-exempt / maxFiles), and listed with honest flags
19
+ (`tooLarge`, `secretFlagged`, `liveSource`) — never silently skipped.
20
+ 2. `CoherenceJournalReader.readOwnAutonomousRuns(topic, ownMachineId)` — the
21
+ own-stream-only journal evidence source (replicas nominate, they never feed
22
+ this machine's manifest), with `liveRun` derived from the NEWEST run's state.
23
+
24
+ Ships as a pure module: nothing constructs it at boot yet (the P2.2 verb +
25
+ trigger wire it). Zero behavior change for any running agent.
26
+
27
+ ## Decision-point inventory
28
+
29
+ - **Jail verdict** (escape vs contained): mirrored from the P1 write-time jail;
30
+ both the realpathed ancestor AND the final path must sit under
31
+ `[autonomous/, stateDir]`. Jail runs BEFORE existence checks so an
32
+ escape-shaped path is `jailRejected` even when nothing exists at it; only an
33
+ in-jail vanished path counts `goneFromDisk` (benign evolution, never an attack
34
+ log).
35
+ - **Final-component symlink**: refused via lstat on the ORIGINAL path even when
36
+ its target realpaths inside the jail — the manifest must not promise what the
37
+ serve-side `O_NOFOLLOW` will refuse.
38
+ - **liveRun**: the NEWEST runId's first-seen action decides (started→live,
39
+ stopped→not). An older crashed run (started, never stopped) does NOT
40
+ resurrect liveness — newest evidence wins; the §3.4 pending-pull re-fire on
41
+ `stopped` covers the re-arm.
42
+ - **secretFlagged**: scan only what could transfer (tooLarge files never move,
43
+ so they are hashed for disclosure but not scanned).
44
+
45
+ ## 1. Over-block
46
+
47
+ **What legitimate inputs does this change reject?** A symlink whose target is a
48
+ legitimate in-jail file is refused (deliberate — serve-time parity). A topic's
49
+ file larger than its cap is listed-not-transferable (deliberate; headline gets
50
+ the 16MiB exemption + the §3.1 Agent-Health notice lands with P2.2). Files past
51
+ maxFiles=64 are dropped from the manifest with a count — deterministic order
52
+ keeps the headline always inside the cap.
53
+
54
+ ## 2. Under-block
55
+
56
+ **What does this still miss?** The credential-shape scan is a LEAK-REDUCTION
57
+ filter, not a boundary (stated in spec §3.1/§5) — content-shaped secrets pass
58
+ it; acceptable strictly under the same-operator peer posture. `sha256: null`
59
+ above the 64MiB hash ceiling keeps compute bounded at the cost of disclosure
60
+ completeness for absurd files (which never transfer anyway). TOCTOU between
61
+ manifest compute and serve-time read is NOT this module's job — §3.2's
62
+ O_NOFOLLOW + fd-verify at the verb layer (P2.2) is.
63
+
64
+ ## 3. Level-of-abstraction fit
65
+
66
+ **Right layer?** Yes. The manifest is a pure function over (stateDir, topic,
67
+ injected journal evidence) — the reader call happens at the caller so the
68
+ module has no journal dependency; the jail logic mirrors `CoherenceJournal`'s
69
+ write-time jail (same rules at every boundary, P1 invariant). The reader
70
+ method lives on `CoherenceJournalReader` because that is the ONLY module the
71
+ §3.9 actuation-ban lint tracks for journal reads.
72
+
73
+ ## 4. Blast radius
74
+
75
+ Nothing imports either addition yet. No routes, no config, no persistence, no
76
+ hooks, no migrations. A bug here can only mis-list files once P2.2 wires it —
77
+ and the pull layer re-verifies every byte against served hashes.
78
+
79
+ ## Evidence
80
+
81
+ - `tests/unit/WorkingSetManifest.test.ts` — 18 passing: sources+dedupe (incl.
82
+ topic-prefix exactness: 134 never matches 13481), jail matrix (escape,
83
+ final-component symlink, symlinked-parent), caps (tooLarge, headline
84
+ exemption, maxFiles keeps headline), secretFlagged honest listing, mtime
85
+ display-only, liveSource covers ALL live-run entries, reader own-stream-only
86
+ + liveRun semantics + artifactPaths union.
87
+ - `tests/unit/CoherenceJournalReader.test.ts` — 15 passing unchanged (no
88
+ regression from the new method).
89
+ - Full typecheck clean.