instar 1.3.368 → 1.3.370
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 +30 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +3 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +20 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +100 -5
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/JournalSyncApplier.d.ts.map +1 -1
- package/dist/core/JournalSyncApplier.js +16 -0
- package/dist/core/JournalSyncApplier.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/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +27 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/ConversationMeshView.d.ts +50 -0
- package/dist/threadline/ConversationMeshView.d.ts.map +1 -0
- package/dist/threadline/ConversationMeshView.js +78 -0
- package/dist/threadline/ConversationMeshView.js.map +1 -0
- package/dist/threadline/ConversationStore.d.ts +17 -0
- package/dist/threadline/ConversationStore.d.ts.map +1 -1
- package/dist/threadline/ConversationStore.js +52 -0
- package/dist/threadline/ConversationStore.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +4 -0
- package/upgrades/{1.3.368.md → 1.3.369.md} +29 -0
- package/upgrades/1.3.370.md +38 -0
- package/upgrades/side-effects/journal-lock-retry-pin-fallback.md +64 -0
- package/upgrades/side-effects/threadline-conversation-kind-p3.md +83 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Side-Effects Review — journal lock retry + heartbeat (#925) and quiet-topic pin fallback (#926)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `journal-lock-retry-pin-fallback`
|
|
4
|
+
**Date:** `2026-06-06`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (two live-found fixes against converged specs; both bounded; both with regression tests)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Two bugs found by the P2 LIVE two-machine proof (echo pair, v1.3.367):
|
|
11
|
+
|
|
12
|
+
1. **#925 — writer lock wedge.** The restart cascade (3 boots/hour on a
|
|
13
|
+
release day) left the journal writer silently read-only for ~75 min:
|
|
14
|
+
boot-time stale-lock reclaim correctly refused while the old process
|
|
15
|
+
lingered, and the locked-out state had NO retry. Fix: (a) a bounded
|
|
16
|
+
retry timer (max(40×flushInterval, 10s)) re-attempts activation and
|
|
17
|
+
recovers IN PLACE with one log line; (b) the live holder heartbeats the
|
|
18
|
+
lock file mtime every ~40 flushes; (c) reclaim treats an mtime-stale
|
|
19
|
+
(5 min) lock as dead even when its recorded pid "exists" — the
|
|
20
|
+
pid-reuse defense; (d) the autonomous scanner does NOT mark runs seen
|
|
21
|
+
while the writer is locked out, so dropped `started` emits re-emit
|
|
22
|
+
after recovery (op-key dedupe makes re-emits safe).
|
|
23
|
+
2. **#926 — quiet-topic reflex refusal.** Ownership only CASes when
|
|
24
|
+
traffic flows, so a topic just moved (pinned, owner:null) — the exact
|
|
25
|
+
state the fetch reflex exists for — answered not-owner. Fix: the
|
|
26
|
+
ownerOf seam falls back to the placement pin (`pinned &&
|
|
27
|
+
preferredMachine === self` ⇒ self at epoch 0); a real claim bumps past
|
|
28
|
+
epoch 0 and aborts an in-flight pull as superseded (the existing
|
|
29
|
+
recheck, by design). Spec §3.3 delta + eli16 amendment ride along.
|
|
30
|
+
|
|
31
|
+
## Decision-point inventory
|
|
32
|
+
|
|
33
|
+
- Retry cadence bounded (P19): one timer, unref'd, cleared on recovery +
|
|
34
|
+
close; no retry while active.
|
|
35
|
+
- mtime-stale threshold (5 min) vs heartbeat cadence (~10s): 30× margin —
|
|
36
|
+
a paused-but-alive holder (debugger, SIGSTOP) longer than 5 min loses
|
|
37
|
+
the lock deliberately (it wasn't flushing anyway; the new holder's
|
|
38
|
+
'wx' open + the old holder's dead fd keep streams append-consistent).
|
|
39
|
+
- The pin fallback only ever returns SELF (never another machine) and
|
|
40
|
+
only when pinned — an unpinned unowned topic still refuses honestly.
|
|
41
|
+
|
|
42
|
+
## 1-2. Over/Under-block
|
|
43
|
+
|
|
44
|
+
Over: a >5-min-frozen live holder is reclaimed (stated trade). Under:
|
|
45
|
+
two processes could still interleave between mtime check and rm in a
|
|
46
|
+
pathological race — the 'wx' open after rm serializes the winner; the
|
|
47
|
+
loser retries on its timer.
|
|
48
|
+
|
|
49
|
+
## 3. Fit / 4. Blast radius
|
|
50
|
+
|
|
51
|
+
Lock logic stays inside CoherenceJournal (the single owner of the lock
|
|
52
|
+
discipline); the scanner guard is one line at the existing seenRuns
|
|
53
|
+
seam; the pin fallback lives in the server's ownerOf wiring (the seam
|
|
54
|
+
the spec names). Blast radius: journal writer recovery behavior +
|
|
55
|
+
reflex eligibility on pinned-unowned topics; both covered by tests.
|
|
56
|
+
|
|
57
|
+
## Evidence
|
|
58
|
+
|
|
59
|
+
- tests/unit/CoherenceJournal.test.ts — 38 passing (3 new: locked-out
|
|
60
|
+
honored for a fresh live-pid lock; mtime-stale reclaim despite an
|
|
61
|
+
"alive" pid; freed lock acquirable). Full typecheck clean.
|
|
62
|
+
- Live remediation already validated the failure analysis: stale-lock
|
|
63
|
+
removal + restart restored emissions (the 77901 proof artifact
|
|
64
|
+
journaled + replicated to the Mini within one cadence).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline Conversation Coherence build (P3.1 + P3.2 surfaces)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-conversation-kind-p3`
|
|
4
|
+
**Date:** `2026-06-06`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (implements the 2-round-converged P3 spec; a 4th journal kind riding P1's proven transport; content-free by typed schema; read-only view)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
THREADLINE-CONVERSATION-COHERENCE-SPEC (converged 2026-06-06, merged in
|
|
11
|
+
#924) — every machine can answer "which machine holds each A2A
|
|
12
|
+
conversation, and is it bound to a topic?" from local disk:
|
|
13
|
+
|
|
14
|
+
1. The 4th journal kind `threadline-conversation` — the spec's honest
|
|
15
|
+
"compiler-guided multi-site edit" performed in full: JournalKind union,
|
|
16
|
+
JOURNAL_KINDS, 6 Record literals (nextSeq/highWaterSeq/opKeys/retention
|
|
17
|
+
merge/rateBuckets/persistMeta), the typed validate() branch
|
|
18
|
+
(action/conversationId/peerFingerprint/topicId? — free text
|
|
19
|
+
structurally excluded, 256-char id bounds), the opKeyOf branch
|
|
20
|
+
((conversationId, action, topicId?) — conversationId lives in data,
|
|
21
|
+
the round-1 finding), the emitThreadlineConversation emitter, AND the
|
|
22
|
+
JournalSyncApplier.validateData mirror branch (without which the
|
|
23
|
+
receive side suspect-flags the sender). DEFAULT_RETENTION +
|
|
24
|
+
ConfigDefaults literal (8MiB × keep 8; applyDefaults backfills).
|
|
25
|
+
2. ConversationStore: the lifecycle emission as a prev/next TRANSITION
|
|
26
|
+
DIFF inside commit() — the store's single write funnel — on `state` +
|
|
27
|
+
`boundTopicId` ONLY (message appends/lastActivity bumps emit NOTHING);
|
|
28
|
+
terminal set = resolved/failed/archived (the real enum);
|
|
29
|
+
setCoherenceJournalSeam + one wiring line at the store's construction
|
|
30
|
+
(journal in scope; emit drops harmlessly when absent/locked-out).
|
|
31
|
+
3. NEW route GET /threadline/conversations (?scope=mesh) + the
|
|
32
|
+
ConversationMeshView fold: OWN rows from the LIVE store (the
|
|
33
|
+
authority — own-stream journal entries ignored), replica rows folded
|
|
34
|
+
per-stream last-writer on the composite (holderMachineId,
|
|
35
|
+
conversationId) key under the P1 reader's bounds, with staleness +
|
|
36
|
+
streamStatus + partial-result honesty. 200 with own rows when
|
|
37
|
+
replication is dark; 503 only when the store itself is absent.
|
|
38
|
+
4. Agent Awareness on ALL THREE surfaces (template + migrateClaudeMd +
|
|
39
|
+
shadow markers + featureSections tracking): the holder-view trigger
|
|
40
|
+
including the relay's REAL offline bound (in-memory ~24h queue) in the
|
|
41
|
+
honest-answer wording.
|
|
42
|
+
|
|
43
|
+
## Decision-point inventory
|
|
44
|
+
|
|
45
|
+
- Transition derivation: first-commit → started (+bound when born
|
|
46
|
+
bound); boundTopicId change → unbound(old)+bound(new); non-terminal →
|
|
47
|
+
terminal → closed. No fingerprint → no emission (nothing coherent to
|
|
48
|
+
record).
|
|
49
|
+
- The fold's `unbound` clears the binding; `closed` keeps the row with
|
|
50
|
+
status closed (existence stays answerable).
|
|
51
|
+
- Emission failure NEVER reaches the conversation write (observability
|
|
52
|
+
invariant; try/catch at the seam).
|
|
53
|
+
|
|
54
|
+
## 1-2. Over/Under-block
|
|
55
|
+
|
|
56
|
+
Over: conversations without peer fingerprints never journal (deliberate).
|
|
57
|
+
Under: the P1.2 reader reports streamStatus 'current' always — the
|
|
58
|
+
gapped qualifier gains teeth with the P1.3 reader states (the spec's
|
|
59
|
+
named dependency); until then partial-result is the honesty signal.
|
|
60
|
+
|
|
61
|
+
## 3. Fit / 4. Blast radius
|
|
62
|
+
|
|
63
|
+
The kind rides P1's transport/trust wholesale (proven by the integration
|
|
64
|
+
test reusing the journal-sync applier verbatim); the store seam is one
|
|
65
|
+
injected callback; the view is read-only. Emission is always-on with the
|
|
66
|
+
journal (like every kind); REPLICATION of it rides the existing explicit
|
|
67
|
+
gate. A bug can only mis-report holder visibility — nothing actuates off
|
|
68
|
+
this view (Signal vs Authority).
|
|
69
|
+
|
|
70
|
+
## Evidence
|
|
71
|
+
|
|
72
|
+
- tests/unit/ThreadlineConversationKind.test.ts — 7 passing: schema
|
|
73
|
+
bounds + op-key dedupe; the commit() diff matrix (started/bound,
|
|
74
|
+
rebind unbound+bound naming the OLD topic, closed, non-lifecycle
|
|
75
|
+
emits NOTHING, no-fingerprint emits nothing); the fold (own-live +
|
|
76
|
+
replica last-writer + unbound clears + closed status + local scope).
|
|
77
|
+
- tests/integration/threadline-conversation-replication.test.ts — 1
|
|
78
|
+
passing: store lifecycle on A → journal → buildServeBatch → apply on
|
|
79
|
+
B under A's authenticated identity → B's mesh view names A as holder
|
|
80
|
+
with the binding → close converges on the next delta.
|
|
81
|
+
- CoherenceJournal (39 incl. the advert test updated for 4 kinds),
|
|
82
|
+
CoherenceJournalReader, JournalSyncApplier suites green;
|
|
83
|
+
feature-delivery-completeness (81) green. Typecheck clean.
|