@indigoai-us/hq-cli 5.210.0 → 5.212.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 +15 -0
- package/dist/commands/lanes.js +12 -1
- package/dist/lib/checkpoint-ontology/plan.d.ts +8 -0
- package/dist/lib/checkpoint-ontology/plan.js +7 -1
- package/dist/lib/lanes/admission.js +1 -1
- package/dist/lib/lanes/profile.d.ts +7 -1
- package/dist/lib/lanes/profile.js +13 -0
- package/dist/lib/lanes/reconcile.js +39 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.212.0] — 2026-09-26
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- `checkpoint.ontology.ignore-annotations` now strips annotator entity lists from the ontology inputs only when the checkpoint sibling runs on grok. On a machine that falls back to claude or codex the model reads the annotated inputs as before, because Claude on stripped inputs lost 0.139 recall on the gold-v2 set.
|
|
10
|
+
|
|
11
|
+
## [5.211.0] — 2026-09-26
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Reconcile now applies `keep_alive` from a recorded worker profile to older
|
|
16
|
+
lanes whose lane field is unset. An explicit lane value wins, unreadable
|
|
17
|
+
profiles fail closed and are reported, and `lanes show --json` identifies
|
|
18
|
+
the source of its effective value.
|
|
19
|
+
|
|
5
20
|
## [5.210.0] — 2026-09-26
|
|
6
21
|
|
|
7
22
|
### Fixed
|
package/dist/commands/lanes.js
CHANGED
|
@@ -38,6 +38,7 @@ import { sessionIdFromEnv } from "../lib/mesh/live/session-identity.js";
|
|
|
38
38
|
import { effectiveAccountHome } from "../lib/lanes/account-home.js";
|
|
39
39
|
import { AccountResolutionError, compareLaneQueueOrder, coveredLaneIds, DEFAULT_ACCOUNT_HOMES, LANE_PROVIDERS, LANE_STATES, PROVIDER_HOME_ENV, QUESTION_STATUSES, SENIOR_KINDS, accountStatus, appendCappedHistory, canonicalizeHome, createLane, createQuestion, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installDrainHook, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, aliveDirectChildren, assignedChildHireGrants, LANE_HIRE_GRANTS_FLAG, planHireGrantBackfill, terminalChildResumeHireGrantError, withHireGrantAdmission, laneStoryLedgerEnabled, validateProjectStories, buildLaneStatusSnapshot, formatLaneStatusHuman, listAccountStatuses, listLaneIds, listQuestionIds, listSessionLiveness, loadLanesConfig, laneRunsHere, MAX_LANE_DEPTH, MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_UNCOVERED_EXIT_CODE, MAX_WATCHED_LANES, monitorReminderText, readLiveMonitorEvidence, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, parseLaneRecord, parseLaneState, parseLivenessState, parseQuestionRecord, parseQuestionStatus, parseSeniorKind, readDaemonPresenceConnected, readLane, retryUpdateLane, syncLaneRecordFromOwner, readQuestion, resolveAccount, resolveLaneWorker, ignoredWorkerProfileFields, loadWorkerProfile, runReconcilePass, wakeAnsweredLaneNow, runLaneWatch, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, writeLanesConfig, appendDropboxMessage, answerDropboxMessage, deliveryRefusalReason, resumeCommandRefusal, dropboxDir, dropboxInboxPath, laneAcceptsDropboxDelivery, laneAcceptsOperatorMessage, laneDeliveryMechanism, hasActiveAdmissionReservation, hasActivePendingResume, hasRecordedSessionId, hasEarlierEligibleQueuedLane, laneAdmissionCapReason, providerSupportsSessionResume, providerSessionPortable, sessionNotPortableMessage, withLaneAdmissionLock, withLaneHireLocks, laneIdForAnswerDelivery, operatorMessageRefusalReason, raiseLaneQuestion, sha256Text, writeQuestionBody, } from "../lib/lanes/index.js";
|
|
40
40
|
import { activeLaneStories, laneStories, laneStory, storyWarning, } from "../lib/lanes/stories.js";
|
|
41
|
+
import { resolveLaneKeepAlive } from "../lib/lanes/profile.js";
|
|
41
42
|
import { questionBodyAbsPath } from "../lib/lanes/questions.js";
|
|
42
43
|
import { compactionAfterUsage, } from "../lib/lanes/compaction.js";
|
|
43
44
|
import { assertUniqueAccountHomes, providerCompactAfterMs } from "../lib/lanes/config.js";
|
|
@@ -4489,6 +4490,15 @@ async function runShow(ctx, laneId) {
|
|
|
4489
4490
|
? { ...storedLane, state: "remote", remote_state: storedLane.state, queued_reason: undefined }
|
|
4490
4491
|
: storedLane;
|
|
4491
4492
|
const askDeliveryFailed = readJsonFile(askDeliveryFailedPath(hqRoot, laneId));
|
|
4493
|
+
let keepAliveState;
|
|
4494
|
+
try {
|
|
4495
|
+
keepAliveState = resolveLaneKeepAlive(hqRoot, storedLane);
|
|
4496
|
+
}
|
|
4497
|
+
catch (err) {
|
|
4498
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4499
|
+
process.stderr.write(`hq lanes show: keep-alive profile could not be loaded for ${laneId}: ${message}\n`);
|
|
4500
|
+
keepAliveState = { enabled: false, source: "none" };
|
|
4501
|
+
}
|
|
4492
4502
|
printJson({
|
|
4493
4503
|
ok: true,
|
|
4494
4504
|
action: "show",
|
|
@@ -4514,7 +4524,8 @@ async function runShow(ctx, laneId) {
|
|
|
4514
4524
|
terminal_reason: lane.terminal_reason ?? null,
|
|
4515
4525
|
terminal_details: lane.terminal_details ?? null,
|
|
4516
4526
|
keep_alive_state: {
|
|
4517
|
-
enabled:
|
|
4527
|
+
enabled: keepAliveState.enabled,
|
|
4528
|
+
source: keepAliveState.source,
|
|
4518
4529
|
consecutive_auto_resumes: lane.keep_alive_resume_count ?? 0,
|
|
4519
4530
|
last_auto_resume_at: lane.keep_alive_last_resume_at ?? null,
|
|
4520
4531
|
next_eligible_at: lane.keep_alive_next_eligible_at ?? null,
|
|
@@ -12,6 +12,12 @@ import { type OntologyCompany } from "./company.js";
|
|
|
12
12
|
export declare const ONTOLOGY_FLAG = "checkpoint.ontology";
|
|
13
13
|
export declare const SHARED_INPUTS_FLAG = "checkpoint.ontology.shared-inputs";
|
|
14
14
|
export declare const COMPANY_BRIEF_FLAG = "checkpoint.ontology.company-brief";
|
|
15
|
+
/**
|
|
16
|
+
* Applies only when the payload's sibling backend is grok. On gold-v2, Claude
|
|
17
|
+
* with stripped inputs lost 0.139 recall; Grok with stripped inputs gained
|
|
18
|
+
* precision without losing recall. A machine that falls back from grok keeps
|
|
19
|
+
* the annotated inputs.
|
|
20
|
+
*/
|
|
15
21
|
export declare const IGNORE_ANNOTATIONS_FLAG = "checkpoint.ontology.ignore-annotations";
|
|
16
22
|
/**
|
|
17
23
|
* With `--backend auto`, `hq core checkpoint` tries grok first for this
|
|
@@ -97,6 +103,8 @@ export interface OntologyPlan {
|
|
|
97
103
|
}
|
|
98
104
|
export interface CheckpointPayloadLike {
|
|
99
105
|
company?: unknown;
|
|
106
|
+
/** The sibling backend `hq core checkpoint` spawned for this payload. */
|
|
107
|
+
backend?: unknown;
|
|
100
108
|
files?: unknown;
|
|
101
109
|
summary?: unknown;
|
|
102
110
|
decisions?: unknown;
|
|
@@ -16,6 +16,12 @@ import { buildEntityIndex, listKnowledgeFiles, listSignalFiles, readSignal } fro
|
|
|
16
16
|
export const ONTOLOGY_FLAG = "checkpoint.ontology";
|
|
17
17
|
export const SHARED_INPUTS_FLAG = "checkpoint.ontology.shared-inputs";
|
|
18
18
|
export const COMPANY_BRIEF_FLAG = "checkpoint.ontology.company-brief";
|
|
19
|
+
/**
|
|
20
|
+
* Applies only when the payload's sibling backend is grok. On gold-v2, Claude
|
|
21
|
+
* with stripped inputs lost 0.139 recall; Grok with stripped inputs gained
|
|
22
|
+
* precision without losing recall. A machine that falls back from grok keeps
|
|
23
|
+
* the annotated inputs.
|
|
24
|
+
*/
|
|
19
25
|
export const IGNORE_ANNOTATIONS_FLAG = "checkpoint.ontology.ignore-annotations";
|
|
20
26
|
/**
|
|
21
27
|
* With `--backend auto`, `hq core checkpoint` tries grok first for this
|
|
@@ -210,7 +216,7 @@ export async function planOntologyRun(options) {
|
|
|
210
216
|
const companyBrief = (await options.readFlag(COMPANY_BRIEF_FLAG, company))
|
|
211
217
|
? writeCompanyBrief(hqRoot, company, options.now ?? new Date())
|
|
212
218
|
: undefined;
|
|
213
|
-
const ignoreAnnotations = await options.readFlag(IGNORE_ANNOTATIONS_FLAG, company);
|
|
219
|
+
const ignoreAnnotations = (await options.readFlag(IGNORE_ANNOTATIONS_FLAG, company)) && payload.backend === "grok";
|
|
214
220
|
recordBackendPreference(hqRoot, company, await options.readFlag(GROK_BACKEND_FLAG, company));
|
|
215
221
|
const touched = sessionTouched(hqRoot, company, payload.files);
|
|
216
222
|
const { ledger, firstRun } = refreshLedger(company, readLedger(hqRoot, company), touched, sharedInputs);
|
|
@@ -137,8 +137,8 @@ export function hasActivePendingResume(lane, nowMs) {
|
|
|
137
137
|
return false;
|
|
138
138
|
if (lane.state === "queued" && pending.trigger === "answered_questions")
|
|
139
139
|
return false;
|
|
140
|
+
// This timestamp tags automatic keep-alive resumes, including profile-derived ones.
|
|
140
141
|
if (lane.state === "queued" &&
|
|
141
|
-
lane.keep_alive === true &&
|
|
142
142
|
pending.trigger === "resume" &&
|
|
143
143
|
pending.resumed_from === "done" &&
|
|
144
144
|
lane.keep_alive_last_resume_at === pending.at)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* and package trees; this module describes the provider launch contract that
|
|
7
7
|
* must be re-read for every spawn.
|
|
8
8
|
*/
|
|
9
|
-
import { type LaneProvider } from "./types.js";
|
|
9
|
+
import { type LaneRecord, type LaneProvider } from "./types.js";
|
|
10
10
|
export interface WorkerProfileMeta {
|
|
11
11
|
version?: string;
|
|
12
12
|
provider: LaneProvider;
|
|
@@ -37,6 +37,12 @@ export declare function personalWorkerProfileDir(hqRoot: string, id: string): st
|
|
|
37
37
|
/** A meta.yaml file is the explicit marker for a personal worker profile. */
|
|
38
38
|
export declare function workerProfileMarker(hqRoot: string, id: string): "absent" | "present";
|
|
39
39
|
export declare function loadWorkerProfile(hqRoot: string, id: string): WorkerProfile;
|
|
40
|
+
export interface EffectiveLaneKeepAlive {
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
source: "lane" | "profile" | "none";
|
|
43
|
+
}
|
|
44
|
+
/** Resolve the keep-alive opt-in recorded on a lane or its attached profile. */
|
|
45
|
+
export declare function resolveLaneKeepAlive(hqRoot: string, lane: Pick<LaneRecord, "keep_alive" | "worker_profile">): EffectiveLaneKeepAlive;
|
|
40
46
|
export declare function workerProfilePrompt(profile: WorkerProfile, delivery?: "hook" | "prompt"): string;
|
|
41
47
|
export declare function ignoredWorkerProfileFields(provider: LaneProvider): string[];
|
|
42
48
|
/**
|
|
@@ -370,6 +370,19 @@ export function loadWorkerProfile(hqRoot, id) {
|
|
|
370
370
|
contentHash: hashProfileFiles(dir, hashFiles),
|
|
371
371
|
};
|
|
372
372
|
}
|
|
373
|
+
/** Resolve the keep-alive opt-in recorded on a lane or its attached profile. */
|
|
374
|
+
export function resolveLaneKeepAlive(hqRoot, lane) {
|
|
375
|
+
if (lane.keep_alive !== undefined) {
|
|
376
|
+
return { enabled: lane.keep_alive, source: "lane" };
|
|
377
|
+
}
|
|
378
|
+
if (lane.worker_profile === undefined) {
|
|
379
|
+
return { enabled: false, source: "none" };
|
|
380
|
+
}
|
|
381
|
+
const profileKeepAlive = loadWorkerProfile(hqRoot, lane.worker_profile).meta.keep_alive;
|
|
382
|
+
return profileKeepAlive === undefined
|
|
383
|
+
? { enabled: false, source: "none" }
|
|
384
|
+
: { enabled: profileKeepAlive, source: "profile" };
|
|
385
|
+
}
|
|
373
386
|
export function workerProfilePrompt(profile, delivery = "prompt") {
|
|
374
387
|
const parts = [profile.systemPrompt.trimEnd()];
|
|
375
388
|
if (delivery === "hook")
|
|
@@ -15,7 +15,7 @@ import { loadLanesConfig, providerQuotaDefaultHoldMs } from "./config.js";
|
|
|
15
15
|
import { MAX_LANE_DEPTH } from "./constants.js";
|
|
16
16
|
import { AccountResolutionError, LanesError, isLaneVersionConflict } from "./errors.js";
|
|
17
17
|
import { LANE_HIRE_GRANTS_FLAG, terminalChildResumeHireGrantError, withHireGrantAdmission, } from "./hire-grants.js";
|
|
18
|
-
import { loadWorkerProfile } from "./profile.js";
|
|
18
|
+
import { loadWorkerProfile, resolveLaneKeepAlive } from "./profile.js";
|
|
19
19
|
import { classifySessionLiveness, defaultLivenessDeps, loadLivenessIndex, readDaemonPresenceConnected, unindexedClaudeSessionLiveness, } from "./liveness.js";
|
|
20
20
|
import { ANSWERED_QUESTIONS_FILE, armLaneWatcher, envelopeRepairMode, isPidRecordAlive, laneRunDir, readPidRecord, readSpawnManifest, markSpawnFailure, spawnEnvelopeRepair, spawnLaneWorker, retryLaneOnAlternateAccount, } from "./spawn.js";
|
|
21
21
|
import { appendCappedHistory, lanesStoreRoot, parseLaneRecord, parseQuestionRecord, readLane, readQuestion, updateLane, updateQuestion, } from "./store.js";
|
|
@@ -801,7 +801,8 @@ export async function runPassBody(hqRoot, deps) {
|
|
|
801
801
|
const keepAliveHireGrantFlagCompanies = new Map();
|
|
802
802
|
for (const lane of lanes) {
|
|
803
803
|
if (lane.state !== "done" ||
|
|
804
|
-
lane.keep_alive !== true
|
|
804
|
+
(lane.keep_alive !== true &&
|
|
805
|
+
!(lane.keep_alive === undefined && lane.worker_profile !== undefined)) ||
|
|
805
806
|
!laneRunsHere(lane, deps.host) ||
|
|
806
807
|
lane.terminal_reason === PROVIDER_REJECTED_REASON ||
|
|
807
808
|
lane.terminal_reason === "account_not_logged_in" ||
|
|
@@ -1417,19 +1418,27 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1417
1418
|
const nowIso = now.toISOString();
|
|
1418
1419
|
const config = loadLanesConfig(hqRoot);
|
|
1419
1420
|
for (const lane of lanes) {
|
|
1421
|
+
const hasRecordedProfileFallback = lane.keep_alive === undefined && lane.worker_profile !== undefined;
|
|
1420
1422
|
if (lane.state !== "done" ||
|
|
1421
|
-
lane.keep_alive
|
|
1423
|
+
lane.keep_alive === false ||
|
|
1424
|
+
(lane.keep_alive !== true && !hasRecordedProfileFallback) ||
|
|
1422
1425
|
!laneRunsHere(lane, deps.host))
|
|
1423
1426
|
continue;
|
|
1424
1427
|
const latest = readLatestEnvelopeRecord(hqRoot, lane.lane_id);
|
|
1425
1428
|
const envelope = latest?.envelope;
|
|
1426
1429
|
if (!envelope || envelope.decision !== "done")
|
|
1427
1430
|
continue;
|
|
1431
|
+
const keepAliveConfigurationUnchanged = (candidate) => lane.keep_alive === true
|
|
1432
|
+
? candidate.keep_alive === true
|
|
1433
|
+
: lane.keep_alive === undefined &&
|
|
1434
|
+
lane.worker_profile !== undefined &&
|
|
1435
|
+
candidate.keep_alive === undefined &&
|
|
1436
|
+
candidate.worker_profile === lane.worker_profile;
|
|
1428
1437
|
if (envelope.story_complete === true) {
|
|
1429
1438
|
if (hasKeepAliveProgress(lane)) {
|
|
1430
1439
|
casLaneIf(hqRoot, lane.lane_id, (current) => current.version === lane.version &&
|
|
1431
1440
|
current.state === "done" &&
|
|
1432
|
-
current
|
|
1441
|
+
keepAliveConfigurationUnchanged(current), (current) => clearedKeepAliveProgress(current), deps.dryRun);
|
|
1433
1442
|
}
|
|
1434
1443
|
continue;
|
|
1435
1444
|
}
|
|
@@ -1440,10 +1449,31 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1440
1449
|
continue;
|
|
1441
1450
|
if (flagByCompany.get(keepAliveCompanyKey(lane.company)) !== true)
|
|
1442
1451
|
continue;
|
|
1452
|
+
let keepAlive;
|
|
1453
|
+
try {
|
|
1454
|
+
keepAlive = resolveLaneKeepAlive(hqRoot, lane);
|
|
1455
|
+
}
|
|
1456
|
+
catch (err) {
|
|
1457
|
+
const message = err instanceof LanesError
|
|
1458
|
+
? `${err.error}: ${err.message}`
|
|
1459
|
+
: err instanceof Error ? err.message : String(err);
|
|
1460
|
+
markDirty(summary, {
|
|
1461
|
+
kind: "lane",
|
|
1462
|
+
id: lane.lane_id,
|
|
1463
|
+
why: `keep-alive worker profile could not be loaded: ${message}`,
|
|
1464
|
+
});
|
|
1465
|
+
continue;
|
|
1466
|
+
}
|
|
1467
|
+
if (!keepAlive.enabled)
|
|
1468
|
+
continue;
|
|
1469
|
+
const keepAliveStillEnabled = (candidate) => keepAlive.source === "lane"
|
|
1470
|
+
? candidate.keep_alive === true
|
|
1471
|
+
: candidate.keep_alive === undefined &&
|
|
1472
|
+
candidate.worker_profile === lane.worker_profile;
|
|
1443
1473
|
const current = readLane(hqRoot, lane.lane_id);
|
|
1444
1474
|
if (current.version !== lane.version ||
|
|
1445
1475
|
current.state !== "done" ||
|
|
1446
|
-
current
|
|
1476
|
+
!keepAliveStillEnabled(current) ||
|
|
1447
1477
|
!laneRunsHere(current, deps.host))
|
|
1448
1478
|
continue;
|
|
1449
1479
|
const currentEnvelope = readLatestEnvelopeRecord(hqRoot, current.lane_id)?.envelope;
|
|
@@ -1453,7 +1483,7 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1453
1483
|
if (hasKeepAliveProgress(current)) {
|
|
1454
1484
|
casLaneIf(hqRoot, current.lane_id, (latestLane) => latestLane.version === current.version &&
|
|
1455
1485
|
latestLane.state === "done" &&
|
|
1456
|
-
latestLane
|
|
1486
|
+
keepAliveStillEnabled(latestLane), (latestLane) => clearedKeepAliveProgress(latestLane), deps.dryRun);
|
|
1457
1487
|
}
|
|
1458
1488
|
continue;
|
|
1459
1489
|
}
|
|
@@ -1470,7 +1500,7 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1470
1500
|
continue;
|
|
1471
1501
|
const exhausted = casLaneIf(hqRoot, current.lane_id, (latestLane) => latestLane.version === current.version &&
|
|
1472
1502
|
latestLane.state === "done" &&
|
|
1473
|
-
latestLane
|
|
1503
|
+
keepAliveStillEnabled(latestLane) &&
|
|
1474
1504
|
(latestLane.keep_alive_resume_count ?? 0) >= LEAD_LANE_KEEP_ALIVE_MAX_RESUMES &&
|
|
1475
1505
|
latestLane.keep_alive_exhausted_at === undefined, (latestLane) => ({ ...latestLane, keep_alive_exhausted_at: nowIso }), deps.dryRun);
|
|
1476
1506
|
if (exhausted.changed && !deps.dryRun) {
|
|
@@ -1495,7 +1525,7 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1495
1525
|
if (resetByHuman && hasKeepAliveProgress(current)) {
|
|
1496
1526
|
casLaneIf(hqRoot, current.lane_id, (latestLane) => latestLane.version === current.version &&
|
|
1497
1527
|
latestLane.state === "done" &&
|
|
1498
|
-
latestLane
|
|
1528
|
+
keepAliveStillEnabled(latestLane), (latestLane) => clearedKeepAliveProgress(latestLane), deps.dryRun);
|
|
1499
1529
|
}
|
|
1500
1530
|
continue;
|
|
1501
1531
|
}
|
|
@@ -1515,7 +1545,7 @@ function resumeDoneKeepAlive(hqRoot, lanes, summary, deps, now, flagByCompany, h
|
|
|
1515
1545
|
}
|
|
1516
1546
|
const queue = (expectedSeniorId) => casLaneIf(hqRoot, current.lane_id, (latestLane) => latestLane.version === current.version &&
|
|
1517
1547
|
latestLane.state === "done" &&
|
|
1518
|
-
latestLane
|
|
1548
|
+
keepAliveStillEnabled(latestLane) &&
|
|
1519
1549
|
(expectedSeniorId === undefined ||
|
|
1520
1550
|
(latestLane.senior.kind === "lane" && latestLane.senior.id === expectedSeniorId)), (latestLane) => ({
|
|
1521
1551
|
...latestLane,
|