instar 1.3.246 → 1.3.248

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 (32) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +39 -6
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  5. package/dist/core/PostUpdateMigrator.js +15 -1
  6. package/dist/core/PostUpdateMigrator.js.map +1 -1
  7. package/dist/core/RelocationNicknameSet.d.ts +42 -0
  8. package/dist/core/RelocationNicknameSet.d.ts.map +1 -0
  9. package/dist/core/RelocationNicknameSet.js +47 -0
  10. package/dist/core/RelocationNicknameSet.js.map +1 -0
  11. package/dist/core/TopicPlacementDescription.d.ts +46 -0
  12. package/dist/core/TopicPlacementDescription.d.ts.map +1 -0
  13. package/dist/core/TopicPlacementDescription.js +32 -0
  14. package/dist/core/TopicPlacementDescription.js.map +1 -0
  15. package/dist/scaffold/templates.d.ts.map +1 -1
  16. package/dist/scaffold/templates.js +3 -1
  17. package/dist/scaffold/templates.js.map +1 -1
  18. package/dist/server/AgentServer.d.ts +6 -0
  19. package/dist/server/AgentServer.d.ts.map +1 -1
  20. package/dist/server/AgentServer.js +3 -0
  21. package/dist/server/AgentServer.js.map +1 -1
  22. package/dist/server/routes.d.ts +11 -0
  23. package/dist/server/routes.d.ts.map +1 -1
  24. package/dist/server/routes.js +163 -0
  25. package/dist/server/routes.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/data/builtin-manifest.json +64 -64
  28. package/src/scaffold/templates.ts +3 -1
  29. package/upgrades/1.3.247.md +48 -0
  30. package/upgrades/1.3.248.md +46 -0
  31. package/upgrades/side-effects/mm-placement-transfer-robustness.md +45 -0
  32. package/upgrades/side-effects/telegraph-e2e-flake-tolerant.md +58 -0
