instar 1.3.821 → 1.3.823

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.
Files changed (31) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +7 -0
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.js +1 -1
  5. package/dist/config/ConfigDefaults.js.map +1 -1
  6. package/dist/core/CartographerSweepEngine.d.ts +3 -3
  7. package/dist/core/CartographerSweepEngine.d.ts.map +1 -1
  8. package/dist/core/CartographerSweepEngine.js +38 -5
  9. package/dist/core/CartographerSweepEngine.js.map +1 -1
  10. package/dist/core/SafeGitExecutor.d.ts +6 -0
  11. package/dist/core/SafeGitExecutor.d.ts.map +1 -1
  12. package/dist/core/SafeGitExecutor.js +33 -0
  13. package/dist/core/SafeGitExecutor.js.map +1 -1
  14. package/dist/core/cartographerDetect.d.ts +21 -2
  15. package/dist/core/cartographerDetect.d.ts.map +1 -1
  16. package/dist/core/cartographerDetect.js +86 -23
  17. package/dist/core/cartographerDetect.js.map +1 -1
  18. package/dist/core/cartographerDetect.worker.js +19 -6
  19. package/dist/core/cartographerDetect.worker.js.map +1 -1
  20. package/dist/messaging/ColdStartFallbackReply.d.ts +7 -0
  21. package/dist/messaging/ColdStartFallbackReply.d.ts.map +1 -1
  22. package/dist/messaging/ColdStartFallbackReply.js +10 -0
  23. package/dist/messaging/ColdStartFallbackReply.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/data/builtin-manifest.json +2 -2
  26. package/upgrades/1.3.822.md +24 -0
  27. package/upgrades/1.3.823.md +24 -0
  28. package/upgrades/eli16/cartographer-streaming-ls-tree.md +7 -0
  29. package/upgrades/eli16/silent-respawn-collision-notice.md +6 -0
  30. package/upgrades/side-effects/cartographer-streaming-ls-tree.md +80 -0
  31. package/upgrades/side-effects/silent-respawn-collision-notice.md +86 -0
