instar 1.3.55 → 1.3.57

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 (45) hide show
  1. package/dist/commands/setup.d.ts +11 -0
  2. package/dist/commands/setup.d.ts.map +1 -1
  3. package/dist/commands/setup.js +31 -14
  4. package/dist/commands/setup.js.map +1 -1
  5. package/dist/commands/test-as-self.d.ts.map +1 -1
  6. package/dist/commands/test-as-self.js +2 -1
  7. package/dist/commands/test-as-self.js.map +1 -1
  8. package/dist/core/PostUpdateMigrator.d.ts +33 -0
  9. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  10. package/dist/core/PostUpdateMigrator.js +117 -0
  11. package/dist/core/PostUpdateMigrator.js.map +1 -1
  12. package/dist/scaffold/templates.d.ts.map +1 -1
  13. package/dist/scaffold/templates.js +4 -0
  14. package/dist/scaffold/templates.js.map +1 -1
  15. package/dist/scheduler/MentorOnboardingRunner.d.ts +10 -1
  16. package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
  17. package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
  18. package/dist/server/AgentServer.d.ts +8 -0
  19. package/dist/server/AgentServer.d.ts.map +1 -1
  20. package/dist/server/AgentServer.js +34 -7
  21. package/dist/server/AgentServer.js.map +1 -1
  22. package/dist/server/routes.d.ts.map +1 -1
  23. package/dist/server/routes.js +1 -0
  24. package/dist/server/routes.js.map +1 -1
  25. package/dist/threadline/AgentDiscovery.d.ts +6 -1
  26. package/dist/threadline/AgentDiscovery.d.ts.map +1 -1
  27. package/dist/threadline/AgentDiscovery.js +3 -0
  28. package/dist/threadline/AgentDiscovery.js.map +1 -1
  29. package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
  30. package/dist/threadline/ThreadlineBootstrap.js +20 -2
  31. package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
  32. package/dist/threadline/ThreadlineEndpoints.d.ts +2 -0
  33. package/dist/threadline/ThreadlineEndpoints.d.ts.map +1 -1
  34. package/dist/threadline/ThreadlineEndpoints.js +13 -1
  35. package/dist/threadline/ThreadlineEndpoints.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/data/builtin-manifest.json +64 -64
  38. package/src/scaffold/templates.ts +4 -0
  39. package/upgrades/1.3.56.md +34 -0
  40. package/upgrades/1.3.57.md +49 -0
  41. package/upgrades/side-effects/launchctl-test-hygiene.md +42 -0
  42. package/upgrades/side-effects/mentee-agent-name-and-botid-coercion.md +55 -0
  43. package/upgrades/side-effects/test-as-self-skill-demote.md +38 -0
  44. package/upgrades/side-effects/threadline-identity-discovery-unification.md +100 -0
  45. package/upgrades/1.3.55.md +0 -38