@@ -0,0 +1,46 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The Telegraph publishing end-to-end test (`tests/e2e/telegraph-publish.test.ts`)
9
+ makes real calls to the live Telegraph API, which occasionally returns transient
10
+ errors (`PAGE_SAVE_FAILED`, network blips, 5xx, rate-limit) through no fault of
11
+ ours. Because the suite runs in the standard CI lane (it only skips when
12
+ `SKIP_E2E=1`), one such hiccup failed the entire build on an unrelated PR — a
13
+ Gemini quota change (#756) that touches zero Telegraph code got a red build
14
+ purely because the Telegraph service blinked at the wrong moment.
15
+
16
+ This change adds a test-local `withTransientRetry` helper wrapping the six
17
+ live-API call sites (`ensureAccount` / `publishPage` / `editPage` /
18
+ `getPageViews`): a transient / network / 5xx / 429 error is retried up to 4× with
19
+ short backoff; a real failure — an assertion-worthy bug, or a persistent outage
20
+ after retries are exhausted — still fails immediately and loudly.
21
+
22
+ ## What to Tell Your User
23
+
24
+ Nothing user-facing — this is an internal CI-reliability fix. No shipped behavior
25
+ changes; agent-only.
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ None — internal test-suite robustness improvement (flaky external-API e2e no
30
+ longer fails CI on unrelated PRs).
31
+
32
+ ## Evidence
33
+
34
+ - **Reproduction:** Codey PR #756 (a Gemini quota-state change touching zero
35
+ Telegraph code) got a red CI build when the live Telegraph API returned a
36
+ transient `PAGE_SAVE_FAILED` during the Unit-Tests node-22 shard. Confirmed via
37
+ `instar dev:ci-failures 756`:
38
+ `✗ src/publishing/TelegraphService.ts:298 Telegraph API error: PAGE_SAVE_FAILED`
39
+ surfacing at `tests/e2e/telegraph-publish.test.ts:102`.
40
+ - **Before:** any transient Telegraph hiccup failed the whole build on unrelated
41
+ PRs — a false failure that blocks merges and sends people chasing a non-bug.
42
+ - **After:** the six live-API calls retry transient errors up to 4×; real
43
+ failures still fail immediately. Verified locally: `tsc --noEmit` clean and all
44
+ 5 e2e tests pass against the live API
45
+ (`npx vitest run tests/e2e/telegraph-publish.test.ts --config vitest.e2e.config.ts`
46
+ → `Tests 5 passed (5)`).
@@ -0,0 +1,45 @@
1
+ # Multi-Machine Placement Observability + Reliable Transfer — Plain-English Overview
2
+
3
+ > The one-line version: an agent (and a user) can now reliably ASK which machine a topic is running on and WHY, and move a topic between machines deterministically — instead of guessing from a hostname and hoping a phrase gets recognized.
4
+
5
+ ## The problem in one breath
6
+
7
+ While testing live topic-transfer on a real laptop↔mini pair, two gaps surfaced. (1) "Move this to <a machine>" worked toward a peer but silently did nothing when moving *back* to the machine currently handling the topic — the command fell through into the session as a normal message. (2) From a standby session there was no way to read where a topic actually runs or why, so the agent inferred placement and stated a guess as fact, confusing the user.
8
+
9
+ ## What already exists
10
+
11
+ - **Session pool routing (§L4)** — the lease-holder polls Telegram and forwards a topic's messages to the machine that owns the session; ownership lives in the SessionOwnership registry, hard pins in the TopicPlacementPinStore (a holder-local file).
12
+ - **"move this to <nickname>" recognizer** — a deterministic recognizer over the known-machine nickname set, fed from `MachinePoolRegistry.getCapacities()`.
13
+ - **GET /pool** — shows machines, nicknames, the lease-holder. It does NOT answer per-topic placement.
14
+
15
+ ## What this adds
16
+
17
+ The root cause of (1): the recognizer's known-nickname set came straight from `getCapacities()`, which can omit a machine's OWN nickname. Because the lifeline forwards inbound to the holder, the relocation check runs on the very machine you're moving back to — so its own nickname being absent made "move to self" unrecognizable. The fix unions the local machine's own nickname (resolved capacities → identity entry → deterministic derive) into the recognizer set.
18
+
19
+ On top of that, two new HTTP surfaces:
20
+
21
+ - **GET /pool/placement?topic=N** — owner machine + nickname, the REASON (`pinned` = deliberate move vs `placed` = load-balanced vs `unowned`), and the lease-holder. Answerable from any machine: a non-holder proxies to the holder, whose pin store is authoritative.
22
+ - **POST /pool/transfer {topic, to}** — a deterministic move that runs the SAME validated planner as the natural-language path (rate-limit, online, already-there checks), without depending on phrasing. A non-holder proxies to the holder.
23
+
24
+ ## The new pieces
25
+
26
+ - **RelocationNicknameSet** (pure) — builds the recognizer's nickname set, unioning the self nickname. Cannot do I/O; fully unit-tested.
27
+ - **TopicPlacementDescription** (pure) — computes the placement answer from already-resolved state + a nickname resolver. No I/O.
28
+ - **Two routes** in the existing pool route group — read-only placement; mutating transfer. Both 503 when the pool is dark/single-machine.
29
+
30
+ ## The safeguards
31
+
32
+ - **Reversibility / blast radius** — the recognizer change is behaviorally identical when the self nickname is already present (the common case); it only ADDS resolution when it was missing. The routes are gated: they 503 unless the pool is wired (dark by default on the fleet), so production agents are unaffected until the pool is enabled.
33
+ - **No new authority** — the transfer route reuses the existing `planTransferByNickname` planner (same rate-limit + offline-confirm gates); it does not invent a new mutation path. Ownership release uses the existing CAS.
34
+ - **Migration parity** — `PostUpdateMigrator` gains an idempotent block that appends the two new capability lines to agents that already have the pool section (guarded by a unique `/pool/placement` marker), and the freshly-injected section includes them for new agents. The CLAUDE.md template is updated in lockstep (Agent Awareness Standard).
35
+ - **Tests** — Tier 1 (12 unit: both pure helpers, incl. the exact regression), Tier 2 (11 integration: both routes over HTTP incl. pinned-vs-placed, 404/409/confirm), Tier 3 (3 e2e: routes alive through the real AgentServer + auth-gated). Full `tsc --noEmit` clean.
36
+
37
+ ## Spec lineage
38
+
39
+ This is §L4 (Session Router / placement + TopicPlacement metadata) and §L5 (Transfer orchestrator) of the approved `docs/specs/MULTI-MACHINE-SESSION-POOL-SPEC.md` — surfacing observability + a deterministic lever over machinery the spec already defines. No new primitives, no new authority.
40
+
41
+ ## CI follow-up (same PR #750)
42
+
43
+ Two CI gates flagged the additive surface; both fixed without behavior change:
44
+ - **Docs Coverage** (`route`/`class` floors): documented the new routes + helper classes (and several related pool/mesh ones) in `site/src/content/docs/architecture/multi-machine-session-pool.md` and `features/multi-machine.md` — real feature docs the area lacked. Both floors back ≥55%.
45
+ - **no-silent-fallbacks ratchet** (457): the proxy/best-effort `catch` blocks added by the two new routes + the self-nickname resolver are annotated `@silent-fallback-ok` with honest justifications (the proxy fallbacks are explicitly labelled in the response or surface a 502; the ownership-release catch is a best-effort optimization the pin already covers). Count back to the 457 baseline — no new genuine silent fallbacks.
@@ -0,0 +1,58 @@
1
+ # Side-Effects Review — Telegraph e2e tolerant of transient external-API errors
2
+
3
+ **Version / slug:** `telegraph-e2e-flake-tolerant`
4
+ **Date:** `2026-06-04`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required`
7
+
8
+ ## Summary of the change
9
+
10
+ `tests/e2e/telegraph-publish.test.ts` makes REAL calls to the public Telegraph
11
+ API. That API intermittently returns transient errors (`PAGE_SAVE_FAILED`,
12
+ network blips, 5xx, rate-limit) under no fault of ours. Because the suite runs
13
+ in the standard CI lane (it only skips when `SKIP_E2E=1`), a transient hiccup
14
+ fails the whole build on UNRELATED PRs — it just failed the Unit-Tests shard on
15
+ Codey PR #756 (a Gemini quota change touching zero Telegraph code).
16
+
17
+ The fix adds a test-local `withTransientRetry(label, fn)` helper and wraps the
18
+ six live-API call sites (`ensureAccount` ×2, `publishPage` ×2, `editPage`,
19
+ `getPageViews`). On a transient/network error it retries up to 4× with linear
20
+ backoff; a non-transient error (real bug / assertion-worthy failure) throws
21
+ immediately; if all retries are exhausted it throws (genuinely-down → fail).
22
+
23
+ ## Decision-point inventory
24
+
25
+ One decision point: `withTransientRetry` classifies a caught error as transient
26
+ (via the `TRANSIENT_API_ERROR` regex) or not. Transient → retry/eventually-fail;
27
+ non-transient → rethrow immediately.
28
+
29
+ ## 1. Over-block
30
+
31
+ **What legitimate failures does this now hide?** None that matter. The regex
32
+ matches only transient external-service signatures (`PAGE_SAVE_FAILED`,
33
+ `ENOTFOUND`/`ECONNRESET`/`ETIMEDOUT`/`EAI_AGAIN`, `socket hang up`,
34
+ `fetch failed`, 5xx, 429). Assertion failures (`expect(...)`) are NOT thrown by
35
+ the wrapped service calls, so real test-logic regressions still fail. A genuine
36
+ persistent API outage still fails the test after the retries are exhausted.
37
+
38
+ ## 2. Under-block
39
+
40
+ **What does it still catch?** Any non-transient error from the service (bad
41
+ auth, a real TelegraphService bug, a 4xx other than 429) rethrows on the first
42
+ attempt — no masking. The retry is scoped to the e2e file only; no production
43
+ code path retries (so the publish-idempotency concern — a retry creating a
44
+ duplicate page — is irrelevant: duplicate test pages are harmless, Telegraph
45
+ pages are free + don't expire, and the assertions check `>= 1`, not an exact
46
+ count).
47
+
48
+ ## 3. Blast radius
49
+
50
+ Test-only: one file, `tests/e2e/telegraph-publish.test.ts`. No `src/` change, no
51
+ production behavior change, no API/schema/config change. The helper is local to
52
+ the file (not exported / not shared).
53
+
54
+ ## 4. Reversibility
55
+
56
+ Fully reversible: revert the one file. No state, no migration, no persisted
57
+ format. Verified locally: `tsc --noEmit` clean and all 5 e2e tests pass against
58
+ the live API.