@@ -0,0 +1,24 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ When a Telegram message arrives while a dead session is already being respawned, Instar now tells the user that this particular message was not queued or delivered and asks them to resend it after the restart. This closes the remaining single-machine silent-loss path without adding another queue.
9
+
10
+ ## What to Tell Your User
11
+
12
+ If a message collides with an in-progress session restart, you will now receive an honest resend instruction instead of waiting indefinitely for a message that was never accepted into custody.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - Detects both normal and context-exhaustion respawn collisions.
17
+ - Routes one deterministic custody notice through the existing Telegram topic-send funnel.
18
+ - Preserves sentinel-before-dedup ordering and all existing emergency-stop, pause, and exactly-once behavior.
19
+
20
+ ## Evidence
21
+
22
+ - `tests/unit/respawn-collision-notice.test.ts`
23
+ - `tests/integration/telegram-forward-sentinel-intercept.test.ts`
24
+ - `tests/integration/exactly-once-ingress.test.ts`
@@ -0,0 +1,7 @@
1
+ # Streaming cartographer tree reads — ELI16
2
+
3
+ The cartographer compares its index with Git's view of every file and directory. Previously Git had to finish producing that entire list before Instar could begin reading it, and the complete output lived in one large memory buffer. A sufficiently large repository could exceed that buffer and make the sweep refuse.
4
+
5
+ Instar now reads each piece as Git produces it. Complete NUL-separated records are parsed immediately; only a record split between chunks is carried forward. The resulting path-to-object map has the same records and ordering as before, so candidate selection and authoring behavior do not change.
6
+
7
+ The detector trusts the map only after Git exits successfully. A spawn error, non-zero exit, signal, or incomplete final record rejects the whole partial result through the existing `detect-git-error` refusal path. The work still runs in the established detect worker by default. The old `gitMaxBuffer` setting remains accepted for compatibility but no longer controls this stream.
@@ -0,0 +1,6 @@
1
+ # Silent respawn collision notice — ELI16
2
+
3
+ Imagine a session is broken and Instar is already starting its replacement. If another message arrives during that small window, the old code noticed that a restart was underway and simply returned. The message was neither queued nor delivered, and the user received no warning.
4
+
5
+ Instar now sends a precise notice for that collision: the message was not queued or delivered, so resend it after the restart finishes. The first message still follows the existing durable pending-injection machinery. This change does not invent a second queue and does not alter emergency-stop, pause, or duplicate-message safety ordering.
6
+
@@ -0,0 +1,80 @@
1
+ # Side-Effects Review — Cartographer streaming ls-tree
2
+
3
+ **Version / slug:** `cartographer-streaming-ls-tree`
4
+ **Date:** `2026-07-11`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** `framework_guard_review`
7
+
8
+ ## Summary
9
+
10
+ The cartographer detect module replaces its buffered `git ls-tree` read with a guarded streaming child process and incremental NUL parser. `runDetect` is now asynchronous so both the default worker and the in-process rollback can await subprocess completion. No scaffold writer, index storage, heap ordering, writer ownership, or rollout setting changes.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Git completion — modify — the map is accepted only on clean exit with a fully terminated NUL stream.
15
+ - Git failure — pass-through — every failure shape still becomes `detect-git-error` and feeds the existing breaker.
16
+ - `gitMaxBuffer` — pass-through — accepted and plumbed for config compatibility, intentionally ignored by the streaming reader.
17
+
18
+ ## Over-block / under-block
19
+
20
+ Malformed output with an unterminated last record now refuses rather than accepting an ambiguous tail. Valid empty-tree output remains successful. The parser's carry can grow to one Git path record; the unavoidable output map remains O(tree entries) because downstream status comparison requires it, but there is no second whole-output string or split array.
21
+
22
+ ## Level of abstraction
23
+
24
+ `SafeGitExecutor.readStream` extends the existing guarded Git funnel so classification, source-tree protection, environment scrubbing, and audit behavior are preserved. Incremental record parsing remains in `cartographerDetect`, the owner of ls-tree semantics. The worker boundary remains unchanged and default-on.
25
+
26
+ ## Signal vs authority
27
+
28
+ No new authority is introduced. Git failure remains a named refusal signal consumed by the existing sweep breaker; partial data never reaches candidate selection.
29
+
30
+ ## Judgment-point check
31
+
32
+ No new static heuristic at a competing-signals decision point. Child-process success is an enumerable protocol invariant: clean zero exit, no signal, and complete NUL framing.
33
+
34
+ ## Interactions
35
+
36
+ - Ordering and shape: real-fixture parity freezes the same insertion order and OIDs as the former buffered parser.
37
+ - Backpressure/memory: every stdout chunk is synchronously reduced into complete records; only the current record carry remains between chunks. Stderr capture is capped at 8 KiB.
38
+ - Failure atomicity: the local map is returned only after `close` reports exit code zero and no signal. Mid-stream SIGKILL, non-zero exit, spawn error, and malformed tail reject it.
39
+ - Lifetime: the read-only stream retains the former 30-second subprocess bound and kills on expiry. On worker timeout, the parent requests cooperative child teardown, retains the reported child PID as a fallback, and force-terminates after a 250 ms grace bound.
40
+ - Configuration: `gitMaxBuffer` remains accepted at `ConfigDefaults`, server plumbing, engine config, and `DetectInput`; removing it would be a needless compatibility break.
41
+ - Scope: #1073 items 1 (scaffold writer) and 2 (SQLite/sharding) are untouched and remain open.
42
+
43
+ ## External surfaces
44
+
45
+ The exported `runDetect` helper now returns a Promise; all repository call sites are updated. Runtime output, snapshot schema, candidate ordering, and persistent state are unchanged. No operator action or external API is added. Timing improves for large Git trees because stdout is reduced as it arrives.
46
+
47
+ ## Operator-surface quality
48
+
49
+ No operator surface — not applicable.
50
+
51
+ ## Multi-machine posture
52
+
53
+ Machine-local by design: each machine compares its own checked-out Git tree inside its own detect worker. It emits no user-facing notice, holds no new durable state, strands no topic state, and generates no URL. Existing snapshot behavior is unchanged.
54
+
55
+ ## Rollback
56
+
57
+ Pure code rollback. No persistent schema or state migration is involved. Reverting restores the explicit 64 MiB buffered floor and its refusal-on-overflow behavior.
58
+
59
+ ## Conclusion
60
+
61
+ The transport upgrade is contained to #1073 item 3 and preserves the existing authority, writer, worker, ordering, and configuration contracts. Independent review found the first draft had lost the buffered executor's subprocess timeout and could orphan Git when a worker was terminated; the shared timeout and explicit two-level reap protocol now close that gap.
62
+
63
+ ## Second-pass review
64
+
65
+ **Reviewer:** `framework_guard_review`
66
+ **Independent read:** concur. The revised stream retains bounded subprocess lifetime in both in-process and worker modes; the real-worker reap proof and funnel/stream suites are green.
67
+
68
+ ## Class-Closure Declaration
69
+
70
+ `defectClass: unbounded-self-action`, `closure: n/a` — one bounded kill attempt is tied to a single detect-worker timeout; this adds no autonomous retry, respawn, notification, or recurring control loop.
71
+
72
+ ## Evidence
73
+
74
+ - CI correction: the no-silent-fallbacks heuristic initially counted four
75
+ intentional error-propagation/terminal-state catches. Each is now explicitly
76
+ annotated in place; the baseline remains 492 and the exact ratchet is green.
77
+ - Unit: chunk-edge NUL, a Unicode record split across four chunks, real-tree parity, empty tree, output beyond a one-byte legacy setting, mid-stream SIGKILL refusal, and hung-stream timeout.
78
+ - Funnel: read-only streaming succeeds; destructive use is rejected before spawn.
79
+ - Dist worker: forced timeout against a fake hung Git process proves the pass refuses and the reported OS PID is no longer alive.
80
+ - Existing detect refusal, bounded heap, routes, config, and dist-worker suites remain green.
@@ -0,0 +1,86 @@
1
+ # Side-Effects Review — Silent respawn collision notice
2
+
3
+ **Version / slug:** `silent-respawn-collision-notice`
4
+ **Date:** `2026-07-11`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** framework_guard_review (Banach)
7
+
8
+ ## Summary of the change
9
+
10
+ The two dead-session respawn collision guards in `wireTelegramRouting` no longer return silently. They send a deterministic, honest custody notice through the existing Telegram topic-send funnel before returning. No queue, persistence format, config, or authority surface is added.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Context-exhaustion dead-session respawn collision — modified — sends the loss notice, then preserves the existing return.
15
+ - Ordinary dead-session respawn collision — modified — sends the loss notice, then preserves the existing return.
16
+ - Initial respawn and durable pending-inject paths — pass-through — unchanged.
17
+ - Sentinel kill/pause intercept and exactly-once ingress gate — pass-through — unchanged and remain in their existing order.
18
+
19
+ ---
20
+
21
+ ## 1. Over-block
22
+
23
+ No new block/allow surface exists. The colliding message was already rejected by the active-spawn guard; the change only makes that pre-existing lack of custody visible. The notice does not suppress, deduplicate, pause, or kill any message or session.
24
+
25
+ ## 2. Under-block
26
+
27
+ The notice is dispatched asynchronously through the existing adapter. If Telegram delivery itself fails, the existing adapter failure behavior and error logging apply; this change does not claim external delivery succeeded. It also intentionally does not retry or queue the colliding user message, avoiding duplicate injection into a session whose startup ownership is already in flight.
28
+
29
+ ## 3. Level-of-abstraction fit
30
+
31
+ The collision guard is the only layer that knows the message was refused specifically because another respawn owns the topic. The wording and injectable send helper live beside the existing cold-start fallback reply machinery, keeping user-facing spawn failure notices in one messaging module.
32
+
33
+ ## 4. Signal vs authority compliance
34
+
35
+ Required reference: [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
36
+
37
+ - [x] No — this change has no block/allow surface.
38
+
39
+ The notice is a truthful signal about custody already declined by existing control flow. It creates no authority and makes no semantic inference about the user's message.
40
+
41
+ ## 5. Interactions
42
+
43
+ - **Shadowing:** Both reachable dead-session collision guards receive identical behavior; neither shadows the other.
44
+ - **Double-fire:** Each inbound traverses only one of the mutually exclusive dead-session branches, so at most one notice is attempted.
45
+ - **Races:** The existing `spawningTopics` ownership remains unchanged. The notice does not mutate it or wait on the spawn.
46
+ - **Feedback loops:** The notice asks for an explicit resend after restart; it does not self-trigger another spawn or injection.
47
+
48
+ ## 6. External surfaces
49
+
50
+ Telegram users may see one new message: “I got this message while the session was already restarting, so it was not queued or delivered. Please resend it once the restart finishes.” No dashboard, API, config, schema, URL, or other external surface changes.
51
+
52
+ ## 6b. Operator-surface quality
53
+
54
+ The wording distinguishes receipt by the bridge from custody by the session, states exactly what failed, and gives one concrete recovery action. It does not falsely promise that the message is queued.
55
+
56
+ ## 7. Multi-machine posture
57
+
58
+ Machine-local by design and fully functional with `multiMachine.sessionPool.inboundQueue` dark. It uses the local respawn ownership set and the existing Telegram adapter. No cross-machine state or dark feature is required.
59
+
60
+ ## 8. Rollback cost
61
+
62
+ Pure code rollback: revert the helper, two call sites, tests, and release artifacts. No durable state or data migration requires repair.
63
+
64
+ ## Conclusion
65
+
66
+ Clear to ship. The change closes the reachable silent-loss collision without changing queue semantics or safety authority.
67
+
68
+ ## Second-pass review (required: messaging/information-flow path)
69
+
70
+ **Reviewer:** framework_guard_review (Banach)
71
+ **Independent read:** Concurred after requesting an executable routing regression. The final test holds the first respawn unresolved, drives a second inbound through `wireTelegramRouting`, and proves exactly one loss notice, one spawn total, and zero injection. The reviewer confirmed both production guards preserve the existing return and that `src/server/routes.ts` safety ordering is untouched.
72
+
73
+ ## Evidence pointers
74
+
75
+ - `tests/unit/respawn-collision-notice.test.ts`
76
+ - `tests/unit/cold-start-fallback-reply.test.ts`
77
+ - `tests/unit/cold-start-fallback-wiring.test.ts`
78
+ - `tests/integration/telegram-forward-sentinel-intercept.test.ts`
79
+ - `tests/integration/exactly-once-ingress.test.ts`
80
+ - `tests/unit/no-silent-fallbacks.test.ts`
81
+
82
+ ## Class-Closure Declaration (display-only mirror)
83
+
84
+ - **Defect class:** `unbounded-self-action`
85
+ - **Closure:** `n/a`
86
+ - **Reason:** One-shot user-driven custody notice emitted only when an inbound message collides with an already-running respawn; not a self-triggered loop.