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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +7 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/SessionManager.d.ts +18 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +20 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/messaging/SpawnRequestManager.d.ts +23 -0
- package/dist/messaging/SpawnRequestManager.d.ts.map +1 -1
- package/dist/messaging/SpawnRequestManager.js +5 -0
- package/dist/messaging/SpawnRequestManager.js.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleStore.d.ts +21 -0
- package/dist/monitoring/ApprenticeshipCycleStore.d.ts.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleStore.js +50 -4
- package/dist/monitoring/ApprenticeshipCycleStore.js.map +1 -1
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +26 -10
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.240.md +72 -0
- package/upgrades/apprenticeship-channel-enforcement.eli16.md +16 -0
- package/upgrades/side-effects/apprenticeship-channel-enforcement.md +39 -0
- package/upgrades/side-effects/threadline-a2a-resume-session-id.md +59 -0
- package/upgrades/threadline-a2a-resume-session-id.eli16.md +28 -0
|
@@ -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._
|