@@ -0,0 +1,42 @@
1
+ # Side-Effects Review — launchctl load test-hygiene guard (MM-Bootstrap Track C follow-up)
2
+
3
+ **Scope.** `src/commands/setup.ts` (new `launchctlLoadAllowed()` helper + guard
4
+ at the 2 install-path `launchctl bootstrap` sites: installMacOSLaunchAgent +
5
+ installFleetWatchdog), `tests/unit/launchctl-load-guard.test.ts` (new).
6
+
7
+ **Problem.** The Track C unit test (merged #470) writes a LaunchAgent plist via
8
+ `installAutoStart` to verify the Label-keyed-replace property. But
9
+ `installMacOSLaunchAgent` does a real `launchctl bootstrap` (load) after writing
10
+ — so the test loaded tmpdir-pointed plists into the operator's REAL launchd,
11
+ leaving stale `ai.instar.mmtesthandoff` / `ai.instar.mmteststandby` entries
12
+ (status 78, program gone) after the tmpdir was cleaned. Inert but real
13
+ test-pollution of the user's launchd, discovered 2026-05-28.
14
+
15
+ **Fix.** `launchctlLoadAllowed()` returns false under a test runner (vitest
16
+ auto-sets `VITEST`) or when `INSTAR_SKIP_LAUNCHCTL_LOAD` is set. The two
17
+ install-path bootout+bootstrap blocks are wrapped in it. The plist file is still
18
+ written/removed; only the LIVE load is gated — so the unit-under-test (plist
19
+ content) is unaffected, and production (neither flag set) loads normally.
20
+
21
+ **Side-effects review.**
22
+ - **No production behavior change** — in a normal environment neither VITEST nor
23
+ INSTAR_SKIP_LAUNCHCTL_LOAD is set, so `launchctlLoadAllowed()` is true and the
24
+ load happens exactly as before.
25
+ - **Tests no longer pollute real launchd** — verified: re-running the Track C
26
+ test creates NO mmtesthandoff/mmteststandby entries (the guard skipped the
27
+ load), and the test still passes (it asserts plist CONTENT, not live load).
28
+ - **uninstallAutoStart's bootout is intentionally NOT gated** — that's cleanup
29
+ (removing a real entry), correct to keep even in tests; only the install-path
30
+ LOAD is the pollution vector.
31
+ - **Minimal surface** — one helper + two wraps; no new dependency.
32
+
33
+ **Test coverage.** Unit `tests/unit/launchctl-load-guard.test.ts` (3): false
34
+ under VITEST, false under INSTAR_SKIP_LAUNCHCTL_LOAD, true when neither set
35
+ (production). Plus the existing Track C test now verifiably runs without
36
+ pollution.
37
+
38
+ **Migration parity.** Server source (setup.ts) — existing agents pick up on
39
+ auto-update. No agent-installed-file change; production load behavior unchanged.
40
+
41
+ **Rollback.** Revert. Tests would resume polluting real launchd (inert stale
42
+ entries). No production impact either way.
@@ -0,0 +1,55 @@
1
+ # Side-Effects Review — menteeAgentName + botId coercion + senderBotId fix
2
+
3
+ **Spec:** `docs/specs/MENTOR-LIVE-READINESS-SPEC.md` §Recipient side. Final
4
+ fixes closing the live round-trip (the reply leg landed in #469; these are the
5
+ three remaining wiring bugs found by running it end-to-end).
6
+
7
+ **Change:** `src/scheduler/MentorOnboardingRunner.ts` (+1 optional config
8
+ field) + `src/server/AgentServer.ts` (menteeAgentName usage at 3 derivation
9
+ sites, botId String-coercion at 3 allowlist sites, senderBotId=sender's-own
10
+ via new `ownPrimaryBotId()` helper) + extended E2E test.
11
+
12
+ ## What changed
13
+ 1. `MentorConfig.menteeAgentName?: string` — the mentee's real registry name.
14
+ Used in `deliverToMentee`, `installMentorMessageHook` (mentor side), and
15
+ `installMentorReceiverHook`, each falling back to `instar-${menteeFramework}`.
16
+ 2. botId `String()`-coercion at every knownAgents construction (mentor side,
17
+ mentee side, receiver hook) — config may store a JSON number; the marker
18
+ senderBotId is always a string; the allowlist uses `===`.
19
+ 3. `deliverA2aMessage` now takes `fromBotId` (sender's own bot id) and sends
20
+ it as the inbox `senderBotId`. `ownPrimaryBotId()` derives this agent's bot
21
+ id from its messaging config token. Replies pass `ownPrimaryBotId()`; sends
22
+ pass the mentor bot id.
23
+
24
+ ## The seven questions
25
+ 1. **Over-block.** N/A — these LOOSEN an over-strict (buggy) comparison that
26
+ was dropping legitimate replies. Coercion only makes a number match its
27
+ string form; it does not widen the allowlist to new agents.
28
+ 2. **Under-block.** The allowlist still requires an exact (coerced) botId
29
+ match + known agent name. Spoof defense intact — a wrong botId still drops.
30
+ 3. **Level-of-abstraction fit.** Small, local fixes at the exact sites; one
31
+ tiny helper (`ownPrimaryBotId`). No new infrastructure.
32
+ 4. **Signal vs authority.** Unchanged — allowlist still decides route/drop.
33
+ 5. **Interactions.** `menteeAgentName` defaults preserve back-compat for any
34
+ agent whose registry name already equals `instar-<framework>`. Coercion is
35
+ idempotent on already-string values.
36
+ 6. **External surfaces.** One new optional config key (`mentor.menteeAgentName`).
37
+ No new routes.
38
+ 7. **Rollback cost.** Trivial — revert restores framework-derived names + the
39
+ number/string comparison (re-introducing the silent reply drop).
40
+
41
+ ## Testing
42
+ Extended `mentor-reply-via-inbox` E2E (now 2 cases): the original
43
+ (framework-derived name, string botId) + the new regression (menteeAgentName
44
+ override, numeric-configured botId, string senderBotId) — both route + persist.
45
+ All prior mentor/mentee/inbox tests green. tsc clean.
46
+
47
+ **Live verification (test-as-self):** the worktree build was shadow-deployed to
48
+ the live Echo + Codey pair; a real mentor prompt round-tripped — Codey spawned
49
+ a mentee session, replied via /a2a/inbox, and Echo persisted the reply to
50
+ mentor-replies.jsonl (corr=FULL-…, from=instar-codey, transport=a2a-inbox-local).
51
+
52
+ ## Migration parity
53
+ `mentor.menteeAgentName` is optional with a back-compat default — no migration
54
+ needed. The botId coercion + senderBotId fix are pure code (no config/state
55
+ change). No PostUpdateMigrator change.
@@ -0,0 +1,38 @@
1
+ # Side-Effects Review — test-as-self SKILL Part 2.1 demote + migrator (Track F follow-up)
2
+
3
+ **Scope.** `.claude/skills/test-as-self/SKILL.md` (lead with the one-button
4
+ command, demote the manual recipe to fallback), `src/core/PostUpdateMigrator.ts`
5
+ (`migrateTestAsSelfSkill` + registration), `tests/unit/migrate-test-as-self-skill.test.ts`.
6
+
7
+ **What + why.** Track F shipped the `instar test-as-self` command but left the
8
+ SKILL.md as the v1 manual runbook (deferred, tracked). This closes that loop:
9
+ the SKILL now leads with "## The one-button path (Part 2.1 — use this first)"
10
+ (the command), with the manual recipe demoted to fallback — so an agent reading
11
+ the skill reaches for the command first. Plus a PostUpdateMigrator method so
12
+ EXISTING agents' on-disk SKILL.md gets the update (installBuiltinSkills is
13
+ install-if-missing, so a dedicated migration is the only path per the Migration
14
+ Parity Standard).
15
+
16
+ **Side-effects review.**
17
+ - **Content-only skill change** — no behavior change; the command itself shipped
18
+ in Track F (#472). This just makes it discoverable in the skill surface.
19
+ - **Migration is conservative + idempotent** — re-copies the bundled SKILL only
20
+ when the installed copy LACKS the Part 2.1 marker AND still matches the stock
21
+ fingerprint (`Throwaway-Deploy Harness` + `verify.mjs`). A customized skill is
22
+ left untouched (recorded in result.skipped); an already-updated one is a no-op;
23
+ a not-installed one is a no-op. Mirrors the proven migrateBuildSkillMethodology
24
+ pattern exactly.
25
+ - **No data/secret impact** — pure doc/skill content.
26
+
27
+ **Test coverage.** Unit `tests/unit/migrate-test-as-self-skill.test.ts` (4):
28
+ stock-v1 → updated (marker present, result.upgraded set); idempotent (already-
29
+ marked → unchanged, no upgrade); customized → untouched (result.skipped);
30
+ not-installed → no-op (no error). All green; tsc clean. The test also implicitly
31
+ verifies the bundled SKILL.md carries the new marker.
32
+
33
+ **Migration parity.** This IS the migration-parity fix for Track F's SKILL
34
+ update. New agents get the new SKILL via installBuiltinSkills; existing agents
35
+ get it via `migrateTestAsSelfSkill` on update.
36
+
37
+ **Rollback.** Revert. The SKILL reverts to the v1 manual-first runbook; the
38
+ command still works (it's independent). No data change.
@@ -0,0 +1,100 @@
1
+ # Side-Effects Review — Threadline Identity-Discovery Unification
2
+
3
+ **Slug:** `threadline-identity-discovery-unification`
4
+ **Date:** 2026-05-28
5
+ **Author:** Echo (instar developer)
6
+ **Spec:** `docs/specs/threadline-identity-discovery-unification.md` (converged iter 2, approved)
7
+
8
+ ## Summary of the change
9
+
10
+ Discovery was advertising an identity the agent's own relay does not answer to.
11
+ `announcePresence` wrote `agent-info.json.publicKey` from the orphan
12
+ `threadline/identity-keys.json` hex key, and `/threadline/health` reported
13
+ `identityPub` from the HandshakeManager key (empty on some agents) — while the
14
+ relay client registers (and routes) by the canonical `identity.json`
15
+ fingerprint. A peer who discovered the agent got a non-routable address, so
16
+ their messages vanished (their side `sent=true`, no "Accepted message from …"
17
+ on the receiver). Fleet-wide for any agent whose canonical identity was
18
+ generated independently of its legacy keys.
19
+
20
+ The fix advertises the **routing identity** everywhere, internally consistent:
21
+ `agent-info.json` and `/threadline/health` now publish a `fingerprint`
22
+ (routable relay address) plus a `publicKey`/`identityPub` set to the SAME
23
+ canonical key, sourced from `IdentityManager.get()` — the exact read-only API
24
+ the relay client uses, so the two can never re-diverge.
25
+
26
+ **Files changed (source):**
27
+ - `src/threadline/AgentDiscovery.ts` — `fingerprint` field on `AgentInfoFile`,
28
+ `ThreadlineAgentInfo`, `HealthResponse`; `announcePresence` accepts +
29
+ persists it; `pingThreadlineHealth`/`verifyAgent` propagate it.
30
+ - `src/threadline/ThreadlineBootstrap.ts` — resolve `IdentityManager.get()` up
31
+ front; advertise canonical `publicKey`(hex)+`fingerprint`+`machine`; omit both
32
+ when `get()` is null (no fabrication).
33
+ - `src/threadline/ThreadlineEndpoints.ts` — `/threadline/health` sources
34
+ `identityPub`+`fingerprint` from `IdentityManager.get()`; `stateDir` added to
35
+ config; falls back to the handshake key + omits fingerprint when no routing
36
+ identity resolves.
37
+ - `src/server/routes.ts` — pass `stateDir` to `createThreadlineRoutes`.
38
+ - `src/core/PostUpdateMigrator.ts` — `migrateThreadlineAgentInfoIdentity`
39
+ (belt-and-suspenders fleet repair) + `migrateClaudeMd` routing-fingerprint
40
+ guidance section.
41
+ - `src/scaffold/templates.ts` — CLAUDE.md template "What address reaches me"
42
+ section (Agent Awareness).
43
+ - `src/data/builtin-manifest.json` — regenerated by the build (template hashes).
44
+
45
+ **Files changed (tests):** `ThreadlineBootstrap.test.ts`,
46
+ `ThreadlineEndpoints.test.ts` (+3 new: migrator unit, health integration,
47
+ bootstrap wiring e2e).
48
+
49
+ **Drive-by (unrelated, green-keeping):** `src/commands/test-as-self.ts` line 60
50
+ — `new URL(import.meta.url).pathname` → `fileURLToPath(import.meta.url)`. This
51
+ is the URL-pathname-path-encoding pattern (breaks when the project path
52
+ contains spaces) that the pre-push gate (`scripts/pre-push-gate.js`) flags; it
53
+ was introduced into `test-as-self.ts` by an earlier merge and the pre-push gate
54
+ blocks any push until it is fixed (the check is pre-push-only, not in CI, which
55
+ is why it landed). One-line fix to the documented-correct pattern; no behavior
56
+ change.
57
+
58
+ ## Blast radius / consumers
59
+
60
+ - **`agent-info.json.publicKey` encoding** is unchanged (hex) and now sourced
61
+ from the canonical key. Consumers (`verifyAgent` does `Buffer.from(.., 'hex')`
62
+ + 32-byte length check) still work; the key is a valid 32-byte Ed25519 key.
63
+ - **`/threadline/health.identityPub`** switches from the handshake key to the
64
+ canonical routing key WHEN one resolves. Safe: `verifyAgent` does not perform
65
+ a real cryptographic challenge (nonce generated, never exchanged), and the E2E
66
+ handshake exchanges keys inline — it does not read `agent-info.json` or the
67
+ health `identityPub`. Verified by reading `ThreadlineEndpoints.ts` handshake
68
+ paths + `AgentDiscovery.verifyAgent`.
69
+ - **No-fabrication boundary:** a relay-disabled / no-identity / locked-encrypted
70
+ agent now OMITS `fingerprint`+`publicKey` instead of advertising a key for an
71
+ identity on no relay. This is a behavior change for brand-new agents on their
72
+ very first announce (before the relay client creates an identity) — correct
73
+ per spec (not relay-discoverable until a routing identity exists), self-heals
74
+ on the next boot once the identity is created.
75
+ - **Migrator** only rewrites `agent-info.json` when `get()` resolves AND the
76
+ file is misaligned; no-ops otherwise (idempotent, atomic write, never
77
+ fabricates).
78
+
79
+ ## Migration parity
80
+
81
+ Existing agents: the in-`announcePresence` rewrite self-heals on the
82
+ post-update server restart; `migrateThreadlineAgentInfoIdentity` closes the
83
+ narrow update-without-restart window; `migrateClaudeMd` adds the guidance for
84
+ agents whose CLAUDE.md predates this. New agents get all of it via `init` +
85
+ the template.
86
+
87
+ ## Out of scope (tracked, not deferred)
88
+
89
+ - Multi-machine same-fingerprint advertisement coordination →
90
+ `project_cross_machine_seamlessness_spec`. This fix sets the `machine` field
91
+ (attributable) and is neutral for multi-machine.
92
+ - Retiring the orphan `identity-keys.json` / collapsing the 3–4 keypairs →
93
+ `bug_threadline_identity_divergence_discovery`. This fix stops *advertising*
94
+ the orphan; deleting it touches the handshake layer and needs its own spec.
95
+
96
+ ## Risk
97
+
98
+ Low. Additive at the field level; `agent-info.json` is regenerated on every
99
+ boot regardless. Reverting removes the field + migrator with no data loss. All
100
+ three test tiers + wiring + both-sides green; full `test:push` suite green.
@@ -1,38 +0,0 @@
1
- # Instar Upgrade Guide — NEXT
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- **Post-publish smoke gate (publish-pipeline regression insurance).** A new step
8
- after `npm publish` clean-installs the just-published version into a throwaway
9
- prefix and runs `instar --version`, asserting the tarball actually installs and
10
- reports the right version. If the publish pipeline ever ships a tarball missing
11
- its compiled output, this catches it within minutes of release instead of when a
12
- fresh install fails in the wild. (Track A was re-scoped from a "fix" to this gate:
13
- the original "empty dist" scare was self-inflicted, not a real publish bug.)
14
-
15
- ## What to Tell Your User
16
-
17
- - Internal release-pipeline hardening: after I publish a new version, CI now
18
- immediately does a clean install of it and checks it runs, so a broken release
19
- can't slip out unnoticed. Nothing changes for you — it's a safety net on my own
20
- shipping process.
21
-
22
- ## Summary of New Capabilities
23
-
24
- | Capability | How to Use |
25
- |-----------|-----------|
26
- | Post-publish smoke gate | Automatic in the publish workflow — clean-installs the just-published version + asserts `instar --version`. |
27
-
28
- ## Evidence
29
-
30
- **Re-scoped to regression insurance (the original premise was a self-inflicted
31
- artifact, not a bug).** `scripts/post-publish-smoke.mjs` waits for npm
32
- propagation, clean-installs into a throwaway prefix, asserts `dist/cli.js` exists
33
- + `--version` matches. Unit test `tests/unit/post-publish-smoke.test.ts` (4)
34
- covers the pure version-match logic incl the 1.3.5-vs-1.3.55 substring trap.
35
- `publish.yml` validates as YAML; the step mirrors the existing publish steps'
36
- structure + gating. Side-effects review:
37
- `upgrades/side-effects/publish-completeness-smoke-gate.md`. Spec: Track A of
38
- `docs/specs/MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS-SPEC.md`.