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.
- package/dist/commands/setup.d.ts +11 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +31 -14
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/test-as-self.d.ts.map +1 -1
- package/dist/commands/test-as-self.js +2 -1
- package/dist/commands/test-as-self.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +33 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +117 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.d.ts +10 -1
- package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
- package/dist/server/AgentServer.d.ts +8 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +34 -7
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +1 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/AgentDiscovery.d.ts +6 -1
- package/dist/threadline/AgentDiscovery.d.ts.map +1 -1
- package/dist/threadline/AgentDiscovery.js +3 -0
- package/dist/threadline/AgentDiscovery.js.map +1 -1
- package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
- package/dist/threadline/ThreadlineBootstrap.js +20 -2
- package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
- package/dist/threadline/ThreadlineEndpoints.d.ts +2 -0
- package/dist/threadline/ThreadlineEndpoints.d.ts.map +1 -1
- package/dist/threadline/ThreadlineEndpoints.js +13 -1
- package/dist/threadline/ThreadlineEndpoints.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +4 -0
- package/upgrades/1.3.56.md +34 -0
- package/upgrades/1.3.57.md +49 -0
- package/upgrades/side-effects/launchctl-test-hygiene.md +42 -0
- package/upgrades/side-effects/mentee-agent-name-and-botid-coercion.md +55 -0
- package/upgrades/side-effects/test-as-self-skill-demote.md +38 -0
- package/upgrades/side-effects/threadline-identity-discovery-unification.md +100 -0
- 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.
|
package/upgrades/1.3.55.md
DELETED
|
@@ -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`.
|