instar 1.3.470 → 1.3.472

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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-10T16:53:50.243Z",
5
- "instarVersion": "1.3.470",
4
+ "generatedAt": "2026-06-10T18:08:30.928Z",
5
+ "instarVersion": "1.3.472",
6
6
  "entryCount": 201,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
14
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
23
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
32
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
41
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
50
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
59
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
68
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
77
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
86
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-collector": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
95
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
95
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:scope-coherence-checkpoint": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
104
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
104
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:free-text-guard": {
@@ -110,7 +110,7 @@
110
110
  "domain": "safety",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
113
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
113
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
122
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
122
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept-response": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
131
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
131
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:stop-gate-router": {
@@ -137,7 +137,7 @@
137
137
  "domain": "safety",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
140
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
140
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:auto-approve-permissions": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
149
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
149
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "job:health-check": {
@@ -1530,7 +1530,7 @@
1530
1530
  "type": "subsystem",
1531
1531
  "domain": "sessions",
1532
1532
  "sourcePath": "src/core/SessionManager.ts",
1533
- "contentHash": "f1ade5cb42806c31d0ebe24e86e66f3fa331f288ec99bae5d8df0a08622b6eb9",
1533
+ "contentHash": "7c1e84f9d52be2ebff9c3701138f9b65d488ae7ff51ee1e8681d8476c66907fd",
1534
1534
  "since": "2025-01-01"
1535
1535
  },
1536
1536
  "subsystem:auto-updater": {
@@ -1554,7 +1554,7 @@
1554
1554
  "type": "subsystem",
1555
1555
  "domain": "updates",
1556
1556
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1557
- "contentHash": "c4b6d22bcb02a0ce956d38326c9d764b47bac8c37545ccf287bef29f9912f908",
1557
+ "contentHash": "91a08551e1f1c321ae5b923cc68577dd8bda1381bc810d8e3444295947b00ab4",
1558
1558
  "since": "2025-01-01"
1559
1559
  },
