instar 1.3.239 → 1.3.240

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,16 @@
1
+ # Enforcing the dogfooded channel — explained simply
2
+
3
+ The apprenticeship rule (just documented) is: a mentor must drive its mentee through
4
+ the REAL Telegram UX (via Playwright), because experiencing the user experience IS the
5
+ test. A shortcut — calling the mentee's CLI directly — gets an answer but skips the
6
+ thing we're actually testing.
7
+
8
+ A doc alone is a wish. This makes it a guarantee: every recorded apprenticeship cycle
9
+ now writes down WHICH channel it actually ran through. And the keystone check — the one
10
+ that tells us the real mentor↔mentee work is happening — only counts a cycle if it ran
11
+ through the real channel (Telegram-Playwright, or the backup). A shortcut cycle is still
12
+ saved (so we're honest it happened), but it does NOT light up the keystone. So a shortcut
13
+ can never make the program look healthier than it is.
14
+
15
+ Older cycles (recorded before this field existed) are grandfathered in — they still
16
+ count, so this never retroactively "un-fires" a keystone we already earned.
@@ -0,0 +1,39 @@
1
+ # Side-Effects Review — Apprenticeship dogfooded-channel enforcement
2
+
3
+ **Slug:** `apprenticeship-channel-enforcement` · **Date:** `2026-06-04` · **Author:** `echo`
4
+ **Second-pass reviewer:** `not required` (additive field + a counting gate; grandfathered)
5
+
6
+ ## Summary
7
+
8
+ Adds a `channel` field to ApprenticeshipCycleStore records (`telegram-playwright` |
9
+ `threadline-backup` | `direct-shortcut` | `unknown`), an idempotent ALTER-TABLE migration
10
+ for existing DBs (default `unknown`), and a `roleCoverage` gate: a
11
+ `mentor-mentee-differential` cycle on `direct-shortcut` is recorded but does NOT count
12
+ toward the keystone axis (surfaced via a new `shortcutDifferentialCount`). Enforces the
13
+ §4a dogfooded-channel standard in code.
14
+
15
+ ## Decision-point inventory
16
+
17
+ One new branch in `roleCoverage`: a mentor-mentee-differential cycle is skipped from axis
18
+ tallying iff `channel === 'direct-shortcut'`. Covered both-sides (dogfooded fires; shortcut
19
+ doesn't + increments the counter; grandfathered/backup fire).
20
+
21
+ ## 1. Over-block
22
+
23
+ Rejects nothing. Garbage/unset channels normalize to `unknown`, which COUNTS (grandfathered)
24
+ — so it never retroactively un-fires an earned keystone (cycle #4, recorded pre-field, holds).
25
+ Only an EXPLICIT `direct-shortcut` is gated, and even then the cycle is still stored + listed.
26
+
27
+ ## 2. Under-block
28
+
29
+ The mentor tick (#743) records cycles without setting `channel` → they default to `unknown`
30
+ → count. That is intentionally grandfathered for now; aligning the automated tick to set
31
+ `direct-shortcut` (or to drive via Playwright, the real fix) is the follow-on once Codey's
32
+ Playwright driving capability exists. The gate is per-axis-tally; it does not retro-rewrite
33
+ stored rows.
34
+
35
+ ## 3. Level-of-abstraction fit
36
+
37
+ Right layer: the enforcement lives in the cycle store's `roleCoverage` (the single place the
38
+ keystone is computed), reusing the existing axis-tally loop. No route/server change — the
39
+ existing `GET /apprenticeship/instances/:id/role-coverage` surfaces the new field for free.
@@ -0,0 +1,59 @@
1
+ # Side-Effects Review — Threadline A2A resume via deterministic session-id
2
+
3
+ **Version / slug:** `threadline-a2a-resume-session-id`
4
+ **Date:** `2026-06-04`
5
+ **Author:** `Echo (instar dev agent)`
6
+ **Second-pass reviewer:** `not required (Tier 1)`
7
+
8
+ ## Summary of the change
9
+
10
+ Path 1 of the A2A continuity fix. Headless `claude -p` reply sessions never reported their session id, so `onSessionComplete` left the resume entry's uuid as a placeholder and resume-after-exit cold-spawned. Fix: when `ThreadlineRouter.spawnNewThread` spawns the first reply session it mints a uuid and passes it as `claude --session-id <uuid>` (so the transcript is created at exactly `<uuid>.jsonl`), and persists that uuid as the resume entry. `resumeThread` spawns the follow-up with `claude --resume <uuid>` (reloading the full transcript) and a minimal prompt (new message + grounding only — the transcript already holds history). Threaded through: `SessionManager.spawnSession` (new `sessionId?`/`resumeSessionId?` options → `--session-id`/`--resume` spliced into the claude-code headless argv before `-p`, mutually exclusive, gated on framework), `SpawnRequestManager` (forwards both from `SpawnRequest` → callback), the relay `spawnSession` callback in `server.ts`. Files: `src/core/SessionManager.ts`, `src/messaging/SpawnRequestManager.ts`, `src/commands/server.ts`, `src/threadline/ThreadlineRouter.ts` + tests.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `SessionManager.spawnSession` headless argv (`src/core/SessionManager.ts`) — **modify (additive)** — splice `--session-id`/`--resume` when the new options are set; no change when absent.
15
+ - `ThreadlineRouter.spawnNewThread` resume-entry uuid (`src/threadline/ThreadlineRouter.ts`) — **modify** — save the real minted uuid instead of the placeholder.
16
+ - `ThreadlineRouter.resumeThread` prompt + spawn (`src/threadline/ThreadlineRouter.ts`) — **modify** — pass `resumeSessionId` + minimal prompt (drop re-injected history).
17
+ - `SpawnRequest`/`SpawnRequestManager.evaluate` forwarding — **modify (additive)** — carry `sessionId`/`resumeSessionId`.
18
+
19
+ ## 1. Over-block
20
+
21
+ **What legitimate inputs does this change reject that it shouldn't?**
22
+
23
+ None — no allow/block surface. The flags only set/resume the conversation id. No message is rejected. When the new options are absent (every non-A2A spawn), behavior is unchanged. "No block/allow surface — over-block not applicable."
24
+
25
+ ## 2. Under-block
26
+
27
+ **What failure modes does this still miss?**
28
+
29
+ Rapid-fire (multiple messages while the reply session is still running): `--resume` on a still-busy session, or a fresh spawn hitting the 30s cooldown, is unchanged by this slice — that is the warm-session follow-up. Also: a `--resume` against a transcript that was deleted/rotated falls back to a fresh spawn (handled by the existing stale-uuid guard), losing that thread's history — acceptable + lossless beyond history.
30
+
31
+ ## 3. Level-of-abstraction fit
32
+
33
+ The uuid is minted + owned by `ThreadlineRouter` (which owns the resume entry) and threaded down to the spawn primitive — the right layering. `SessionManager` only learns "set/resume this id," mirroring its existing `--resume` (triage) and `extraClaudeFlags` patterns.
34
+
35
+ ## 4. Signal vs authority compliance
36
+
37
+ Not a gate/authority change. No approval surface added or relaxed. Trust gates on the inbound path are untouched.
38
+
39
+ ## 5. Interactions
40
+
41
+ - Builds on shipped slices 1+2 (router finds the live session + real tmux name). With this, `get()`'s `jsonlExists(uuid)` now passes legitimately (the transcript exists at the minted id) → resume path fires for spaced follow-ups.
42
+ - The relay `spawnSession` callback keeps `codexAllowMcpTools: true` + all MCP/permission flags → the A2A worker still replies via `threadline_send`.
43
+ - 1548 threadline/fixes/continuity unit tests pass; tsc clean. One obsolete test (`includes thread history in resume prompt`) replaced — it asserted the now-removed history-re-injection behavior.
44
+
45
+ ## 6. External surfaces
46
+
47
+ No new HTTP routes, no config defaults, no template/CLAUDE.md change. Pure internal session-lifecycle behavior. Migration-parity: nothing to migrate (no config/hook/template surface).
48
+
49
+ ## 7. Rollback cost
50
+
51
+ Low — revert the four source files. No persisted-format change (the resume entry already had a `uuid` field; it now holds a real id instead of a placeholder — old placeholder entries simply fail `jsonlExists` and cold-spawn as before). No external dependency.
52
+
53
+ ## Conclusion
54
+
55
+ Low-risk, additive, deterministic fix that completes the realistic turn-based A2A continuity case on top of the shipped foundation. The mechanism (`--session-id` set + `--resume` reload) was empirically verified before coding. Rapid-fire smoothness is explicitly out of scope.
56
+
57
+ ## Second-pass review (if required)
58
+
59
+ Not required — Tier 1 (additive, gated, ~single-concern).
@@ -0,0 +1,28 @@
1
+ # Why agent-to-agent conversations can now actually remember
2
+
3
+ ## The one-sentence version
4
+ When another agent sends me several messages over a conversation, each of my replies used to run as a throwaway that finished and forgot everything — so the next message met a stranger. Now I give each reply session a **known name tag** when it starts, write that tag down, and on the next message I **re-open the exact same conversation by its tag** — so I pick up right where we left off, with the full history.
5
+
6
+ ## What was broken (proven live)
7
+ A real round-trip with Dawn showed every follow-up still cold-spawned a memoryless session. The deep reason: each reply ran as a headless one-shot Claude that **never reports its own session id back to me**, so when it finished I had no handle to reconnect to. My earlier fix made the router *try* to reconnect, but there was nothing to reconnect to.
8
+
9
+ ## The fix (deterministic, no guessing)
10
+ Claude lets you (a) **set** a session's id when you launch it (`--session-id <uuid>`) and (b) **re-open** a session by that id later (`--resume <uuid>`). I verified both directly: setting an id creates the transcript under that exact id, and resuming it reloads the whole prior conversation (I planted a secret word in turn 1 and the resumed session recalled it).
11
+
12
+ So now:
13
+ - When a peer's first message spawns a reply session, I **mint a fresh id and pass it as `--session-id`**, then store that id as the thread's resume handle.
14
+ - When the next message arrives, I spawn with **`--resume <that id>`** so the session reloads the full prior transcript and continues — and I send it only the new message (the transcript already holds the history, so re-pasting it would just duplicate it).
15
+
16
+ ## The safety rails
17
+ 1. **Additive + off by default.** The new options do nothing unless set. Every other kind of session (jobs, your topic sessions, Codex) is byte-for-byte unchanged.
18
+ 2. **Claude-code only, and the two flags are mutually exclusive** — a launch either sets a new id or resumes one, never both.
19
+ 3. **A stale id can't wedge me.** If a transcript no longer exists, the existing resume-crash guard falls back to a fresh spawn instead of hanging.
20
+ 4. **The reply path is untouched.** Setting/resuming the conversation id doesn't change tools or permissions, so the agent still replies normally over the secure channel.
21
+ 5. **Built on the shipped foundation** (the router already finds the live session + carries the real session name); this adds the missing piece — the real, resumable id.
22
+
23
+ ## What it does NOT yet fix
24
+ The *rapid-fire* case (three messages in ten seconds, while the reply is still being written) still isn't smooth — that needs the bigger persistent-session work. This fixes the realistic **turn-based** conversation (you reply, I reply, you reply a minute later), which is exactly what the agent-to-agent feedback migration needs.
25
+
26
+ ---
27
+
28
+ **Rendered (verified) view:** _set below after creating the tunnel view._