@indigoai-us/hq-cli 5.301.0 → 5.303.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/assets/scaffold/core/scripts/rebuild-projects-index.sh +99 -12
  3. package/assets/scaffold/core/scripts/token-usage-report.sh +72 -20
  4. package/dist/command-catalog.generated.d.ts +4 -1
  5. package/dist/command-catalog.generated.js +5 -1
  6. package/dist/commands/bot.js +1 -0
  7. package/dist/commands/core-checkpoint.js +1 -0
  8. package/dist/commands/core-handoff-fast.js +1 -0
  9. package/dist/commands/core-handoff.js +2 -0
  10. package/dist/commands/deploy-comments.js +5 -2
  11. package/dist/commands/integrations-connect.d.ts +3 -0
  12. package/dist/commands/integrations-connect.js +21 -2
  13. package/dist/commands/lanes-message.js +33 -3
  14. package/dist/commands/lanes-questions.d.ts +4 -2
  15. package/dist/commands/lanes-questions.js +123 -2
  16. package/dist/commands/lanes-resume.js +25 -4
  17. package/dist/commands/lanes-shared.d.ts +13 -1
  18. package/dist/commands/lanes-watch.js +5 -1
  19. package/dist/commands/lanes.js +91 -9
  20. package/dist/commands/monitor.js +17 -2
  21. package/dist/commands/report.js +5 -2
  22. package/dist/commands/rescue.d.ts +4 -0
  23. package/dist/commands/rescue.js +27 -17
  24. package/dist/lib/agent-kit/fallback.d.ts +1 -0
  25. package/dist/lib/agent-kit/fallback.js +1 -0
  26. package/dist/lib/bot/cli-update.d.ts +0 -8
  27. package/dist/lib/bot/cli-update.js +5 -5
  28. package/dist/lib/bot/daemon.d.ts +5 -1
  29. package/dist/lib/bot/daemon.js +4 -4
  30. package/dist/lib/bot/local-jobs.d.ts +1 -21
  31. package/dist/lib/bot/local-jobs.js +12 -12
  32. package/dist/lib/core-utils/soft-timeout.js +1 -1
  33. package/dist/lib/daemon/config.d.ts +0 -1
  34. package/dist/lib/daemon/config.js +1 -1
  35. package/dist/lib/deploy-apps.d.ts +13 -0
  36. package/dist/lib/deploy-apps.js +24 -0
  37. package/dist/lib/index-render/projects.js +82 -5
  38. package/dist/lib/lanes/delivery.d.ts +7 -3
  39. package/dist/lib/lanes/delivery.js +18 -8
  40. package/dist/lib/lanes/index.d.ts +1 -1
  41. package/dist/lib/lanes/keep-alive.d.ts +13 -3
  42. package/dist/lib/lanes/keep-alive.js +29 -5
  43. package/dist/lib/lanes/outpost-dispatch.d.ts +5 -0
  44. package/dist/lib/lanes/outpost-dispatch.js +12 -0
  45. package/dist/lib/lanes/reconcile.d.ts +1 -0
  46. package/dist/lib/lanes/reconcile.js +358 -38
  47. package/dist/lib/lanes/spawn.d.ts +1 -0
  48. package/dist/lib/lanes/spawn.js +20 -10
  49. package/dist/lib/lanes/store.js +24 -0
  50. package/dist/lib/lanes/story-ledger.d.ts +2 -0
  51. package/dist/lib/lanes/story-ledger.js +8 -0
  52. package/dist/lib/lanes/types.d.ts +26 -4
  53. package/dist/lib/lanes/types.js +33 -1
  54. package/dist/lib/lanes/watch.d.ts +1 -0
  55. package/dist/lib/lanes/watch.js +19 -6
  56. package/dist/lib/lanes/watcher.js +139 -9
  57. package/dist/lib/mesh/live/daemon/run.js +36 -2
  58. package/dist/lib/report-snapshot.d.ts +0 -2
  59. package/dist/lib/report-snapshot.js +2 -2
  60. package/dist/lib/search-index/background.d.ts +1 -0
  61. package/dist/lib/search-index/background.js +1 -0
  62. package/dist/utils/run-bundled-script.js +103 -1
  63. package/dist/utils/update-command-supervisor.cjs +1 -0
  64. package/dist/utils/version-gate.js +1 -1
  65. package/package.json +1 -1
@@ -1,6 +1,9 @@
1
- import type { LaneRecord, ManagerStatusGateHistoryEntry, QuestionRecord } from "./types.js";
1
+ import { type LaneRecord, type ManagerStatusGateHistoryEntry, type QuestionRecord } from "./types.js";
2
2
  export declare const LEAD_LANE_KEEP_ALIVE_FLAG = "lanes.lead-keep-alive";
