instar 1.3.509 → 1.3.511
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 +8 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +19 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +4 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +3 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/TopicProfileOrchestrator.d.ts +3 -1
- package/dist/core/TopicProfileOrchestrator.d.ts.map +1 -1
- package/dist/core/TopicProfileOrchestrator.js +8 -3
- package/dist/core/TopicProfileOrchestrator.js.map +1 -1
- package/dist/core/TopicProfileResolver.d.ts +9 -1
- package/dist/core/TopicProfileResolver.d.ts.map +1 -1
- package/dist/core/TopicProfileResolver.js +38 -2
- package/dist/core/TopicProfileResolver.js.map +1 -1
- package/dist/core/TopicProfileStore.d.ts +8 -1
- package/dist/core/TopicProfileStore.d.ts.map +1 -1
- package/dist/core/TopicProfileStore.js +2 -2
- package/dist/core/TopicProfileStore.js.map +1 -1
- package/dist/core/classifyProfileChange.d.ts.map +1 -1
- package/dist/core/classifyProfileChange.js +32 -1
- package/dist/core/classifyProfileChange.js.map +1 -1
- package/dist/core/frameworkSessionLaunch.d.ts +28 -1
- package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
- package/dist/core/frameworkSessionLaunch.js +35 -3
- package/dist/core/frameworkSessionLaunch.js.map +1 -1
- package/dist/core/topicProfileIngress.d.ts.map +1 -1
- package/dist/core/topicProfileIngress.js +14 -0
- package/dist/core/topicProfileIngress.js.map +1 -1
- package/dist/core/topicProfileValidation.d.ts +12 -0
- package/dist/core/topicProfileValidation.d.ts.map +1 -1
- package/dist/core/topicProfileValidation.js +30 -0
- package/dist/core/topicProfileValidation.js.map +1 -1
- package/dist/core/topicProfileWriteSurface.d.ts.map +1 -1
- package/dist/core/topicProfileWriteSurface.js +3 -2
- package/dist/core/topicProfileWriteSurface.js.map +1 -1
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +142 -9
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.510.md +54 -0
- package/upgrades/1.3.511.md +46 -0
- package/upgrades/side-effects/multi-machine-seamlessness-ws43-jobs-pool-read.md +88 -0
- package/upgrades/side-effects/topic-effort-pin.md +117 -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
|
+
- **`GET /jobs?scope=pool`** merges every online machine's scheduled jobs into one
|
|
9
|
+
view, each tagged with the machine that runs it — mirroring the proven
|
|
10
|
+
`sessions?scope=pool` / `attention?scope=pool` family: per-peer 5s timeout with a
|
|
11
|
+
`pool.failed[]` marker on a dark/offline peer (never a 500), a 3s short-TTL cache,
|
|
12
|
+
non-recursive peer calls. Plain `GET /jobs` is byte-for-byte unchanged.
|
|
13
|
+
- **F8 placement-divergence detector** (observe-only, `pool.divergences[]`): flags a
|
|
14
|
+
machine that DECLARES jobs (N>0) but RUNS none of them locally — "config says jobs
|
|
15
|
+
here, this machine isn't running them." Derived honestly from each machine's own
|
|
16
|
+
`/jobs` reply; no fabricated counts; never gates. A machine with zero jobs is NOT
|
|
17
|
+
flagged (legitimate scheduler-less/dispatcher machine).
|
|
18
|
+
- CLAUDE.md template + idempotent PostUpdateMigrator bullet (Agent Awareness +
|
|
19
|
+
Migration Parity).
|
|
20
|
+
|
|
21
|
+
This is the READ half of WS4.3. The role-guard-at-spawn (refuse state-writing jobs on
|
|
22
|
+
a read-only standby → re-route or attention) and the journal-lease claim cutover are
|
|
23
|
+
SEPARATE follow-up slices. <!-- tracked: CMT-1416 -->
|
|
24
|
+
|
|
25
|
+
## What to Tell Your User
|
|
26
|
+
|
|
27
|
+
On a multi-machine setup, "what jobs are running where?" now answers across all your
|
|
28
|
+
machines at once — each scheduled job tagged with the machine running it, a machine
|
|
29
|
+
that's offline noted rather than dropped, and a heads-up if a machine is configured to
|
|
30
|
+
run jobs but isn't actually running any.
|
|
31
|
+
|
|
32
|
+
## Summary of New Capabilities
|
|
33
|
+
|
|
34
|
+
- One pooled view of scheduled jobs across the fleet (`GET /jobs?scope=pool`),
|
|
35
|
+
machine-tagged, dark peers surfaced as `failed`, plus an observe-only placement-
|
|
36
|
+
divergence signal.
|
|
37
|
+
|
|
38
|
+
## Evidence
|
|
39
|
+
|
|
40
|
+
- `tests/integration/jobs-pool-scope.test.ts` (9, new): plain GET self-tags identity;
|
|
41
|
+
scope=pool merges a REAL peer server's jobs; offline peer → failed without waiting;
|
|
42
|
+
unreachable peer → failed, local still answers; no-peers → local-only; divergence
|
|
43
|
+
flags declares-N-runs-0; a zero-jobs peer is NOT flagged; scheduler-less shape.
|
|
44
|
+
- `tests/unit/PostUpdateMigrator-jobsPoolScope.test.ts` (4, new): migration + template
|
|
45
|
+
parity, idempotent. `tsc --noEmit` clean. Existing jobs-endpoints-auth (15) +
|
|
46
|
+
guardian-jobs (11) + attention-pool-scope (7) all still green.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Side-Effects Review — WS4.3 read-side: GET /jobs?scope=pool + divergence detector
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `multi-machine-seamlessness-ws43-jobs-pool-read`
|
|
4
|
+
**Date:** `2026-06-12`
|
|
5
|
+
**Author:** `Instar Agent (echo)`
|
|
6
|
+
**Second-pass reviewer:** `workflow adversarial reviewer (CONCUR — 1 LOW fixed)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The read-side of WS4.3 (MULTI-MACHINE-SEAMLESSNESS-SPEC §WS4.3): `GET /jobs?scope=pool`
|
|
11
|
+
merges every online peer's jobs into one view (which machine runs each job),
|
|
12
|
+
mirroring the proven `sessions?scope=pool` / WS4.1 `attention?scope=pool` family —
|
|
13
|
+
per-peer 5s timeout, `pool.failed[]` markers (never a 500), offline-peer skip, 3s
|
|
14
|
+
short-TTL cache, machine tagging. Plus an observe-only F8 placement-divergence
|
|
15
|
+
detector. Files: `src/server/routes.ts` (route + `jobsPoolMerge` + `detectJobDivergences`),
|
|
16
|
+
`src/scaffold/templates.ts` + `src/core/PostUpdateMigrator.ts` (Agent Awareness +
|
|
17
|
+
Migration Parity). The role-guard-at-spawn and journal-lease cutover are SEPARATE
|
|
18
|
+
follow-up slices (not in this PR). <!-- tracked: CMT-1416 -->
|
|
19
|
+
|
|
20
|
+
## Decision-point inventory
|
|
21
|
+
|
|
22
|
+
- `GET /jobs?scope=pool` merge — **add** — read-only aggregation; never mutates a
|
|
23
|
+
job, never gates; tolerant fan-out.
|
|
24
|
+
- `detectJobDivergences` — **add** — observe-only signal in `pool.divergences[]`;
|
|
25
|
+
flags ONLY `declared>0 && running===0` (a machine that should run jobs but isn't).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 1. Over-block
|
|
30
|
+
No block/allow surface — read-only. The divergence detector after the LOW fix flags
|
|
31
|
+
ONLY the real case (declares N>0, runs 0). A machine declaring 0 jobs is NOT flagged
|
|
32
|
+
(was self-noise — fixed: a scheduler-less/dispatcher-only machine legitimately has none).
|
|
33
|
+
|
|
34
|
+
## 2. Under-block
|
|
35
|
+
Capacity carries no declared-job count, so divergence is derived from each machine's
|
|
36
|
+
own `/jobs` reply (declared = jobs returned, running = `runsOnThisMachine===true`
|
|
37
|
+
count). A machine that is DOWN (no reply) is in `pool.failed[]`, not `divergences` —
|
|
38
|
+
so a fully-dark machine's jobs aren't flagged as "running 0" (correct; it's a
|
|
39
|
+
reachability failure, surfaced separately). No fabricated counts.
|
|
40
|
+
|
|
41
|
+
## 3. Level-of-abstraction fit
|
|
42
|
+
Right layer — mirrors the sessions/attention pool-scope route code exactly (same
|
|
43
|
+
fan-out/timeout/failed/cache/tag shape); the divergence helper is a pure function
|
|
44
|
+
over the merged replies.
|
|
45
|
+
|
|
46
|
+
## 4. Signal vs authority compliance
|
|
47
|
+
Compliant — pure read + an observe-only signal. Gates nothing.
|
|
48
|
+
|
|
49
|
+
## 5. Interactions
|
|
50
|
+
- Plain `GET /jobs` is byte-for-byte unchanged (`{jobs,queue}`; no `pool` object, no
|
|
51
|
+
machine tags) — only `?scope=pool` adds them.
|
|
52
|
+
- The cache key is fixed (`'jobs'`) and read/written only inside `jobsPoolMerge`;
|
|
53
|
+
there are no status/scope variants to cross-contaminate (stronger isolation than
|
|
54
|
+
attention's status-keyed cache).
|
|
55
|
+
- Peers are called WITHOUT `scope` → no recursive fan-out storm.
|
|
56
|
+
|
|
57
|
+
## 6. External surfaces
|
|
58
|
+
- New query mode on an existing route; old callers (no `?scope=pool`) unaffected.
|
|
59
|
+
- Calls each peer's `GET /jobs` with the agent bearer (same pattern as
|
|
60
|
+
sessions/attention pool scope). An old peer returns its local jobs → merges fine.
|
|
61
|
+
|
|
62
|
+
## Framework generality
|
|
63
|
+
No framework-launch abstraction touched (this is a read/merge route only; no change
|
|
64
|
+
to `frameworkSessionLaunch.ts`). The job model is framework-agnostic; the merge tags
|
|
65
|
+
machines, not frameworks. N/A beyond that.
|
|
66
|
+
|
|
67
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
68
|
+
**proxied-on-read** — fans out to peers per request (cached 3s), each job tagged with
|
|
69
|
+
its owning machine; consults the pool registry's online flag to skip dark peers
|
|
70
|
+
cheaply. No replication, no durable cross-machine state in this slice. Phase-C clean:
|
|
71
|
+
per-online-peer fan-out, O(jobs) divergence, no 2-peer assumption.
|
|
72
|
+
|
|
73
|
+
## 8. Rollback cost
|
|
74
|
+
Trivial: additive scope branch; reverting restores today's local-only `GET /jobs`.
|
|
75
|
+
No durable state; the CLAUDE.md migrator bullet is idempotent (content-sniffed).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Second-pass review
|
|
80
|
+
|
|
81
|
+
Workflow adversarial reviewer: **CONCUR** (tscClean, testsPass; all 7 audit points
|
|
82
|
+
verified incl. tolerant fan-out, back-compat, cache isolation, observe-only +
|
|
83
|
+
no-fabricated-count divergence, non-recursive peers, awareness+migration parity,
|
|
84
|
+
tests proven failing pre-change). One **LOW**: a scheduler-less/no-jobs machine
|
|
85
|
+
self-flagged a "declares 0 jobs while online" divergence (self-noise). **FIXED**:
|
|
86
|
+
the detector now flags ONLY `declared>0 && running===0`; the 0-jobs case is dropped
|
|
87
|
+
(legitimate, not a divergence), and its test now asserts NO divergence for a
|
|
88
|
+
zero-jobs peer.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Side-Effects Review — per-topic effort pin (--effort at spawn)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `topic-effort-pin`
|
|
4
|
+
**Date:** `2026-06-12`
|
|
5
|
+
**Author:** `Instar Agent (echo)`
|
|
6
|
+
**Second-pass reviewer:** `workflow adversarial reviewer (CONCUR — 1 MEDIUM fixed, see below)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Adds an optional `effort` field (enum `low|medium|high|xhigh|max`) to the
|
|
11
|
+
topic-profile system, threaded through validation, store, resolver, write
|
|
12
|
+
surface, change-classifier, orchestrator, conversational ingress, types, and the
|
|
13
|
+
two routes; and injects `--effort <level>` into the Claude Code launch argv
|
|
14
|
+
(interactive + headless builders in `frameworkSessionLaunch.ts`), resolved from
|
|
15
|
+
the topic profile at spawn in `SessionManager`/`server.ts`. Mirrors `thinkingMode`'s
|
|
16
|
+
plumbing. Operator request: Justin, topic 13481, "set ultracode for this topic"
|
|
17
|
+
(ultracode is not a CLI value; this pins the CLI ceiling `max`).
|
|
18
|
+
|
|
19
|
+
## Decision-point inventory
|
|
20
|
+
|
|
21
|
+
- Topic-profile resolution — **modify** — adds an `effort` resolution arm
|
|
22
|
+
(pin > config-default > unset); off-enum value → fail-open `undefined`.
|
|
23
|
+
- Launch argv builders — **modify** — push `--effort` for claude-code only when
|
|
24
|
+
set + enum-valid; non-claude untouched.
|
|
25
|
+
- `classifyProfileChange` — **modify** — adds a dedicated effort-only row
|
|
26
|
+
(kill+resume, none-loss when resume-ready) so it is not misclassified as a
|
|
27
|
+
thinking change (the second-pass MEDIUM finding, now fixed).
|
|
28
|
+
- Write surface / routes / ingress — **modify** — accept + validate `effort`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. Over-block
|
|
33
|
+
Off-enum values are rejected at the write API (HTTP 400, profile unchanged) — that
|
|
34
|
+
is the intended block. No legitimate input is rejected; the five CLI-valid levels
|
|
35
|
+
all pass. `ultracode` is deliberately refused (not a CLI value).
|
|
36
|
+
|
|
37
|
+
## 2. Under-block
|
|
38
|
+
A value that is enum-valid but unsupported by the *running model* (e.g. `xhigh`
|
|
39
|
+
on a model that floors to `high`) is passed through — the CLI itself floors it
|
|
40
|
+
(documented behavior), so no instar-side block is needed. Headless one-shot/job
|
|
41
|
+
spawns do NOT thread effort (interactive-only); acceptable — per-topic effort is
|
|
42
|
+
a per-conversation pin, and the headless builder support is forward-looking
|
|
43
|
+
defense-in-depth (flagged by the reviewer as a deliberate choice, not a bug).
|
|
44
|
+
|
|
45
|
+
## 3. Level-of-abstraction fit
|
|
46
|
+
Right layer: mirrors `thinkingMode` exactly across the same files; the resolver
|
|
47
|
+
owns precedence, the launch builder owns argv, the classifier owns respawn
|
|
48
|
+
semantics. No parallel machinery invented.
|
|
49
|
+
|
|
50
|
+
## 4. Signal vs authority compliance
|
|
51
|
+
N/A as a gate — this is a config field, not a decision point. The one authority-
|
|
52
|
+
adjacent concern (a bad value reaching the CLI) is defended by three independent
|
|
53
|
+
fail-open/validate layers.
|
|
54
|
+
|
|
55
|
+
## 5. Interactions
|
|
56
|
+
- Interacts with the `thinkingMode`→`--effort` mapping in the interactive builder:
|
|
57
|
+
a direct effort pin WINS and suppresses the thinkingMode-derived mapping, so
|
|
58
|
+
`--effort` is emitted exactly once (unit-tested).
|
|
59
|
+
- The change-classifier effort row composes with model/tier/thinking rows: a
|
|
60
|
+
combined change is handled by those rows (their respawn carries the new flag);
|
|
61
|
+
only effort-only needed the new row.
|
|
62
|
+
|
|
63
|
+
## 6. External surfaces
|
|
64
|
+
- `GET /topic-profile/:id` gains `resolved.effort` + `sources.effort` (additive).
|
|
65
|
+
- POST profile/propose accept `effort` (additive; off-enum → 400).
|
|
66
|
+
- A spawned Claude session's argv gains `--effort <level>` when the topic pins it.
|
|
67
|
+
Old behavior (no pin) is byte-identical.
|
|
68
|
+
|
|
69
|
+
## Framework generality
|
|
70
|
+
|
|
71
|
+
The change DOES route through the framework abstraction (`frameworkSessionLaunch.ts`
|
|
72
|
+
builders), and is **deliberately Claude-optimizing, not Claude-leaking**:
|
|
73
|
+
|
|
74
|
+
- `--effort <low|medium|high|xhigh|max>` is a **Claude Code CLI flag**. Only the
|
|
75
|
+
`claudeCodeBuilder` (interactive) and `claudeCodeHeadlessBuilder` (headless) push
|
|
76
|
+
it. `InteractiveLaunchOptions.effort` / `HeadlessLaunchOptions.effort` are optional
|
|
77
|
+
inputs the non-Claude builders simply **ignore** — `codexCliBuilder`,
|
|
78
|
+
`geminiCliBuilder`, and `piCliBuilder` are untouched and emit no effort flag.
|
|
79
|
+
- This is the "Framework-Agnostic — and Framework-Optimizing" standard satisfied:
|
|
80
|
+
the abstraction stays framework-agnostic (every builder receives the same options
|
|
81
|
+
object; none is forced to honor a flag it doesn't have), while Claude gets its
|
|
82
|
+
native knob. Codex/Gemini have their own reasoning/effort controls
|
|
83
|
+
(e.g. codex `-c model_reasoning_effort`); wiring those is explicitly OUT OF SCOPE
|
|
84
|
+
here and would be a separate per-framework mapping (a future `resolveEffortForFramework`
|
|
85
|
+
analogous to `resolveModelForFramework`), not a generalization of this Claude flag.
|
|
86
|
+
- The topic-profile `effort` field itself is framework-agnostic (it's a profile
|
|
87
|
+
value); only its TRANSLATION to a launch flag is Claude-specific, which is the
|
|
88
|
+
correct layer for framework specificity (mirrors how `model` resolves per-framework
|
|
89
|
+
via `resolveModelForFramework`).
|
|
90
|
+
|
|
91
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
92
|
+
**proxied-on-read / machine-local-by-design.** The topic profile already resolves
|
|
93
|
+
per-machine at spawn; effort rides the same path. When a topic transfers machines,
|
|
94
|
+
its profile carrier (the existing topic-profile pull-at-acquire seam) carries
|
|
95
|
+
`effort` along with the other fields (it's in `PROFILE_FIELDS`), so the pin
|
|
96
|
+
follows the conversation. No new replication surface; no new URL/notice.
|
|
97
|
+
|
|
98
|
+
## 8. Rollback cost
|
|
99
|
+
Trivial: additive field, unset by default. Reverting the PR removes the field and
|
|
100
|
+
the argv injection; no durable migration (the field simply stops being read). A
|
|
101
|
+
stored `effort` on a profile file is ignored by older code (additive JSON).
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Second-pass review
|
|
106
|
+
|
|
107
|
+
Workflow adversarial reviewer: **CONCUR** (tscClean, testsPass). Two findings:
|
|
108
|
+
- **MEDIUM — effort half-wired in `classifyProfileChange`** (in AXES but no
|
|
109
|
+
branch → effort-only change fell through to the thinkingMode row, wrong reason
|
|
110
|
+
+ wrong verification gate). **FIXED**: added a dedicated effort-only row
|
|
111
|
+
(kill+resume, none-loss when resume-ready; fresh recent-only otherwise) with an
|
|
112
|
+
effort-specific reason; +4 classifier unit tests asserting it resolves as
|
|
113
|
+
`resume`/none-loss, is NOT gated on the thinking flags, and the reason says
|
|
114
|
+
"effort change" not "thinking".
|
|
115
|
+
- **LOW — headless builder has no live caller** (interactive-only data flow).
|
|
116
|
+
Acknowledged as a deliberate, documented forward-looking choice (per-topic
|
|
117
|
+
effort is a per-conversation interactive pin), not a bug (§2 above).
|