@indigoai-us/hq-cli 5.311.4 → 5.312.1

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 (96) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/assets/scaffold/core/scripts/lib/work-mesh-live-hook.sh +378 -0
  3. package/assets/scaffold/core/scripts/lib/work-mesh-live-rebind.sh +141 -0
  4. package/assets/scaffold/core/scripts/migrate-policy-triggers.sh +373 -0
  5. package/assets/scaffold/core/scripts/register-project.sh +262 -0
  6. package/assets/scaffold/core/scripts/work-mesh-live-rebind.sh +59 -0
  7. package/dist/command-catalog.generated.d.ts +160 -0
  8. package/dist/command-catalog.generated.js +200 -0
  9. package/dist/command-registration-plan.d.ts +6 -0
  10. package/dist/command-registration-plan.js +1 -0
  11. package/dist/commands/company-rename-flag.d.ts +4 -0
  12. package/dist/commands/company-rename-flag.js +7 -0
  13. package/dist/commands/company-rename.d.ts +4 -0
  14. package/dist/commands/company-rename.js +90 -0
  15. package/dist/commands/company.js +2 -0
  16. package/dist/commands/core-checkpoint-stop-gate-native.js +12 -0
  17. package/dist/commands/core-eval-trigger-native.d.ts +4 -0
  18. package/dist/commands/core-eval-trigger-native.js +12 -0
  19. package/dist/commands/core-migrate-policy-triggers-native.d.ts +21 -0
  20. package/dist/commands/core-migrate-policy-triggers-native.js +378 -0
  21. package/dist/commands/core-native-hook-helper-commands.d.ts +4 -0
  22. package/dist/commands/core-native-hook-helper-commands.js +56 -0
  23. package/dist/commands/core-native-hook-helpers-flag.d.ts +4 -0
  24. package/dist/commands/core-native-hook-helpers-flag.js +7 -0
  25. package/dist/commands/core-register-project-native.d.ts +30 -0
  26. package/dist/commands/core-register-project-native.js +347 -0
  27. package/dist/commands/core-work-mesh-live-rebind-native.d.ts +18 -0
  28. package/dist/commands/core-work-mesh-live-rebind-native.js +262 -0
  29. package/dist/commands/core.js +7 -0
  30. package/dist/commands/daemon.js +22 -0
  31. package/dist/commands/dm.js +22 -6
  32. package/dist/commands/files-browse.js +16 -4
  33. package/dist/commands/lanes-message.js +17 -2
  34. package/dist/commands/lanes-shared.d.ts +1 -0
  35. package/dist/commands/lanes.js +96 -20
  36. package/dist/commands/vault-retention-flag.d.ts +3 -0
  37. package/dist/commands/vault-retention-flag.js +9 -0
  38. package/dist/commands/vault-retention.d.ts +11 -0
  39. package/dist/commands/vault-retention.js +69 -0
  40. package/dist/fast-core.js +10 -3
  41. package/dist/fast-scaffold.d.ts +2 -0
  42. package/dist/fast-scaffold.js +11 -0
  43. package/dist/lib/agents/model-catalog.d.ts +3 -2
  44. package/dist/lib/company-skill-wrapper.d.ts +0 -8
  45. package/dist/lib/core-utils/codex-skill-bridge.d.ts +2 -1
  46. package/dist/lib/core-utils/sentry-report.js +21 -4
  47. package/dist/lib/daemon/catalog.d.ts +2 -0
  48. package/dist/lib/daemon/catalog.js +13 -1
  49. package/dist/lib/daemon/config.d.ts +2 -0
  50. package/dist/lib/daemon/config.js +4 -0
  51. package/dist/lib/daemon/run.d.ts +2 -0
  52. package/dist/lib/daemon/run.js +5 -0
  53. package/dist/lib/deploy-api.d.ts +0 -1
  54. package/dist/lib/deploy-api.js +1 -1
  55. package/dist/lib/doctor/checks/work-context.js +9 -1
  56. package/dist/lib/lanes/autopilot.d.ts +38 -1
  57. package/dist/lib/lanes/autopilot.js +353 -5
  58. package/dist/lib/lanes/flag-keys.d.ts +9 -1
  59. package/dist/lib/lanes/flag-keys.js +9 -1
  60. package/dist/lib/lanes/keep-alive.d.ts +2 -0
  61. package/dist/lib/lanes/keep-alive.js +2 -0
  62. package/dist/lib/lanes/reconcile.d.ts +5 -0
  63. package/dist/lib/lanes/reconcile.js +57 -4
  64. package/dist/lib/lanes/watcher-main.js +20 -1
  65. package/dist/lib/lanes/watcher.d.ts +9 -0
  66. package/dist/lib/lanes/watcher.js +47 -1
  67. package/dist/lib/mesh/client.js +23 -5
  68. package/dist/lib/mesh/denial-codes.d.ts +5 -0
  69. package/dist/lib/mesh/denial-codes.js +14 -0
  70. package/dist/lib/mesh/live/daemon/doctor.d.ts +2 -0
  71. package/dist/lib/mesh/live/daemon/doctor.js +11 -1
  72. package/dist/lib/report-run.d.ts +3 -2
  73. package/dist/lib/report-templates.d.ts +0 -1
  74. package/dist/lib/report-templates.js +0 -3
  75. package/dist/lib/scaffold-cli-floor.d.ts +0 -1
  76. package/dist/lib/scaffold-cli-floor.js +1 -1
  77. package/dist/lib/search-index/embed-lock.d.ts +2 -0
  78. package/dist/lib/search-index/embed-lock.js +10 -1
  79. package/dist/lib/work-context/contract.d.ts +3 -0
  80. package/dist/lib/work-context/contract.schema.json +3 -1
  81. package/dist/lib/work-context/outbox.d.ts +14 -5
  82. package/dist/lib/work-context/outbox.js +48 -5
  83. package/dist/lib/work-context/reconcile.js +26 -5
  84. package/dist/main.d.ts +20 -0
  85. package/dist/main.js +8 -1
  86. package/dist/run/discover-schemas.d.ts +2 -1
  87. package/dist/utils/core-eval-trigger.d.ts +4 -0
  88. package/dist/utils/core-eval-trigger.js +88 -0
  89. package/dist/utils/hq-roots.d.ts +0 -2
  90. package/dist/utils/hq-roots.js +1 -8
  91. package/dist/utils/incomplete-install-error.d.ts +7 -6
  92. package/dist/utils/large-file-guard.d.ts +0 -10
  93. package/dist/utils/large-file-guard.js +1 -1
  94. package/dist/utils/package-root-diagnostics.d.ts +1 -1
  95. package/dist/utils/self-update.d.ts +2 -1
  96. package/package.json +1 -1