3
3
  export declare const LEAD_LANE_KEEP_ALIVE_DEFAULT_ENABLED = false;
4
+ export declare const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_FLAG = "lanes.keep-alive-next-check-at";
5
+ export declare const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_DEFAULT_ENABLED = false;
6
+ export declare const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_MAX_DELAY_MS: number;
4
7
  export declare const LEAD_LANE_KEEP_ALIVE_RESUME_BLOCKED_FLAG = "lanes.keep-alive-resume-blocked";
5
8
  export declare const LEAD_LANE_KEEP_ALIVE_RESUME_BLOCKED_DEFAULT_ENABLED = false;
6
9
  export declare const LEAD_LANE_KEEP_ALIVE_BLOCKED_GRACE_MS: number;
@@ -35,10 +38,17 @@ export type KeepAliveBlockedReason = NonNullable<LaneRecord["keep_alive_blocked_
35
38
  export interface KeepAliveDoneEnvelope {
36
39
  decision?: string;
37
40
  story_complete?: boolean;
41
+ next_check_at?: string;
38
42
  }
39
- export type DoneKeepAliveVerdict = "eligible" | "standing_idle" | "story_complete";
43
+ export type DoneKeepAliveVerdict = "eligible" | "standing_idle" | "story_complete" | "next_check_at";
44
+ export declare function keepAliveNextCheckAtMs(value: unknown, nowMs: number, anchorMs?: number): number | undefined;
40
45
  /** Shared done-state policy used by watch, reconcile, and the show command. */
41
- export declare function doneKeepAliveVerdict(lane: Pick<LaneRecord, "keep_alive_standing">, envelope: KeepAliveDoneEnvelope, hasQueuedWork: boolean): DoneKeepAliveVerdict | null;
46
+ export declare function doneKeepAliveVerdict(lane: Pick<LaneRecord, "keep_alive_standing">, envelope: KeepAliveDoneEnvelope, hasQueuedWork: boolean, options?: {
47
+ nextCheckAtEnabled?: boolean;
48
+ hasPendingWork?: boolean;
49
+ nowMs?: number;
50
+ nextCheckAnchorMs?: number;
51
+ }): DoneKeepAliveVerdict | null;
42
52
  export declare function canResumeDoneKeepAliveLane(lane: Pick<LaneRecord, "keep_alive_standing">, envelope: KeepAliveDoneEnvelope, hasQueuedWork: boolean): boolean;
43
53
  /** Work signals already persisted for a lane that ended its turn. */
44
54
  export declare function hasPendingKeepAliveWork(hqRoot: string, lane: Pick<LaneRecord, "lane_id" | "company" | "pending_resume">, questionRecords?: readonly QuestionRecord[]): boolean;
@@ -3,8 +3,12 @@ import * as path from "node:path";
3
3
  import { LanesError } from "./errors.js";
4
4
  import { dropboxInboxHasMessages } from "./dropbox.js";
5
5
  import { appendCappedHistory, listQuestionIds, readQuestion, retryUpdateLane } from "./store.js";
6
+ import { isIsoDateTime } from "./types.js";
6
7
  export const LEAD_LANE_KEEP_ALIVE_FLAG = "lanes.lead-keep-alive";
7
8
  export const LEAD_LANE_KEEP_ALIVE_DEFAULT_ENABLED = false;
9
+ export const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_FLAG = "lanes.keep-alive-next-check-at";
10
+ export const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_DEFAULT_ENABLED = false;
11
+ export const LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_MAX_DELAY_MS = 24 * 60 * 60 * 1000;
8
12
  export const LEAD_LANE_KEEP_ALIVE_RESUME_BLOCKED_FLAG = "lanes.keep-alive-resume-blocked";
9
13
  export const LEAD_LANE_KEEP_ALIVE_RESUME_BLOCKED_DEFAULT_ENABLED = false;
10
14
  export const LEAD_LANE_KEEP_ALIVE_BLOCKED_GRACE_MS = 15 * 60 * 1000;
@@ -98,15 +102,35 @@ export function queueManagerStatusGateResume(hqRoot, laneId, entry, resumeText)
98
102
  export const LEAD_LANE_KEEP_ALIVE_RESUME_TEXT = "Automatic keep-alive resume: your last turn ended with decision done and story_complete false. Continue the open work from where you stopped. End with done only when story_complete is true; if you are waiting, use hq lanes ask or stay in the loop.";
99
103
  export const LEAD_LANE_KEEP_ALIVE_BLOCKED_RESUME_TEXT = "You ended blocked with no pending question. Record the event you wait on in waiting_on, re-check each blocker, and continue the next unblocked story.";
100
104
  export const LEAD_LANE_KEEP_ALIVE_INTERRUPTED_RESUME_TEXT = "Automatic keep-alive resume: your previous turn was interrupted by a provider process exit. Check your last state before continuing. Continue the open work from where you stopped. End with done only when story_complete is true; if you are waiting, use hq lanes ask or stay in the loop.";
105
+ export function keepAliveNextCheckAtMs(value, nowMs, anchorMs = nowMs) {
106
+ if (typeof value !== "string" || !isIsoDateTime(value))
107
+ return undefined;
108
+ const parsed = Date.parse(value);
109
+ if (parsed <= nowMs)
110
+ return undefined;
111
+ const stableAnchorMs = Number.isFinite(anchorMs) ? anchorMs : nowMs;
112
+ const capped = Math.min(parsed, stableAnchorMs + LEAD_LANE_KEEP_ALIVE_NEXT_CHECK_MAX_DELAY_MS);
113
+ return capped > nowMs ? capped : undefined;
114
+ }
101
115
  /** Shared done-state policy used by watch, reconcile, and the show command. */
102
- export function doneKeepAliveVerdict(lane, envelope, hasQueuedWork) {
116
+ export function doneKeepAliveVerdict(lane, envelope, hasQueuedWork, options = {}) {
103
117
  if (envelope.decision !== "done")
104
118
  return null;
119
+ let verdict;
105
120
  if (envelope.story_complete !== true)
106
- return "eligible";
107
- if (lane.keep_alive_standing !== true)
108
- return "story_complete";
109
- return hasQueuedWork ? "eligible" : "standing_idle";
121
+ verdict = "eligible";
122
+ else if (lane.keep_alive_standing !== true)
123
+ verdict = "story_complete";
124
+ else
125
+ verdict = hasQueuedWork ? "eligible" : "standing_idle";
126
+ if (verdict === "eligible" && options.nextCheckAtEnabled === true && options.hasPendingWork !== true) {
127
+ const nowMs = options.nowMs ?? Date.now();
128
+ const anchorMs = options.nextCheckAnchorMs ?? nowMs;
129
+ const nextCheckAtMs = keepAliveNextCheckAtMs(envelope.next_check_at, nowMs, anchorMs);
130
+ if (nextCheckAtMs !== undefined)
131
+ return "next_check_at";
132
+ }
133
+ return verdict;
110
134
  }
111
135
  export function canResumeDoneKeepAliveLane(lane, envelope, hasQueuedWork) {
112
136
  return doneKeepAliveVerdict(lane, envelope, hasQueuedWork) === "eligible";
@@ -105,6 +105,11 @@ export declare function buildOutpostQuestionListCommand(input?: {
105
105
  }): string;
106
106
  /** Read one question's body and owner-computed audience from its Outpost. */
107
107
  export declare function buildOutpostQuestionShowCommand(questionId: string): string;
108
+ /** Cancel an owner-hosted question through the existing questions command. */
109
+ export declare function buildOutpostQuestionCancelCommand(input: {
110
+ questionId: string;
111
+ reason: string;
112
+ }): string;
108
113
  /** Commit a queued lane move on the host that currently owns its state. */
109
114
  export declare function buildOutpostMoveTargetCommand(input: {
110
115
  laneId: string;
@@ -113,6 +113,18 @@ export function buildOutpostQuestionShowCommand(questionId) {
113
113
  questionId,
114
114
  ]));
115
115
  }
116
+ /** Cancel an owner-hosted question through the existing questions command. */
117
+ export function buildOutpostQuestionCancelCommand(input) {
118
+ return withRemoteHqDir(joinCommandParts([
119
+ "hq",
120
+ "lanes",
121
+ "questions",
122
+ "cancel",
123
+ input.questionId,
124
+ "--reason",
125
+ input.reason,
126
+ ]));
127
+ }
116
128
  /** Commit a queued lane move on the host that currently owns its state. */
117
129
  export function buildOutpostMoveTargetCommand(input) {
118
130
  return withRemoteHqDir(joinCommandParts([
@@ -24,6 +24,7 @@ export declare const RECONCILE_LOCK_TIMEOUT_MS = 5000;
24
24
  /** A pickup probe that has not cleared its marker within this window is abandoned. */
25
25
  export declare const PICKUP_VALIDATION_MAX_AGE_MS: number;
26
26
  export declare const PICKUP_VALIDATION_TIMEOUT_REASON: "pickup_validation_timeout";
27
+ export declare const CLOSE_INTERRUPTED_DONE_STORY_WORKERS_FLAG = "lanes.close-interrupted-done-story-workers";
27
28
  export declare const RECONCILE_UNIT_NAME = "hq-lanes-reconcile.service";
28
29
  export declare const RECONCILE_TIMER_NAME = "hq-lanes-reconcile.timer";
29
30
  export interface ReconcileSkip {