instar 1.3.774 → 1.3.775
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 +95 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +7 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +9 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +175 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/WorkingSetArtifactManager.d.ts +104 -0
- package/dist/core/WorkingSetArtifactManager.d.ts.map +1 -0
- package/dist/core/WorkingSetArtifactManager.js +174 -0
- package/dist/core/WorkingSetArtifactManager.js.map +1 -0
- package/dist/core/WorkingSetArtifactReplicatedStore.d.ts +203 -0
- package/dist/core/WorkingSetArtifactReplicatedStore.d.ts.map +1 -0
- package/dist/core/WorkingSetArtifactReplicatedStore.js +384 -0
- package/dist/core/WorkingSetArtifactReplicatedStore.js.map +1 -0
- package/dist/core/WorkingSetManifest.d.ts +5 -0
- package/dist/core/WorkingSetManifest.d.ts.map +1 -1
- package/dist/core/WorkingSetManifest.js +10 -0
- package/dist/core/WorkingSetManifest.js.map +1 -1
- package/dist/core/WorkingSetPull.d.ts +5 -0
- package/dist/core/WorkingSetPull.d.ts.map +1 -1
- package/dist/core/WorkingSetPull.js +1 -0
- package/dist/core/WorkingSetPull.js.map +1 -1
- package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
- package/dist/core/WriteDomainRegistry.js +12 -0
- package/dist/core/WriteDomainRegistry.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 +7 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +104 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/templates/hooks/settings-template.json +10 -0
- package/upgrades/1.3.775.md +44 -0
- package/upgrades/side-effects/intelligent-working-set-lazy-sync.md +220 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Side-Effects Review — Intelligent Working-Set Lazy-Sync (agent-artifact scope)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `intelligent-working-set-lazy-sync`
|
|
4
|
+
**Date:** `2026-07-05`
|
|
5
|
+
**Author:** Echo (autonomous)
|
|
6
|
+
**Second-pass reviewer:** not required (multi-reviewer spec-converge already ran on the spec, incl. cross-model codex-cli:gpt-5.5)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Adds ONE new source to the existing computed-not-declared working-set engine
|
|
11
|
+
(`WorkingSetManifest.computeWorkingSet`) so that files an agent writes **interactively**
|
|
12
|
+
(a conversational report/analysis under the `.instar/` jail, with no autonomous run) follow a
|
|
13
|
+
conversation across machines — the case the engine misses today (it only sees autonomous-run
|
|
14
|
+
`artifactPaths` + the convention dir). Implementation:
|
|
15
|
+
|
|
16
|
+
- **New WS2 replicated kind `working-set-artifact`** (`WorkingSetArtifactReplicatedStore.ts`) —
|
|
17
|
+
recordKey `sha256(jailedRelPath)+':'+producerMachineId` (NON-path-shaped, survives envelope
|
|
18
|
+
validation); `relPath` carved out of `pathSensitiveFields` with the canonical
|
|
19
|
+
`jailValidateRelPath` receive-validator (relative-only; reject abs/drive/UNC/`..`/NUL/empty,
|
|
20
|
+
length-capped); row states `pendingHash → ready → tooLarge/secretFlagged`; OWNER-ONLY tombstone.
|
|
21
|
+
- **`WorkingSetArtifactManager.ts`** — durable own-origin rows at `.instar/working-set/artifacts.json`
|
|
22
|
+
(atomic tmp+rename); `record`/`setState`/`tombstone`/`getReadyRows`/`getAllRows`/`gc(30d)`.
|
|
23
|
+
- **Dual-registry wiring** — `working-set-artifact` added to `CoherenceJournal.JOURNAL_KINDS` (static
|
|
24
|
+
half, all 7 `Record<JournalKind>` maps) + `server.ts` registers `WORKING_SET_ARTIFACT_KIND_REGISTRATION`
|
|
25
|
+
and builds the union reader + emit seam (dynamic half).
|
|
26
|
+
- **`computeWorkingSet` Source-3** — a new `interactiveArtifactRelPaths` option unions the manager's
|
|
27
|
+
`ready` rows at the serve boundary, through the IDENTICAL jail + secret-scan + caps pipeline.
|
|
28
|
+
- **Recorder** — `POST /coherence/working-set/record` + a built-in PostToolUse Write/Edit hook
|
|
29
|
+
(`working-set-artifact-recorder.js`, fire-and-forget, dark by default) + `migrateHooks`/`migrateSettings`/
|
|
30
|
+
settings-template registration.
|
|
31
|
+
- **Read + grounding** — `GET /coherence/working-set` + `GET /coherence/working-set/session-context`
|
|
32
|
+
(Layer-3 advisory grounding block, `<replicated-untrusted-data>` envelope) injected by the session-start hook.
|
|
33
|
+
- **Config** — `coherenceJournal.workingSet.recordInteractive` (dark) + `recordTtlDays` (30) in ConfigDefaults; boot-time GC.
|
|
34
|
+
|
|
35
|
+
Files: `WorkingSetArtifactReplicatedStore.ts` (new), `WorkingSetArtifactManager.ts` (new),
|
|
36
|
+
`CoherenceJournal.ts`, `WorkingSetManifest.ts`, `WorkingSetPull.ts`, `commands/server.ts`,
|
|
37
|
+
`server/AgentServer.ts`, `server/routes.ts`, `config/ConfigDefaults.ts`, `core/PostUpdateMigrator.ts`,
|
|
38
|
+
`templates/hooks/settings-template.json` + 4 test files (store/manager/wiring/route) + 3 modified tests.
|
|
39
|
+
|
|
40
|
+
## Decision-point inventory
|
|
41
|
+
|
|
42
|
+
This change adds NO block/allow decision point. `jailValidateRelPath` is a data FILTER (rejects an
|
|
43
|
+
unsafe path, fail-clean → null; never a user-facing block). The recorder is signal-only.
|
|
44
|
+
|
|
45
|
+
- `jailValidateRelPath` (`WorkingSetArtifactReplicatedStore.ts`) — **add** — canonical relPath validator
|
|
46
|
+
(record + replication-receive + serve-jail), fail-clean; not an authority.
|
|
47
|
+
- `POST /coherence/working-set/record` — **add** — records interactive artifacts; 503 when unwired, no block surface.
|
|
48
|
+
- `computeWorkingSet` Source-3 — **add** — a new manifest input; the existing jail/scan/caps are the authority.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 1. Over-block
|
|
53
|
+
|
|
54
|
+
No block/allow surface — over-block not applicable. The nearest thing to a "reject" is
|
|
55
|
+
`jailValidateRelPath` returning null for an unsafe path; a legitimate `.instar/`-relative path (e.g.
|
|
56
|
+
`reports/x.md`) is accepted. A file OUTSIDE the `.instar/` jail is deliberately NOT recorded (F10 —
|
|
57
|
+
project files are git-synced), which is scope, not over-block.
|
|
58
|
+
|
|
59
|
+
## 2. Under-block
|
|
60
|
+
|
|
61
|
+
No block/allow surface — under-block not applicable. The honest coverage gaps (by design, not defects):
|
|
62
|
+
the recorder only fires on claude-code (the PostToolUse hook); on non-emitting frameworks the diff-recorder
|
|
63
|
+
is a documented follow-up (F8). A `secretFlagged` file is caught at the serve-boundary hash scan (the
|
|
64
|
+
existing engine authority), not at record — a `pendingHash` row is never a fetch-nominee, so nothing leaks
|
|
65
|
+
before the scan runs.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 3. Level-of-abstraction fit
|
|
70
|
+
|
|
71
|
+
Correct layer. This is a SOURCE feeding an existing engine, not a new engine. The recorder hook is a
|
|
72
|
+
low-level signal (a real tool event) that POSTs to a durable store; the store's `ready` rows FEED the
|
|
73
|
+
existing `computeWorkingSet` authority (which re-jails + re-scans every candidate — defense in depth), which
|
|
74
|
+
FEEDS the existing `WorkingSetPullCoordinator` fetch reflex. No re-implementation: the jail, the 4/16MB/64/32MB
|
|
75
|
+
caps, and the `PendingPullLedger` are all the engine's existing primitives, used verbatim. The replication
|
|
76
|
+
rides the existing WS2 replicated-store machinery (envelope, union reader, emit seam), not a new path.
|
|
77
|
+
|
|
78
|
+
## 4. Signal vs authority compliance
|
|
79
|
+
|
|
80
|
+
- [x] No — this change produces a signal consumed by an existing smart gate / has no block/allow surface.
|
|
81
|
+
|
|
82
|
+
The recorder hook is fire-and-forget signal-only (records metadata; ALWAYS exit(0)). The grounding block is
|
|
83
|
+
ADVISORY (wrapped `<replicated-untrusted-data>`, explicitly "never an instruction"). `jailValidateRelPath` is a
|
|
84
|
+
deterministic data filter with fail-clean semantics, not a brittle detector holding block authority — it
|
|
85
|
+
rejects structurally-unsafe paths (abs/`..`/NUL) where a deterministic rule IS the correct authority (a path
|
|
86
|
+
either escapes the jail or it doesn't; no context/reasoning needed). The serve-boundary hash-verify remains the
|
|
87
|
+
content authority.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 5. Interactions
|
|
92
|
+
|
|
93
|
+
- **Shadowing:** the recorder route + hook are new endpoints; nothing pre-existing shadows them. Source-3 is
|
|
94
|
+
ADDITIVE in `computeWorkingSet` — it `candidates.set`s new entries and dedupes on the canonical path against
|
|
95
|
+
the other two sources (a convention-dir hit and an interactive record for the same file collapse to one entry).
|
|
96
|
+
- **Double-fire:** the manager is a SINGLE hoisted instance shared by the read-side (WorkingSetPullServer), the
|
|
97
|
+
replication emit-side, and the recorder route — so a route-recorded artifact replicates through the SAME emit
|
|
98
|
+
seam (verified: sharing is load-bearing; three separate instances would have left route writes un-replicated).
|
|
99
|
+
- **Races:** the manager persists atomically (tmp+rename). Concurrent PostToolUse fires upsert on
|
|
100
|
+
(topic,relPath,producer) — last-write-wins within a producer row, which is correct (latest hash wins).
|
|
101
|
+
- **Feedback loops:** none. The recorder records; it never triggers a write. Deletes are NOT inferred from a
|
|
102
|
+
write (an editor/temp churn never emits phantom rows) — a delete is only the explicit owner-only tombstone.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 6. External surfaces
|
|
107
|
+
|
|
108
|
+
- **Other agents on the same machine:** none — machine-scoped store + routes.
|
|
109
|
+
- **Install base (Migration Parity):** existing agents get the recorder hook via `migrateHooks` (always-overwrite
|
|
110
|
+
built-in), the settings.json PostToolUse matcher via `migrateSettings` (idempotent), and the config defaults via
|
|
111
|
+
`ConfigDefaults` deepMerge. New installs get all three via the settings template + init. A new PostToolUse hook
|
|
112
|
+
fires per Write/Edit — but it early-exits fast when `recordInteractive` is off (the dark default), so a default
|
|
113
|
+
agent pays only a quick no-op node spawn; noted as the one fleet-wide runtime cost.
|
|
114
|
+
- **External systems:** none (Telegram/Slack/GitHub/Cloudflare untouched). Cross-machine transfer rides the
|
|
115
|
+
existing mesh working-set pull path.
|
|
116
|
+
- **Persistent state:** NEW file `.instar/working-set/artifacts.json` (metadata rows only — never file bodies).
|
|
117
|
+
Bounded by the boot-time GC (30d record TTL) + the engine's fetch caps. Gitignored (under `.instar/`).
|
|
118
|
+
- **Timing/runtime:** the PostToolUse hook adds a bounded (~5s timeout) fire-and-forget POST on Write/Edit when enabled.
|
|
119
|
+
|
|
120
|
+
"No operator-facing actions" — the routes are Bearer-auth API + a session-start grounding block; there is no
|
|
121
|
+
dashboard form, grant/revoke, PIN gate, or secret-drop surface.
|
|
122
|
+
|
|
123
|
+
## 6b. Operator-surface quality
|
|
124
|
+
|
|
125
|
+
No operator surface — not applicable. This change touches no `dashboard/*` renderer/markup, approval page, or
|
|
126
|
+
grant/revoke/secret-drop form. The only human-visible output is the session-start grounding block (an advisory
|
|
127
|
+
context injection, not an interactive operator surface).
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
132
|
+
|
|
133
|
+
**replicated** — this IS a cross-machine feature by design. The `working-set-artifact` rows replicate via the WS2
|
|
134
|
+
coherence-journal kind (the emit seam → journal → peer union reader), and the actual FILES follow the conversation
|
|
135
|
+
via the existing `WorkingSetPullCoordinator` fetch reflex on topic-move. Both halves ship DARK: row replication is
|
|
136
|
+
gated by `multiMachine.stateSync.workingSetArtifact.enabled` (omitted from config ⇒ `resolveStateSyncStores`
|
|
137
|
+
never lists it ⇒ the emitter's `enabled===true` check fails ⇒ strict no-op), and the pull rides
|
|
138
|
+
`coherenceJournal.replication.enabled`. A single-machine agent records + unions locally (Source-3) and simply has
|
|
139
|
+
no peer to replicate to — a strict no-op.
|
|
140
|
+
|
|
141
|
+
- **User-facing notices:** the session-start grounding block is per-session, per-machine context injection (not a
|
|
142
|
+
Telegram send), so no one-voice gating is needed — each machine grounds its own session on the artifacts it can
|
|
143
|
+
serve/knows about.
|
|
144
|
+
- **Durable state on topic transfer:** does NOT strand — the whole point is that the rows replicate + the files are
|
|
145
|
+
fetched by the receiving machine. Owner-only tombstones ensure a delete on the producer erases everywhere; a
|
|
146
|
+
receiver deleting its fetched copy is a machine-local suppression, not a cross-peer delete.
|
|
147
|
+
- **Generated URLs:** none.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 8. Rollback cost
|
|
152
|
+
|
|
153
|
+
- **Hot-fix release:** the whole feature ships dark. Set `coherenceJournal.workingSet.recordInteractive: false`
|
|
154
|
+
(stops recording — already the default) and leave `stateSync.workingSetArtifact` omitted (no replication). To
|
|
155
|
+
fully back out the code: revert the change and ship a patch.
|
|
156
|
+
- **Data migration:** the only persistent state is `.instar/working-set/artifacts.json` (bounded metadata). On
|
|
157
|
+
rollback it is simply orphaned (harmless) or deleted; no schema/column migration, no downtime.
|
|
158
|
+
- **Agent state repair:** none. The migrateHooks/migrateSettings additions are idempotent and inert while dark;
|
|
159
|
+
a reverted release's next migration would stop re-adding them (the recorder hook file would remain but be
|
|
160
|
+
unregistered/never-fired — harmless).
|
|
161
|
+
- **User visibility:** none while dark. No user-visible regression during a rollback window.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Conformance fixes surfaced by full-suite CI (post-first-push)
|
|
166
|
+
|
|
167
|
+
The targeted local test runs were green, but the full CI suite's constitutional-enforcement ratchets
|
|
168
|
+
caught four things the targeted runs did not exercise — each a real, correct requirement that was fixed:
|
|
169
|
+
|
|
170
|
+
- **Write-domain classification** (`write-domain-conformance-ratchet`): `POST /coherence/working-set/record`
|
|
171
|
+
is a mutating route, so it is classified in `WriteDomainRegistry` as `machine-local` with a
|
|
172
|
+
`ws2x-replicated` convergence story (own-origin rows under the git-sync-excluded `.instar/` jail).
|
|
173
|
+
- **Compaction Parity** (`session-context-compaction-parity`): every session-start `/session-context`
|
|
174
|
+
injector must have a compaction-recovery twin. The working-set grounding fetch was wired into
|
|
175
|
+
`getCompactionRecovery()` as well, so the grounding survives a compaction (not just a fresh boot).
|
|
176
|
+
- **No Silent Fallbacks** (`no-silent-fallbacks`): the store/manager's intentional best-effort catches
|
|
177
|
+
(a fire-and-forget replication emit, a corrupt-catalog→empty read, a malformed-percent-encoding→null
|
|
178
|
+
decode) are annotated `@silent-fallback-ok` with their justifications — none is a data-loss fallback.
|
|
179
|
+
- **Dark-gate golden map** (`lint-dev-agent-dark-gate`): the ConfigDefaults insertion shifted four
|
|
180
|
+
`enabled:` line numbers; the hand-authored dotted-path map was updated by hand to match.
|
|
181
|
+
|
|
182
|
+
## Conclusion
|
|
183
|
+
|
|
184
|
+
The review produced no design changes — the spec was already converged (multi-reviewer + cross-model) and the
|
|
185
|
+
build followed it verbatim, grep-verifying each foundation (the computed-not-declared engine, the WS2 replicated-store
|
|
186
|
+
machinery, the built-in-hook + migration infrastructure) before writing. The one load-bearing implementation decision
|
|
187
|
+
surfaced during the build — the manager must be a SINGLE shared instance so route-recorded artifacts replicate through
|
|
188
|
+
the emit seam — was verified and is covered by a wiring test. The feature is additive, jailed to `.instar/`, dark by
|
|
189
|
+
default on both the recording and replication axes, and fully unit + route-integration tested (Tier-1 + Tier-2). The
|
|
190
|
+
Tier-3 cross-machine E2E is an honest named blocker (the Laptop is offline), not a completion gap for the buildable
|
|
191
|
+
slice. Clear to ship dark.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Second-pass review (if required)
|
|
196
|
+
|
|
197
|
+
**Reviewer:** not required
|
|
198
|
+
**Independent read of the artifact: concur**
|
|
199
|
+
|
|
200
|
+
The converged spec (review-convergence + approved, cross-model codex-cli:gpt-5.5 ran clean) already provided the
|
|
201
|
+
multi-angle adversarial read this change's risk class warrants; the build introduced no design deviation from it.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Evidence pointers
|
|
206
|
+
|
|
207
|
+
- 138 unit + route-integration tests green (`working-set-artifact-{store,manager,wiring,route}.test.ts`,
|
|
208
|
+
`WorkingSetManifest.test.ts`, `CoherenceJournal.test.ts`, `generated-hooks-parse.test.ts`, `migration-parity-hooks.test.ts`).
|
|
209
|
+
- `npx tsc --noEmit` exit 0 across all edits.
|
|
210
|
+
- Generated recorder hook passes `node --check`; generated session-start hook passes `bash -n`.
|
|
211
|
+
- Dark-ship verified: `resolveStateSyncStores` is generic (omitted store ⇒ no emit); `recordInteractive` code-default false.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Class-Closure Declaration (display-only mirror)
|
|
216
|
+
|
|
217
|
+
No agent-authored-artifact defect — not applicable. This is a net-new additive feature; it fixes no defect in an
|
|
218
|
+
LLM prompt/hook/config/skill/standards text, and it adds no self-triggered controller in the `unbounded-self-action`
|
|
219
|
+
class (the PostToolUse recorder is fire-and-forget signal-only — it never restarts/swaps/respawns/spawns/notifies/
|
|
220
|
+
retries/kills; the boot-time GC is a one-shot bounded purge, not a loop).
|