@@ -20,6 +20,7 @@ import { mkdirSync, readdirSync, readFileSync, renameSync, rmdirSync, statSync,
20
20
  import { tmpdir } from "node:os";
21
21
  import { dirname, join } from "node:path";
22
22
  import * as Sentry from "@sentry/node";
23
+ import { gte as semverGte, valid as validSemver } from "semver";
23
24
  import { CLI_VERSION } from "../../cli-version.js";
24
25
  import { beforeSend } from "../../sentry-before-send.js";
25
26
  import { resolveLiveRoot } from "../../utils/hq-roots.js";
@@ -47,6 +48,10 @@ const HOOK_TIMEOUT_EXCEEDED_METRIC = "hq.hook_timeout_exceeded";
47
48
  const MAX_HOOK_SEQUENCE_ENTRIES = 20;
48
49
  const MAX_HOOK_TIMEOUT_DEBUG_PHASES = 24;
49
50
  const MAX_HOOK_TIMEOUT_DEBUG_MS = 86_400_000;
51
+ // This is the hqVersion embedded in the first hq-core tag whose master-hook
52
+ // replaces BASH_ENV with /dev/null before reading it (tag v15.0.157-beta.2).
53
+ // Earlier cores only report whether BASH_ENV is non-empty, which is ambiguous.
54
+ const BASH_ENV_NEUTRALIZED_CORE_VERSION = "15.0.157-beta.2";
50
55
  const HOOK_TIMEOUT_RATE_LIMIT_WINDOW_MS = 10 * 60 * 1_000;
51
56
  const RATE_LIMIT_LOCK_WAIT_MS = 500;
52
57
  const RATE_LIMIT_LOCK_POLL_MS = 5;
@@ -578,9 +583,10 @@ function hookTimeoutDebugContextTags(context) {
578
583
  function safeSlowChild(metadata) {
579
584
  const value = metadata.slow_child;
580
585
  const slowChildMs = metadata.slow_child_ms;
586
+ const bashEnv = bashEnvTag(metadata);
581
587
  const hasMeasuredChild = typeof slowChildMs === "number" && Number.isFinite(slowChildMs) && slowChildMs >= 0;
582
588
  if (metadata.hook_event === "SessionStart" &&
583
- (metadata.bash_env_set === true || metadata.bash_env_set === "set") &&
589
+ (bashEnv === "profile" || bashEnv === "set") &&
584
590
  !hasMeasuredChild &&
585
591
  (typeof value !== "string" || value.length === 0 || value === "other")) {
586
592
  return "entry-bash-startup";
@@ -605,8 +611,15 @@ function isMachineWideHookSlowness(metadata) {
605
611
  }
606
612
  function bashEnvTag(metadata) {
607
613
  const value = metadata.bash_env_set;
608
- if (value === true || value === "set")
609
- return "set";
614
+ if (value === "profile" || value === "devnull")
615
+ return value;
616
+ if (value === true || value === "set") {
617
+ const coreVersion = metadata.hq_version;
618
+ const parsedCoreVersion = typeof coreVersion === "string" ? validSemver(coreVersion) : null;
619
+ if (!parsedCoreVersion)
620
+ return "unknown";
621
+ return semverGte(parsedCoreVersion, BASH_ENV_NEUTRALIZED_CORE_VERSION) ? "devnull" : "set";
622
+ }
610
623
  if (value === false || value === "unset")
611
624
  return "unset";
612
625
  return "unknown";
@@ -882,9 +895,13 @@ function timeoutRateLimitLease(event, kind, options, dependencies) {
882
895
  }
883
896
  }
884
897
  function metricAttributes(metadata) {
885
- return Object.fromEntries(Object.entries(metadata)
898
+ const attributes = Object.fromEntries(Object.entries(metadata)
886
899
  .filter(([, value]) => isScalarMetadataValue(value))
887
900
  .map(([key, value]) => [key, typeof value === "string" ? safeTagValue(value) : value]));
901
+ if (Object.hasOwn(metadata, "bash_env_set")) {
902
+ attributes.bash_env_set = bashEnvTag(metadata);
903
+ }
904
+ return attributes;
888
905
  }
889
906
  function addHookSequenceBreadcrumbs(event, dependencies) {
890
907
  const sequence = event.metadata.hook_sequence;
@@ -79,6 +79,8 @@ export interface PlanContext {
79
79
  sessionHostRunnerPath: string | null;
80
80
  /** Environment retained from legacy outpost sync systemd drop-ins. */
81
81
  legacySyncEnv: Record<string, string>;
82
+ /** Keep the sync runner's event-driven instant-sync watcher enabled. */
83
+ instantSyncEnabled?: boolean;
82
84
  /** Keep the local sync runner stopped until the operator resumes it. */
83
85
  syncPaused: boolean;
84
86
  /** Persisted/effective owner selected for this machine. */
@@ -128,7 +128,19 @@ function planService(service, ctx) {
128
128
  command: {
129
129
  type: "node",
130
130
  script: ctx.syncRunnerPath,
131
- args: ["--companies", "--direction", "both", "--on-conflict", "keep", "--hq-root", ctx.hqRoot ?? "", "--watch", "--event-push", "--owner", SYNC_RUNNER_OWNER],
131
+ args: [
132
+ "--companies",
133
+ "--direction",
134
+ "both",
135
+ "--on-conflict",
136
+ "keep",
137
+ "--hq-root",
138
+ ctx.hqRoot ?? "",
139
+ "--watch",
140
+ ...(ctx.instantSyncEnabled === false ? [] : ["--event-push"]),
141
+ "--owner",
142
+ SYNC_RUNNER_OWNER,
143
+ ],
132
144
  },
133
145
  env: { ...ctx.legacySyncEnv },
134
146
  heartbeatTimeoutMs: ctx.syncHeartbeatTimeoutMs,
@@ -14,6 +14,8 @@ export interface DaemonConfig {
14
14
  hqCloudVersion?: string;
15
15
  /** Persisted machine-local sync pause. */
16
16
  syncPaused?: boolean;
17
+ /** Desktop Instant Sync preference, applied when the sync unit is planned. */
18
+ instantSyncEnabled?: boolean;
17
19
  /** Explicit desktop handoff; absent values preserve the legacy per-machine owner. */
18
20
  syncOwner?: SyncOwner;
19
21
  /** Services turned on here beyond the machine type's defaults. */
@@ -45,6 +45,8 @@ export function readDaemonConfig(file) {
45
45
  enable: stringList(obj.enable),
46
46
  disable: stringList(obj.disable),
47
47
  };
48
+ if (typeof obj.instantSyncEnabled === "boolean")
49
+ config.instantSyncEnabled = obj.instantSyncEnabled;
48
50
  if (isMachineType(obj.machineType))
49
51
  config.machineType = obj.machineType;
50
52
  if (obj.syncOwner === "daemon" || obj.syncOwner === "desktop-app")
@@ -67,6 +69,8 @@ export function writeDaemonConfig(file, config) {
67
69
  if (config.hqCloudVersion)
68
70
  ordered.hqCloudVersion = config.hqCloudVersion;
69
71
  ordered.syncPaused = config.syncPaused === true;
72
+ if (typeof config.instantSyncEnabled === "boolean")
73
+ ordered.instantSyncEnabled = config.instantSyncEnabled;
70
74
  if (config.syncOwner)
71
75
  ordered.syncOwner = config.syncOwner;
72
76
  ordered.enable = config.enable;
@@ -24,6 +24,8 @@ export interface RunDaemonOptions {
24
24
  hqBinary: string;
25
25
  }
26
26
  export declare function resolveSyncRunnerPath(): string | null;
27
+ /** The hosted desktop app uses this env value when planning daemon services. */
28
+ export declare function daemonInstantSyncEnabled(env: NodeJS.ProcessEnv, configured?: boolean): boolean;
27
29
  export declare function listLocalBots(root?: string): string[];
28
30
  export declare function windowsTaskExists(taskName: string): boolean;
29
31
  export declare function probeLegacyUnits(platform: NodeJS.Platform, home: string): LegacyUnit[];
@@ -53,6 +53,10 @@ export function resolveSyncRunnerPath() {
53
53
  return null;
54
54
  }
55
55
  }
56
+ /** The hosted desktop app uses this env value when planning daemon services. */
57
+ export function daemonInstantSyncEnabled(env, configured) {
58
+ return configured ?? env.HQ_DAEMON_INSTANT_SYNC !== "0";
59
+ }
56
60
  export function listLocalBots(root = botsRoot()) {
57
61
  if (!fs.existsSync(root))
58
62
  return [];
@@ -447,6 +451,7 @@ export async function runDaemon(opts) {
447
451
  heartbeatRunnerPath: runners.heartbeat,
448
452
  sessionHostRunnerPath: runners.sessionHost,
449
453
  legacySyncEnv: readLegacySyncEnv(platform),
454
+ instantSyncEnabled: daemonInstantSyncEnabled(env, config.instantSyncEnabled),
450
455
  signedIn: isSignedIn,
451
456
  kitConfigured: fs.existsSync(agentKitPaths(home, env).kitConfigPath),
452
457
  syncPaused: config.syncPaused === true,
@@ -1,6 +1,5 @@
1
1
  /** Shared authenticated request path for the hq-deploy control plane. */
2
2
  export declare const DEPLOY_API_URL: string;
3
3
  export declare function deployHeaders(token: string, json?: boolean, extra?: Record<string, string>): Record<string, string>;
4
- export declare function deployApiUrl(route: string): string;
5
4
  export declare function deployApiRequest(token: string, route: string, method: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<Response>;
6
5
  //# sourceMappingURL=deploy-api.d.ts.map
@@ -8,7 +8,7 @@ export function deployHeaders(token, json = true, extra = {}) {
8
8
  ...extra,
9
9
  };
10
10
  }
11
- export function deployApiUrl(route) {
11
+ function deployApiUrl(route) {
12
12
  return `${DEPLOY_API_URL.replace(/\/+$/, "")}${route}`;
13
13
  }
14
14
  export async function deployApiRequest(token, route, method, body, extraHeaders = {}) {
@@ -89,12 +89,20 @@ function runChecks(deps) {
89
89
  message: `Outbox queued depth=${stats.depth} (acked=${stats.acked}).`,
90
90
  });
91
91
  const showQuarantineReason = stats.quarantined > 0 && outboxQuarantineStatusEnabled();
92
+ const quarantineDetails = [
93
+ stats.lastQuarantineHttpStatus !== null
94
+ ? `HTTP ${stats.lastQuarantineHttpStatus}`
95
+ : "",
96
+ stats.lastQuarantineServerCode ?? "",
97
+ ]
98
+ .filter(Boolean)
99
+ .join(" ");
92
100
  results.push({
93
101
  status: stats.quarantined > 0 ? "WARN" : "PASS",
94
102
  checkId: "work-context.outbox-quarantined",
95
103
  target: path.join(root, "outbox"),
96
104
  message: `Outbox quarantined count=${stats.quarantined}${showQuarantineReason
97
- ? ` (last reason=${stats.lastQuarantineReason ?? "unknown"})`
105
+ ? ` (last reason=${stats.lastQuarantineReason ?? "unknown"}${quarantineDetails ? `; ${quarantineDetails}` : ""})`
98
106
  : ""}.`,
99
107
  });
100
108
  // Default-company mode + migration capability (US-017B)
@@ -2,9 +2,13 @@ import { readLanesRegistryFlag } from "./registry-flag.js";
2
2
  import type { LaneRecord } from "./types.js";
3
3
  export declare const LEAD_AUTOPILOT_FLAG = "lanes.lead-autopilot";
4
4
  export declare const LEAD_AUTOPILOT_DEFAULT_ENABLED = false;
5
+ export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = "lanes.autopilot-missed-deadline-escalation";
6
+ export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DEFAULT_ENABLED = false;
7
+ export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DELAY_MS: number;
5
8
  export declare const LEAD_AUTOPILOT_REVIEW_DELAY_MS: number;
6
9
  export declare const LEAD_AUTOPILOT_FILL_DELAY_MS: number;
7
10
  export declare const LEAD_AUTOPILOT_PROMPT_LOOP = "personal/knowledge/team-lead-operating-loop.md";
11
+ export declare const LEAD_AUTOPILOT_KPI_STALE_AFTER_MINUTES = 55;
8
12
  export interface RegisteredLead {
9
13
  team: string;
10
14
  lane: string;
@@ -12,7 +16,7 @@ export interface RegisteredLead {
12
16
  status: string;
13
17
  prd: string;
14
18
  }
15
- export type AutopilotCondition = "review_finished_worker" | "fill_grant" | "plan_free_slots" | "flat_kpi" | "blocker_record_needs_update" | "project_ready_to_close" | "stale_worker_ledger" | "story_without_live_lane";
19
+ export type AutopilotCondition = "review_finished_worker" | "fill_grant" | "plan_free_slots" | "flat_kpi" | "stale_kpi" | "blocker_record_needs_update" | "project_ready_to_close" | "stale_worker_ledger" | "story_without_live_lane" | "missed_deadline";
16
20
  export interface AutopilotWake {
17
21
  condition: AutopilotCondition;
18
22
  lead_lane: string;
@@ -20,6 +24,23 @@ export interface AutopilotWake {
20
24
  worker_lane?: string;
21
25
  prompt: string;
22
26
  fingerprint: string;
27
+ kpi_id?: string;
28
+ }
29
+ export interface AutopilotKpiStatus {
30
+ lead_lane: string;
31
+ team: string;
32
+ kpi: string;
33
+ age_minutes: number | null;
34
+ stale: boolean;
35
+ stale_after_minutes: number;
36
+ status?: string;
37
+ error?: "invalid_kpi";
38
+ }
39
+ interface AutopilotDeadlineError {
40
+ lead_lane: string;
41
+ item_ref: string;
42
+ field: string;
43
+ reason: string;
23
44
  }
24
45
  export interface AutopilotPassResult {
25
46
  ok: true;
@@ -38,11 +59,23 @@ export interface AutopilotPassResult {
38
59
  story_id: string;
39
60
  at: string;
40
61
  fingerprint: string;
62
+ owner?: string;
63
+ due?: string;
64
+ miss_count?: number;
65
+ }>;
66
+ missed_deadlines?: Array<{
67
+ lead_lane: string;
68
+ item: string;
69
+ owner: string;
70
+ due: string;
71
+ miss_count: number;
41
72
  }>;
73
+ deadline_errors?: AutopilotDeadlineError[];
42
74
  skipped: Array<{
43
75
  lead_lane: string;
44
76
  reason: string;
45
77
  }>;
78
+ kpi_status?: AutopilotKpiStatus[];
46
79
  /** Set on an Outpost that has not received a lead registry from the primary yet. */
47
80
  registry?: "missing";
48
81
  }
@@ -54,6 +87,7 @@ interface ProjectStory {
54
87
  laneIds?: string[];
55
88
  updatedAt?: string;
56
89
  externalBlocker?: string;
90
+ deadlineFields?: Record<string, unknown>;
57
91
  }
58
92
  export declare function planLeadAutopilotWakes(input: {
59
93
  lead: LaneRecord;
@@ -62,6 +96,7 @@ export declare function planLeadAutopilotWakes(input: {
62
96
  now: Date;
63
97
  managerStatus?: Record<string, unknown>;
64
98
  keepAliveResumed?: boolean;
99
+ kpiStalenessEnabled?: boolean;
65
100
  }): AutopilotWake[];
66
101
  export declare function runLeadAutopilotPass(input: {
67
102
  hqRoot: string;
@@ -71,7 +106,9 @@ export declare function runLeadAutopilotPass(input: {
71
106
  now: Date;
72
107
  dryRun?: boolean;
73
108
  readFlag?: typeof readLanesRegistryFlag;
109
+ readDeadlineFlag?: typeof readLanesRegistryFlag;
74
110
  keepAliveResumedLeads?: ReadonlySet<string>;
111
+ missedDeadlineEscalationDelayMs?: number;
75
112
  startWorker?: (input: {
76
113
  lead: LaneRecord;
77
114
  story: ProjectStory;