@indigoai-us/hq-cli 5.294.0 → 5.295.0
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/CHANGELOG.md +25 -0
- package/dist/command-catalog.generated.d.ts +12 -9
- package/dist/command-catalog.generated.js +15 -12
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +76 -1
- package/dist/commands/doctor.js +0 -74
- package/dist/commands/lanes-message.js +23 -5
- package/dist/commands/lanes-resume.js +0 -3
- package/dist/commands/lanes-shared.d.ts +1 -2
- package/dist/commands/lanes.d.ts +1 -9
- package/dist/commands/lanes.js +177 -172
- package/dist/fast-scaffold.d.ts +0 -5
- package/dist/fast-scaffold.js +0 -10
- package/dist/index.js +1 -10
- package/dist/lib/core-utils/sentry-report.d.ts +0 -19
- package/dist/lib/core-utils/sentry-report.js +8 -61
- package/dist/lib/doctor/checks/claude-wiring.js +9 -0
- package/dist/lib/lanes/flag-keys.d.ts +2 -0
- package/dist/lib/lanes/flag-keys.js +2 -0
- package/dist/lib/lanes/manager-status-gate.d.ts +0 -17
- package/dist/lib/lanes/manager-status-gate.js +2 -43
- package/dist/lib/lanes/outpost-dispatch.d.ts +2 -0
- package/dist/lib/lanes/outpost-dispatch.js +7 -1
- package/dist/lib/lanes/outpost-hire-cache.d.ts +0 -1
- package/dist/lib/lanes/outpost-hire-cache.js +0 -1
- package/dist/lib/lanes/outpost-snapshot-memo.d.ts +6 -0
- package/dist/lib/lanes/outpost-snapshot-memo.js +14 -0
- package/dist/lib/lanes/reconcile.d.ts +2 -3
- package/dist/lib/lanes/reconcile.js +44 -38
- package/dist/lib/lanes/spawn.d.ts +0 -2
- package/dist/lib/lanes/spawn.js +18 -5
- package/dist/lib/lanes/store.js +22 -0
- package/dist/lib/lanes/types.d.ts +18 -1
- package/dist/lib/lanes/types.js +1 -1
- package/dist/lib/lanes/watcher.d.ts +4 -3
- package/dist/lib/lanes/watcher.js +102 -34
- package/dist/lib/mesh/live/daemon/run.js +18 -1
- package/dist/utils/cognito-session.d.ts +6 -0
- package/dist/utils/cognito-session.js +9 -0
- package/dist/utils/self-update.js +31 -0
- package/dist/utils/version-gate.js +22 -3
- package/package.json +1 -1
- package/dist/fast-lanes-list-route.d.ts +0 -8
- package/dist/fast-lanes-list-route.js +0 -32
- package/dist/fast-lanes-list.d.ts +0 -3
- package/dist/fast-lanes-list.js +0 -224
- package/dist/lib/doctor/client-health-sentry-flag.d.ts +0 -23
- package/dist/lib/doctor/client-health-sentry-flag.js +0 -99
- package/dist/lib/doctor/client-health-sentry.d.ts +0 -71
- package/dist/lib/doctor/client-health-sentry.js +0 -286
- package/dist/lib/lanes/outpost-snapshot-cache.d.ts +0 -26
- package/dist/lib/lanes/outpost-snapshot-cache.js +0 -215
- package/dist/lib/lanes/outpost-snapshot-refresh.d.ts +0 -21
- package/dist/lib/lanes/outpost-snapshot-refresh.js +0 -329
package/dist/commands/lanes.js
CHANGED
|
@@ -31,18 +31,17 @@ import { registerLaneReviewCommand } from "./lanes-review.js";
|
|
|
31
31
|
import { ensureCognitoToken } from "../utils/cognito-session.js";
|
|
32
32
|
import { withCliFeatureUsed } from "../utils/cli-telemetry.js";
|
|
33
33
|
import { resolveLanesHqRoot } from "../lib/lanes/hq-root.js";
|
|
34
|
-
import { startOutpostLaneSnapshotRefresh } from "../lib/lanes/outpost-snapshot-refresh.js";
|
|
35
34
|
import { isSsmRunCommandProcess } from "../lib/lanes/ssm-command-context.js";
|
|
36
35
|
import { readLanesRegistryFlag } from "../lib/lanes/registry-flag.js";
|
|
37
36
|
import { runLeadAutopilotPass } from "../lib/lanes/autopilot.js";
|
|
38
|
-
import {
|
|
37
|
+
import { OutpostSnapshotInvocationMemo } from "../lib/lanes/outpost-snapshot-memo.js";
|
|
39
38
|
import { createOutpostHireGrantContext, parseOutpostHireGrantContext, selectOutpostHireGrantHierarchy, sameHireGrantSenior, } from "../lib/lanes/hire-grant-dispatch.js";
|
|
40
39
|
import { createOutpostProfileRepinContext, parseOutpostProfileRepinContext, } from "../lib/lanes/outpost-profile-repin.js";
|
|
41
40
|
import { createOutpostRegistryWorkerApprovalContext, parseOutpostRegistryWorkerApprovalContext, } from "../lib/lanes/outpost-registry-worker-approval.js";
|
|
42
41
|
import { OUTPOST_DIR, OUTPOST_ID_PATH, readOutpostIdentity, resolveAdmissionHost, } from "../lib/lanes/admission-host.js";
|
|
43
42
|
export { OUTPOST_DIR, OUTPOST_ID_PATH, readOutpostIdentity } from "../lib/lanes/admission-host.js";
|
|
44
43
|
import { buildOutpostCapacityCommand, buildOutpostIdentityBackfillCommand, buildOutpostLaneCommand, buildOutpostQuestionListCommand, buildOutpostPickupCommand, createOutpostsClient, dispatchErrorMessage, dispatchOutpostPickup, buildOutpostLaneListCommand, REMOTE_LANE_READ_ENV, outpostRejectedEffortOption, parseOutpostPickupPayload, PICKUP_WAIT_MS, stageOutpostPayload, } from "../lib/lanes/outpost-dispatch.js";
|
|
45
|
-
import { outpostHireSummaryCacheKey,
|
|
44
|
+
import { outpostHireSummaryCacheKey, OUTPOST_HIRE_SUMMARY_CACHE_TTL_MS, readOutpostHireSummaryCache, readOutpostHireSummaryCacheIncludingStale, writeOutpostHireSummaryCache, } from "../lib/lanes/outpost-hire-cache.js";
|
|
46
45
|
import { buildHostCapacitySnapshot, chooseHostForLane, parseHostCapacitySnapshot, } from "../lib/lanes/host-capacity.js";
|
|
47
46
|
import { BALANCE_MOVABLE_STATES, selectClaudeAccount, } from "../lib/lanes/claude-balance.js";
|
|
48
47
|
import { parseUserYaml } from "../utils/user-yaml-error.js";
|
|
@@ -69,7 +68,7 @@ import { LanesError } from "../lib/lanes/errors.js";
|
|
|
69
68
|
import { readLatestEnvelopeRecord } from "../lib/lanes/watcher.js";
|
|
70
69
|
import { loadQuotaState, quotaBlockFor } from "../lib/lanes/quota.js";
|
|
71
70
|
import { SESSION_MOVE_REASON } from "../lib/lanes/move-account.js";
|
|
72
|
-
import {
|
|
71
|
+
import { resolveManagerStatusTarget, } from "../lib/lanes/manager-status-gate.js";
|
|
73
72
|
import { blockerFreshnessFingerprint, resolveBlockerFreshnessForLane, } from "../lib/lanes/blocker-freshness.js";
|
|
74
73
|
import { resolveKrFreshnessForShow } from "../lib/lanes/kr-freshness.js";
|
|
75
74
|
import { ensureSessionHome } from "../lib/lanes/session-relink.js";
|
|
@@ -85,7 +84,6 @@ const REMOTE_MIRROR_REFRESH_BATCH_SIZE = 100;
|
|
|
85
84
|
const REMOTE_LANE_NOT_FOUND_GRACE_MS = 15 * 60_000;
|
|
86
85
|
/** The lane → mesh seam. Defined in lib/lanes/mesh-events.ts; the watcher shares it. */
|
|
87
86
|
export { emitLaneDecisionEvents };
|
|
88
|
-
export { LANE_OUTPOST_SNAPSHOT_CACHE_FLAG };
|
|
89
87
|
function withoutProviderHome(value) {
|
|
90
88
|
if (Array.isArray(value))
|
|
91
89
|
return value.map(withoutProviderHome);
|
|
@@ -301,8 +299,6 @@ function resolveDeps(deps = {}) {
|
|
|
301
299
|
})),
|
|
302
300
|
fetchText: deps.fetchText ?? defaultFetchText,
|
|
303
301
|
lanePlacementEnabled: deps.lanePlacementEnabled ?? defaultLanePlacementEnabled,
|
|
304
|
-
outpostSnapshotCacheEnabled: deps.outpostSnapshotCacheEnabled ?? (() => readLanesRegistryFlag(LANE_OUTPOST_SNAPSHOT_CACHE_FLAG, { env })),
|
|
305
|
-
startOutpostLaneSnapshotRefresh: deps.startOutpostLaneSnapshotRefresh ?? ((root) => startOutpostLaneSnapshotRefresh(root, env)),
|
|
306
302
|
storyLedgerEnabled: deps.storyLedgerEnabled ?? laneStoryLedgerEnabled,
|
|
307
303
|
isSsmOwnerDispatch: deps.isSsmOwnerDispatch ?? (() => isSsmRunCommandProcess()),
|
|
308
304
|
withGrantHireLocks: deps.withGrantHireLocks ?? withLaneHireLocks,
|
|
@@ -514,7 +510,7 @@ async function readRemoteHireGrantSenior(ctx, hqRoot, seniorLaneId) {
|
|
|
514
510
|
laneIds: [seniorLaneId],
|
|
515
511
|
snapshot: true,
|
|
516
512
|
strictSnapshot: true,
|
|
517
|
-
}, {}, {
|
|
513
|
+
}, {}, { bypassMemo: true });
|
|
518
514
|
}
|
|
519
515
|
catch (error) {
|
|
520
516
|
throw unavailable(isLanesError(error) ? error.error : "outpost_lane_list_unavailable");
|
|
@@ -1053,7 +1049,7 @@ function laneHostFromCtx(ctx, expectedId) {
|
|
|
1053
1049
|
return { kind: "local", id: hostname };
|
|
1054
1050
|
}
|
|
1055
1051
|
async function readOutpostCapacity(ctx, outpostId) {
|
|
1056
|
-
return
|
|
1052
|
+
return readOutpostCapacityUncached(ctx, outpostId);
|
|
1057
1053
|
}
|
|
1058
1054
|
async function readOutpostCapacityUncached(ctx, outpostId) {
|
|
1059
1055
|
let result;
|
|
@@ -1089,39 +1085,6 @@ async function readOutpostCapacityUncached(ctx, outpostId) {
|
|
|
1089
1085
|
}
|
|
1090
1086
|
return snapshot;
|
|
1091
1087
|
}
|
|
1092
|
-
async function readOutpostSnapshotWithCache(ctx, key, isValue, fetch) {
|
|
1093
|
-
let enabled = false;
|
|
1094
|
-
try {
|
|
1095
|
-
enabled = await ctx.outpostSnapshotCacheEnabled();
|
|
1096
|
-
}
|
|
1097
|
-
catch (err) {
|
|
1098
|
-
process.stderr.write(`lanes snapshot cache flag read failed; using uncached Outpost read: ${dispatchErrorMessage(err)}\n`);
|
|
1099
|
-
}
|
|
1100
|
-
if (!enabled)
|
|
1101
|
-
return fetch();
|
|
1102
|
-
return getOrFetchOutpostSnapshot({ hqRoot: ctx.hqRoot(), key, isValue, fetch });
|
|
1103
|
-
}
|
|
1104
|
-
function isLaneRecordArray(value) {
|
|
1105
|
-
if (!Array.isArray(value))
|
|
1106
|
-
return false;
|
|
1107
|
-
try {
|
|
1108
|
-
for (const lane of value)
|
|
1109
|
-
parseLaneRecord(lane);
|
|
1110
|
-
return true;
|
|
1111
|
-
}
|
|
1112
|
-
catch {
|
|
1113
|
-
return false;
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
function isOutpostCapacitySnapshot(value, outpostId) {
|
|
1117
|
-
try {
|
|
1118
|
-
const snapshot = parseHostCapacitySnapshot(value);
|
|
1119
|
-
return snapshot.host.kind === "outpost" && snapshot.host.id === outpostId;
|
|
1120
|
-
}
|
|
1121
|
-
catch {
|
|
1122
|
-
return false;
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
1088
|
async function loadHostCapacitySnapshots(ctx, hqRoot, config = loadLanesConfig(hqRoot), localLanes = loadAllLanes(hqRoot)) {
|
|
1126
1089
|
const localHost = laneHostFromCtx(ctx);
|
|
1127
1090
|
let outpostIds;
|
|
@@ -1280,7 +1243,7 @@ async function readOutpostLaneRecordsUncached(ctx, outpostId, query, dispatchOpt
|
|
|
1280
1243
|
}
|
|
1281
1244
|
async function readOutpostLaneRecords(ctx, outpostId, requestedQuery = {}, dispatchOptions = {}, options = {}) {
|
|
1282
1245
|
const query = normalizedLaneListQuery(requestedQuery);
|
|
1283
|
-
if (options.
|
|
1246
|
+
if (options.bypassMemo === true) {
|
|
1284
1247
|
return readOutpostLaneRecordsUncached(ctx, outpostId, query, dispatchOptions);
|
|
1285
1248
|
}
|
|
1286
1249
|
let invocationMemo = outpostLaneListMemo.get(ctx);
|
|
@@ -1288,10 +1251,10 @@ async function readOutpostLaneRecords(ctx, outpostId, requestedQuery = {}, dispa
|
|
|
1288
1251
|
invocationMemo = new OutpostSnapshotInvocationMemo();
|
|
1289
1252
|
outpostLaneListMemo.set(ctx, invocationMemo);
|
|
1290
1253
|
}
|
|
1291
|
-
return invocationMemo.getOrCreate(outpostId, query, () =>
|
|
1254
|
+
return invocationMemo.getOrCreate(outpostId, query, () => readOutpostLaneRecordsUncached(ctx, outpostId, query, dispatchOptions));
|
|
1292
1255
|
}
|
|
1293
|
-
/** Refresh
|
|
1294
|
-
async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds) {
|
|
1256
|
+
/** Refresh this host's selected Outpost mirrors in one bounded owner query per Outpost. */
|
|
1257
|
+
async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds, options = {}) {
|
|
1295
1258
|
const result = {
|
|
1296
1259
|
updated: new Map(),
|
|
1297
1260
|
unverifiedRemote: new Map(),
|
|
@@ -1316,11 +1279,21 @@ async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds) {
|
|
|
1316
1279
|
.filter((lane) => lane.host.kind === "outpost" &&
|
|
1317
1280
|
(host.outpostId === null || lane.host.id !== host.outpostId) &&
|
|
1318
1281
|
originMatchesThisHost(lane) &&
|
|
1319
|
-
(parentLaneIds === undefined || (lane.senior.kind === "lane" &&
|
|
1282
|
+
((parentLaneIds === undefined || (lane.senior.kind === "lane" &&
|
|
1320
1283
|
lane.senior.id !== undefined &&
|
|
1321
|
-
parentLaneIds.has(lane.senior.id))) &&
|
|
1322
|
-
!isTerminalLaneState(lane.state))
|
|
1323
|
-
.sort((a, b) =>
|
|
1284
|
+
parentLaneIds.has(lane.senior.id))) || options.laneIds?.has(lane.lane_id) === true) &&
|
|
1285
|
+
(options.includeTerminalMirrors === true || !isTerminalLaneState(lane.state)))
|
|
1286
|
+
.sort((a, b) => {
|
|
1287
|
+
const terminalOrder = Number(isTerminalLaneState(a.state)) - Number(isTerminalLaneState(b.state));
|
|
1288
|
+
if (terminalOrder !== 0)
|
|
1289
|
+
return terminalOrder;
|
|
1290
|
+
if (isTerminalLaneState(a.state)) {
|
|
1291
|
+
const updatedAtOrder = Date.parse(b.updated_at) - Date.parse(a.updated_at);
|
|
1292
|
+
if (updatedAtOrder !== 0)
|
|
1293
|
+
return updatedAtOrder;
|
|
1294
|
+
}
|
|
1295
|
+
return a.lane_id.localeCompare(b.lane_id);
|
|
1296
|
+
});
|
|
1324
1297
|
if (candidates.length === 0)
|
|
1325
1298
|
return result;
|
|
1326
1299
|
const enabledByCompany = new Map();
|
|
@@ -1406,7 +1379,13 @@ async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds) {
|
|
|
1406
1379
|
: undefined;
|
|
1407
1380
|
const before = readLane(hqRoot, mirror.lane_id);
|
|
1408
1381
|
if (before.host.kind !== "outpost" || before.host.id !== outpostId ||
|
|
1409
|
-
!originMatchesThisHost(before) ||
|
|
1382
|
+
!originMatchesThisHost(before) ||
|
|
1383
|
+
(!options.includeTerminalMirrors && isTerminalLaneState(before.state))) {
|
|
1384
|
+
result.updated.set(mirror.lane_id, before);
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
if (owner.version < before.version) {
|
|
1388
|
+
result.unverifiedRemote.set(mirror.lane_id, "owner_snapshot_behind_mirror");
|
|
1410
1389
|
result.updated.set(mirror.lane_id, before);
|
|
1411
1390
|
continue;
|
|
1412
1391
|
}
|
|
@@ -1424,10 +1403,16 @@ async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds) {
|
|
|
1424
1403
|
result.updated.set(mirror.lane_id, before);
|
|
1425
1404
|
continue;
|
|
1426
1405
|
}
|
|
1406
|
+
let ownerSnapshotLostVersionRace = false;
|
|
1427
1407
|
const updated = retryUpdateLane(hqRoot, mirror.lane_id, "reconcile", (current) => {
|
|
1428
1408
|
if (current.host.kind !== "outpost" || current.host.id !== outpostId ||
|
|
1429
|
-
!originMatchesThisHost(current) ||
|
|
1409
|
+
!originMatchesThisHost(current) ||
|
|
1410
|
+
(!options.includeTerminalMirrors && isTerminalLaneState(current.state)))
|
|
1430
1411
|
return current;
|
|
1412
|
+
if (owner.version < current.version) {
|
|
1413
|
+
ownerSnapshotLostVersionRace = true;
|
|
1414
|
+
return current;
|
|
1415
|
+
}
|
|
1431
1416
|
return {
|
|
1432
1417
|
...current,
|
|
1433
1418
|
state: owner.state,
|
|
@@ -1445,6 +1430,9 @@ async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds) {
|
|
|
1445
1430
|
} : {}),
|
|
1446
1431
|
};
|
|
1447
1432
|
});
|
|
1433
|
+
if (ownerSnapshotLostVersionRace) {
|
|
1434
|
+
result.unverifiedRemote.set(mirror.lane_id, "owner_snapshot_behind_mirror");
|
|
1435
|
+
}
|
|
1448
1436
|
result.updated.set(mirror.lane_id, updated);
|
|
1449
1437
|
}
|
|
1450
1438
|
}
|
|
@@ -1524,6 +1512,7 @@ async function resolveCommandLaneTarget(ctx, laneId, options = {}) {
|
|
|
1524
1512
|
const hostOutpostIdSet = new Set(hostOutpostIds);
|
|
1525
1513
|
const matches = [];
|
|
1526
1514
|
const failedOutpostIds = [];
|
|
1515
|
+
const probedOutpostIds = [];
|
|
1527
1516
|
const lookupOutpostIds = requestedOutpostId !== undefined
|
|
1528
1517
|
? [requestedOutpostId]
|
|
1529
1518
|
: [
|
|
@@ -1537,6 +1526,7 @@ async function resolveCommandLaneTarget(ctx, laneId, options = {}) {
|
|
|
1537
1526
|
hierarchy: [laneId],
|
|
1538
1527
|
snapshot: true,
|
|
1539
1528
|
});
|
|
1529
|
+
probedOutpostIds.push(outpostId);
|
|
1540
1530
|
}
|
|
1541
1531
|
catch (err) {
|
|
1542
1532
|
if (requestedOutpostId !== undefined)
|
|
@@ -1555,7 +1545,10 @@ async function resolveCommandLaneTarget(ctx, laneId, options = {}) {
|
|
|
1555
1545
|
}
|
|
1556
1546
|
}
|
|
1557
1547
|
if (matches.length === 0) {
|
|
1558
|
-
throw commandLaneNotFound(laneId, options.outpostHint === true,
|
|
1548
|
+
throw commandLaneNotFound(laneId, options.outpostHint === true, {
|
|
1549
|
+
...(failedOutpostIds.length > 0 ? { failed_outpost_ids: failedOutpostIds } : {}),
|
|
1550
|
+
...(probedOutpostIds.length > 0 ? { probed_outpost_ids: probedOutpostIds } : {}),
|
|
1551
|
+
});
|
|
1559
1552
|
}
|
|
1560
1553
|
if (matches.length !== 1) {
|
|
1561
1554
|
throw new LanesError("lane_outpost_ambiguous", `More than one registered Outpost reported lane ${laneId} with the same recorded host identity`, { lane_id: laneId, outpost_ids: matches.map((match) => match.outpostId) });
|
|
@@ -3502,7 +3495,6 @@ async function runCreate(ctx, opts) {
|
|
|
3502
3495
|
if (admission.action === "start") {
|
|
3503
3496
|
started = spawnLaneWorker(hqRoot, lane, {
|
|
3504
3497
|
env: ctx.env,
|
|
3505
|
-
managerStatusGateEnabled: await managerStatusGateEnabledForLane(hqRoot, lane, { env: ctx.env }),
|
|
3506
3498
|
modelDeps: {
|
|
3507
3499
|
readFileSync: ctx.readFileSync,
|
|
3508
3500
|
probe: ctx.probeProvider,
|
|
@@ -4276,6 +4268,7 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options, behavior =
|
|
|
4276
4268
|
outpost_id: outpostId,
|
|
4277
4269
|
outpost_command_id: dispatched.commandId,
|
|
4278
4270
|
outpost_transport: "outposts_exec",
|
|
4271
|
+
delivered_to: { host: outpostId, lane_id: ownerLane.lane_id, mechanism: "outposts_exec" },
|
|
4279
4272
|
});
|
|
4280
4273
|
return;
|
|
4281
4274
|
}
|
|
@@ -4306,6 +4299,9 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options, behavior =
|
|
|
4306
4299
|
outpost_id: outpostId,
|
|
4307
4300
|
outpost_command_id: dispatched.commandId,
|
|
4308
4301
|
outpost_transport: "outposts_exec",
|
|
4302
|
+
...(action === "message"
|
|
4303
|
+
? { delivered_to: { host: outpostId, lane_id: lane.lane_id, mechanism: "outposts_exec" } }
|
|
4304
|
+
: {}),
|
|
4309
4305
|
});
|
|
4310
4306
|
}
|
|
4311
4307
|
function dispatchedOwnerLane(ctx, laneId, outpostId, rawLane, behavior) {
|
|
@@ -4581,7 +4577,6 @@ async function runPickup(ctx, opts) {
|
|
|
4581
4577
|
try {
|
|
4582
4578
|
return spawnLaneWorker(hqRoot, current, {
|
|
4583
4579
|
env: ctx.env,
|
|
4584
|
-
managerStatusGateEnabled: await managerStatusGateEnabledForLane(hqRoot, current, { env: ctx.env }),
|
|
4585
4580
|
modelDeps: {
|
|
4586
4581
|
readFileSync: ctx.readFileSync,
|
|
4587
4582
|
probe: ctx.probeProvider,
|
|
@@ -4626,7 +4621,7 @@ async function runPickup(ctx, opts) {
|
|
|
4626
4621
|
lane: started,
|
|
4627
4622
|
});
|
|
4628
4623
|
}
|
|
4629
|
-
async function runList(ctx, opts
|
|
4624
|
+
async function runList(ctx, opts) {
|
|
4630
4625
|
if (opts.json && opts.human) {
|
|
4631
4626
|
throw new LanesError("conflicting_output_format", "Use either --json or --human for hq lanes list", { json: true, human: true });
|
|
4632
4627
|
}
|
|
@@ -4666,15 +4661,14 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4666
4661
|
const hierarchyIds = opts.hierarchy === undefined
|
|
4667
4662
|
? undefined
|
|
4668
4663
|
: new Set(opts.hierarchy.flatMap((laneId) => selectOutpostHireGrantHierarchy(laneId, laneSource).map((lane) => lane.lane_id)));
|
|
4669
|
-
|
|
4670
|
-
.filter((lane) => {
|
|
4664
|
+
const matchesLaneFilters = (lane, includeState) => {
|
|
4671
4665
|
if (requestedLaneIds.length > 0 && !requestedIds.has(lane.lane_id))
|
|
4672
4666
|
return false;
|
|
4673
|
-
if (opts.active && isTerminalLaneState(lane.state))
|
|
4667
|
+
if (includeState && opts.active && isTerminalLaneState(lane.state))
|
|
4674
4668
|
return false;
|
|
4675
4669
|
if (hierarchyIds && !hierarchyIds.has(lane.lane_id))
|
|
4676
4670
|
return false;
|
|
4677
|
-
if (state && lane.state !== state)
|
|
4671
|
+
if (includeState && state && lane.state !== state)
|
|
4678
4672
|
return false;
|
|
4679
4673
|
const carriesFilter = laneStories(lane).some((story) => (!opts.project || story.project_id === opts.project) &&
|
|
4680
4674
|
(!opts.story || story.story_id === opts.story));
|
|
@@ -4689,8 +4683,11 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4689
4683
|
if (senior && seniorKey(lane.senior) !== seniorKey(senior))
|
|
4690
4684
|
return false;
|
|
4691
4685
|
return true;
|
|
4692
|
-
}
|
|
4686
|
+
};
|
|
4687
|
+
const selectLanes = () => laneSource
|
|
4688
|
+
.filter((lane) => matchesLaneFilters(lane, true))
|
|
4693
4689
|
.sort(compareLaneQueueOrder);
|
|
4690
|
+
let selectedLanes = selectLanes();
|
|
4694
4691
|
if (opts.snapshot) {
|
|
4695
4692
|
printJson({
|
|
4696
4693
|
ok: true,
|
|
@@ -4707,15 +4704,20 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4707
4704
|
const remoteRead = ctx.env[REMOTE_LANE_READ_ENV] === "1";
|
|
4708
4705
|
const remoteRefresh = remoteRead
|
|
4709
4706
|
? { updated: new Map(), unverifiedRemote: new Map(), missingOnOwner: new Map() }
|
|
4710
|
-
: await refreshRemoteLaneMirrors(ctx, hqRoot, laneSource, new Set(
|
|
4711
|
-
.filter((lane) =>
|
|
4712
|
-
.map((lane) => lane.lane_id))
|
|
4707
|
+
: await refreshRemoteLaneMirrors(ctx, hqRoot, laneSource, new Set(laneSource
|
|
4708
|
+
.filter((lane) => matchesLaneFilters(lane, false))
|
|
4709
|
+
.map((lane) => lane.lane_id)), {
|
|
4710
|
+
includeTerminalMirrors: true,
|
|
4711
|
+
laneIds: new Set(laneSource
|
|
4712
|
+
.filter((lane) => matchesLaneFilters(lane, false))
|
|
4713
|
+
.map((lane) => lane.lane_id)),
|
|
4714
|
+
});
|
|
4713
4715
|
for (const [laneId, updated] of remoteRefresh.updated) {
|
|
4714
4716
|
const index = laneSource.findIndex((lane) => lane.lane_id === laneId);
|
|
4715
4717
|
if (index >= 0)
|
|
4716
4718
|
laneSource[index] = updated;
|
|
4717
4719
|
}
|
|
4718
|
-
selectedLanes =
|
|
4720
|
+
selectedLanes = selectLanes();
|
|
4719
4721
|
const now = ctx.now();
|
|
4720
4722
|
const host = reconcileHostFromCtx(ctx);
|
|
4721
4723
|
const allLanes = laneSource;
|
|
@@ -4736,33 +4738,7 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4736
4738
|
ownerEligibleLaneIds.add(lane.lane_id);
|
|
4737
4739
|
}
|
|
4738
4740
|
const ownerLanes = selectedLanes.filter((lane) => ownerEligibleLaneIds.has(lane.lane_id));
|
|
4739
|
-
const refreshRemote = ctx.env.HQ_INTERNAL_LANES_REFRESH_REMOTE_SNAPSHOT === "1";
|
|
4740
|
-
let snapshotCacheEnabled = fastRouteFlags?.snapshotCacheEnabled ?? false;
|
|
4741
|
-
if (fastRouteFlags === undefined &&
|
|
4742
|
-
(refreshRemote || (!opts.fresh && ownerLanes.length > 0))) {
|
|
4743
|
-
try {
|
|
4744
|
-
snapshotCacheEnabled = await ctx.outpostSnapshotCacheEnabled();
|
|
4745
|
-
}
|
|
4746
|
-
catch (err) {
|
|
4747
|
-
process.stderr.write(`lanes snapshot cache flag read failed; using wait-for-remote list: ${dispatchErrorMessage(err)}\n`);
|
|
4748
|
-
}
|
|
4749
|
-
}
|
|
4750
|
-
if (refreshRemote) {
|
|
4751
|
-
if (snapshotCacheEnabled && ownerLanes.length > 0) {
|
|
4752
|
-
const outcomes = await batchOwnerLaneHireFields(ctx, ownerLanes, allLanes, { forceRefresh: true });
|
|
4753
|
-
const failures = [...outcomes.entries()].filter(([, outcome]) => "error" in outcome);
|
|
4754
|
-
if (failures.length > 0) {
|
|
4755
|
-
const firstOutcome = failures[0][1];
|
|
4756
|
-
const firstError = "error" in firstOutcome ? firstOutcome.error : undefined;
|
|
4757
|
-
process.stderr.write(`lanes snapshot refresh failed for ${failures.length} lane(s): ${firstError?.error ?? "outpost_lane_hire_summary_missing"}: ${firstError?.message ?? "owner summary outcome was missing"}\n`);
|
|
4758
|
-
throw firstError ?? new LanesError("outpost_lane_hire_summary_missing", "Background Outpost lane summary refresh returned a missing outcome", { lane_ids: failures.map(([laneId]) => laneId) });
|
|
4759
|
-
}
|
|
4760
|
-
}
|
|
4761
|
-
return;
|
|
4762
|
-
}
|
|
4763
4741
|
const hireByLane = new Map();
|
|
4764
|
-
const remoteSnapshotMetadata = new Map();
|
|
4765
|
-
let remoteLanesLoading = false;
|
|
4766
4742
|
for (const lane of selectedLanes) {
|
|
4767
4743
|
if (!ownerEligibleLaneIds.has(lane.lane_id)) {
|
|
4768
4744
|
hireByLane.set(lane.lane_id, {
|
|
@@ -4772,47 +4748,7 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4772
4748
|
continue;
|
|
4773
4749
|
}
|
|
4774
4750
|
}
|
|
4775
|
-
if (
|
|
4776
|
-
const nowMs = ctx.now().getTime();
|
|
4777
|
-
const cached = readOutpostHireSummaryCacheIncludingStale(hqRoot, nowMs);
|
|
4778
|
-
let refreshNeeded = false;
|
|
4779
|
-
for (const lane of ownerLanes) {
|
|
4780
|
-
if (lane.host.kind !== "outpost")
|
|
4781
|
-
continue;
|
|
4782
|
-
const summary = cached.get(outpostHireSummaryCacheKey(lane.host.id, lane.lane_id));
|
|
4783
|
-
if (!summary) {
|
|
4784
|
-
hireByLane.set(lane.lane_id, {
|
|
4785
|
-
...laneHireFields(lane, allLanes, aliveChildrenByParent),
|
|
4786
|
-
hire_source: "local",
|
|
4787
|
-
});
|
|
4788
|
-
remoteSnapshotMetadata.set(lane.lane_id, { ageSeconds: null, stale: true, loading: true });
|
|
4789
|
-
refreshNeeded = true;
|
|
4790
|
-
remoteLanesLoading = true;
|
|
4791
|
-
continue;
|
|
4792
|
-
}
|
|
4793
|
-
const ageMs = Math.max(0, nowMs - Date.parse(summary.cached_at));
|
|
4794
|
-
const stale = ageMs >= OUTPOST_SNAPSHOT_CACHE_TTL_MS;
|
|
4795
|
-
hireByLane.set(lane.lane_id, {
|
|
4796
|
-
hire_grant: summary.hire_grant,
|
|
4797
|
-
hire_alive_children: summary.hire_alive_children,
|
|
4798
|
-
hire: summary.hire,
|
|
4799
|
-
hire_summary: summary.hire_summary,
|
|
4800
|
-
hire_source: "owner",
|
|
4801
|
-
});
|
|
4802
|
-
remoteSnapshotMetadata.set(lane.lane_id, {
|
|
4803
|
-
ageSeconds: Math.floor(ageMs / 1_000),
|
|
4804
|
-
stale,
|
|
4805
|
-
loading: stale,
|
|
4806
|
-
});
|
|
4807
|
-
if (stale) {
|
|
4808
|
-
refreshNeeded = true;
|
|
4809
|
-
remoteLanesLoading = true;
|
|
4810
|
-
}
|
|
4811
|
-
}
|
|
4812
|
-
if (refreshNeeded)
|
|
4813
|
-
ctx.startOutpostLaneSnapshotRefresh(hqRoot);
|
|
4814
|
-
}
|
|
4815
|
-
else if (ownerLanes.length > 0) {
|
|
4751
|
+
if (ownerLanes.length > 0) {
|
|
4816
4752
|
const ownerSummaries = await batchOwnerLaneHireFields(ctx, ownerLanes, allLanes);
|
|
4817
4753
|
for (const lane of ownerLanes) {
|
|
4818
4754
|
const outcome = ownerSummaries.get(lane.lane_id);
|
|
@@ -4846,15 +4782,6 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4846
4782
|
...(remoteQueued
|
|
4847
4783
|
? { state: "remote", remote_state: lane.state, queued_reason: undefined, queued_details: undefined }
|
|
4848
4784
|
: {}),
|
|
4849
|
-
...(remoteSnapshotMetadata.has(lane.lane_id)
|
|
4850
|
-
? {
|
|
4851
|
-
remote_snapshot_age_s: remoteSnapshotMetadata.get(lane.lane_id).ageSeconds,
|
|
4852
|
-
remote_snapshot_stale: remoteSnapshotMetadata.get(lane.lane_id).stale,
|
|
4853
|
-
...(remoteSnapshotMetadata.get(lane.lane_id).loading
|
|
4854
|
-
? { remote_snapshot_loading: true }
|
|
4855
|
-
: {}),
|
|
4856
|
-
}
|
|
4857
|
-
: {}),
|
|
4858
4785
|
overdue: Boolean(lane.overdue) || isOverdue(hqRoot, lane.lane_id, now),
|
|
4859
4786
|
stalled: Boolean(lane.stalled),
|
|
4860
4787
|
// Listing is observational. Reconcile owns durable liveness transitions.
|
|
@@ -4878,8 +4805,7 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4878
4805
|
};
|
|
4879
4806
|
});
|
|
4880
4807
|
const placementCompany = company ?? processLanePlacementCompany(ctx);
|
|
4881
|
-
const placementEnabled = !remoteRead && (
|
|
4882
|
-
await readLanePlacementEnabled(ctx, placementCompany));
|
|
4808
|
+
const placementEnabled = !remoteRead && await readLanePlacementEnabled(ctx, placementCompany);
|
|
4883
4809
|
const host_capacity = placementEnabled
|
|
4884
4810
|
? (await loadHostCapacitySnapshots(ctx, hqRoot, undefined, allLanes)).entries
|
|
4885
4811
|
: undefined;
|
|
@@ -4890,43 +4816,24 @@ async function runList(ctx, opts, fastRouteFlags) {
|
|
|
4890
4816
|
...(remoteRefresh.unverifiedRemote.size > 0
|
|
4891
4817
|
? { unverified_remote_lanes: [...remoteRefresh.unverifiedRemote.keys()] }
|
|
4892
4818
|
: {}),
|
|
4893
|
-
...(remoteLanesLoading ? { remote_lanes_loading: true } : {}),
|
|
4894
4819
|
...(host_capacity !== undefined ? { host_capacity } : {}),
|
|
4895
4820
|
};
|
|
4896
4821
|
if (opts.human)
|
|
4897
|
-
console.log(formatLaneListHuman(lanes
|
|
4822
|
+
console.log(formatLaneListHuman(lanes));
|
|
4898
4823
|
else
|
|
4899
4824
|
printJson(result);
|
|
4900
4825
|
}
|
|
4901
|
-
|
|
4902
|
-
export async function runFastCachedLanesListFromEntrypoint() {
|
|
4903
|
-
try {
|
|
4904
|
-
await runList(resolveDeps(), { json: true }, {
|
|
4905
|
-
snapshotCacheEnabled: true,
|
|
4906
|
-
lanePlacementEnabled: true,
|
|
4907
|
-
});
|
|
4908
|
-
}
|
|
4909
|
-
catch (err) {
|
|
4910
|
-
failJson(err);
|
|
4911
|
-
}
|
|
4912
|
-
}
|
|
4913
|
-
function formatLaneListHuman(lanes, remoteLanesLoading = false) {
|
|
4826
|
+
function formatLaneListHuman(lanes) {
|
|
4914
4827
|
const rows = lanes.map((lane) => {
|
|
4915
4828
|
const ids = lane.story_ids;
|
|
4916
4829
|
const storyLabel = ids.length > 0
|
|
4917
4830
|
? "stories: " + ids.join(", ")
|
|
4918
4831
|
: "no story: " + (lane.no_story_reason ?? "reason not recorded");
|
|
4919
|
-
const snapshotNote = lane.remote_snapshot_stale && lane.remote_snapshot_age_s !== null &&
|
|
4920
|
-
lane.remote_snapshot_age_s !== undefined
|
|
4921
|
-
? ` remote snapshot stale (${lane.remote_snapshot_age_s}s)`
|
|
4922
|
-
: "";
|
|
4923
4832
|
return lane.lane_id + " " + lane.state + " " + lane.provider + " " + lane.project_id +
|
|
4924
|
-
" " + storyLabel
|
|
4833
|
+
" " + storyLabel;
|
|
4925
4834
|
});
|
|
4926
4835
|
if (rows.length === 0)
|
|
4927
4836
|
rows.push("No lanes.");
|
|
4928
|
-
if (remoteLanesLoading)
|
|
4929
|
-
rows.push("Remote lanes loading.");
|
|
4930
4837
|
return rows.join("\n");
|
|
4931
4838
|
}
|
|
4932
4839
|
async function runStatus(ctx, opts) {
|
|
@@ -5121,8 +5028,17 @@ async function runShow(ctx, laneId) {
|
|
|
5121
5028
|
const doneStateVerdict = storedLane.state === "done" && storedLane.keep_alive === true
|
|
5122
5029
|
? doneKeepAliveVerdict(storedLane, { decision: storedLane.last_envelope?.decision, story_complete: storedLane.story_complete }, storedLane.keep_alive_standing === true && hasPendingKeepAliveWork(hqRoot, storedLane))
|
|
5123
5030
|
: null;
|
|
5124
|
-
|
|
5125
|
-
|
|
5031
|
+
let managerStatusTarget;
|
|
5032
|
+
let managerStatusGateError;
|
|
5033
|
+
try {
|
|
5034
|
+
resolveLaneCompany(hqRoot, storedLane);
|
|
5035
|
+
managerStatusTarget = resolveManagerStatusTarget(hqRoot, storedLane);
|
|
5036
|
+
}
|
|
5037
|
+
catch (err) {
|
|
5038
|
+
managerStatusGateError = err instanceof LanesError ? err.error : "manager_status_gate_unavailable";
|
|
5039
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5040
|
+
process.stderr.write(`hq lanes: manager status gate disabled for ${storedLane.lane_id}: ${managerStatusGateError}: ${message}\n`);
|
|
5041
|
+
}
|
|
5126
5042
|
const blockerFreshness = await resolveBlockerFreshnessForLane(hqRoot, storedLane, {
|
|
5127
5043
|
env: ctx.env,
|
|
5128
5044
|
now: ctx.now().getTime(),
|
|
@@ -5163,6 +5079,7 @@ async function runShow(ctx, laneId) {
|
|
|
5163
5079
|
envelope_repair_mode: lane.envelope_repair?.mode ?? null,
|
|
5164
5080
|
envelope_validation_errors: lane.envelope_validation_errors ?? [],
|
|
5165
5081
|
last_resume: lane.last_resume ?? null,
|
|
5082
|
+
keep_alive_history: lane.keep_alive_history ?? [],
|
|
5166
5083
|
account: lane.account ?? null,
|
|
5167
5084
|
account_history: lane.account_history ?? [],
|
|
5168
5085
|
failed_resume_history: lane.failed_resume_history ?? [],
|
|
@@ -5186,15 +5103,16 @@ async function runShow(ctx, laneId) {
|
|
|
5186
5103
|
(storedLane.keep_alive === true ? null : "not_opted_in"),
|
|
5187
5104
|
consecutive_auto_resumes: lane.keep_alive_resume_count ?? 0,
|
|
5188
5105
|
last_auto_resume_at: lane.keep_alive_last_resume_at ?? null,
|
|
5106
|
+
keep_alive_history: lane.keep_alive_history ?? [],
|
|
5189
5107
|
next_eligible_at: lane.keep_alive_next_eligible_at ?? null,
|
|
5190
5108
|
exhausted_at: lane.keep_alive_exhausted_at ?? null,
|
|
5191
5109
|
},
|
|
5192
|
-
manager_status_gate:
|
|
5110
|
+
manager_status_gate: managerStatusGateError !== undefined
|
|
5193
5111
|
? {
|
|
5194
5112
|
status_path: null,
|
|
5195
5113
|
skipped: null,
|
|
5196
5114
|
consecutive_misses: storedLane.status_gate?.consecutive_misses ?? 0,
|
|
5197
|
-
error:
|
|
5115
|
+
error: managerStatusGateError,
|
|
5198
5116
|
}
|
|
5199
5117
|
: managerStatusTarget?.manager
|
|
5200
5118
|
? {
|
|
@@ -5910,7 +5828,6 @@ async function runAdmit(ctx, laneId, opts) {
|
|
|
5910
5828
|
}
|
|
5911
5829
|
const started = spawnLaneWorker(hqRoot, lane, {
|
|
5912
5830
|
env: ctx.env,
|
|
5913
|
-
managerStatusGateEnabled: await managerStatusGateEnabledForLane(hqRoot, lane, { env: ctx.env }),
|
|
5914
5831
|
modelDeps: {
|
|
5915
5832
|
readFileSync: ctx.readFileSync,
|
|
5916
5833
|
probe: ctx.probeProvider,
|
|
@@ -6917,6 +6834,89 @@ function isDefiniteOutpostLaneNotFound(dispatched, laneId, ownerError) {
|
|
|
6917
6834
|
ownerError?.error === "lane_not_found" &&
|
|
6918
6835
|
ownerError.details.lane_id === laneId;
|
|
6919
6836
|
}
|
|
6837
|
+
async function dispatchPrimaryLaneMessage(ctx, laneId, options) {
|
|
6838
|
+
const outpostId = "primary";
|
|
6839
|
+
const waitMs = outpostSingleLaneWaitMs(ctx.env);
|
|
6840
|
+
let dispatched;
|
|
6841
|
+
try {
|
|
6842
|
+
dispatched = await ctx.dispatchOutpostExec({
|
|
6843
|
+
outpostId,
|
|
6844
|
+
command: buildOutpostLaneCommand({
|
|
6845
|
+
action: "message",
|
|
6846
|
+
laneId,
|
|
6847
|
+
text: options.text,
|
|
6848
|
+
project: options.project,
|
|
6849
|
+
story: options.story,
|
|
6850
|
+
account: options.account,
|
|
6851
|
+
model: options.model,
|
|
6852
|
+
effort: options.effort,
|
|
6853
|
+
worker: options.worker,
|
|
6854
|
+
compact: options.compact,
|
|
6855
|
+
callerLaneId: ctx.env.HQ_LANE_ID?.trim() || undefined,
|
|
6856
|
+
callerSessionId: sessionIdFromEnv(ctx.env),
|
|
6857
|
+
}),
|
|
6858
|
+
timeoutSeconds: Math.ceil(waitMs / 1000),
|
|
6859
|
+
waitMs,
|
|
6860
|
+
});
|
|
6861
|
+
}
|
|
6862
|
+
catch (err) {
|
|
6863
|
+
const message = dispatchErrorMessage(err);
|
|
6864
|
+
throw new LanesError("outpost_dispatch_failed", `Could not dispatch message for lane ${laneId} to primary: ${message}`, { lane_id: laneId, outpost_id: outpostId, wait_ms: waitMs, wait_env: OUTPOST_SINGLE_LANE_WAIT_ENV });
|
|
6865
|
+
}
|
|
6866
|
+
const confirmedCommandId = dispatched.commandId?.trim();
|
|
6867
|
+
const ownerError = ownerErrorFromOutput(dispatched.stdout);
|
|
6868
|
+
if (isDefiniteOutpostLaneNotFound(dispatched, laneId, ownerError)) {
|
|
6869
|
+
throw new LanesError("lane_not_found", ownerError.message, {
|
|
6870
|
+
...ownerError.details,
|
|
6871
|
+
lane_id: laneId,
|
|
6872
|
+
outpost_id: outpostId,
|
|
6873
|
+
command_id: confirmedCommandId,
|
|
6874
|
+
});
|
|
6875
|
+
}
|
|
6876
|
+
if (dispatched.done === true &&
|
|
6877
|
+
Boolean(confirmedCommandId) &&
|
|
6878
|
+
dispatched.status === "Failed" &&
|
|
6879
|
+
dispatched.exitCode !== null &&
|
|
6880
|
+
dispatched.exitCode !== 0 &&
|
|
6881
|
+
ownerError) {
|
|
6882
|
+
throw new LanesError(ownerError.error, ownerError.message, {
|
|
6883
|
+
...ownerError.details,
|
|
6884
|
+
lane_id: laneId,
|
|
6885
|
+
outpost_id: outpostId,
|
|
6886
|
+
command_id: confirmedCommandId,
|
|
6887
|
+
});
|
|
6888
|
+
}
|
|
6889
|
+
if (dispatched.done !== true ||
|
|
6890
|
+
dispatched.status !== "Success" ||
|
|
6891
|
+
dispatched.exitCode !== 0 ||
|
|
6892
|
+
!confirmedCommandId) {
|
|
6893
|
+
throw new LanesError("outpost_delivery_unconfirmed", `Primary did not confirm message delivery for lane ${laneId}`, {
|
|
6894
|
+
lane_id: laneId,
|
|
6895
|
+
outpost_id: outpostId,
|
|
6896
|
+
command_id: confirmedCommandId ?? null,
|
|
6897
|
+
status: dispatched.status,
|
|
6898
|
+
done: dispatched.done ?? false,
|
|
6899
|
+
exit_code: dispatched.exitCode,
|
|
6900
|
+
});
|
|
6901
|
+
}
|
|
6902
|
+
const remote = parseRemoteJson(dispatched.stdout, "Primary lane message");
|
|
6903
|
+
if (remote === null ||
|
|
6904
|
+
remote.ok !== true ||
|
|
6905
|
+
remote.action !== "message" ||
|
|
6906
|
+
remote.lane_id !== laneId ||
|
|
6907
|
+
remote.accepted !== true) {
|
|
6908
|
+
throw new LanesError("outpost_delivery_unconfirmed", `Primary completed exec without a confirmed message result for lane ${laneId}`, { lane_id: laneId, outpost_id: outpostId, command_id: confirmedCommandId });
|
|
6909
|
+
}
|
|
6910
|
+
if (!options.silent) {
|
|
6911
|
+
printJson({
|
|
6912
|
+
...remote,
|
|
6913
|
+
outpost_id: outpostId,
|
|
6914
|
+
outpost_command_id: confirmedCommandId,
|
|
6915
|
+
outpost_transport: "outposts_exec",
|
|
6916
|
+
delivered_to: { host: outpostId, lane_id: laneId, mechanism: "outposts_exec" },
|
|
6917
|
+
});
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6920
6920
|
async function dispatchOutpostLaneStop(ctx, lane, reason, quiet = false) {
|
|
6921
6921
|
if (lane.host.kind !== "outpost") {
|
|
6922
6922
|
throw new LanesError("outpost_dispatch_failed", `Lane ${lane.lane_id} has no Outpost host to dispatch stop to`, { lane_id: lane.lane_id });
|
|
@@ -7591,6 +7591,7 @@ async function runReconcile(ctx, opts, recoverQueuedMessages) {
|
|
|
7591
7591
|
? { model: automatic.preservedModel, model_source: "preserved" }
|
|
7592
7592
|
: {}),
|
|
7593
7593
|
},
|
|
7594
|
+
accountSelection: selection,
|
|
7594
7595
|
};
|
|
7595
7596
|
}
|
|
7596
7597
|
let latest;
|
|
@@ -7608,7 +7609,10 @@ async function runReconcile(ctx, opts, recoverQueuedMessages) {
|
|
|
7608
7609
|
latest.last_resume?.session_id !== lane.last_resume?.session_id)
|
|
7609
7610
|
return { lane: latest };
|
|
7610
7611
|
if (selection.account === lane.account) {
|
|
7611
|
-
return {
|
|
7612
|
+
return {
|
|
7613
|
+
lane: persistClaudeAccountSelection(hqRoot, recoveredLane, selection),
|
|
7614
|
+
accountSelection: selection,
|
|
7615
|
+
};
|
|
7612
7616
|
}
|
|
7613
7617
|
try {
|
|
7614
7618
|
const moved = await prepareAccountMove(ctx, recoveredLane, {
|
|
@@ -7622,7 +7626,7 @@ async function runReconcile(ctx, opts, recoverQueuedMessages) {
|
|
|
7622
7626
|
admissionLocksHeld: true,
|
|
7623
7627
|
accountSelection: selection,
|
|
7624
7628
|
});
|
|
7625
|
-
return { lane: moved.lane };
|
|
7629
|
+
return { lane: moved.lane, accountSelection: selection };
|
|
7626
7630
|
}
|
|
7627
7631
|
catch (err) {
|
|
7628
7632
|
let latest;
|
|
@@ -7830,6 +7834,7 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
7830
7834
|
assessLaneAdmission,
|
|
7831
7835
|
casUpdateLane,
|
|
7832
7836
|
dispatchOutpostLaneCommand,
|
|
7837
|
+
dispatchPrimaryLaneMessage,
|
|
7833
7838
|
drainHookStatusFor,
|
|
7834
7839
|
laneIsHostedHere,
|
|
7835
7840
|
laneWithRecoveredProviderSession,
|
package/dist/fast-scaffold.d.ts
CHANGED
|
@@ -66,11 +66,6 @@ export type ParsedSecretsEnvFastRequest = {
|
|
|
66
66
|
* the full CLI, which remains the source of truth for help and errors.
|
|
67
67
|
*/
|
|
68
68
|
export declare function parseSecretsEnvFastRequest(argv: readonly string[]): ParsedSecretsEnvFastRequest | null;
|
|
69
|
-
/**
|
|
70
|
-
* The cache-first list path only handles the bare JSON request. `--fresh`,
|
|
71
|
-
* filters, help, and unknown options stay with Commander and the full CLI.
|
|
72
|
-
*/
|
|
73
|
-
export declare function isFastCachedLanesListRequest(argv: readonly string[]): boolean;
|
|
74
69
|
/**
|
|
75
70
|
* Parse `hq core [--hq-root <path>] <name> [args...]` when `<name>` is a
|
|
76
71
|
* fast-path script. Returns null for anything else so the caller defers to the
|