instar 1.3.129 → 1.3.131
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 +12 -4
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +4 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/InstarWorktreeManager.d.ts +13 -0
- package/dist/core/InstarWorktreeManager.d.ts.map +1 -1
- package/dist/core/InstarWorktreeManager.js +33 -4
- package/dist/core/InstarWorktreeManager.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +9 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +60 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +39 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +104 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +7 -5
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +12 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +7 -5
- package/src/templates/scripts/instar-worktree-create.sh +4 -0
- package/upgrades/1.3.130.md +74 -0
- package/upgrades/1.3.131.md +56 -0
- package/upgrades/side-effects/sessionreaper-cpu-aware-and-decision-audit.md +122 -0
- package/upgrades/side-effects/worktree-spotlight-exclusion.md +81 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**The SessionReaper now reaps under CPU pressure, not only memory — and keeps a
|
|
8
|
+
silent, reviewable record of every decision it makes.**
|
|
9
|
+
|
|
10
|
+
The idle-session reaper used to compute its pressure tier purely from free
|
|
11
|
+
memory. But on a busy multi-agent box the real squeeze is almost always CPU, not
|
|
12
|
+
RAM (free memory can look fine while the load average is well past the core
|
|
13
|
+
count). So an idle session could sit holding CPU baseline indefinitely and the
|
|
14
|
+
reaper, watching only memory, would never wake up.
|
|
15
|
+
|
|
16
|
+
Pressure is now the WORST of two signals: memory (free %) and CPU (1-minute load
|
|
17
|
+
average ÷ core count). A CPU-bound box raises the tier even when memory is fine,
|
|
18
|
+
so genuinely-idle sessions become eligible under load — while the reaper's
|
|
19
|
+
positive-idle proof, hysteresis, confirmation window, rate limits, and grace
|
|
20
|
+
period are all unchanged, so it still never reaps a working session. The two CPU
|
|
21
|
+
thresholds are configurable; sensible defaults ship (moderate at 1.0 load per
|
|
22
|
+
core, critical at 1.5), and a transient build spike won't trigger a reaping spree
|
|
23
|
+
because the existing 3-observation confirmation smooths it.
|
|
24
|
+
|
|
25
|
+
Second, the reaper now writes a dedicated decision audit trail. Previously its
|
|
26
|
+
structured events were mixed into the shared sentinel log and only covered the
|
|
27
|
+
reap path — there was no record of the routine keep decisions, so "what is the
|
|
28
|
+
reaper considering, and why?" had no grounded answer. It now logs every keep/kill
|
|
29
|
+
decision change (on transition, not every tick, so a multi-day kept session logs
|
|
30
|
+
once) plus the reap-path events, each stamped with the pressure tier that drove
|
|
31
|
+
it, to a dedicated file readable through a new read-only endpoint.
|
|
32
|
+
|
|
33
|
+
## What to Tell Your User
|
|
34
|
+
|
|
35
|
+
Nothing to configure. Your idle-session cleanup is now aware of CPU load, not
|
|
36
|
+
just memory — so on a busy machine it can finally relieve pressure that free
|
|
37
|
+
memory alone would have hidden. It is still just as careful: it never touches a
|
|
38
|
+
session that might be working. You can also now ask me what the cleanup is
|
|
39
|
+
considering and why it kept or shut down any session — there is a quiet,
|
|
40
|
+
inspectable decision log behind it. None of this sends you notifications; it is
|
|
41
|
+
all there for when you want to look.
|
|
42
|
+
|
|
43
|
+
## Summary of New Capabilities
|
|
44
|
+
|
|
45
|
+
- Reaper pressure is CPU-aware: tier is the worst of memory (free %) and CPU
|
|
46
|
+
(1-min load ÷ cores), via the new pure `computePressure()` classifier.
|
|
47
|
+
- Two new tunable thresholds: `cpuModerateLoadPerCore` (default 1.0) and
|
|
48
|
+
`cpuCriticalLoadPerCore` (default 1.5) under `monitoring.sessionReaper`.
|
|
49
|
+
Existing agents receive them automatically via the canonical config defaults.
|
|
50
|
+
- `GET /sessions/reaper`'s `pressure.inputs` now exposes `freePct`,
|
|
51
|
+
`loadPerCore`, and the `memTier`/`cpuTier` breakdown.
|
|
52
|
+
- New read-only endpoint `GET /sessions/reaper/audit?limit=N` returns the tail
|
|
53
|
+
of the dedicated decision trail at `logs/reaper-audit.jsonl`.
|
|
54
|
+
- A `decision` audit row is written on first sight and on every (verdict,
|
|
55
|
+
keptBy) change — transition-only, so no per-tick log spam. Silent: no Telegram,
|
|
56
|
+
no attention items.
|
|
57
|
+
|
|
58
|
+
## Evidence
|
|
59
|
+
|
|
60
|
+
- `tests/unit/session-reaper-pressure-audit.test.ts` — new: `computePressure`
|
|
61
|
+
(memory-only when cores unknown, CPU-raises-tier, worst-of combos, custom
|
|
62
|
+
thresholds, non-finite load ignored); the `reaperAuditSink`/`readReaperAudit`
|
|
63
|
+
round-trip (bounded tail, `[]` when absent); and the transition-only decision
|
|
64
|
+
audit (logs on first sight + on change, not when unchanged).
|
|
65
|
+
- `tests/integration/session-reaper-routes.test.ts` — new: `GET
|
|
66
|
+
/sessions/reaper/audit` returns 200 with the tail, honors `?limit`, and `[]`
|
|
67
|
+
when no trail exists.
|
|
68
|
+
- `tests/e2e/session-reaper-lifecycle.test.ts` — new Phase-1 "feature alive"
|
|
69
|
+
test: the audit route returns 200 (not 503) through the real AgentServer
|
|
70
|
+
plumbing and reads a written row back.
|
|
71
|
+
- `tests/unit/feature-delivery-completeness.test.ts` + `capabilities-discoverability.test.ts`
|
|
72
|
+
green: migrator parity (new `migrateClaudeMd` section), config parity, and
|
|
73
|
+
route classification all satisfied.
|
|
74
|
+
- Full `npm run lint` + the reaper test tiers pass.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**Agent worktrees are now excluded from macOS Spotlight indexing — a top
|
|
8
|
+
OS-level CPU drain on multi-worktree machines.**
|
|
9
|
+
|
|
10
|
+
Each `instar worktree create` leaves a full source tree on disk under the agent's
|
|
11
|
+
`.worktrees/` directory. macOS Spotlight (mds_stores) and mediaanalysisd treat
|
|
12
|
+
every one of those trees as new content to index and re-index — and on a machine
|
|
13
|
+
that has accumulated dozens of worktrees that becomes one of the single biggest
|
|
14
|
+
CPU consumers on the box (measured: mediaanalysisd pulling ~80% CPU under a
|
|
15
|
+
~120-worktree backlog), entirely separate from anything instar's own code is
|
|
16
|
+
doing.
|
|
17
|
+
|
|
18
|
+
instar now drops a single `.metadata_never_index` marker at the `.worktrees/`
|
|
19
|
+
container root, which tells Spotlight to skip that whole subtree. New worktrees
|
|
20
|
+
are covered automatically at creation time, and existing agents get the marker
|
|
21
|
+
backfilled on update via a new migration. The marker lives at the container (not
|
|
22
|
+
inside any worktree, so it adds no git noise), is honored recursively for every
|
|
23
|
+
worktree beneath it, is harmless on non-macOS, and is idempotent.
|
|
24
|
+
|
|
25
|
+
This is the first piece of the **OS resource hygiene** facet of the Responsible
|
|
26
|
+
Resource Usage standard.
|
|
27
|
+
|
|
28
|
+
## What to Tell Your User
|
|
29
|
+
|
|
30
|
+
Nothing to configure. On a Mac, the throwaway worktrees instar creates for
|
|
31
|
+
parallel development will no longer be re-indexed by Spotlight — which quietly
|
|
32
|
+
removes a large chunk of background CPU load that had nothing to do with your
|
|
33
|
+
agents actually working. If you have built up a lot of worktrees over time, you
|
|
34
|
+
should feel this as lower idle CPU after the update settles.
|
|
35
|
+
|
|
36
|
+
## Summary of New Capabilities
|
|
37
|
+
|
|
38
|
+
- `instar worktree create` (and the convention wrapper's fallback path) drop a
|
|
39
|
+
`.metadata_never_index` marker at the `.worktrees/` container so Spotlight skips
|
|
40
|
+
indexing every worktree under it.
|
|
41
|
+
- New exported helper `ensureWorktreeSpotlightExclusion(worktreesDir)` — idempotent,
|
|
42
|
+
best-effort, never throws, returns whether it created the marker.
|
|
43
|
+
- New `PostUpdateMigrator.migrateWorktreeSpotlightExclusion` backfills the marker
|
|
44
|
+
into existing agents' `.worktrees/` on update.
|
|
45
|
+
|
|
46
|
+
## Evidence
|
|
47
|
+
|
|
48
|
+
- `tests/unit/worktree-spotlight-exclusion.test.ts` — new: the helper (creates the
|
|
49
|
+
marker, idempotent return, never throws on an unwritable path) and the migration
|
|
50
|
+
backfill (drops the marker into an existing `.worktrees/`, idempotent on re-run).
|
|
51
|
+
- `tests/unit/InstarWorktreeManager.test.ts` + `migrateWorktreeConvention.test.ts`
|
|
52
|
+
still green (the `ensureWorktreesDir` hook + always-overwrite wrapper unchanged
|
|
53
|
+
in behavior).
|
|
54
|
+
- Operationally verified live: dropping the marker on echo's real 121-worktree
|
|
55
|
+
`.worktrees/` directory; mediaanalysisd dropped from its earlier ~80% spike.
|
|
56
|
+
- Full `npm run lint` clean.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Side-Effects Review — SessionReaper CPU-aware pressure + decision audit
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `sessionreaper-cpu-aware-and-decision-audit`
|
|
4
|
+
**Date:** `2026-05-30`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The idle-session reaper's pressure tier was computed from free memory only. This
|
|
11
|
+
change makes it the WORST of memory (free %) and CPU (1-min load ÷ cores) via a
|
|
12
|
+
new pure `computePressure()` classifier, with two tunable thresholds
|
|
13
|
+
(`cpuModerateLoadPerCore` 1.0 / `cpuCriticalLoadPerCore` 1.5) auto-migrated to
|
|
14
|
+
existing agents. It also adds a silent decision audit: every keep/kill decision
|
|
15
|
+
*change* + the reap-path events land in `logs/reaper-audit.jsonl`, served
|
|
16
|
+
read-only at `GET /sessions/reaper/audit`.
|
|
17
|
+
|
|
18
|
+
## Decision-point inventory
|
|
19
|
+
|
|
20
|
+
- **Pressure tier computation** (existing decision, widened): now also keys on CPU
|
|
21
|
+
load. Gates *when* the reaper may consider acting.
|
|
22
|
+
- **Decision audit emission** (new, zero-authority signal): writes an observability
|
|
23
|
+
row on `(verdict, keptBy)` transitions. No control-flow effect.
|
|
24
|
+
|
|
25
|
+
## 1. Over-block
|
|
26
|
+
|
|
27
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
28
|
+
|
|
29
|
+
CPU-awareness can raise the tier from `normal` to `moderate`/`critical` during a
|
|
30
|
+
load spike, making genuinely-idle sessions eligible sooner. It cannot cause a
|
|
31
|
+
*working* session to be reaped: the kill path still requires the full positive-idle
|
|
32
|
+
proof, transcript-stasis, render-stasis, 3-observation hysteresis over the
|
|
33
|
+
confirmation window, the two-phase reap, and the per-tick/per-hour budget — all
|
|
34
|
+
unchanged. A transient build spike is smoothed by the multi-observation
|
|
35
|
+
requirement. Default thresholds (1.0/1.5 load-per-core) are deliberately at/above
|
|
36
|
+
full subscription so "moderate" means genuinely oversubscribed.
|
|
37
|
+
|
|
38
|
+
## 2. Under-block
|
|
39
|
+
|
|
40
|
+
**What failure modes does this still miss?**
|
|
41
|
+
|
|
42
|
+
`os.loadavg()` is a trailing 1-minute average, so a very brief CPU famine may not
|
|
43
|
+
register, and a famine caused by non-session processes still only lets the reaper
|
|
44
|
+
trim *idle* sessions (it cannot reduce the load of the busy processes themselves).
|
|
45
|
+
This is acceptable — the reaper is one lever among several (load-shed, hosting
|
|
46
|
+
migration, tool/agent sleep); it is not meant to be a complete CPU governor.
|
|
47
|
+
|
|
48
|
+
## 3. Level-of-abstraction fit
|
|
49
|
+
|
|
50
|
+
**Is this at the right layer?**
|
|
51
|
+
|
|
52
|
+
Yes. Pressure sensing belongs in the reaper's injected `pressure()` provider; the
|
|
53
|
+
pure classifier lives next to the reaper and is unit-tested without `os`. The audit
|
|
54
|
+
is a sink/reader pair beside the existing `fileAuditSink`, mirroring the
|
|
55
|
+
`/sessions/reap-log` read-surface pattern. No business logic leaks into routes.
|
|
56
|
+
|
|
57
|
+
## 4. Signal vs authority compliance
|
|
58
|
+
|
|
59
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
60
|
+
|
|
61
|
+
**Does this change hold blocking authority with brittle logic?**
|
|
62
|
+
|
|
63
|
+
No new blocking authority. The reaper remains the authority it already was; this
|
|
64
|
+
change does not add a brittle check that gates behavior — it widens an existing,
|
|
65
|
+
heavily-confirmed kill path's *eligibility window*, and every safety gate still has
|
|
66
|
+
to clear independently. The decision audit is a pure signal producer (write-only
|
|
67
|
+
observability) with zero authority. `computePressure` is total: unknown/non-finite
|
|
68
|
+
CPU input degrades to the prior memory-only behavior rather than failing.
|
|
69
|
+
|
|
70
|
+
## 5. Interactions
|
|
71
|
+
|
|
72
|
+
**Does this interact with existing checks, recovery paths, or infrastructure?**
|
|
73
|
+
|
|
74
|
+
- Reads the same `monitoring.sessionReaper` config block; two additive fields.
|
|
75
|
+
- `reapNotify`, the reap-log (`/sessions/reap-log`), and the silently-stopped
|
|
76
|
+
sentinels are untouched; the new audit writes a SEPARATE file
|
|
77
|
+
(`reaper-audit.jsonl`), so nothing reading `sentinel-events.jsonl` is affected.
|
|
78
|
+
(Reaper events previously co-mingled there now route to the dedicated file —
|
|
79
|
+
reviewed: no consumer filters `sentinel-events.jsonl` for `kind:'session-reaper'`.)
|
|
80
|
+
- Migration: canonical config defaults (`applyDefaults` deep-merge) + a
|
|
81
|
+
content-sniffed `migrateClaudeMd` section; both idempotent.
|
|
82
|
+
|
|
83
|
+
## 6. External surfaces
|
|
84
|
+
|
|
85
|
+
**Does this change anything visible outside the immediate code path?**
|
|
86
|
+
|
|
87
|
+
One new read-only HTTP route (`GET /sessions/reaper/audit`, Bearer-auth, classified
|
|
88
|
+
in the capabilities-discoverability lint). `GET /sessions/reaper`'s `pressure.inputs`
|
|
89
|
+
gains `loadPerCore`/`memTier`/`cpuTier` fields (additive). One new on-disk file
|
|
90
|
+
(`logs/reaper-audit.jsonl`). No Telegram, no attention items, no notifications.
|
|
91
|
+
|
|
92
|
+
## 7. Rollback cost
|
|
93
|
+
|
|
94
|
+
**If this turns out wrong in production, what's the back-out?**
|
|
95
|
+
|
|
96
|
+
Cheap and layered. (a) Operationally, set the CPU thresholds absurdly high to
|
|
97
|
+
neutralize CPU-awareness with no deploy; the audit is write-only and harmless to
|
|
98
|
+
ignore. (b) A full revert of the PR restores the prior behavior exactly (the change
|
|
99
|
+
is additive). No data migration, no schema change, no irreversible state.
|
|
100
|
+
|
|
101
|
+
## Conclusion
|
|
102
|
+
|
|
103
|
+
Low-risk, additive, reversible. The safety-critical "never reap a working session"
|
|
104
|
+
contract is untouched; the change only widens *when* the existing gated path may
|
|
105
|
+
act and adds zero-authority observability. Ships behind the reaper's existing
|
|
106
|
+
OFF + dry-run default.
|
|
107
|
+
|
|
108
|
+
## Second-pass review (if required)
|
|
109
|
+
|
|
110
|
+
Not required — additive change, no new blocking authority, safety classifier
|
|
111
|
+
untouched.
|
|
112
|
+
|
|
113
|
+
## Evidence pointers
|
|
114
|
+
|
|
115
|
+
- `tests/unit/session-reaper-pressure-audit.test.ts` — `computePressure` matrix,
|
|
116
|
+
transition-only decision audit, sink/reader round-trip.
|
|
117
|
+
- `tests/integration/session-reaper-routes.test.ts` — `GET /sessions/reaper/audit`.
|
|
118
|
+
- `tests/e2e/session-reaper-lifecycle.test.ts` — Phase-1 feature-alive for the
|
|
119
|
+
audit route through the real AgentServer.
|
|
120
|
+
- `tests/unit/feature-delivery-completeness.test.ts` + capabilities-discoverability
|
|
121
|
+
lint — migration + route-classification parity.
|
|
122
|
+
- `upgrades/NEXT.md` — upgrade guide.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Side-Effects Review — Worktree Spotlight exclusion
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `worktree-spotlight-exclusion`
|
|
4
|
+
**Date:** `2026-05-30`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Drop a `.metadata_never_index` marker at the `.worktrees/` container root so macOS
|
|
11
|
+
Spotlight/mediaanalysisd skip indexing every worktree beneath it. Covered at
|
|
12
|
+
creation (`ensureWorktreesDir` → `ensureWorktreeSpotlightExclusion`, plus the
|
|
13
|
+
convention wrapper's fallback path) and backfilled for existing agents via a new
|
|
14
|
+
`PostUpdateMigrator.migrateWorktreeSpotlightExclusion`.
|
|
15
|
+
|
|
16
|
+
## Decision-point inventory
|
|
17
|
+
|
|
18
|
+
None. The change adds no decision logic — it writes one inert OS-hint file.
|
|
19
|
+
|
|
20
|
+
## 1. Over-block
|
|
21
|
+
|
|
22
|
+
**What legitimate inputs does this change reject?** Nothing is rejected. The marker
|
|
23
|
+
only affects Spotlight indexing of throwaway build trees; it does not change git,
|
|
24
|
+
the worktree, the build, or any agent behavior. Source files inside worktrees are
|
|
25
|
+
unaffected (the marker is at the container, not inside a worktree).
|
|
26
|
+
|
|
27
|
+
## 2. Under-block
|
|
28
|
+
|
|
29
|
+
**What does this still miss?** It does not reduce indexing of anything outside
|
|
30
|
+
`.worktrees/` (by design), and it does not reclaim the worktrees themselves (the
|
|
31
|
+
sibling reaper work). Spotlight may take time to honor a newly-dropped marker on an
|
|
32
|
+
already-indexed tree, so the relief on existing backlogs is gradual, not instant.
|
|
33
|
+
|
|
34
|
+
## 3. Level-of-abstraction fit
|
|
35
|
+
|
|
36
|
+
**Right layer?** Yes. The marker-ensure lives in `ensureWorktreesDir`, the single
|
|
37
|
+
chokepoint all CLI create paths run through, and the backfill lives beside the
|
|
38
|
+
existing `migrateWorktreeConvention`. The exported helper keeps the rule in one
|
|
39
|
+
place, reused by the migrator.
|
|
40
|
+
|
|
41
|
+
## 4. Signal vs authority compliance
|
|
42
|
+
|
|
43
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
44
|
+
|
|
45
|
+
No blocking authority added. The helper is best-effort and total: a write failure
|
|
46
|
+
returns false and is swallowed (`@silent-fallback-ok`), never throwing and never
|
|
47
|
+
blocking worktree creation or a migration pass.
|
|
48
|
+
|
|
49
|
+
## 5. Interactions
|
|
50
|
+
|
|
51
|
+
Reuses `resolveAgentHomeForWorktree` (same validation as `migrateWorktreeConvention`)
|
|
52
|
+
so non-convention agents are skipped silently. The wrapper fallback change rides the
|
|
53
|
+
existing always-overwrite of `instar-worktree-create.sh`. No interaction with the
|
|
54
|
+
SessionReaper, sentinels, or recovery paths. Idempotent everywhere.
|
|
55
|
+
|
|
56
|
+
## 6. External surfaces
|
|
57
|
+
|
|
58
|
+
One new on-disk file per agent (`.worktrees/.metadata_never_index`, empty). No HTTP
|
|
59
|
+
routes, no config, no notifications, no Telegram. Purely a filesystem hint to the OS.
|
|
60
|
+
|
|
61
|
+
## 7. Rollback cost
|
|
62
|
+
|
|
63
|
+
Trivial. Delete the marker to restore indexing; revert the PR to remove the
|
|
64
|
+
create-path drop + migration. No state, no schema, no irreversible op.
|
|
65
|
+
|
|
66
|
+
## Conclusion
|
|
67
|
+
|
|
68
|
+
Lowest-risk possible change: additive, inert, idempotent, best-effort, reversible,
|
|
69
|
+
no decision logic. Directly targets a measured top OS-level CPU drain (mediaanalysisd
|
|
70
|
+
~80% under a ~120-worktree backlog). Operationally pre-validated by dropping the
|
|
71
|
+
marker on echo's real `.worktrees/` (121 worktrees) live.
|
|
72
|
+
|
|
73
|
+
## Second-pass review (if required)
|
|
74
|
+
|
|
75
|
+
Not required — inert additive OS hint, no authority, no decision logic.
|
|
76
|
+
|
|
77
|
+
## Evidence pointers
|
|
78
|
+
|
|
79
|
+
- `tests/unit/worktree-spotlight-exclusion.test.ts` — helper + migration backfill.
|
|
80
|
+
- `tests/unit/InstarWorktreeManager.test.ts`, `migrateWorktreeConvention.test.ts` — green.
|
|
81
|
+
- `upgrades/NEXT.md` — upgrade guide.
|