instar 1.3.543 → 1.3.545
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.js +3 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +9 -5
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/CredentialRebalancer.d.ts +116 -0
- package/dist/core/CredentialRebalancer.d.ts.map +1 -0
- package/dist/core/CredentialRebalancer.js +159 -0
- package/dist/core/CredentialRebalancer.js.map +1 -0
- package/dist/core/CredentialRebalancerPolicy.d.ts +137 -0
- package/dist/core/CredentialRebalancerPolicy.d.ts.map +1 -0
- package/dist/core/CredentialRebalancerPolicy.js +284 -0
- package/dist/core/CredentialRebalancerPolicy.js.map +1 -0
- package/dist/core/CredentialRebalancerSnapshot.d.ts +66 -0
- package/dist/core/CredentialRebalancerSnapshot.d.ts.map +1 -0
- package/dist/core/CredentialRebalancerSnapshot.js +111 -0
- package/dist/core/CredentialRebalancerSnapshot.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +12 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +49 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +10 -5
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/scaffold/templates.js +1 -1
- package/dist/server/CapabilityIndex.js +1 -1
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.js +2 -2
- 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 +1 -1
- package/upgrades/1.3.544.md +27 -0
- package/upgrades/1.3.545.md +68 -0
- package/upgrades/side-effects/ws52-incb-b1-rebalancer-policy.md +44 -0
- package/upgrades/side-effects/ws52-incb-b2-default-eviction.md +42 -0
- package/upgrades/side-effects/ws52-incb-b3a-rebalancer-orchestrator.md +44 -0
- package/upgrades/side-effects/ws52-incb-b3b-snapshot-mappers.md +37 -0
- package/upgrades/side-effects/ws52-regate-dev-live.md +42 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialRebalancerPolicy — the §2.4 "stock-trader loop" decision core, as a PURE
|
|
3
|
+
* function (Increment B, step B1 of live credential re-pointing).
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/specs/live-credential-repointing-rebalancer.md §2.4 (the balancer).
|
|
6
|
+
*
|
|
7
|
+
* ── What this is ──
|
|
8
|
+
* Given a read-only snapshot of a pass (per-account quota + reset proximity, per-slot
|
|
9
|
+
* tenancy/verify/activity, cooldown state, resolved+clamped config), this computes the
|
|
10
|
+
* ZERO-OR-MORE swap decisions for ONE pass. It performs NO IO and holds NO authority:
|
|
11
|
+
* it DECIDES; a separate actuator (step B3) routes an accepted decision through the
|
|
12
|
+
* Step-5 CredentialSwapExecutor under the dark/dry-run gate. Splitting the decision out
|
|
13
|
+
* makes the entire policy — every threshold, cap, cooldown, and eligibility rule —
|
|
14
|
+
* exhaustively unit-testable without a keychain (Tier-0 supervision, §2.4: a
|
|
15
|
+
* deterministic policy over enumerable numeric thresholds).
|
|
16
|
+
*
|
|
17
|
+
* ── Priority of objectives (§2.4) ──
|
|
18
|
+
* 1. Wall avoidance — a tenant over the high-water mark gets the highest-headroom
|
|
19
|
+
* eligible account. A tenant over the CRITICAL mark triggers a wall-OVERRIDE that
|
|
20
|
+
* bypasses the cooldowns + the 1-swap/pass cap, bounded by its own caps
|
|
21
|
+
* (fresh-data gate, maxForcedSwapsPerPass, maxForcedOverridesPerWindow).
|
|
22
|
+
* 2. Use-it-or-lose-it drain — an account whose WEEKLY window resets soon with unused
|
|
23
|
+
* headroom is dealt to the busiest slot (weekly only; 5h windows regenerate).
|
|
24
|
+
* 3. Default-slot preference — keep the designated default account in `~/.claude`.
|
|
25
|
+
*
|
|
26
|
+
* Non-forced objectives are bounded to ONE swap per pass (acting twice on one sensor
|
|
27
|
+
* reading is noise). Only the wall-override may emit up to `maxForcedSwapsPerPass`.
|
|
28
|
+
*
|
|
29
|
+
* Dead-default eviction, the correlated-oracle-outage floor, quarantine-exit, the P19
|
|
30
|
+
* breaker, and the scheduled identity audit are step B2 (this module decides swaps; B2
|
|
31
|
+
* adds the degraded-state machinery). This module surfaces the terminal "nothing to do"
|
|
32
|
+
* / "no eligible target" states so B2/B3 can act on them.
|
|
33
|
+
*/
|
|
34
|
+
function sortedPair(a, b) {
|
|
35
|
+
return a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
36
|
+
}
|
|
37
|
+
/** Max utilization across the two windows (the wall is whichever is closer). */
|
|
38
|
+
function maxUtil(acc) {
|
|
39
|
+
return Math.max(acc.fiveHrPct ?? 0, acc.weeklyPct ?? 0);
|
|
40
|
+
}
|
|
41
|
+
/** A slot whose verify is recent AND not divergent is a valid swap-in target (§2.4 recency gate). */
|
|
42
|
+
function targetVerifiedRecent(slot, now, auditCadenceMs) {
|
|
43
|
+
return (!slot.quarantined &&
|
|
44
|
+
!slot.lastAuditDivergent &&
|
|
45
|
+
slot.lastVerifiedAt !== null &&
|
|
46
|
+
now - slot.lastVerifiedAt <= auditCadenceMs);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Decide the swap(s) for one pass. Pure: same input → same output, no IO.
|
|
50
|
+
* A pass with no actuation returns `decisions: []` + a `noActuationReason` (the caller
|
|
51
|
+
* audits the no-op pass and performs ZERO keychain/CLI operations — the §2.4 invariant).
|
|
52
|
+
*/
|
|
53
|
+
export function decidePass(input) {
|
|
54
|
+
const { now, slots, accounts, cooldowns, config, auditCadenceMs } = input;
|
|
55
|
+
const degraded = [];
|
|
56
|
+
const attention = [];
|
|
57
|
+
const accById = new Map(accounts.map((a) => [a.accountId, a]));
|
|
58
|
+
// Eligibility (§2.4): a tenant that is needs-reauth/disabled never participates; a
|
|
59
|
+
// quarantined/unverified slot never participates; a slot with no tenant can't move.
|
|
60
|
+
const participatingSlots = slots.filter((s) => {
|
|
61
|
+
if (s.tenantAccountId === null)
|
|
62
|
+
return false;
|
|
63
|
+
const acc = accById.get(s.tenantAccountId);
|
|
64
|
+
if (!acc)
|
|
65
|
+
return false;
|
|
66
|
+
return acc.status === 'ok';
|
|
67
|
+
});
|
|
68
|
+
// A slot is a valid swap-in TARGET only if its quota is fresh (stale headroom may mask a
|
|
69
|
+
// wall — the anti-conservative direction → SOURCE-only) AND its identity verify is recent.
|
|
70
|
+
const isFreshQuota = (acc) => now - acc.measuredAt <= config.staleQuotaMs;
|
|
71
|
+
// ── Objective 0: dead/quarantined-default eviction (the slot that must never be empty) ──
|
|
72
|
+
// Keep `~/.claude` serving a HEALTHY VERIFIED tenant so manual `claude` keeps working
|
|
73
|
+
// (goal 3 beats slot symmetry + the quarantine-exclusion rule, but ONLY for the default
|
|
74
|
+
// slot). Runs FIRST: a frozen default freezes the operator's manual invocations.
|
|
75
|
+
if (input.desiredDefaultAccountId) {
|
|
76
|
+
const defaultSlot = slots.find((s) => s.isDefault);
|
|
77
|
+
if (defaultSlot) {
|
|
78
|
+
const defTenant = defaultSlot.tenantAccountId ? accById.get(defaultSlot.tenantAccountId) : undefined;
|
|
79
|
+
const defaultDead = defaultSlot.quarantined ||
|
|
80
|
+
!defTenant ||
|
|
81
|
+
defTenant.status === 'needs-reauth' ||
|
|
82
|
+
defTenant.status === 'disabled';
|
|
83
|
+
if (defaultDead) {
|
|
84
|
+
// A healthy VERIFIED tenant to deal in (identity-verified THIS pass before the move —
|
|
85
|
+
// a "healthy per stale ledger" target that is actually dead would re-quarantine the
|
|
86
|
+
// default; the recency gate is that pre-check in the pure policy).
|
|
87
|
+
const healthy = slots
|
|
88
|
+
.filter((s) => s.slot !== defaultSlot.slot && !s.quarantined && s.tenantAccountId !== null)
|
|
89
|
+
.filter((s) => {
|
|
90
|
+
const a = accById.get(s.tenantAccountId);
|
|
91
|
+
return a?.status === 'ok' && targetVerifiedRecent(s, now, auditCadenceMs);
|
|
92
|
+
})
|
|
93
|
+
.sort((a, b) => maxUtil(accById.get(a.tenantAccountId)) - maxUtil(accById.get(b.tenantAccountId)))[0];
|
|
94
|
+
if (healthy) {
|
|
95
|
+
return {
|
|
96
|
+
decisions: [{
|
|
97
|
+
targetSlot: defaultSlot.slot,
|
|
98
|
+
sourceSlot: healthy.slot,
|
|
99
|
+
objective: 'default-eviction',
|
|
100
|
+
forced: 'default-eviction',
|
|
101
|
+
reason: `default slot ${defaultSlot.slot} is ${defaultSlot.quarantined ? 'quarantined' : 'dead (' + (defTenant?.status ?? 'no-tenant') + ')'}; dealing healthy verified ${healthy.tenantAccountId} in to keep manual claude working`,
|
|
102
|
+
}],
|
|
103
|
+
degraded: [],
|
|
104
|
+
attention: [`default slot ${defaultSlot.slot} was ${defaultSlot.quarantined ? 'quarantined' : 'dead'} — rescued with ${healthy.tenantAccountId}; the displaced credential is parked and needs re-auth/re-probe`],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Correlated-oracle-outage floor: NO slot is currently oracle-verifiable (an
|
|
108
|
+
// identity-oracle endpoint storm quarantines every probe at once). Do NOT empty/churn the
|
|
109
|
+
// default — preserve its last-known-good assignment + surface; honest bound: this is
|
|
110
|
+
// "preserve last KNOWN-GOOD + flag", NOT "manual claude is certified working".
|
|
111
|
+
const anyVerifiable = slots.some((s) => targetVerifiedRecent(s, now, auditCadenceMs));
|
|
112
|
+
if (!anyVerifiable) {
|
|
113
|
+
return {
|
|
114
|
+
decisions: [],
|
|
115
|
+
degraded: ['no slot is oracle-verifiable — default-slot eviction suspended (correlated-outage floor)'],
|
|
116
|
+
attention: [`oracle unavailable for every slot; ${defaultSlot.slot} preserved at its last-known-good${defaultSlot.lastKnownGoodAccountId ? ' (' + defaultSlot.lastKnownGoodAccountId + ')' : ''} — NOT certified live; no eviction until the oracle returns`],
|
|
117
|
+
noActuationReason: 'correlated oracle outage — default preserved at last-known-good, no eviction',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// Verifiable slots exist but none is an eligible healthy tenant: surface, do not act.
|
|
121
|
+
return {
|
|
122
|
+
decisions: [],
|
|
123
|
+
degraded: [],
|
|
124
|
+
attention: [`default slot ${defaultSlot.slot} is dead/quarantined and no healthy verified tenant is available to rescue it`],
|
|
125
|
+
noActuationReason: 'default slot dead but no eligible healthy tenant to deal in',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// ── Objective 1: wall avoidance ───────────────────────────────────────────────
|
|
131
|
+
// Slots whose tenant exceeds the high-water mark, worst-first.
|
|
132
|
+
const walling = participatingSlots
|
|
133
|
+
.map((s) => ({ slot: s, acc: accById.get(s.tenantAccountId), util: maxUtil(accById.get(s.tenantAccountId)) }))
|
|
134
|
+
.filter((x) => x.util >= config.highWaterPct)
|
|
135
|
+
.sort((a, b) => b.util - a.util);
|
|
136
|
+
// Eligible rescue targets: an account with the most headroom whose CURRENT slot is a
|
|
137
|
+
// verified-recent, fresh-quota, non-walling slot we can exchange with.
|
|
138
|
+
const rescueTargets = participatingSlots
|
|
139
|
+
.map((s) => ({ slot: s, acc: accById.get(s.tenantAccountId) }))
|
|
140
|
+
.filter((x) => maxUtil(x.acc) < config.highWaterPct && isFreshQuota(x.acc) && targetVerifiedRecent(x.slot, now, auditCadenceMs))
|
|
141
|
+
.sort((a, b) => maxUtil(a.acc) - maxUtil(b.acc)); // lowest utilization (most headroom) first
|
|
142
|
+
const decisions = [];
|
|
143
|
+
const actedSlots = new Set();
|
|
144
|
+
const actedTenants = new Set();
|
|
145
|
+
// Wall-override: critical-mark slots bypass cooldowns + the 1-swap cap, bounded by
|
|
146
|
+
// maxForcedSwapsPerPass + the fresh-data gate + maxForcedOverridesPerWindow.
|
|
147
|
+
const critical = walling.filter((x) => x.util >= config.criticalPct);
|
|
148
|
+
let overridesLeft = Math.max(0, cooldowns.maxForcedOverridesPerWindow - cooldowns.forcedOverridesInWindow);
|
|
149
|
+
let forcedThisPass = 0;
|
|
150
|
+
for (const w of critical) {
|
|
151
|
+
if (forcedThisPass >= config.maxForcedSwapsPerPass)
|
|
152
|
+
break;
|
|
153
|
+
if (overridesLeft <= 0) {
|
|
154
|
+
degraded.push('wall-override budget exhausted — no durable rescue available');
|
|
155
|
+
attention.push(`wall-override budget exhausted for slot ${w.slot.slot} — a thrashing tenant the rescue can't durably help`);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
// Fresh-data gate: act on a NEW critical reading only (the tenant's quota must be newer
|
|
159
|
+
// than its last actuation), so the override never re-fires on the same snapshot.
|
|
160
|
+
const lastAct = cooldowns.lastActuationByTenant[w.acc.accountId] ?? -Infinity;
|
|
161
|
+
if (w.acc.measuredAt <= lastAct)
|
|
162
|
+
continue;
|
|
163
|
+
const target = rescueTargets.find((t) => !actedSlots.has(t.slot.slot) && t.slot.slot !== w.slot.slot && !actedTenants.has(t.acc.accountId));
|
|
164
|
+
if (!target) {
|
|
165
|
+
attention.push(`no eligible non-walling rescue target for critical slot ${w.slot.slot}`);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
decisions.push({
|
|
169
|
+
targetSlot: w.slot.slot,
|
|
170
|
+
sourceSlot: target.slot.slot,
|
|
171
|
+
objective: 'wall',
|
|
172
|
+
forced: 'wall-override',
|
|
173
|
+
reason: `critical wall ${w.util}%≥${config.criticalPct}% on ${w.acc.accountId}; rescued with ${target.acc.accountId} (${maxUtil(target.acc)}%) — cooldowns bypassed`,
|
|
174
|
+
});
|
|
175
|
+
actedSlots.add(w.slot.slot);
|
|
176
|
+
actedSlots.add(target.slot.slot);
|
|
177
|
+
actedTenants.add(w.acc.accountId);
|
|
178
|
+
actedTenants.add(target.acc.accountId);
|
|
179
|
+
forcedThisPass += 1;
|
|
180
|
+
overridesLeft -= 1;
|
|
181
|
+
}
|
|
182
|
+
// If a forced override already acted this pass, we are done (the override is the highest
|
|
183
|
+
// priority; non-forced objectives wait for the next pass to respect 1-swap hygiene).
|
|
184
|
+
if (decisions.length > 0) {
|
|
185
|
+
return { decisions, degraded, attention };
|
|
186
|
+
}
|
|
187
|
+
// Non-forced wall avoidance (85–95%): respects per-pair + per-tenant cooldowns, 1 swap/pass.
|
|
188
|
+
const cooldownOk = (_slotA, _slotB, accA, accB) => {
|
|
189
|
+
// The per-pair cooldown keys on the TENANT pair (the two accounts being exchanged),
|
|
190
|
+
// consistent with the per-tenant cooldown — "don't re-exchange these two tenants too
|
|
191
|
+
// soon" — NOT on the fixed slot seats.
|
|
192
|
+
const pairLast = cooldowns.lastActuationByPair[sortedPair(accA, accB)] ?? -Infinity;
|
|
193
|
+
if (now - pairLast < config.perPairCooldownMs)
|
|
194
|
+
return false;
|
|
195
|
+
const tA = cooldowns.lastActuationByTenant[accA] ?? -Infinity;
|
|
196
|
+
const tB = cooldowns.lastActuationByTenant[accB] ?? -Infinity;
|
|
197
|
+
if (now - tA < config.perTenantCooldownMs || now - tB < config.perTenantCooldownMs)
|
|
198
|
+
return false;
|
|
199
|
+
return true;
|
|
200
|
+
};
|
|
201
|
+
// Fresh-data gate for non-forced moves: both tenants' quota newer than their last actuation.
|
|
202
|
+
const freshDataOk = (accA, accB) => {
|
|
203
|
+
const lA = cooldowns.lastActuationByTenant[accA.accountId] ?? -Infinity;
|
|
204
|
+
const lB = cooldowns.lastActuationByTenant[accB.accountId] ?? -Infinity;
|
|
205
|
+
return accA.measuredAt > lA && accB.measuredAt > lB;
|
|
206
|
+
};
|
|
207
|
+
// The non-forced path handles ONLY the [highWater, critical) band. A critical (≥95%)
|
|
208
|
+
// slot is the override path's responsibility; if the override couldn't act (budget /
|
|
209
|
+
// fresh-data / no target) it was surfaced above and WAITS — it is never silently
|
|
210
|
+
// downgraded to a cooldown-respecting rescue in the same pass (that would re-churn the
|
|
211
|
+
// exact thrashing slot the override budget gave up on).
|
|
212
|
+
for (const w of walling.filter((x) => x.util < config.criticalPct)) {
|
|
213
|
+
const target = rescueTargets.find((t) => t.slot.slot !== w.slot.slot);
|
|
214
|
+
if (!target) {
|
|
215
|
+
attention.push(`no eligible non-walling rescue target for slot ${w.slot.slot}`);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
if (!cooldownOk(w.slot.slot, target.slot.slot, w.acc.accountId, target.acc.accountId))
|
|
219
|
+
continue;
|
|
220
|
+
if (!freshDataOk(w.acc, target.acc))
|
|
221
|
+
continue;
|
|
222
|
+
decisions.push({
|
|
223
|
+
targetSlot: w.slot.slot,
|
|
224
|
+
sourceSlot: target.slot.slot,
|
|
225
|
+
objective: 'wall',
|
|
226
|
+
forced: null,
|
|
227
|
+
reason: `wall ${w.util}%≥${config.highWaterPct}% on ${w.acc.accountId}; rescued with ${target.acc.accountId} (${maxUtil(target.acc)}%)`,
|
|
228
|
+
});
|
|
229
|
+
return { decisions, degraded, attention };
|
|
230
|
+
}
|
|
231
|
+
// ── Objective 2: use-it-or-lose-it drain ──────────────────────────────────────
|
|
232
|
+
// An account whose WEEKLY window resets within the horizon with ≥ headroom-min unused,
|
|
233
|
+
// dealt to the busiest eligible slot that is NOT itself a drain-in-progress destination.
|
|
234
|
+
const drainable = accounts
|
|
235
|
+
.filter((a) => a.status === 'ok' && a.weeklyResetsInHours !== null && a.weeklyResetsInHours <= config.drainHorizonHours)
|
|
236
|
+
.filter((a) => a.weeklyPct !== null && 100 - a.weeklyPct >= config.drainHeadroomMinPct)
|
|
237
|
+
.filter((a) => isFreshQuota(a))
|
|
238
|
+
.sort((a, b) => (a.weeklyResetsInHours - b.weeklyResetsInHours)); // most-reset-proximate first
|
|
239
|
+
if (drainable.length > 0) {
|
|
240
|
+
const drainAcc = drainable[0];
|
|
241
|
+
// The drain SOURCE slot currently holding that account (the one whose tenant we deal out).
|
|
242
|
+
const drainSourceSlot = participatingSlots.find((s) => s.tenantAccountId === drainAcc.accountId);
|
|
243
|
+
// Busiest eligible destination: not the source, not drain-in-progress-held, verified-recent.
|
|
244
|
+
const dest = participatingSlots
|
|
245
|
+
.filter((s) => s.tenantAccountId !== drainAcc.accountId && !s.drainInProgress && targetVerifiedRecent(s, now, auditCadenceMs))
|
|
246
|
+
.sort((a, b) => b.busyness - a.busyness)[0];
|
|
247
|
+
if (drainSourceSlot && dest) {
|
|
248
|
+
const accDest = accById.get(dest.tenantAccountId);
|
|
249
|
+
// Drain respects cooldowns + fresh-data + the min improvement floor (urgency-clamped).
|
|
250
|
+
if (cooldownOk(drainSourceSlot.slot, dest.slot, drainAcc.accountId, accDest.accountId) && freshDataOk(drainAcc, accDest)) {
|
|
251
|
+
const hoursUntil = Math.max(config.urgencyClampHours, drainAcc.weeklyResetsInHours);
|
|
252
|
+
const urgency = 1 / hoursUntil;
|
|
253
|
+
const score = (100 - drainAcc.weeklyPct) * urgency * 100; // headroom × clamped urgency
|
|
254
|
+
if (score >= config.minScoreDelta) {
|
|
255
|
+
decisions.push({
|
|
256
|
+
targetSlot: dest.slot,
|
|
257
|
+
sourceSlot: drainSourceSlot.slot,
|
|
258
|
+
objective: 'drain',
|
|
259
|
+
forced: null,
|
|
260
|
+
reason: `drain ${drainAcc.accountId} (weekly resets in ${drainAcc.weeklyResetsInHours}h, ${100 - drainAcc.weeklyPct}% unused) → busiest slot ${dest.slot}`,
|
|
261
|
+
});
|
|
262
|
+
return { decisions, degraded, attention };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// ── Objective 3: default-slot preference ──────────────────────────────────────
|
|
268
|
+
// Keep the designated default account in `~/.claude` when neither (1) nor (2) overrode.
|
|
269
|
+
// (The pure policy only signals the preference when the default slot does NOT already
|
|
270
|
+
// hold the default account AND the move clears the floor; B3 supplies which account is
|
|
271
|
+
// "the default" via the slot.isDefault marker + a desiredDefaultAccountId in config-land.
|
|
272
|
+
// In B1 we surface the preference as a no-op reason when nothing else acted.)
|
|
273
|
+
return {
|
|
274
|
+
decisions: [],
|
|
275
|
+
degraded,
|
|
276
|
+
attention,
|
|
277
|
+
noActuationReason: walling.length > 0
|
|
278
|
+
? 'walling slots present but every candidate move was held by a cooldown / fresh-data gate / missing eligible target'
|
|
279
|
+
: drainable.length > 0
|
|
280
|
+
? 'drainable account present but the move did not clear cooldown / fresh-data / min-improvement'
|
|
281
|
+
: 'no wall, no drainable window, slots balanced — zero actuation',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=CredentialRebalancerPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialRebalancerPolicy.js","sourceRoot":"","sources":["../../src/core/CredentialRebalancerPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialRebalancerSnapshot — pure mappers from the live system's state into the
|
|
3
|
+
* balancer's read-only pass snapshot (Increment B, step B3b wiring helper).
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/specs/live-credential-repointing-rebalancer.md §2.4.
|
|
6
|
+
*
|
|
7
|
+
* The CredentialRebalancer orchestrator (B3a) consumes injected `listSlots` / `listAccounts`
|
|
8
|
+
* / `resolveConfig` providers. These pure functions ARE those providers — they translate
|
|
9
|
+
* the CredentialLocationLedger assignments and the SubscriptionPool accounts into the
|
|
10
|
+
* policy's `SlotState` / `AccountState`, and clamp the configured balancer knobs into the
|
|
11
|
+
* resolved config. Kept pure + out of server.ts so the mapping (the place a units/sign
|
|
12
|
+
* bug would silently mis-steer the balancer) is unit-testable.
|
|
13
|
+
*/
|
|
14
|
+
import type { SlotState, AccountState } from './CredentialRebalancerPolicy.js';
|
|
15
|
+
import type { RebalancerResolvedConfig } from './CredentialRebalancer.js';
|
|
16
|
+
import type { SubscriptionAccount, SubscriptionAccountStatus } from './SubscriptionPool.js';
|
|
17
|
+
import type { CredentialAssignment } from './CredentialLocationLedger.js';
|
|
18
|
+
/**
|
|
19
|
+
* Map the pool account lifecycle status into the policy's eligibility status.
|
|
20
|
+
* Only needs-reauth/disabled are INELIGIBLE (dead credentials). rate-limited is `ok`:
|
|
21
|
+
* a walled account must stay eligible so wall-avoidance can RESCUE its slot (its high
|
|
22
|
+
* utilization % drives the wall objective; excluding it would strand the very slot that
|
|
23
|
+
* needs help).
|
|
24
|
+
*/
|
|
25
|
+
export declare function mapAccountStatus(s: SubscriptionAccountStatus): AccountState['status'];
|
|
26
|
+
/** One pool account → the policy's AccountState. */
|
|
27
|
+
export declare function mapAccount(account: SubscriptionAccount, now: number): AccountState;
|
|
28
|
+
export declare function mapAccounts(accounts: readonly SubscriptionAccount[], now: number): AccountState[];
|
|
29
|
+
export interface SlotMapOptions {
|
|
30
|
+
/** The config-home slot that is the default (`~/.claude`), so isDefault is set. */
|
|
31
|
+
defaultSlot?: string | null;
|
|
32
|
+
/** Optional per-slot busyness (recent activity); absent ⇒ 0 (drain has no busiest preference). */
|
|
33
|
+
busynessBySlot?: Record<string, number>;
|
|
34
|
+
/** Optional per-slot "drain in progress" hold (balancer-tracked); absent ⇒ false. */
|
|
35
|
+
drainInProgressBySlot?: Record<string, boolean>;
|
|
36
|
+
/** Optional per-slot last-audit-divergent flag (scheduled-audit-tracked); absent ⇒ false. */
|
|
37
|
+
auditDivergentBySlot?: Record<string, boolean>;
|
|
38
|
+
}
|
|
39
|
+
/** One ledger assignment → the policy's SlotState. */
|
|
40
|
+
export declare function mapSlot(a: CredentialAssignment, opts: SlotMapOptions): SlotState;
|
|
41
|
+
export declare function mapSlots(assignments: readonly CredentialAssignment[], opts: SlotMapOptions): SlotState[];
|
|
42
|
+
/** The raw balancer config block (subscriptionPool.credentialRepointing.balancer + siblings). */
|
|
43
|
+
export interface RawRebalancerConfig {
|
|
44
|
+
passIntervalMs?: number;
|
|
45
|
+
highWaterPct?: number;
|
|
46
|
+
criticalPct?: number;
|
|
47
|
+
maxForcedSwapsPerPass?: number;
|
|
48
|
+
minScoreDelta?: number;
|
|
49
|
+
drainHorizonHours?: number;
|
|
50
|
+
drainHeadroomMinPct?: number;
|
|
51
|
+
staleQuotaPollPeriods?: number;
|
|
52
|
+
urgencyClampHours?: number;
|
|
53
|
+
maxForcedOverridesPerWindow?: number;
|
|
54
|
+
breakerThreshold?: number;
|
|
55
|
+
auditCadenceMs?: number;
|
|
56
|
+
desiredDefaultAccountId?: string | null;
|
|
57
|
+
/** Number of slots — clamps maxForcedSwapsPerPass upper bound. */
|
|
58
|
+
slotCount?: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Clamp the configured knobs into the resolved config the orchestrator/policy use.
|
|
62
|
+
* Cooldowns are DERIVED from the poll interval (per-pair ≥1×, per-tenant ≥2× — the
|
|
63
|
+
* lag-sensored controller floors, §2.4); stale-quota is N poll periods.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveRebalancerConfig(raw: RawRebalancerConfig): RebalancerResolvedConfig;
|
|
66
|
+
//# sourceMappingURL=CredentialRebalancerSnapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialRebalancerSnapshot.d.ts","sourceRoot":"","sources":["../../src/core/CredentialRebalancerSnapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAI1E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,yBAAyB,GAAG,YAAY,CAAC,QAAQ,CAAC,CAUrF;AAaD,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAYlF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAEjG;AAED,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChD;AAED,sDAAsD;AACtD,wBAAgB,OAAO,CAAC,CAAC,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,GAAG,SAAS,CAahF;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,SAAS,EAAE,CAExG;AAOD,iGAAiG;AACjG,MAAM,WAAW,mBAAmB;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,mBAAmB,GAAG,wBAAwB,CAsB1F"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialRebalancerSnapshot — pure mappers from the live system's state into the
|
|
3
|
+
* balancer's read-only pass snapshot (Increment B, step B3b wiring helper).
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/specs/live-credential-repointing-rebalancer.md §2.4.
|
|
6
|
+
*
|
|
7
|
+
* The CredentialRebalancer orchestrator (B3a) consumes injected `listSlots` / `listAccounts`
|
|
8
|
+
* / `resolveConfig` providers. These pure functions ARE those providers — they translate
|
|
9
|
+
* the CredentialLocationLedger assignments and the SubscriptionPool accounts into the
|
|
10
|
+
* policy's `SlotState` / `AccountState`, and clamp the configured balancer knobs into the
|
|
11
|
+
* resolved config. Kept pure + out of server.ts so the mapping (the place a units/sign
|
|
12
|
+
* bug would silently mis-steer the balancer) is unit-testable.
|
|
13
|
+
*/
|
|
14
|
+
const HOUR_MS = 3600_000;
|
|
15
|
+
/**
|
|
16
|
+
* Map the pool account lifecycle status into the policy's eligibility status.
|
|
17
|
+
* Only needs-reauth/disabled are INELIGIBLE (dead credentials). rate-limited is `ok`:
|
|
18
|
+
* a walled account must stay eligible so wall-avoidance can RESCUE its slot (its high
|
|
19
|
+
* utilization % drives the wall objective; excluding it would strand the very slot that
|
|
20
|
+
* needs help).
|
|
21
|
+
*/
|
|
22
|
+
export function mapAccountStatus(s) {
|
|
23
|
+
switch (s) {
|
|
24
|
+
case 'needs-reauth': return 'needs-reauth';
|
|
25
|
+
case 'disabled': return 'disabled';
|
|
26
|
+
case 'active':
|
|
27
|
+
case 'warming':
|
|
28
|
+
case 'rate-limited':
|
|
29
|
+
default:
|
|
30
|
+
return 'ok';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function pctOrNull(v) {
|
|
34
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : null;
|
|
35
|
+
}
|
|
36
|
+
function hoursUntil(resetsAt, now) {
|
|
37
|
+
if (!resetsAt)
|
|
38
|
+
return null;
|
|
39
|
+
const t = Date.parse(resetsAt);
|
|
40
|
+
if (Number.isNaN(t))
|
|
41
|
+
return null;
|
|
42
|
+
return Math.max(0, (t - now) / HOUR_MS);
|
|
43
|
+
}
|
|
44
|
+
/** One pool account → the policy's AccountState. */
|
|
45
|
+
export function mapAccount(account, now) {
|
|
46
|
+
const q = account.lastQuota ?? null;
|
|
47
|
+
const measuredAt = q?.measuredAt ? Date.parse(q.measuredAt) : NaN;
|
|
48
|
+
return {
|
|
49
|
+
accountId: account.id,
|
|
50
|
+
status: mapAccountStatus(account.status),
|
|
51
|
+
fiveHrPct: pctOrNull(q?.fiveHour?.utilizationPct),
|
|
52
|
+
weeklyPct: pctOrNull(q?.sevenDay?.utilizationPct),
|
|
53
|
+
weeklyResetsInHours: hoursUntil(q?.sevenDay?.resetsAt, now),
|
|
54
|
+
// No quota reading at all ⇒ measuredAt 0 (epoch) ⇒ always STALE ⇒ source-only.
|
|
55
|
+
measuredAt: Number.isNaN(measuredAt) ? 0 : measuredAt,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function mapAccounts(accounts, now) {
|
|
59
|
+
return accounts.map((a) => mapAccount(a, now));
|
|
60
|
+
}
|
|
61
|
+
/** One ledger assignment → the policy's SlotState. */
|
|
62
|
+
export function mapSlot(a, opts) {
|
|
63
|
+
const lastVerifiedAt = a.lastVerifiedAt ? Date.parse(a.lastVerifiedAt) : NaN;
|
|
64
|
+
return {
|
|
65
|
+
slot: a.slot,
|
|
66
|
+
// The ledger uses '' for a quarantined-but-unassigned slot; normalize to null.
|
|
67
|
+
tenantAccountId: a.accountId ? a.accountId : null,
|
|
68
|
+
isDefault: opts.defaultSlot != null && a.slot === opts.defaultSlot,
|
|
69
|
+
quarantined: a.quarantined,
|
|
70
|
+
lastVerifiedAt: Number.isNaN(lastVerifiedAt) ? null : lastVerifiedAt,
|
|
71
|
+
lastAuditDivergent: opts.auditDivergentBySlot?.[a.slot] ?? false,
|
|
72
|
+
drainInProgress: opts.drainInProgressBySlot?.[a.slot] ?? false,
|
|
73
|
+
busyness: opts.busynessBySlot?.[a.slot] ?? 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function mapSlots(assignments, opts) {
|
|
77
|
+
return assignments.map((a) => mapSlot(a, opts));
|
|
78
|
+
}
|
|
79
|
+
function clamp(v, lo, hi, dflt) {
|
|
80
|
+
const n = typeof v === 'number' && Number.isFinite(v) ? v : dflt;
|
|
81
|
+
return Math.min(hi, Math.max(lo, n));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Clamp the configured knobs into the resolved config the orchestrator/policy use.
|
|
85
|
+
* Cooldowns are DERIVED from the poll interval (per-pair ≥1×, per-tenant ≥2× — the
|
|
86
|
+
* lag-sensored controller floors, §2.4); stale-quota is N poll periods.
|
|
87
|
+
*/
|
|
88
|
+
export function resolveRebalancerConfig(raw) {
|
|
89
|
+
const passIntervalMs = clamp(raw.passIntervalMs, 60_000, 3_600_000, 300_000);
|
|
90
|
+
const slotCount = Math.max(1, raw.slotCount ?? 1);
|
|
91
|
+
const stalePeriods = clamp(raw.staleQuotaPollPeriods, 1, 10, 2);
|
|
92
|
+
return {
|
|
93
|
+
policy: {
|
|
94
|
+
highWaterPct: clamp(raw.highWaterPct, 50, 99, 85),
|
|
95
|
+
criticalPct: clamp(raw.criticalPct, 85, 99, 95),
|
|
96
|
+
drainHorizonHours: clamp(raw.drainHorizonHours, 1, 96, 24),
|
|
97
|
+
drainHeadroomMinPct: clamp(raw.drainHeadroomMinPct, 0, 100, 30),
|
|
98
|
+
minScoreDelta: clamp(raw.minScoreDelta, 0, 1000, 10),
|
|
99
|
+
maxForcedSwapsPerPass: clamp(raw.maxForcedSwapsPerPass, 1, slotCount, 1),
|
|
100
|
+
perPairCooldownMs: passIntervalMs, // ≥1× poll interval
|
|
101
|
+
perTenantCooldownMs: passIntervalMs * 2, // ≥2× poll interval (defeats 3-way rotation)
|
|
102
|
+
staleQuotaMs: passIntervalMs * stalePeriods,
|
|
103
|
+
urgencyClampHours: clamp(raw.urgencyClampHours, 1, 24, 4),
|
|
104
|
+
},
|
|
105
|
+
auditCadenceMs: clamp(raw.auditCadenceMs, HOUR_MS, 24 * HOUR_MS, 6 * HOUR_MS),
|
|
106
|
+
desiredDefaultAccountId: raw.desiredDefaultAccountId ?? null,
|
|
107
|
+
maxForcedOverridesPerWindow: clamp(raw.maxForcedOverridesPerWindow, 1, 100, 5),
|
|
108
|
+
breakerThreshold: clamp(raw.breakerThreshold, 1, 20, 3),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=CredentialRebalancerSnapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialRebalancerSnapshot.js","sourceRoot":"","sources":["../../src/core/CredentialRebalancerSnapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,18 @@ export interface MigratorConfig {
|
|
|
53
53
|
* A stripped seamlessness block left empty is removed so the file stays clean.
|
|
54
54
|
*/
|
|
55
55
|
export declare function migrateConfigWs44PoolLinks(config: Record<string, unknown>): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Live credential re-pointing was re-gated from DARK_GATE_EXCLUSIONS (off+dry-run for
|
|
58
|
+
* everyone) to the developmentAgent gate (live-on-dev in dry-run, dark fleet) per the
|
|
59
|
+
* 2026-06-13 operator directive. Existing agents that ran the old ConfigDefaults carry an
|
|
60
|
+
* explicit `subscriptionPool.credentialRepointing.enabled: false`, which (being explicit)
|
|
61
|
+
* would keep resolveDevAgentGate DARK even on a dev agent. Strip that default-shaped
|
|
62
|
+
* `false` so the gate resolves (live on dev, dark on fleet) — mirroring the ws44PoolLinks
|
|
63
|
+
* strip. An explicit `true` is preserved (an operator who deliberately turned it on). The
|
|
64
|
+
* separate `dryRun`/`manualLeversEnabled` fields are left untouched (dryRun stays the
|
|
65
|
+
* write-safety canary). Idempotent.
|
|
66
|
+
*/
|
|
67
|
+
export declare function migrateConfigCredentialRepointingDevGate(config: Record<string, unknown>): boolean;
|
|
56
68
|
export declare class PostUpdateMigrator {
|
|
57
69
|
private config;
|
|
58
70
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -104,6 +104,32 @@ export function migrateConfigWs44PoolLinks(config) {
|
|
|
104
104
|
delete mm.seamlessness;
|
|
105
105
|
return true;
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Live credential re-pointing was re-gated from DARK_GATE_EXCLUSIONS (off+dry-run for
|
|
109
|
+
* everyone) to the developmentAgent gate (live-on-dev in dry-run, dark fleet) per the
|
|
110
|
+
* 2026-06-13 operator directive. Existing agents that ran the old ConfigDefaults carry an
|
|
111
|
+
* explicit `subscriptionPool.credentialRepointing.enabled: false`, which (being explicit)
|
|
112
|
+
* would keep resolveDevAgentGate DARK even on a dev agent. Strip that default-shaped
|
|
113
|
+
* `false` so the gate resolves (live on dev, dark on fleet) — mirroring the ws44PoolLinks
|
|
114
|
+
* strip. An explicit `true` is preserved (an operator who deliberately turned it on). The
|
|
115
|
+
* separate `dryRun`/`manualLeversEnabled` fields are left untouched (dryRun stays the
|
|
116
|
+
* write-safety canary). Idempotent.
|
|
117
|
+
*/
|
|
118
|
+
export function migrateConfigCredentialRepointingDevGate(config) {
|
|
119
|
+
const sp = config.subscriptionPool;
|
|
120
|
+
if (!sp || typeof sp !== 'object')
|
|
121
|
+
return false;
|
|
122
|
+
const cr = sp.credentialRepointing;
|
|
123
|
+
if (!cr || typeof cr !== 'object')
|
|
124
|
+
return false;
|
|
125
|
+
if (!Object.prototype.hasOwnProperty.call(cr, 'enabled'))
|
|
126
|
+
return false;
|
|
127
|
+
// Only a default-shaped `false` is stripped; an explicit `true` is preserved.
|
|
128
|
+
if (cr.enabled !== false)
|
|
129
|
+
return false;
|
|
130
|
+
delete cr.enabled;
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
107
133
|
export class PostUpdateMigrator {
|
|
108
134
|
config;
|
|
109
135
|
/**
|
|
@@ -5872,10 +5898,23 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
|
|
|
5872
5898
|
// migration is idempotent and skips template-generated CLAUDE.md files. Harmless
|
|
5873
5899
|
// on agents where the feature is dark (every lever 503s).
|
|
5874
5900
|
if (!content.includes('Live Credential Re-pointing (move a pool account')) {
|
|
5875
|
-
content += `\n**Live Credential Re-pointing (move a pool account's login between config-home "slots" without restarting — WS5.2)** — Beyond the subscription pool's session-MOVING, this MOVES the credential itself: it exchanges which pool account's OAuth login sits in which config-home "slot" via a staged keychain swap, so the sessions already reading that slot pick up the new account on their NEXT API call — no restart, no re-login, nothing on your screen. The unit shuffled is the CREDENTIAL (always a clean SWAP between two slots, never a copy — one home per credential), verified by identity after every move (quarantine-never-repair when the identity oracle can't confirm). **
|
|
5901
|
+
content += `\n**Live Credential Re-pointing (move a pool account's login between config-home "slots" without restarting — WS5.2)** — Beyond the subscription pool's session-MOVING, this MOVES the credential itself: it exchanges which pool account's OAuth login sits in which config-home "slot" via a staged keychain swap, so the sessions already reading that slot pick up the new account on their NEXT API call — no restart, no re-login, nothing on your screen. The unit shuffled is the CREDENTIAL (always a clean SWAP between two slots, never a copy — one home per credential), verified by identity after every move (quarantine-never-repair when the identity oracle can't confirm). **On a development agent it runs LIVE in dry-run** (the developmentAgent gate, \`subscriptionPool.credentialRepointing.enabled\` omitted → resolves live-on-dev / dark-fleet) — the \`/credentials/*\` levers return real data and the balancer runs its full decision loop, but the executor performs ZERO credential writes while \`dryRun\` holds (the write-safety canary; on the fleet every lever 503s). Actually MOVING a credential needs a deliberate \`dryRun:false\` — that decision is yours (gated behind running the §5 livetest battery first).\n- **Which account is in which slot?** (Registry First — read it, never guess) \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/credentials/locations\` → the ledger census (slot ↔ account, since, lastVerifiedAt, quarantine state, journal tail, mode).\n- **Flip your default account (zero-touch)** — \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:${port}/credentials/set-default -H 'Content-Type: application/json' -d '{"toAccountId":"<account>"}'\` swaps which account \`~/.claude\` serves, with no restart of the session you're talking to.\n- **Swap two slots' credentials live** — \`POST /credentials/swap\` \`{"slotA":"<home>","slotB":"<home>"}\` (the staged §2.3 exchange). **Restore the enrollment layout** — \`POST /credentials/restore-enrollment\` (parks any identity-incoherent blob one-directionally; never exchanges it into a healthy slot). All levers are DETECTIVE controls — operator-notified + audited + param-validated + per-pair cooldown + a force budget on \`force:true\`. No token material ever exits any \`/credentials/*\` surface (the single CredentialAuditEmit scrub chokepoint).\n- **The autonomous balancer surface** — \`GET /credentials/rebalancer\` (the use-it-or-lose-it drainer is Increment B; this surfaces the env-token applicability gate's verdict + WHY re-pointing would refuse, when enabled).\n- **When to use** (PROACTIVE — these are the triggers): "flip my default account to X" / "make X my default" → \`POST /credentials/set-default\`; "which account is this session/slot on?" / "where does ~/.claude point?" → \`GET /credentials/locations\` (read it, don't infer from \`claude auth status\` — that reads a metadata file, not the live credential). Single-account agents are a no-op. (Spec: \`docs/specs/live-credential-repointing-rebalancer.md\`.)\n`;
|
|
5876
5902
|
patched = true;
|
|
5877
5903
|
result.upgraded.push('CLAUDE.md: added Live Credential Re-pointing awareness section');
|
|
5878
5904
|
}
|
|
5905
|
+
// In-place re-word for agents that ALREADY have the credential section with the stale
|
|
5906
|
+
// "Ships DARK ... enabled:true + dryRun:false" wording (pre-2026-06-13 re-gate). Replace
|
|
5907
|
+
// that one sentence with the live-on-dev-dry-run truth; idempotent (the new text lacks the
|
|
5908
|
+
// old phrase, so a second run is a no-op).
|
|
5909
|
+
{
|
|
5910
|
+
const stale = '**Ships DARK** behind `subscriptionPool.credentialRepointing.enabled` — every lever 503s/no-ops while disabled (byte-for-byte today\'s behavior); going live needs a deliberate `enabled:true` + `dryRun:false` flip, and that ON decision is yours, separate from any build.';
|
|
5911
|
+
const fresh = '**On a development agent it runs LIVE in dry-run** (the developmentAgent gate, `subscriptionPool.credentialRepointing.enabled` omitted → resolves live-on-dev / dark-fleet) — the `/credentials/*` levers return real data and the balancer runs its full decision loop, but the executor performs ZERO credential writes while `dryRun` holds (the write-safety canary; on the fleet every lever 503s). Actually MOVING a credential needs a deliberate `dryRun:false` — that decision is yours (gated behind running the §5 livetest battery first).';
|
|
5912
|
+
if (content.includes(stale)) {
|
|
5913
|
+
content = content.replace(stale, fresh);
|
|
5914
|
+
patched = true;
|
|
5915
|
+
result.upgraded.push('CLAUDE.md: re-worded Live Credential Re-pointing to live-on-dev dry-run (2026-06-13 re-gate)');
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5879
5918
|
if (patched) {
|
|
5880
5919
|
try {
|
|
5881
5920
|
fs.writeFileSync(claudeMdPath, content);
|
|
@@ -6795,6 +6834,15 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
|
|
|
6795
6834
|
else {
|
|
6796
6835
|
result.skipped.push('config.json: multiMachine.seamlessness.ws44PoolLinks dev-gate already correct (omitted or operator-set)');
|
|
6797
6836
|
}
|
|
6837
|
+
// Live credential re-pointing re-gated to the developmentAgent gate (2026-06-13 operator
|
|
6838
|
+
// directive): strip a default-shaped enabled:false so it resolves live-on-dev / dark-fleet.
|
|
6839
|
+
if (migrateConfigCredentialRepointingDevGate(config)) {
|
|
6840
|
+
patched = true;
|
|
6841
|
+
result.upgraded.push('config.json: stripped default-shaped subscriptionPool.credentialRepointing.enabled=false so the developmentAgent gate resolves it (live-on-dev dry-run, dark fleet)');
|
|
6842
|
+
}
|
|
6843
|
+
else {
|
|
6844
|
+
result.skipped.push('config.json: subscriptionPool.credentialRepointing.enabled dev-gate already correct (omitted or operator-set)');
|
|
6845
|
+
}
|
|
6798
6846
|
if (patched) {
|
|
6799
6847
|
try {
|
|
6800
6848
|
// Atomic write: backup, then write to tmp, then rename
|