instar 1.2.29 → 1.2.31
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/setup-wizard/codex-driver.d.ts.map +1 -1
- package/dist/commands/setup-wizard/codex-driver.js +36 -55
- package/dist/commands/setup-wizard/codex-driver.js.map +1 -1
- package/dist/core/Config.d.ts +1 -1
- package/dist/core/Config.d.ts.map +1 -1
- package/dist/core/Config.js +26 -2
- package/dist/core/Config.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +21 -9
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/types.d.ts +11 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.2.30.md +60 -0
- package/upgrades/1.2.31.md +90 -0
- package/upgrades/side-effects/fix-codex-only-lifeline-topic.md +83 -0
- package/upgrades/side-effects/framework-spawn-portability.md +92 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"instarVersion": "1.2.
|
|
4
|
+
"generatedAt": "2026-05-22T18:31:32.419Z",
|
|
5
|
+
"instarVersion": "1.2.31",
|
|
6
6
|
"entryCount": 191,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -1448,7 +1448,7 @@
|
|
|
1448
1448
|
"type": "subsystem",
|
|
1449
1449
|
"domain": "sessions",
|
|
1450
1450
|
"sourcePath": "src/core/SessionManager.ts",
|
|
1451
|
-
"contentHash": "
|
|
1451
|
+
"contentHash": "c8a43e38d2707bf0f1e7f3bfc958b5f6f885a4cfc383cb99135100caad6fc901",
|
|
1452
1452
|
"since": "2025-01-01"
|
|
1453
1453
|
},
|
|
1454
1454
|
"subsystem:auto-updater": {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Upgrade Guide — v1.2.30 (Codex creates only Lifeline topic)
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
<!-- patch = bug fixes, refactors, test additions, doc updates -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**Fix: duplicate Dashboard topic in the Codex Telegram setup.**
|
|
9
|
+
|
|
10
|
+
Real-user retest showed two "Dashboard" topics in the Telegram
|
|
11
|
+
group — one created by the Codex agentic flow (📊), one by the
|
|
12
|
+
instar server on boot (📢). The Codex flow was creating all four
|
|
13
|
+
system topics (Lifeline, Updates, Dashboard, Attention), but the
|
|
14
|
+
server ALSO creates Dashboard / Updates / Attention on its first
|
|
15
|
+
boot. They didn't coordinate, so Dashboard got made twice.
|
|
16
|
+
|
|
17
|
+
Lifeline never duplicated because the Codex flow persists its ID
|
|
18
|
+
and the server reuses it. The fix extends that pattern: the Codex
|
|
19
|
+
flow now creates ONLY Lifeline. The server creates Dashboard,
|
|
20
|
+
Updates, and Attention like it always has — with its own
|
|
21
|
+
canonical intros, emojis, colors, and the dashboard-link wiring.
|
|
22
|
+
|
|
23
|
+
The Lifeline orientation message now tells the user that "a few
|
|
24
|
+
more topics will appear automatically once my server starts," so
|
|
25
|
+
the brief single-topic state between Codex-done and server-boot
|
|
26
|
+
doesn't look incomplete.
|
|
27
|
+
|
|
28
|
+
Spec: `specs/dev-infrastructure/codex-only-lifeline-topic.md`.
|
|
29
|
+
ELI16: `specs/dev-infrastructure/codex-only-lifeline-topic.eli16.md`.
|
|
30
|
+
Side-effects: `upgrades/side-effects/fix-codex-only-lifeline-topic.md`.
|
|
31
|
+
|
|
32
|
+
## What to Tell Your User
|
|
33
|
+
|
|
34
|
+
The setup no longer creates a duplicate Dashboard topic. You'll
|
|
35
|
+
get one of each system topic, created by the part of instar that
|
|
36
|
+
owns it. The Lifeline topic now mentions that the other topics
|
|
37
|
+
appear automatically once your agent's server starts.
|
|
38
|
+
|
|
39
|
+
(Separately: if your dashboard link is missing, it's usually
|
|
40
|
+
because the Cloudflare tunnel can't connect — often a temporary
|
|
41
|
+
rate limit. Two follow-up improvements are planned: a clear
|
|
42
|
+
"tunnel couldn't connect" message in the Dashboard topic, and a
|
|
43
|
+
pool of backup tunnel providers.)
|
|
44
|
+
|
|
45
|
+
## Summary of New Capabilities
|
|
46
|
+
|
|
47
|
+
No new capabilities. Duplicate-topic bug fix.
|
|
48
|
+
|
|
49
|
+
## Evidence
|
|
50
|
+
|
|
51
|
+
Reproduction prior: live instar-codey config showed
|
|
52
|
+
`config.dashboardTopicId = 14` (server's "📢 Dashboard") plus a
|
|
53
|
+
separate Codex-created "📊 Dashboard" with no config reference.
|
|
54
|
+
The user's screenshot showed both in the chat list.
|
|
55
|
+
|
|
56
|
+
After fix: 81 wizard tests pass; the topic-creation canary now
|
|
57
|
+
asserts the prompt creates ONLY Lifeline and explicitly forbids
|
|
58
|
+
creating the other three. The retired Attention/Updates/Dashboard
|
|
59
|
+
color codes are no longer hard-coded in the prompt (only
|
|
60
|
+
Lifeline's remains).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
<!-- patch = bug fix, no new capability, no breaking change -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**fix(framework): Codex-only agents now spawn Codex sessions on every path.**
|
|
9
|
+
|
|
10
|
+
A Codex-only agent ("codey") spawned a Claude Code session when messaged on
|
|
11
|
+
Telegram — even though the install was Codex-only. The whole point of a
|
|
12
|
+
codex-cli install is that the agent runs on Codex, so this was a direct
|
|
13
|
+
framework-portability violation.
|
|
14
|
+
|
|
15
|
+
Two compounding bugs caused it:
|
|
16
|
+
|
|
17
|
+
1. **`spawnInteractiveSession` hardcoded the framework default.** The
|
|
18
|
+
interactive-session path — the one that handles incoming Telegram/Slack
|
|
19
|
+
messages — resolved its framework as `options?.framework ?? 'claude-code'`.
|
|
20
|
+
It never read the agent's config or the `INSTAR_FRAMEWORK` env. The
|
|
21
|
+
messaging callsites never pass `options.framework`, so this path ALWAYS
|
|
22
|
+
defaulted to claude-code.
|
|
23
|
+
|
|
24
|
+
2. **The runtime read a different config field than the wizard wrote.** The
|
|
25
|
+
setup wizard persists the framework choice as top-level
|
|
26
|
+
`config.enabledFrameworks` (e.g. `['codex-cli']`). But the runtime's
|
|
27
|
+
`resolveConfiguredFramework` only consulted `sessions.framework` and
|
|
28
|
+
`INSTAR_FRAMEWORK` — neither of which the wizard sets. So a codex-cli agent
|
|
29
|
+
had `enabledFrameworks: ['codex-cli']` set, both other fields empty, and the
|
|
30
|
+
runtime resolved claude-code.
|
|
31
|
+
|
|
32
|
+
The fix makes `enabledFrameworks` the authority that flows into the runtime.
|
|
33
|
+
`resolveConfiguredFramework` now takes `enabledFrameworks` as a third input
|
|
34
|
+
with precedence `sessions.framework` → `INSTAR_FRAMEWORK` env →
|
|
35
|
+
`enabledFrameworks[0]` → `'claude-code'`. `Config.load` stores the resolved
|
|
36
|
+
value as a new `config.framework` field, and BOTH spawn paths
|
|
37
|
+
(`spawnSession` for jobs, `spawnInteractiveSession` for messages) now read it.
|
|
38
|
+
A per-call `options.framework` override still wins, so a caller can force a
|
|
39
|
+
specific framework for one session.
|
|
40
|
+
|
|
41
|
+
Because the fix derives the framework at config-load time from a field existing
|
|
42
|
+
agents already have on disk, deployed Codex agents are fixed the moment they
|
|
43
|
+
update and reload — no reinstall, no migration.
|
|
44
|
+
|
|
45
|
+
## Evidence
|
|
46
|
+
|
|
47
|
+
The original failure: messaging codey (an agent installed with
|
|
48
|
+
`enabledFrameworks: ['codex-cli']`, no `sessions.framework`, no
|
|
49
|
+
`INSTAR_FRAMEWORK` env) in its Lifeline topic spawned a Claude Code session.
|
|
50
|
+
|
|
51
|
+
10 new unit tests in `tests/unit/framework-spawn-portability.test.ts`
|
|
52
|
+
reproduce and lock the fix:
|
|
53
|
+
|
|
54
|
+
1. `resolveConfiguredFramework` returns codex-cli when only
|
|
55
|
+
`enabledFrameworks: ['codex-cli']` is set (the codey configuration) — was
|
|
56
|
+
claude-code before the fix.
|
|
57
|
+
2. Explicit `sessions.framework` still wins over enabledFrameworks.
|
|
58
|
+
3. `INSTAR_FRAMEWORK=codex` env wins over an enabledFrameworks of claude-code.
|
|
59
|
+
4. `INSTAR_FRAMEWORK=claude` env wins over an enabledFrameworks of codex-cli
|
|
60
|
+
(the new explicit-claude env branch).
|
|
61
|
+
5. Empty/absent inputs still resolve to the claude-code historical default.
|
|
62
|
+
6. Per-call `options.framework` is highest precedence.
|
|
63
|
+
7–8. Source-grep assertions that both `spawnSession` and
|
|
64
|
+
`spawnInteractiveSession` resolve via `this.config.framework` (catches a
|
|
65
|
+
regression that re-hardcodes the default).
|
|
66
|
+
9–10. `Config.load` wiring — `enabledFrameworks` flows into
|
|
67
|
+
`config.framework`.
|
|
68
|
+
|
|
69
|
+
All 11 existing `frameworkPrerequisite.test.ts` tests still pass — the shared
|
|
70
|
+
resolver behaves identically for every previously-covered case. `tsc --noEmit`
|
|
71
|
+
clean, lint clean.
|
|
72
|
+
|
|
73
|
+
## What to Tell Your User
|
|
74
|
+
|
|
75
|
+
If you set up an agent to run on Codex, it will now correctly run on Codex
|
|
76
|
+
every time — including when you message it. Before this fix, a Codex-only agent
|
|
77
|
+
could quietly start up on Claude instead when you sent it a message, which was
|
|
78
|
+
the wrong engine entirely.
|
|
79
|
+
|
|
80
|
+
You do not need to do anything. There is no reinstall and no setup to redo. The
|
|
81
|
+
next time your agent updates and restarts, it reads the framework choice already
|
|
82
|
+
saved from when you set it up, and uses it for every session from then on.
|
|
83
|
+
Agents set up on Claude, or set up to use both, keep working exactly as before.
|
|
84
|
+
|
|
85
|
+
## Summary of New Capabilities
|
|
86
|
+
|
|
87
|
+
| Capability | How to Use |
|
|
88
|
+
|-----------|-----------|
|
|
89
|
+
| Codex-only agents spawn Codex on all paths (jobs + messages) | Automatic — derived from your install-time framework choice |
|
|
90
|
+
| Existing Codex agents fixed on update | Automatic — no reinstall or migration; the choice is read from disk at startup |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Side-effects review — Codex creates only Lifeline
|
|
2
|
+
|
|
3
|
+
Per L6. Seven dimensions.
|
|
4
|
+
|
|
5
|
+
## 1. Over-block / under-block
|
|
6
|
+
|
|
7
|
+
Before: OVER-creation. The Codex flow created all 4 system topics
|
|
8
|
+
AND the server created 3 of them on boot, yielding duplicate
|
|
9
|
+
Dashboard (and latent duplicate risk for Updates/Attention).
|
|
10
|
+
|
|
11
|
+
After: precisely scoped. Codex creates only Lifeline (which the
|
|
12
|
+
server reuses by persisted ID). Server creates the other 3.
|
|
13
|
+
Single creator per topic. No duplicates.
|
|
14
|
+
|
|
15
|
+
## 2. Level-of-abstraction fit
|
|
16
|
+
|
|
17
|
+
Prompt-content change only — steps 13 + 14 of
|
|
18
|
+
`buildTelegramAgenticPrompt`. No new functions, no signature
|
|
19
|
+
change, no server-side change. Follows the existing ownership
|
|
20
|
+
boundary (server owns Dashboard/Updates/Attention; Lifeline is
|
|
21
|
+
shared via `config.lifelineTopicId`).
|
|
22
|
+
|
|
23
|
+
## 3. Signal vs Authority compliance
|
|
24
|
+
|
|
25
|
+
- The server's `ensureDashboardTopic` / `ensureAgentUpdatesTopic`
|
|
26
|
+
/ `ensureAgentAttentionTopic` remain the single AUTHORITY for
|
|
27
|
+
those three topics.
|
|
28
|
+
- `config.lifelineTopicId` remains the coordination AUTHORITY
|
|
29
|
+
between the Codex flow and the server's `ensureLifelineTopic`.
|
|
30
|
+
- The Codex flow no longer emits create-SIGNALS for the three
|
|
31
|
+
server-owned topics.
|
|
32
|
+
|
|
33
|
+
## 4. Interactions with adjacent systems
|
|
34
|
+
|
|
35
|
+
- **Server `ensureDashboardTopic` / `ensureAgentUpdatesTopic` /
|
|
36
|
+
`ensureAgentAttentionTopic`**: unchanged. They now run without
|
|
37
|
+
a Codex-created duplicate to collide with.
|
|
38
|
+
- **Server `ensureLifelineTopic`**: unchanged. Still reuses
|
|
39
|
+
`config.lifelineTopicId` written by the Codex flow.
|
|
40
|
+
- **`runSendLifelineGreeting`** (post-server greeting): unchanged.
|
|
41
|
+
Still reads `lifelineTopicId` from config and posts the
|
|
42
|
+
agent's first hello.
|
|
43
|
+
- **`broadcastDashboardUrl`**: unchanged. Posts the dashboard
|
|
44
|
+
link to `config.dashboardTopicId` (set by the server's
|
|
45
|
+
`ensureDashboardTopic`) once a tunnel is up.
|
|
46
|
+
- **Tests**: one test rewritten (was "creates the 4 canonical
|
|
47
|
+
system topics" → now "creates ONLY the Lifeline topic"); the
|
|
48
|
+
other 80 wizard tests unchanged.
|
|
49
|
+
|
|
50
|
+
## 5. Rollback cost
|
|
51
|
+
|
|
52
|
+
Trivial. Prompt-content change in two steps. `git revert`
|
|
53
|
+
restores the 4-topic creation (and the duplicate).
|
|
54
|
+
|
|
55
|
+
## 6. Backwards compatibility / drift surface
|
|
56
|
+
|
|
57
|
+
Fully backwards-compatible.
|
|
58
|
+
|
|
59
|
+
- Existing agents already set up: unaffected — their topics
|
|
60
|
+
already exist; the server's ensure functions are idempotent on
|
|
61
|
+
their stored IDs.
|
|
62
|
+
- New Codex installs: get exactly 4 topics, one creator each, no
|
|
63
|
+
duplicates.
|
|
64
|
+
- Claude wizard path: untouched.
|
|
65
|
+
- No config schema change. No agent-installed-files change.
|
|
66
|
+
|
|
67
|
+
Drift surface reduced: the Codex prompt no longer hard-codes the
|
|
68
|
+
Dashboard/Updates/Attention names + colors, so it can't drift
|
|
69
|
+
from the server's TOPIC_STYLE constants. Only Lifeline's color
|
|
70
|
+
(9367192) remains in the prompt, matching SYSTEM.
|
|
71
|
+
|
|
72
|
+
## 7. Authorization / Trust posture
|
|
73
|
+
|
|
74
|
+
No change. Same Codex spawn flags, same Bot API access.
|
|
75
|
+
|
|
76
|
+
## Outcome
|
|
77
|
+
|
|
78
|
+
Ship. Closes the duplicate-Dashboard bug by restoring the natural
|
|
79
|
+
ownership boundary: server owns its three system topics; Codex
|
|
80
|
+
owns only Lifeline (the shared coordination point). The
|
|
81
|
+
no-dashboard-link issue is separate (Cloudflare rate-limit) and
|
|
82
|
+
addressed by two tracked follow-ups (tunnel-failure user
|
|
83
|
+
notification + backup tunnel pool).
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Side-effects review — framework-spawn portability (codex agents spawn Codex)
|
|
2
|
+
|
|
3
|
+
**Scope**: A Codex-only agent ("codey") spawned a Claude Code session when
|
|
4
|
+
messaged on Telegram. Two compounding bugs: (1) `spawnInteractiveSession`
|
|
5
|
+
hardcoded `'claude-code'` and never read config/env; (2) the runtime's
|
|
6
|
+
`resolveConfiguredFramework` read `sessions.framework` + `INSTAR_FRAMEWORK`,
|
|
7
|
+
neither of which the wizard sets — the wizard persists `enabledFrameworks`.
|
|
8
|
+
So the runtime always resolved claude-code for wizard-installed Codex agents.
|
|
9
|
+
|
|
10
|
+
**Files touched**:
|
|
11
|
+
- `src/core/types.ts` — add optional `framework?: 'claude-code' | 'codex-cli'`
|
|
12
|
+
to `SessionManagerConfig` (the resolved runtime framework).
|
|
13
|
+
- `src/core/Config.ts` — `resolveConfiguredFramework` takes a third arg
|
|
14
|
+
`enabledFrameworks`; new precedence configValue → env → enabledFrameworks[0]
|
|
15
|
+
→ 'claude-code'; explicit `claude`/`claude-code` env branch added; `loadConfig`
|
|
16
|
+
passes `fileConfig.enabledFrameworks` and stores the result on
|
|
17
|
+
`sessions.framework` (the SessionManagerConfig field).
|
|
18
|
+
- `src/core/SessionManager.ts` — `spawnInteractiveSession` replaces the
|
|
19
|
+
hardcoded default with `resolveInteractiveFramework({ perCall, configFramework:
|
|
20
|
+
this.config.framework, envFramework })`; `spawnSession` changes
|
|
21
|
+
`configFramework: undefined` → `this.config.framework`.
|
|
22
|
+
- `tests/unit/framework-spawn-portability.test.ts` — 10 tests: precedence of
|
|
23
|
+
resolveConfiguredFramework (incl. enabledFrameworks fallback + explicit-claude
|
|
24
|
+
env), source-grep that both spawn paths read config.framework, and Config.load
|
|
25
|
+
wiring (enabledFrameworks → config.framework).
|
|
26
|
+
|
|
27
|
+
**Under-block**: None. The fix makes a previously-ignored config field
|
|
28
|
+
authoritative. There is no path where a framework that *should* spawn is now
|
|
29
|
+
suppressed — per-call override and explicit config/env all still win.
|
|
30
|
+
|
|
31
|
+
**Over-block**: None. A codex-cli agent will now correctly REFUSE to silently
|
|
32
|
+
fall back to Claude. If a caller genuinely wants a one-off Claude session on a
|
|
33
|
+
Codex agent, the per-call `options.framework` override still does that — it sits
|
|
34
|
+
at the top of the precedence chain. So the "block" here is exactly the intended
|
|
35
|
+
behavior (honor the install choice), with a documented escape hatch.
|
|
36
|
+
|
|
37
|
+
**Level-of-abstraction fit**: Framework resolution stays in one place
|
|
38
|
+
(`resolveConfiguredFramework` / `resolveInteractiveFramework`). The spawn paths
|
|
39
|
+
do not re-implement precedence; they pass their three inputs and take the
|
|
40
|
+
answer. `enabledFrameworks` (install choice) is reduced to a single resolved
|
|
41
|
+
`config.framework` at load time, so SessionManager never has to know about the
|
|
42
|
+
array shape. Correct layering: array-of-enabled is an install concept; the
|
|
43
|
+
runtime sees one resolved framework.
|
|
44
|
+
|
|
45
|
+
**Signal vs authority**: Compliant. `enabledFrameworks`, env, and per-call
|
|
46
|
+
options are all SIGNALS fed into the resolver. The resolver
|
|
47
|
+
(`resolveConfiguredFramework`) is the single AUTHORITY that picks one framework.
|
|
48
|
+
No spawn-path makes its own framework decision anymore — both defer to the
|
|
49
|
+
resolved value.
|
|
50
|
+
|
|
51
|
+
**Interactions**:
|
|
52
|
+
- `spawnSession` (scheduled jobs) and `spawnInteractiveSession` (messages) now
|
|
53
|
+
resolve identically. Before, only spawnSession read env; the interactive path
|
|
54
|
+
was the one that hit the bug. They are now symmetric.
|
|
55
|
+
- `frameworkBinaryPaths[framework] ?? claudePath` fallback is unchanged — if a
|
|
56
|
+
codex-cli framework has no binary path mapped, it still falls back to
|
|
57
|
+
claudePath. That fallback is a *binary-path* concern, separate from framework
|
|
58
|
+
*selection*; out of scope here. For correctly-installed Codex agents the codex
|
|
59
|
+
binary path is populated by `detectCodexPath()` in loadConfig.
|
|
60
|
+
- No change to `checkFrameworkPrerequisite` or the parity sentinel — they read
|
|
61
|
+
`enabledFrameworks` directly and are unaffected by the new derived field.
|
|
62
|
+
|
|
63
|
+
**External surfaces**: None. No new API endpoint, no new config field the user
|
|
64
|
+
writes (the new `framework` is derived, not user-authored), no CLI change. The
|
|
65
|
+
`enabledFrameworks` field already existed and was already written by the wizard.
|
|
66
|
+
|
|
67
|
+
**Migration / existing agents**: No migration needed. The fix is a config-LOAD
|
|
68
|
+
derivation. Deployed Codex agents already have `enabledFrameworks: ['codex-cli']`
|
|
69
|
+
on disk (their install wrote it). The moment they update and the server reloads
|
|
70
|
+
config, `config.framework` resolves to codex-cli and both spawn paths honor it.
|
|
71
|
+
Verified by the Config.load wiring test.
|
|
72
|
+
|
|
73
|
+
**Rollback cost**: Trivial. Revert three source files + the test. The derived
|
|
74
|
+
field is optional; nothing persists it to disk, so a revert leaves no orphaned
|
|
75
|
+
state.
|
|
76
|
+
|
|
77
|
+
**Tests**: 10/10 new tests pass; 11/11 existing `frameworkPrerequisite.test.ts`
|
|
78
|
+
pass (no regression in the shared resolver). `npx tsc --noEmit` clean.
|
|
79
|
+
`npm run lint` clean.
|
|
80
|
+
|
|
81
|
+
**Decision-point inventory**:
|
|
82
|
+
1. Derive `config.framework` at load (vs. teach every spawn path to read
|
|
83
|
+
`enabledFrameworks` itself) — single resolution point, single authority,
|
|
84
|
+
keeps SessionManager ignorant of the array shape. Chosen.
|
|
85
|
+
2. `enabledFrameworks[0]` slots BELOW env (vs. above) — an explicit
|
|
86
|
+
`INSTAR_FRAMEWORK` env at boot is a deliberate per-boot override and should
|
|
87
|
+
beat the persisted install default. Matches the existing env-over-default
|
|
88
|
+
intent.
|
|
89
|
+
3. No init-time write of `sessions.framework` (vs. backfilling it) — the
|
|
90
|
+
load-time derivation already fixes existing agents with zero migration; a
|
|
91
|
+
redundant on-disk write is deferred as unnecessary (noted out-of-scope in the
|
|
92
|
+
spec).
|