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.
Files changed (54) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +8 -1
  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 +19 -0
  6. package/dist/core/PostUpdateMigrator.js.map +1 -1
  7. package/dist/core/SessionManager.d.ts +4 -0
  8. package/dist/core/SessionManager.d.ts.map +1 -1
  9. package/dist/core/SessionManager.js +3 -0
  10. package/dist/core/SessionManager.js.map +1 -1
  11. package/dist/core/TopicProfileOrchestrator.d.ts +3 -1
  12. package/dist/core/TopicProfileOrchestrator.d.ts.map +1 -1
  13. package/dist/core/TopicProfileOrchestrator.js +8 -3
  14. package/dist/core/TopicProfileOrchestrator.js.map +1 -1
  15. package/dist/core/TopicProfileResolver.d.ts +9 -1
  16. package/dist/core/TopicProfileResolver.d.ts.map +1 -1
  17. package/dist/core/TopicProfileResolver.js +38 -2
  18. package/dist/core/TopicProfileResolver.js.map +1 -1
  19. package/dist/core/TopicProfileStore.d.ts +8 -1
  20. package/dist/core/TopicProfileStore.d.ts.map +1 -1
  21. package/dist/core/TopicProfileStore.js +2 -2
  22. package/dist/core/TopicProfileStore.js.map +1 -1
  23. package/dist/core/classifyProfileChange.d.ts.map +1 -1
  24. package/dist/core/classifyProfileChange.js +32 -1
  25. package/dist/core/classifyProfileChange.js.map +1 -1
  26. package/dist/core/frameworkSessionLaunch.d.ts +28 -1
  27. package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
  28. package/dist/core/frameworkSessionLaunch.js +35 -3
  29. package/dist/core/frameworkSessionLaunch.js.map +1 -1
  30. package/dist/core/topicProfileIngress.d.ts.map +1 -1
  31. package/dist/core/topicProfileIngress.js +14 -0
  32. package/dist/core/topicProfileIngress.js.map +1 -1
  33. package/dist/core/topicProfileValidation.d.ts +12 -0
  34. package/dist/core/topicProfileValidation.d.ts.map +1 -1
  35. package/dist/core/topicProfileValidation.js +30 -0
  36. package/dist/core/topicProfileValidation.js.map +1 -1
  37. package/dist/core/topicProfileWriteSurface.d.ts.map +1 -1
  38. package/dist/core/topicProfileWriteSurface.js +3 -2
  39. package/dist/core/topicProfileWriteSurface.js.map +1 -1
  40. package/dist/core/types.d.ts +1 -0
  41. package/dist/core/types.d.ts.map +1 -1
  42. package/dist/scaffold/templates.d.ts.map +1 -1
  43. package/dist/scaffold/templates.js +1 -0
  44. package/dist/scaffold/templates.js.map +1 -1
  45. package/dist/server/routes.d.ts.map +1 -1
  46. package/dist/server/routes.js +142 -9
  47. package/dist/server/routes.js.map +1 -1
  48. package/package.json +1 -1
  49. package/src/data/builtin-manifest.json +64 -64
  50. package/src/scaffold/templates.ts +1 -0
  51. package/upgrades/1.3.510.md +54 -0
  52. package/upgrades/1.3.511.md +46 -0
  53. package/upgrades/side-effects/multi-machine-seamlessness-ws43-jobs-pool-read.md +88 -0
  54. 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).