1560
1560
  "subsystem:scheduler": {
@@ -0,0 +1,50 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The `/spec-converge` review's Lessons-aware reviewer gained a new mandate — clause
9
+ **(d) FOUNDATION/SUBSYSTEM AUDIT**: the review must now reach one layer below the spec
10
+ boundary and weigh the subsystem the spec *tests, extends, or builds on* against known
11
+ standards and lessons, not just the spec's own surface. When that foundation is flawed,
12
+ the finding is "this spec is sound but the subsystem it depends on violates standard X /
13
+ repeats mistake Y — surface it before building on/around it."
14
+
15
+ This closes a real review gap (2026-06-09): a test-harness spec converged cleanly while
16
+ the permission gate it proved still held brittle blocking authority in violation of
17
+ Signal-vs-Authority. The convergence audited only the harness and took the flawed
18
+ foundation as given. A new idempotent `PostUpdateMigrator` step
19
+ (`migrateSpecConvergeFoundationAudit`) backfills the clause into existing agents'
20
+ installed spec-converge skill on update (fingerprint-guarded; customized skills are left
21
+ untouched).
22
+
23
+ ## What to Tell Your User
24
+
25
+ Nothing changes for end users — this is an internal hardening of the instar
26
+ spec-review process used by instar-developing agents. No runtime behavior, gate, or
27
+ message path changes. The practical effect is that future instar specs are reviewed one
28
+ layer deeper, so a spec can no longer pass review while quietly testing or extending a
29
+ component that itself violates a standard.
30
+
31
+ ## Summary of New Capabilities
32
+
33
+ - `/spec-converge` Lessons-aware reviewer clause (d): foundation/subsystem audit one
34
+ layer below the spec boundary.
35
+ - `PostUpdateMigrator.migrateSpecConvergeFoundationAudit`: idempotent, fingerprint-guarded
36
+ backfill of the clause for existing agents (customized skills untouched).
37
+
38
+ ## Evidence
39
+
40
+ - `skills/spec-converge/SKILL.md` — clause (d) added to the Lessons-aware bullet.
41
+ - `src/core/PostUpdateMigrator.ts` — `migrateSpecConvergeFoundationAudit` registered in
42
+ the migrate runner; mirrors the established fingerprint-guarded skill-content migration
43
+ idiom (`migrateInstarDevInternalOnlyReleaseNoteLane`, `migrateTestAsSelfSkill`).
44
+ - `tests/unit/migrate-spec-converge-foundation-audit.test.ts` — 5 tests: updates a stock
45
+ skill, idempotent when the marker is present, leaves a customized skill untouched,
46
+ no-ops when not installed, and a wiring-integrity test asserting the bundled source
47
+ actually carries the marker (so the migration cannot silently no-op for every agent).
48
+ - `tsc --noEmit` clean; sibling skill-migration + builtin-dev-skills suites green (19
49
+ tests across the touched area).
50
+ - Side-effects review: `upgrades/side-effects/spec-converge-foundation-audit.md`.
@@ -0,0 +1,40 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The interactive (user-facing) session lane now pins to a subscription-pool account,
9
+ mirroring the headless lane. When `subscriptionPool.pinSessionsToPool` is enabled,
10
+ `SessionManager.spawnInteractiveSession` consults the same spawn-account resolver
11
+ that `spawnSession` uses (unless the caller passed an explicit `configHome`, e.g. the
12
+ account-swap path, which still wins). The session launches under the scheduler-picked
13
+ pool account's config home and is tagged with `subscriptionAccountId` — making the
14
+ user's own conversation directly eligible for proactive and reactive auto-swap,
15
+ instead of riding the default login untagged (rescuable only by the
16
+ ProactiveSwapMonitor's default-login fallback). The resolver-pinned home is seeded
17
+ onboarding-ready first, so a headless-enrolled home can't wedge the launch on the
18
+ first-launch wizard. Claude-code only; complete no-op when pinning is off.
19
+
20
+ ## What to Tell Your User
21
+
22
+ The conversation you actually chat with is now protected the same first-class way
23
+ your background sessions are. When you pool several logins, your own chat session is
24
+ tagged to whichever login it is running on, so the moment that login gets close to
25
+ full I can move your conversation to a fresh login before it ever stalls — not just
26
+ rescue it after the fact. Nothing changes unless you have pooling turned on.
27
+
28
+ ## Summary of New Capabilities
29
+
30
+ - The interactive session lane pins to a pool account and carries its account tag,
31
+ so the user's conversation is first-class for both proactive and reactive swap.
32
+
33
+ ## Evidence
34
+
35
+ - `tests/unit/interactive-session-pin.test.ts` — 6 cases: resolver-pin, explicit
36
+ home wins, unwired no-op, empty-pool no-op, codex-not-pinned, onboarding-safe seeding.
37
+ - `tests/integration/subscription-pin-sessions.test.ts` — interactive lane pins via
38
+ the real `selectAccount`-wired resolver; empty-pool no-op.
39
+ - `tests/e2e/session-management-e2e.test.ts` — real tmux: an interactive session is
40
+ tagged with the resolver-picked account and its home is seeded onboarding-ready.
@@ -0,0 +1,47 @@
1
+ # Side-effects review — Pin the interactive session lane (B1)
2
+
3
+ **Change:** `SessionManager.spawnInteractiveSession` now consults the wired
4
+ spawn-account resolver (set under `subscriptionPool.pinSessionsToPool`) when the
5
+ caller did not pass an explicit `configHome`. The interactive (user-facing) lane
6
+ launches under, and is tagged with, the scheduler-picked pool account — mirroring
7
+ the headless lane (`spawnSession`). One file: `src/core/SessionManager.ts`.
8
+
9
+ ## Blast radius
10
+
11
+ - **Scope is gated three ways.** No-op unless (a) `pinSessionsToPool` wired the
12
+ resolver, (b) the framework is `claude-code`, and (c) the caller passed no
13
+ explicit `configHome`. With pooling off the resolver is never set → `pinnedAccount`
14
+ is null → `effectiveConfigHome`/`effectiveAccountId` are undefined → byte-for-byte
15
+ the prior default-login behavior.
16
+ - **Explicit configHome still wins.** The account-swap path (SessionRefresh) passes
17
+ a `configHome`; that suppresses the resolver, so a swap target is never overridden.
18
+ - **Non-claude lanes untouched.** Codex/Pi interactive sessions are never put on a
19
+ Claude pool home (the `framework === 'claude-code'` guard).
20
+
21
+ ## Interactions considered
22
+
23
+ - **Onboarding-safe seeding (#1043):** `ensurePinnedHomeInteractiveReady` is now
24
+ invoked for the resolver-pinned home too (not only explicit-configHome), so a
25
+ headless-enrolled pool home is seeded interactive-ready before the launch — the
26
+ 2026-06-09 wizard-wedge cannot recur via this new path. Tokens/oauthAccount are
27
+ never read or written by that helper.
28
+ - **ProactiveSwapMonitor / autoSwapOnRateLimit:** these key on
29
+ `session.subscriptionAccountId`. B1 makes the interactive session carry that tag,
30
+ so it becomes directly swap-eligible. The monitor's default-login resolution
31
+ remains the safety net for the still-untagged case (pooling off / empty pool).
32
+ - **`tmuxSessionExists` early-return:** an already-running session is reused and not
33
+ re-pinned — correct; live sessions are moved by the swap engine, not re-tagged here.
34
+ - **Fail-safe:** `ensureInteractiveReady` logs and continues on a missing/unwritable
35
+ home; a launch never crashes on it (verified by the unit case using a fake path).
36
+
37
+ ## Migration / awareness
38
+
39
+ - No config default, hook, skill, or CLAUDE.md template change → no `PostUpdateMigrator`
40
+ entry required. B1 rides the existing `pinSessionsToPool` flag; the user-facing
41
+ continuity capability is already documented (template "Pre-limit (proactive) swap"
42
+ bullet). Existing agents pick up the behavior on the normal code update.
43
+
44
+ ## Tests
45
+
46
+ Unit (6), integration (+2 interactive cases in the existing pin suite), e2e (+1 real
47
+ tmux case). Full sibling spawn/session/wiring suites green (96 tests). tsc clean.
@@ -0,0 +1,92 @@
1
+ # Side-Effects Review — spec-converge clause (d) foundation/subsystem audit
2
+
3
+ **Version / slug:** `spec-converge-foundation-audit`
4
+ **Date:** `2026-06-10`
5
+ **Author:** `echo`
6
+ **Tier:** `1` (skill-prompt clause + idempotent content migration + tests; no new runtime subsystem, route, or config)
7
+ **Second-pass reviewer:** `not required`
8
+
9
+ ## Summary of the change
10
+
11
+ Extend the `/spec-converge` Lessons-aware reviewer's mandate with clause **(d)
12
+ FOUNDATION/SUBSYSTEM AUDIT**: the review must reach one layer below the spec boundary
13
+ and weigh the subsystem the spec *tests / extends / builds on* against known standards
14
+ and lessons — not just the spec's own surface. When that foundation is flawed, the
15
+ finding is "this spec is sound but the subsystem it depends on violates standard X /
16
+ repeats mistake Y — surface it before building on/around it."
17
+
18
+ Two edits + tests:
19
+ 1. `skills/spec-converge/SKILL.md` — the bundled source skill gains clause (d) on the
20
+ Lessons-aware bullet (the `## Internal reviewers` section).
21
+ 2. `src/core/PostUpdateMigrator.ts` — a new `migrateSpecConvergeFoundationAudit`
22
+ (registered in the migrate runner) so existing agents' installed
23
+ `.claude/skills/spec-converge/SKILL.md` receives clause (d) on update. Idempotent +
24
+ conservative: re-copies the bundled skill only when the installed copy (a) lacks the
25
+ `FOUNDATION/SUBSYSTEM AUDIT` marker AND (b) still matches the stock spec-converge
26
+ fingerprint (`# /spec-converge` + `**Internal reviewers (Claude subagents):**`). A
27
+ customized skill is skipped untouched.
28
+ 3. `tests/unit/migrate-spec-converge-foundation-audit.test.ts` — 5 tests (update,
29
+ idempotent, customized-untouched, not-installed no-op, bundled-source wiring
30
+ integrity).
31
+
32
+ Motivation: the 2026-06-09 gap where a test-harness spec converged cleanly while the
33
+ permission gate it proved still held brittle blocking authority in violation of
34
+ Signal-vs-Authority. The convergence audited only the harness and took the flawed
35
+ foundation as given. This closes that gap structurally (Structure > Willpower): the
36
+ reviewer is *instructed* to look below the spec, rather than the author having to
37
+ remember to.
38
+
39
+ ## Decision-point inventory
40
+
41
+ - **Migration content-sniff guard** — re-copy vs. skip. Inputs: installed skill text.
42
+ Branch 1: marker already present → return (idempotent no-op). Branch 2: stock
43
+ fingerprint missing → skip + record `customized`. Branch 3: stock fingerprint present
44
+ AND marker absent → re-copy the bundled skill. No LLM, no runtime authority — pure
45
+ string-presence checks at update time.
46
+
47
+ ## 1. Over-block
48
+
49
+ **What legitimate inputs does this change reject?** Nothing is rejected at runtime — no
50
+ gate, no message path, no API. The migration's only "rejection" is *declining to update*
51
+ a skill it can't confidently recognize as stock (fingerprint missing → skipped). That is
52
+ the safe direction: a customized spec-converge skill keeps the operator's edits rather
53
+ than being clobbered. The reviewer clause makes the review *stricter* (one more thing to
54
+ check), but the Lessons-aware reviewer is signal-only — it surfaces findings, it does not
55
+ block; blocking authority remains the separate Standards-Conformance Gate path.
56
+
57
+ ## 2. Under-block
58
+
59
+ **What does this still miss?** (a) The clause is a *prompt* instruction, so its
60
+ effectiveness depends on the reviewing model actually reaching one layer down — it is a
61
+ stronger signal, not a code-enforced guarantee (a future code-backed "foundation
62
+ referenced by the spec was audited" check could harden it, but that is out of scope for a
63
+ Tier-1 prompt change). (b) The migration re-copies the *whole* bundled skill (matching the
64
+ established skill-migration idiom); an agent on a much older stock version receives all
65
+ accumulated bundled changes, not just clause (d) — acceptable because the fingerprint
66
+ guard only fires on stock copies. (c) Agents who customized the skill are intentionally
67
+ not upgraded; they must adopt clause (d) by hand.
68
+
69
+ ## 3. Level-of-abstraction fit
70
+
71
+ **Right layer?** Yes. The clause lives in the one reviewer whose job is standards/lessons
72
+ conformance (Lessons-aware), beside its existing (a)/(b)/(c) checks — not bolted onto an
73
+ unrelated reviewer. The migration lives beside the sibling skill-content migrations
74
+ (`migrateInstarDevInternalOnlyReleaseNoteLane`, `migrateTestAsSelfSkill`) and reuses their
75
+ exact fingerprint-guarded re-copy pattern, so it inherits the proven Migration-Parity
76
+ idiom rather than inventing a new one.
77
+
78
+ ## Migration / rollback
79
+
80
+ - **Migration:** `migrateSpecConvergeFoundationAudit` runs on the normal post-update path.
81
+ Idempotent (marker check) and conservative (fingerprint guard). No state, no config.
82
+ - **Rollback:** pure revert — drop the clause from the bundled skill, remove the migration
83
+ method + its registration line, delete the test. No data migration to undo; the migration
84
+ only ever copied a newer skill prompt over a stock older one.
85
+
86
+ ## Testing-integrity note
87
+
88
+ Unit tests cover both sides of the migration's decision boundary (updates stock /
89
+ skips customized / idempotent / not-installed) plus a wiring-integrity test asserting the
90
+ bundled source actually carries the marker (so the migration cannot silently no-op for
91
+ every agent). `tsc --noEmit` clean; sibling skill-migration + builtin-dev-skills suites
92
+ stay green (19 tests total across the touched area).