@indigoai-us/hq-cli 5.345.38 → 5.345.40
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 +11 -0
- package/assets/scaffold/core/scripts/derive-trigger-facts.sh +12 -3
- package/assets/scaffold/core/scripts/rebuild-companies-index.sh +12 -0
- package/dist/command-catalog.generated.d.ts +43 -0
- package/dist/command-catalog.generated.js +54 -0
- package/dist/commands/core-dm-bind-native.js +5 -4
- package/dist/commands/db-destroy.d.ts +15 -0
- package/dist/commands/db-destroy.js +143 -0
- package/dist/commands/db-dump.d.ts +9 -0
- package/dist/commands/db-dump.js +19 -11
- package/dist/commands/db.js +2 -0
- package/dist/commands/files-browse.js +1 -1
- package/dist/commands/lanes-message.js +14 -5
- package/dist/commands/lanes-resume.js +62 -14
- package/dist/commands/lanes.js +21 -4
- package/dist/commands/report.js +5 -1
- package/dist/lib/db/control-plane.d.ts +10 -0
- package/dist/lib/db/control-plane.js +18 -0
- package/dist/lib/deploy-api.js +2 -0
- package/dist/lib/doctor/fix/apply.d.ts +2 -0
- package/dist/lib/doctor/fix/apply.js +52 -1
- package/dist/lib/flag-registry.d.ts +1 -1
- package/dist/lib/flag-registry.js +20 -7
- package/dist/lib/lanes/accounts.js +24 -2
- package/dist/lib/lanes/delivery.d.ts +5 -2
- package/dist/lib/lanes/delivery.js +14 -5
- package/dist/lib/lanes/index.d.ts +1 -1
- package/dist/lib/lanes/index.js +1 -1
- package/dist/lib/lanes/reconcile.js +49 -5
- package/dist/lib/lanes/spawn.d.ts +7 -3
- package/dist/lib/lanes/spawn.js +97 -5
- package/dist/lib/lanes/store.js +54 -20
- package/dist/lib/lanes/story-ledger.d.ts +1 -1
- package/dist/lib/lanes/story-ledger.js +4 -4
- package/dist/lib/lanes/types.js +3 -3
- package/package.json +1 -1
package/dist/lib/lanes/spawn.js
CHANGED
|
@@ -51,6 +51,7 @@ export const SPAWN_TERMINAL_REASONS = [
|
|
|
51
51
|
"watcher_not_armed",
|
|
52
52
|
"model_unsupported",
|
|
53
53
|
"account_quota_exhausted",
|
|
54
|
+
"account_model_unavailable",
|
|
54
55
|
];
|
|
55
56
|
const PROVIDER_COMMAND = {
|
|
56
57
|
claude: "claude",
|
|
@@ -237,6 +238,7 @@ function selectSpawnAccount(input) {
|
|
|
237
238
|
existsSync,
|
|
238
239
|
accountDeps,
|
|
239
240
|
hostname,
|
|
241
|
+
now,
|
|
240
242
|
...(pinnedModel ?? profileModel ? { model: pinnedModel ?? profileModel } : {}),
|
|
241
243
|
};
|
|
242
244
|
if (lane.account === undefined) {
|
|
@@ -374,6 +376,27 @@ function selectSpawnAccount(input) {
|
|
|
374
376
|
};
|
|
375
377
|
}
|
|
376
378
|
catch (err) {
|
|
379
|
+
if (refusal instanceof AccountResolutionError &&
|
|
380
|
+
refusal.error === "account_quota_exhausted" &&
|
|
381
|
+
err instanceof AccountResolutionError &&
|
|
382
|
+
err.error === "account_quota_exhausted") {
|
|
383
|
+
const fallbackReasons = Array.isArray(err.details.account_reasons)
|
|
384
|
+
? err.details.account_reasons.filter((candidate) => candidate !== null && typeof candidate === "object" && !Array.isArray(candidate))
|
|
385
|
+
: [{ account: err.details.account, reason: err.error, quota_reset_at: err.details.quota_reset_at }];
|
|
386
|
+
const accountReasons = [
|
|
387
|
+
{ account: lane.account, reason: refusal.error, quota_reset_at: refusal.details.quota_reset_at },
|
|
388
|
+
...fallbackReasons,
|
|
389
|
+
];
|
|
390
|
+
const resetAt = accountReasons
|
|
391
|
+
.map((candidate) => candidate.quota_reset_at)
|
|
392
|
+
.filter((value) => typeof value === "string" && Number.isFinite(Date.parse(value)))
|
|
393
|
+
.sort((a, b) => Date.parse(a) - Date.parse(b))[0];
|
|
394
|
+
throw new AccountResolutionError("account_quota_exhausted", err.message, {
|
|
395
|
+
...err.details,
|
|
396
|
+
...(resetAt === undefined ? {} : { quota_reset_at: resetAt }),
|
|
397
|
+
account_reasons: accountReasons,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
377
400
|
if (reason === "account_unavailable" || reason === "recorded_account_logged_out") {
|
|
378
401
|
if (refusal instanceof Error)
|
|
379
402
|
throw refusal;
|
|
@@ -1458,22 +1481,56 @@ function killQuietly(kill, pid, label) {
|
|
|
1458
1481
|
throw err;
|
|
1459
1482
|
}
|
|
1460
1483
|
}
|
|
1461
|
-
export function markSpawnFailure(hqRoot, laneId, reasonRaw, details) {
|
|
1484
|
+
export function markSpawnFailure(hqRoot, laneId, reasonRaw, details, options = {}) {
|
|
1462
1485
|
const reason = parseSpawnTerminalReason(reasonRaw);
|
|
1463
1486
|
return retryUpdateLane(hqRoot, laneId, "spawn", (current) => {
|
|
1464
1487
|
const existing = current
|
|
1465
1488
|
.terminal_reason;
|
|
1466
|
-
|
|
1489
|
+
const resetCandidates = [
|
|
1490
|
+
details.quota_reset_at,
|
|
1491
|
+
...(Array.isArray(details.account_reasons)
|
|
1492
|
+
? details.account_reasons.flatMap((candidate) => candidate !== null && typeof candidate === "object" && !Array.isArray(candidate)
|
|
1493
|
+
? [candidate.quota_reset_at]
|
|
1494
|
+
: [])
|
|
1495
|
+
: []),
|
|
1496
|
+
].filter((value) => typeof value === "string" && Number.isFinite(Date.parse(value)));
|
|
1497
|
+
const quotaResetAt = resetCandidates.sort((a, b) => Date.parse(a) - Date.parse(b))[0];
|
|
1498
|
+
const resumableQuotaHold = current.keep_alive === true &&
|
|
1499
|
+
(current.pending_resume !== undefined || options.resumeTrigger !== undefined) &&
|
|
1500
|
+
(reason === "account_quota_exhausted" || reason === "account_model_unavailable") &&
|
|
1501
|
+
typeof quotaResetAt === "string" &&
|
|
1502
|
+
Number.isFinite(Date.parse(quotaResetAt));
|
|
1503
|
+
if (current.state === "failed" && existing === reason && !resumableQuotaHold)
|
|
1467
1504
|
return current;
|
|
1505
|
+
const operatorQuotaHold = resumableQuotaHold && options.resumeTrigger !== undefined;
|
|
1468
1506
|
return {
|
|
1469
1507
|
...current,
|
|
1470
|
-
state: "failed",
|
|
1508
|
+
state: resumableQuotaHold ? "interrupted" : "failed",
|
|
1471
1509
|
queued_reason: undefined,
|
|
1472
1510
|
queued_details: undefined,
|
|
1473
1511
|
queued_at: undefined,
|
|
1474
1512
|
admission_reserved_at: undefined,
|
|
1475
1513
|
terminal_reason: reason,
|
|
1476
1514
|
terminal_details: details,
|
|
1515
|
+
...(resumableQuotaHold
|
|
1516
|
+
? {
|
|
1517
|
+
...(options.pendingResume !== undefined
|
|
1518
|
+
? { pending_resume: options.pendingResume }
|
|
1519
|
+
: current.pending_resume === undefined && options.resumeTrigger !== undefined
|
|
1520
|
+
? { pending_resume: { trigger: options.resumeTrigger, at: options.at ?? current.updated_at } }
|
|
1521
|
+
: {}),
|
|
1522
|
+
interrupted_at: options.at ?? current.updated_at,
|
|
1523
|
+
quota_reset_at: quotaResetAt,
|
|
1524
|
+
keep_alive_next_eligible_at: quotaResetAt,
|
|
1525
|
+
...(operatorQuotaHold
|
|
1526
|
+
? {
|
|
1527
|
+
keep_alive_resume_count: 0,
|
|
1528
|
+
keep_alive_last_resume_at: undefined,
|
|
1529
|
+
keep_alive_exhausted_at: undefined,
|
|
1530
|
+
}
|
|
1531
|
+
: {}),
|
|
1532
|
+
}
|
|
1533
|
+
: {}),
|
|
1477
1534
|
};
|
|
1478
1535
|
});
|
|
1479
1536
|
}
|
|
@@ -1891,8 +1948,41 @@ export function spawnLaneWorker(hqRoot, lane, deps = {}, launch = {}) {
|
|
|
1891
1948
|
if (err instanceof AccountResolutionError ||
|
|
1892
1949
|
(err instanceof LanesError &&
|
|
1893
1950
|
(err.error === "account_not_logged_in" || err.error === "model_unsupported"))) {
|
|
1894
|
-
|
|
1895
|
-
|
|
1951
|
+
const resumableQuotaFailure = existing.keep_alive === true &&
|
|
1952
|
+
(existing.pending_resume !== undefined || trigger.kind === "resume" || trigger.kind === "message") &&
|
|
1953
|
+
err instanceof AccountResolutionError &&
|
|
1954
|
+
(err.error === "account_quota_exhausted" || err.error === "account_model_unavailable") &&
|
|
1955
|
+
typeof err.details.quota_reset_at === "string" &&
|
|
1956
|
+
Number.isFinite(Date.parse(err.details.quota_reset_at));
|
|
1957
|
+
if (markPreSpawnFailure || resumableQuotaFailure) {
|
|
1958
|
+
const at = (deps.now ?? (() => new Date()))().toISOString();
|
|
1959
|
+
const pendingResume = trigger.kind === "message"
|
|
1960
|
+
? {
|
|
1961
|
+
...(plan.mode === "resume" ? { session_id: plan.session_id } : {}),
|
|
1962
|
+
trigger: "message",
|
|
1963
|
+
caller: typeof env.HQ_LANE_ID === "string" ? env.HQ_LANE_ID.trim() || "user" : "user",
|
|
1964
|
+
text: trigger.text,
|
|
1965
|
+
...(trigger.message_id !== undefined ? { message_id: trigger.message_id } : {}),
|
|
1966
|
+
...(trigger.monitor_event === true ? { monitor_event: true } : {}),
|
|
1967
|
+
compact: launch.compact !== false,
|
|
1968
|
+
at,
|
|
1969
|
+
}
|
|
1970
|
+
: trigger.kind === "resume"
|
|
1971
|
+
? {
|
|
1972
|
+
...(plan.mode === "resume" ? { session_id: plan.session_id } : {}),
|
|
1973
|
+
trigger: "resume",
|
|
1974
|
+
resumed_from: trigger.from,
|
|
1975
|
+
...(trigger.text !== undefined ? { text: trigger.text } : {}),
|
|
1976
|
+
...(trigger.message_id !== undefined ? { message_id: trigger.message_id } : {}),
|
|
1977
|
+
compact: launch.compact !== false,
|
|
1978
|
+
at,
|
|
1979
|
+
}
|
|
1980
|
+
: existing.pending_resume;
|
|
1981
|
+
markSpawnFailure(hqRoot, lane.lane_id, err.error, err.details, {
|
|
1982
|
+
...(trigger.kind === "resume" || trigger.kind === "message" ? { resumeTrigger: trigger.kind } : {}),
|
|
1983
|
+
...(pendingResume !== undefined ? { pendingResume } : {}),
|
|
1984
|
+
at,
|
|
1985
|
+
});
|
|
1896
1986
|
}
|
|
1897
1987
|
throw err;
|
|
1898
1988
|
}
|
|
@@ -2410,6 +2500,8 @@ export function spawnLaneWorker(hqRoot, lane, deps = {}, launch = {}) {
|
|
|
2410
2500
|
const failed = markSpawnFailure(hqRoot, lane.lane_id, reason, {
|
|
2411
2501
|
message: err instanceof Error ? err.message : String(err),
|
|
2412
2502
|
...(err instanceof LanesError ? err.details : {}),
|
|
2503
|
+
}, {
|
|
2504
|
+
...(trigger.kind === "resume" || trigger.kind === "message" ? { resumeTrigger: trigger.kind } : {}),
|
|
2413
2505
|
});
|
|
2414
2506
|
if (err instanceof LanesError) {
|
|
2415
2507
|
throw new LanesError(err.error, err.message, {
|
package/dist/lib/lanes/store.js
CHANGED
|
@@ -18,7 +18,7 @@ import { readOutpostIdentity } from "./admission-host.js";
|
|
|
18
18
|
import { LaneNotFoundError, LaneSchemaError, LaneVersionConflict, LanesError, isLaneVersionConflict, } from "./errors.js";
|
|
19
19
|
import { HISTORY_CAP, HOST_KINDS, LANE_STORY_STATUSES, LANE_SCHEMA_VERSION, QUESTION_SCHEMA_VERSION, SENIOR_KINDS, isHostKind, isLaneProvider, isQueuedReason, isLaneState, isQuestionStatus, isSeniorKind, isTerminalLaneState, parseMajorSchema, REQUIRED_LANE_RECORD_FIELDS, LANE_FIELD_WRITERS, LANE_WRITERS, } from "./types.js";
|
|
20
20
|
import { laneStories } from "./stories.js";
|
|
21
|
-
import { laneStoryLedgerEnabled, syncLaneToProjectStoryLedger, } from "./story-ledger.js";
|
|
21
|
+
import { laneStoryLedgerEnabled, syncLaneToProjectStoryLedger, validateProjectStories, } from "./story-ledger.js";
|
|
22
22
|
export const LANES_STORE_REL = path.join("workspace", "lanes");
|
|
23
23
|
export const LANE_RECORDS_DIR = "lanes";
|
|
24
24
|
export const QUESTION_RECORDS_DIR = "questions";
|
|
@@ -1608,7 +1608,8 @@ export function updateLane(hqRoot, laneId, expectedVersion, writer, updater, dep
|
|
|
1608
1608
|
beforeWrite: (current) => assertLaneStoreWriteAllowed(current, laneId, writer),
|
|
1609
1609
|
stamp: (current) => ({ written_by_version: newestLaneStoreVersion(current.written_by_version) }),
|
|
1610
1610
|
});
|
|
1611
|
-
|
|
1611
|
+
const ledgerRelevantChange = before !== undefined && laneLedgerRelevantChange(before, updated);
|
|
1612
|
+
if (ledgerRelevantChange) {
|
|
1612
1613
|
return syncStoryLedgerForLane(hqRoot, updated, deps);
|
|
1613
1614
|
}
|
|
1614
1615
|
return updated;
|
|
@@ -1620,21 +1621,54 @@ function laneLedgerRelevantChange(before, after) {
|
|
|
1620
1621
|
JSON.stringify(before.stories) !== JSON.stringify(after.stories) ||
|
|
1621
1622
|
JSON.stringify(before.last_envelope) !== JSON.stringify(after.last_envelope);
|
|
1622
1623
|
}
|
|
1623
|
-
function
|
|
1624
|
-
|
|
1624
|
+
function validateLaneStoriesInLedgers(hqRoot, lane) {
|
|
1625
|
+
for (const story of laneStories(lane)) {
|
|
1626
|
+
validateProjectStories(hqRoot, story.project_id, [story.story_id], lane.company?.slug);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
function clearResolvedLedgerSyncError(hqRoot, lane, deps) {
|
|
1630
|
+
if (lane.ledger_sync_error === undefined)
|
|
1625
1631
|
return lane;
|
|
1632
|
+
try {
|
|
1633
|
+
validateLaneStoriesInLedgers(hqRoot, lane);
|
|
1634
|
+
}
|
|
1635
|
+
catch (error) {
|
|
1636
|
+
if (error instanceof LanesError)
|
|
1637
|
+
return lane;
|
|
1638
|
+
throw error;
|
|
1639
|
+
}
|
|
1640
|
+
return retryUpdateLane(hqRoot, lane.lane_id, "story-ledger", (current) => {
|
|
1641
|
+
if (current.ledger_sync_error === undefined)
|
|
1642
|
+
return current;
|
|
1643
|
+
try {
|
|
1644
|
+
validateLaneStoriesInLedgers(hqRoot, current);
|
|
1645
|
+
}
|
|
1646
|
+
catch (error) {
|
|
1647
|
+
if (error instanceof LanesError)
|
|
1648
|
+
return current;
|
|
1649
|
+
throw error;
|
|
1650
|
+
}
|
|
1651
|
+
return { ...current, ledger_sync_error: undefined };
|
|
1652
|
+
}, deps);
|
|
1653
|
+
}
|
|
1654
|
+
function syncStoryLedgerForLane(hqRoot, lane, deps) {
|
|
1655
|
+
const currentLane = lane.ledger_sync_error === undefined
|
|
1656
|
+
? lane
|
|
1657
|
+
: clearResolvedLedgerSyncError(hqRoot, lane, deps);
|
|
1658
|
+
if (!laneStoryLedgerEnabled(currentLane.company?.uid))
|
|
1659
|
+
return currentLane;
|
|
1626
1660
|
try {
|
|
1627
1661
|
const questionRefs = [];
|
|
1628
|
-
for (const questionId of
|
|
1662
|
+
for (const questionId of currentLane.pending_question_ids ?? []) {
|
|
1629
1663
|
const question = readQuestion(hqRoot, questionId, deps);
|
|
1630
1664
|
const sameCompany = question.company === null
|
|
1631
|
-
?
|
|
1632
|
-
:
|
|
1633
|
-
question.company.uid ===
|
|
1634
|
-
question.company.slug ===
|
|
1635
|
-
if (question.lane_id !==
|
|
1636
|
-
throw new LanesError("story_ledger_question_mismatch", `Pending question ${questionId} does not belong to lane ${
|
|
1637
|
-
lane_id:
|
|
1665
|
+
? currentLane.company === null
|
|
1666
|
+
: currentLane.company !== null &&
|
|
1667
|
+
question.company.uid === currentLane.company.uid &&
|
|
1668
|
+
question.company.slug === currentLane.company.slug;
|
|
1669
|
+
if (question.lane_id !== currentLane.lane_id || !sameCompany) {
|
|
1670
|
+
throw new LanesError("story_ledger_question_mismatch", `Pending question ${questionId} does not belong to lane ${currentLane.lane_id}`, {
|
|
1671
|
+
lane_id: currentLane.lane_id,
|
|
1638
1672
|
question_id: questionId,
|
|
1639
1673
|
question_lane_id: question.lane_id,
|
|
1640
1674
|
company: question.company?.slug ?? null,
|
|
@@ -1648,24 +1682,24 @@ function syncStoryLedgerForLane(hqRoot, lane, deps) {
|
|
|
1648
1682
|
});
|
|
1649
1683
|
}
|
|
1650
1684
|
}
|
|
1651
|
-
syncLaneToProjectStoryLedger(hqRoot,
|
|
1652
|
-
if (
|
|
1653
|
-
retryUpdateLane(hqRoot,
|
|
1685
|
+
syncLaneToProjectStoryLedger(hqRoot, currentLane, questionRefs);
|
|
1686
|
+
if (currentLane.ledger_sync_error !== undefined) {
|
|
1687
|
+
retryUpdateLane(hqRoot, currentLane.lane_id, "story-ledger", (current) => current.ledger_sync_error === undefined
|
|
1654
1688
|
? current
|
|
1655
1689
|
: { ...current, ledger_sync_error: undefined }, deps);
|
|
1656
1690
|
}
|
|
1657
|
-
return readLane(hqRoot,
|
|
1691
|
+
return readLane(hqRoot, currentLane.lane_id, deps);
|
|
1658
1692
|
}
|
|
1659
1693
|
catch (error) {
|
|
1660
1694
|
const message = (error instanceof Error ? error.message : String(error)).slice(0, 1000) || "Story ledger synchronization failed";
|
|
1661
1695
|
try {
|
|
1662
|
-
retryUpdateLane(hqRoot,
|
|
1696
|
+
retryUpdateLane(hqRoot, currentLane.lane_id, "story-ledger", (current) => current.ledger_sync_error === message
|
|
1663
1697
|
? current
|
|
1664
1698
|
: { ...current, ledger_sync_error: message }, deps);
|
|
1665
|
-
return readLane(hqRoot,
|
|
1699
|
+
return readLane(hqRoot, currentLane.lane_id, deps);
|
|
1666
1700
|
}
|
|
1667
1701
|
catch (recordError) {
|
|
1668
|
-
throw new LanesError("story_ledger_sync_error_unrecorded", "Story ledger synchronization failed and the failure could not be recorded on lane " +
|
|
1702
|
+
throw new LanesError("story_ledger_sync_error_unrecorded", "Story ledger synchronization failed and the failure could not be recorded on lane " + currentLane.lane_id, { lane_id: currentLane.lane_id, cause: recordError instanceof Error ? recordError.message : String(recordError) });
|
|
1669
1703
|
}
|
|
1670
1704
|
}
|
|
1671
1705
|
}
|
|
@@ -1833,7 +1867,7 @@ export function updateQuestion(hqRoot, questionId, expectedVersion, updater, dep
|
|
|
1833
1867
|
return next;
|
|
1834
1868
|
}
|
|
1835
1869
|
function syncLaneQuestionReference(hqRoot, question, deps) {
|
|
1836
|
-
if (!laneStoryLedgerEnabled())
|
|
1870
|
+
if (!laneStoryLedgerEnabled(question.company?.uid))
|
|
1837
1871
|
return;
|
|
1838
1872
|
const lane = tryReadLane(hqRoot, question.lane_id, deps);
|
|
1839
1873
|
if (!lane || question.company?.slug !== lane.company?.slug || question.company?.uid !== lane.company?.uid)
|
|
@@ -60,7 +60,7 @@ export interface LaneStatusSnapshot {
|
|
|
60
60
|
by_state: Record<(typeof STORY_STATES)[number], number>;
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
export declare function laneStoryLedgerEnabled(): boolean;
|
|
63
|
+
export declare function laneStoryLedgerEnabled(companyUid?: string): boolean;
|
|
64
64
|
export declare function resolveProjectStoryLedger(hqRoot: string, projectId: string, companySlug?: string): ProjectStoryLedger;
|
|
65
65
|
export declare function validateProjectStories(hqRoot: string, projectId: string, storyIds: readonly string[], companySlug?: string): ProjectStoryLedger;
|
|
66
66
|
export declare function syncLaneToProjectStoryLedger(hqRoot: string, lane: LaneRecord, questionRefs?: readonly StoryLedgerQuestionRef[], deps?: StoryLedgerWriteDeps): void;
|
|
@@ -11,8 +11,8 @@ const LOCK_RETRY_MS = 10;
|
|
|
11
11
|
const STORY_STATES = ["todo", "in_progress", "review", "waiting", "blocked", "done", "dropped"];
|
|
12
12
|
const MANAGER_OWNED_STATES = new Set(["review", "done", "dropped"]);
|
|
13
13
|
const TERMINAL_STATES = new Set(["done", "failed", "interrupted", "cancelled", "killed"]);
|
|
14
|
-
export function laneStoryLedgerEnabled() {
|
|
15
|
-
return resolveProcessFlagGate(LANE_STORY_LEDGER_FLAG, { fallback: false }, () => false);
|
|
14
|
+
export function laneStoryLedgerEnabled(companyUid) {
|
|
15
|
+
return resolveProcessFlagGate(LANE_STORY_LEDGER_FLAG, { fallback: false }, () => false, companyUid);
|
|
16
16
|
}
|
|
17
17
|
function isSafePathSegment(value) {
|
|
18
18
|
return /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(value) &&
|
|
@@ -646,7 +646,7 @@ function updateOneStory(current, ledger, lane, storyId, projectId, questionRefs)
|
|
|
646
646
|
return current;
|
|
647
647
|
}
|
|
648
648
|
export function syncLaneToProjectStoryLedger(hqRoot, lane, questionRefs = [], deps = {}) {
|
|
649
|
-
if (!laneStoryLedgerEnabled())
|
|
649
|
+
if (!laneStoryLedgerEnabled(lane.company?.uid))
|
|
650
650
|
return;
|
|
651
651
|
const stories = laneStoriesForLedger(lane);
|
|
652
652
|
if (stories.length === 0)
|
|
@@ -664,7 +664,7 @@ export function syncLaneToProjectStoryLedger(hqRoot, lane, questionRefs = [], de
|
|
|
664
664
|
}
|
|
665
665
|
/** Remove only this lane's attribution from its former personal story ledgers. */
|
|
666
666
|
export function removeLaneFromProjectStoryLedger(hqRoot, lane) {
|
|
667
|
-
if (!laneStoryLedgerEnabled())
|
|
667
|
+
if (!laneStoryLedgerEnabled(lane.company?.uid))
|
|
668
668
|
return;
|
|
669
669
|
const refs = [...new Map(laneStoriesForLedger(lane).map((story) => [
|
|
670
670
|
story.project_id + "\u0000" + story.story_id,
|
package/dist/lib/lanes/types.js
CHANGED
|
@@ -232,14 +232,14 @@ export const LANE_FIELD_WRITERS = {
|
|
|
232
232
|
pickup_validation_pending: ["creator", "command", "spawn", "reconcile"],
|
|
233
233
|
pickup_validation_pending_since: ["creator", "command", "spawn", "reconcile"],
|
|
234
234
|
priority: ["command"], worker: ["creator", "command"], worker_path: ["creator", "command"], worker_pack: ["creator", "command"], worker_profile: ["creator", "command"], worker_profile_hash: ["creator", "command", "spawn"], registry_worker: ["creator", "command", "spawn"], registry_worker_approval_history: ["command", "watcher", "reconcile"], worker_profile_repin_history: ["command"], worker_profile_ignored: ["creator", "command", "spawn"], worker_policy_delivery: ["command", "spawn"],
|
|
235
|
-
keep_alive: ["creator", "command"], keep_alive_standing: ["command"], keep_alive_opted_in_at: ["creator", "command"], keep_alive_blocked_reason: ["command", "reconcile"], keep_alive_resume_count: ["command", "reconcile"], keep_alive_history: ["reconcile"], keep_alive_blocked_resume_streak: ["reconcile", "spawn", "watcher"], keep_alive_last_resume_at: ["command", "reconcile"], keep_alive_next_eligible_at: ["command", "reconcile"], keep_alive_exhausted_at: ["command", "reconcile"],
|
|
235
|
+
keep_alive: ["creator", "command"], keep_alive_standing: ["command"], keep_alive_opted_in_at: ["creator", "command"], keep_alive_blocked_reason: ["command", "reconcile"], keep_alive_resume_count: ["command", "reconcile", "spawn"], keep_alive_history: ["reconcile"], keep_alive_blocked_resume_streak: ["reconcile", "spawn", "watcher"], keep_alive_last_resume_at: ["command", "reconcile", "spawn"], keep_alive_next_eligible_at: ["command", "reconcile", "spawn"], keep_alive_exhausted_at: ["command", "reconcile", "spawn"],
|
|
236
236
|
provider: ["creator", "command"], provider_source: ["creator", "command"], account: ["creator", "spawn", "command", "watcher", "reconcile"], account_source: ["creator", "command"], profile_settings_pinned: ["command"], account_selection: ["creator", "command"], admission_accounts: ["creator", "command"], account_history: ["command", "spawn", "watcher", "reconcile"], failed_resume_history: ["command"], fallback_question_cancellation_failures: ["command"], pending_resume: ["command", "spawn", "watcher", "reconcile"], placement_default: ["creator"], host: ["creator", "command"], origin_host: ["creator"], origin_host_source: ["creator"],
|
|
237
237
|
version: ["creator"], created_at: ["creator"], updated_at: ["creator"], ended_at: ["reconcile"], envelope_summary: ["reconcile"], attribution_history: ["command", "watcher", "reconcile"], story_switch_pending: ["command", "watcher", "reconcile"], story_switch_unacknowledged: ["watcher", "reconcile"],
|
|
238
238
|
last_envelope: ["watcher", "reconcile"], model: ["creator", "spawn", "command"], model_source: ["creator", "spawn", "command"], effort: ["creator", "spawn", "command"], effort_source: ["creator", "spawn", "command"], fast_mode: ["spawn"],
|
|
239
239
|
last_message_at: ["command"], status_gate: ["spawn", "watcher"], status_gate_history: ["watcher", "reconcile"], blocker_freshness_state: ["watcher"], kr_freshness_state: ["watcher"], last_compaction: ["spawn"], story_complete: ["watcher", "reconcile"], story_complete_reason: ["watcher", "reconcile"], story_status: ["watcher", "reconcile"],
|
|
240
240
|
overdue: ["reconcile"], overdue_at: ["reconcile"], last_host_report_at: ["watcher", "spawn", "reconcile"], stalled: ["watcher"], stalled_at: ["watcher"], stalled_reason: ["watcher"],
|
|
241
|
-
admitted_reason: ["command", "reconcile"], terminal_reason: ["command", "watcher", "spawn", "reconcile"], stop_history: ["command", "reconcile"], settings_history: ["command"], pending_settings: ["command", "spawn"], interrupted_at: ["command", "watcher", "reconcile"], terminal_details: ["command", "spawn", "watcher", "reconcile"],
|
|
242
|
-
quota_reset_at: ["watcher", "reconcile"], model_quota_marker: ["watcher", "reconcile"], outpost_command_id: ["command"],
|
|
241
|
+
admitted_reason: ["command", "reconcile"], terminal_reason: ["command", "watcher", "spawn", "reconcile"], stop_history: ["command", "reconcile"], settings_history: ["command"], pending_settings: ["command", "spawn"], interrupted_at: ["command", "watcher", "reconcile", "spawn"], terminal_details: ["command", "spawn", "watcher", "reconcile"],
|
|
242
|
+
quota_reset_at: ["watcher", "reconcile", "spawn", "command"], model_quota_marker: ["watcher", "reconcile"], outpost_command_id: ["command"],
|
|
243
243
|
provider_session_id: ["watcher", "command", "spawn"], provider_session_id_absent: ["watcher", "command"], provider_home_at_spawn: ["spawn"], last_resume: ["spawn"], resume_history: ["spawn", "watcher"], last_run_usage: ["watcher"], last_run_usage_at: ["watcher"], envelope_repair: ["watcher", "reconcile"], envelope_validation_errors: ["watcher"], last_progress_event_at: ["watcher"],
|
|
244
244
|
};
|
|
245
245
|
function isPlainObject(value) {
|