@indigoai-us/hq-cli 5.345.129 → 5.345.131

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 (35) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/assets/scaffold/core/scripts/lib/codex-output-schema.mjs +304 -0
  3. package/assets/scaffold/core/scripts/workflow-runner.mjs +2890 -0
  4. package/dist/command-catalog.generated.d.ts +29 -0
  5. package/dist/command-catalog.generated.js +34 -0
  6. package/dist/commands/capacity.d.ts +1 -2
  7. package/dist/commands/capacity.js +7 -9
  8. package/dist/commands/core-pipeline-workflow-runner-native.d.ts +175 -0
  9. package/dist/commands/core-pipeline-workflow-runner-native.js +3237 -0
  10. package/dist/commands/core-workflow-run-command.d.ts +4 -0
  11. package/dist/commands/core-workflow-run-command.js +41 -0
  12. package/dist/commands/core.js +4 -0
  13. package/dist/commands/lanes-accounts.js +0 -1
  14. package/dist/commands/lanes-loop.d.ts +14 -0
  15. package/dist/commands/lanes-loop.js +43 -2
  16. package/dist/commands/lanes.js +8 -4
  17. package/dist/lib/capacity/freshness.d.ts +17 -0
  18. package/dist/lib/capacity/freshness.js +16 -0
  19. package/dist/lib/capacity/route.d.ts +7 -0
  20. package/dist/lib/capacity/route.js +46 -1
  21. package/dist/lib/core-utils/workflow-runner-schema.d.ts +7 -0
  22. package/dist/lib/core-utils/workflow-runner-schema.js +259 -0
  23. package/dist/lib/lanes/config.d.ts +8 -4
  24. package/dist/lib/lanes/config.js +30 -36
  25. package/dist/lib/lanes/index.d.ts +1 -1
  26. package/dist/lib/lanes/index.js +1 -1
  27. package/dist/lib/lanes/loop.d.ts +5 -0
  28. package/dist/lib/lanes/loop.js +8 -0
  29. package/dist/lib/lanes/reconcile.js +21 -27
  30. package/dist/lib/lanes/throttle.js +5 -9
  31. package/dist/lib/lanes/types.d.ts +4 -5
  32. package/dist/lib/lanes/types.js +1 -0
  33. package/dist/lib/lanes/worker-continuity.d.ts +13 -1
  34. package/dist/lib/lanes/worker-continuity.js +14 -0
  35. package/package.json +1 -1
@@ -9124,6 +9124,35 @@ export declare const COMMAND_CATALOG: readonly [{
9124
9124
  }];
9125
9125
  readonly subcommands: readonly [];
9126
9126
  }];
9127
+ }, {
9128
+ readonly name: "workflow";
9129
+ readonly description: "Workflow orchestration";
9130
+ readonly aliases: readonly [];
9131
+ readonly hidden: false;
9132
+ readonly helpOption: true;
9133
+ readonly helpCommand: true;
9134
+ readonly usage: "[options] [command]";
9135
+ readonly helpText: readonly [];
9136
+ readonly arguments: readonly [];
9137
+ readonly options: readonly [];
9138
+ readonly subcommands: readonly [{
9139
+ readonly name: "run";
9140
+ readonly description: "Run a workflow script or pipeline lane";
9141
+ readonly aliases: readonly [];
9142
+ readonly hidden: false;
9143
+ readonly helpOption: false;
9144
+ readonly helpCommand: false;
9145
+ readonly usage: "[args...]";
9146
+ readonly helpText: readonly [];
9147
+ readonly arguments: readonly [{
9148
+ readonly name: "args";
9149
+ readonly required: false;
9150
+ readonly variadic: true;
9151
+ readonly description: "";
9152
+ }];
9153
+ readonly options: readonly [];
9154
+ readonly subcommands: readonly [];
9155
+ }];
9127
9156
  }, {
9128
9157
  readonly name: "session-journal";
9129
9158
  readonly description: "Write and read session journal entries";
@@ -11073,6 +11073,40 @@ export const COMMAND_CATALOG = [
11073
11073
  }
11074
11074
  ]
11075
11075
  },
11076
+ {
11077
+ "name": "workflow",
11078
+ "description": "Workflow orchestration",
11079
+ "aliases": [],
11080
+ "hidden": false,
11081
+ "helpOption": true,
11082
+ "helpCommand": true,
11083
+ "usage": "[options] [command]",
11084
+ "helpText": [],
11085
+ "arguments": [],
11086
+ "options": [],
11087
+ "subcommands": [
11088
+ {
11089
+ "name": "run",
11090
+ "description": "Run a workflow script or pipeline lane",
11091
+ "aliases": [],
11092
+ "hidden": false,
11093
+ "helpOption": false,
11094
+ "helpCommand": false,
11095
+ "usage": "[args...]",
11096
+ "helpText": [],
11097
+ "arguments": [
11098
+ {
11099
+ "name": "args",
11100
+ "required": false,
11101
+ "variadic": true,
11102
+ "description": ""
11103
+ }
11104
+ ],
11105
+ "options": [],
11106
+ "subcommands": []
11107
+ }
11108
+ ]
11109
+ },
11076
11110
  {
11077
11111
  "name": "session-journal",
11078
11112
  "description": "Write and read session journal entries",
@@ -15,8 +15,7 @@ import { type ClaudeRefreshLastEntry } from "../lib/capacity/collectors/claude-o
15
15
  export declare const CAPACITY_SCHEMA_VERSION: "hq-capacity-now-view.v1";
16
16
  export declare const DOCTOR_SCHEMA_VERSION = "hq-capacity-doctor.v1";
17
17
  export declare const PARSER_FAILURE_WINDOW_MS: number;
18
- /** now.json older than this is stale: the collector is not keeping the view current. */
19
- export declare const CAPACITY_STALE_MS: number;
18
+ export { CAPACITY_STALE_MS } from "../lib/capacity/freshness.js";
20
19
  /** Short versions inside test/fixtures/capacity/cli-versions.json. */
21
20
  export declare const PINNED_CLI_VERSIONS: Record<string, string>;
22
21
  export interface CapacityJson extends NowView {
@@ -7,6 +7,7 @@ import { LedgerCorrupt, LedgerMissing, READING_SOURCES, capacityOptionsFromEnv,
7
7
  import { listCapacityAccounts, registryAccountIds } from "../lib/capacity/accounts.js";
8
8
  import { claudeIdentityKeys, readClaudeRefreshLast } from "../lib/capacity/collectors/claude-oauth.js";
9
9
  import { projectCapacityView } from "../lib/capacity/project.js";
10
+ import { capacityViewAge } from "../lib/capacity/freshness.js";
10
11
  import { capacityWidgetTimeZone, renderCapacityWidget } from "../lib/capacity/widget.js";
11
12
  import { resolveLanesHqRoot } from "../lib/lanes/hq-root.js";
12
13
  import { loadLanesConfig } from "../lib/lanes/config.js";
@@ -18,8 +19,7 @@ import { CapacityUsageError, REFUSAL_HELP, ingestRefusal, } from "../lib/capacit
18
19
  export const CAPACITY_SCHEMA_VERSION = nowViewJsonSchema.$id;
19
20
  export const DOCTOR_SCHEMA_VERSION = "hq-capacity-doctor.v1";
20
21
  export const PARSER_FAILURE_WINDOW_MS = 24 * 60 * 60 * 1000;
21
- /** now.json older than this is stale: the collector is not keeping the view current. */
22
- export const CAPACITY_STALE_MS = 5 * 60 * 1000;
22
+ export { CAPACITY_STALE_MS } from "../lib/capacity/freshness.js";
23
23
  /** Short versions inside test/fixtures/capacity/cli-versions.json. */
24
24
  export const PINNED_CLI_VERSIONS = {
25
25
  claude: "2.1.152",
@@ -54,20 +54,18 @@ export function withSchemaVersion(view) {
54
54
  }
55
55
  /** Stale when generatedAt is missing or older than five minutes. */
56
56
  export function capacityFreshness(generatedAt, nowMs) {
57
- const at = Date.parse(generatedAt);
58
- if (Number.isNaN(at)) {
57
+ const age = capacityViewAge(generatedAt, nowMs);
58
+ if (!age.known) {
59
59
  return {
60
60
  stale: true,
61
61
  ageMs: 0,
62
62
  message: "collector not running, numbers may be stale; last update unknown",
63
63
  };
64
64
  }
65
- const ageMs = Math.max(0, nowMs - at);
66
- const stale = ageMs > CAPACITY_STALE_MS;
67
65
  return {
68
- stale,
69
- ageMs,
70
- message: stale
66
+ stale: age.stale,
67
+ ageMs: age.ageMs,
68
+ message: age.stale
71
69
  ? `collector not running, numbers may be stale; last update ${formatAge(generatedAt, nowMs)}`
72
70
  : null,
73
71
  };
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+ /** # hq-core: public */
3
+ /**
4
+ * workflow-runner.mjs — multi-agent workflow orchestration over headless
5
+ * coding-agent CLIs (Codex, Grok, Claude), with human gates.
6
+ *
7
+ * Runs a plain-JavaScript orchestration script (Workflow-tool authoring shape:
8
+ * agent()/parallel()/pipeline()/phase()/log()/gate()/workflow(), top-level
9
+ * await, top-level return) where every agent() call spawns a headless CLI
10
+ * subprocess chosen by opts.engine:
11
+ *
12
+ * engine "codex" (default) — `codex exec` with the unattended-run flags
13
+ * (--dangerously-bypass-hook-trust --skip-git-repo-check
14
+ * --dangerously-bypass-approvals-and-sandbox); result read from a
15
+ * dedicated --output-last-message file (transcripts are huge — never
16
+ * tailed); structured output via --output-schema.
17
+ * engine "grok" — `grok --single` / `grok -p` (aliases) with
18
+ * --permission-mode bypassPermissions --always-approve --output-format json;
19
+ * result unwrapped from the JSON envelope; structured output via
20
+ * --json-schema when the CLI supports it (in-prompt fallback otherwise).
21
+ * engine "claude" — `claude -p` (single-turn headless) with
22
+ * --permission-mode bypassPermissions --output-format json; the result
23
+ * envelope ({type,subtype,is_error,result,stop_reason,permission_denials})
24
+ * is captured from stdout and unwrapped to its `result` text — a run that
25
+ * ended in error (is_error / subtype != success) fails loudly instead of
26
+ * surfacing downstream as a bogus parse error; structured output via a
27
+ * schema instruction appended to the prompt (the CLI has no schema flag),
28
+ * parsed from the reply. Hooks run normally: bypassPermissions skips only
29
+ * the interactive prompt, so HQ's PreToolUse/SessionStart hooks still fire.
30
+ *
31
+ * Hardening shared by both engines:
32
+ * - soft per-agent timeout: on expiry the agent is NOT killed — a
33
+ * TIMEOUT WARNING line prints to stdout and repeats every interval so the
34
+ * watching orchestrator decides to kill the process group
35
+ * (`kill -- -<pid>`) or let it run
36
+ * - stdin closed (/dev/null) — headless CLIs otherwise block on stdin
37
+ * - every agent is anchored at the HQ root (codex via -C, grok and claude via
38
+ * spawn cwd) so project-level agent config and safety hooks load; opts.cd names
39
+ * the task's directory and is injected as a prompt preamble, and must
40
+ * resolve inside the HQ root (or to a company repo symlink registered
41
+ * under repos/ or companies/manifest.yaml)
42
+ * - stderr (and codex's combined output) streamed to a per-agent log file
43
+ * - CPU governor: at high load, resolved concurrency is halved (floor 1)
44
+ *
45
+ * Human gates (spec: core/knowledge/public/hq-core/workflow-gates-spec.md):
46
+ * gate(id, question, opts?) pauses the run IN PLACE — a self-contained
47
+ * question file lands in <gates>/pending/, a GATE OPEN line prints to
48
+ * stdout (even under --quiet — it is the wake signal), and the run polls
49
+ * until <gates>/answered/<id>.json exists, then resumes and returns the
50
+ * parsed answer. No agents run and no concurrency slot is held while gated.
51
+ * Answers are durable: an already-answered id returns instantly
52
+ * (GATE CACHED), so a re-launched run never re-asks a human. Answer with
53
+ * `bash core/scripts/workflow-gate.sh answer <id> <choice|N>` (the runner
54
+ * prints whichever copy exists on this install).
55
+ *
56
+ * Usage:
57
+ * node core/scripts/workflow-runner.mjs <script.mjs> [options]
58
+ * node core/scripts/workflow-runner.mjs --eval '<script source>' [options]
59
+ *
60
+ * Options:
61
+ * --args <json> Value exposed to the script as `args`
62
+ * --concurrency <n> Max concurrent agent processes
63
+ * (default: min(16, cores-2), env HQ_WORKFLOW_CONCURRENCY)
64
+ * --timeout <secs> Default per-agent soft timeout — the warning interval
65
+ * (default: 1800, env HQ_WORKFLOW_TIMEOUT_SECS)
66
+ * --run-dir <dir> Where logs/journal land
67
+ * (default: <hq-root>/workspace/tmp/workflow-runner/<runId>)
68
+ * --resume <runId|dir> Replay a previous run's finished agents instead of
69
+ * re-running them. Walks the recorded calls in order and
70
+ * returns each cached result until one call differs
71
+ * (edited prompt, changed model, new args); from that
72
+ * point the run is live. Run ids are the directory names
73
+ * under <hq-root>/workspace/tmp/workflow-runner/.
74
+ * --quiet Suppress narrator lines on stderr
75
+ * --loop Persistent lane: no script; wait on
76
+ * <run-dir>/inbox/pending/ and run one phase envelope
77
+ * per agent() call until a {"kind":"stop"} envelope
78
+ * (see "loop mode" below main's helpers; poll interval
79
+ * env HQ_WORKFLOW_LOOP_POLL_MS, default 1000)
80
+ * --no-resume Loop mode: run every phase as a fresh engine call
81
+ * instead of resuming the story's engine session
82
+ * (env HQ_WORKFLOW_NO_RESUME=1 does the same)
83
+ *
84
+ * Env:
85
+ * HQ_ROOT Explicit HQ root. Unset -> auto-detected by
86
+ * walking up from this script (then cwd) to the
87
+ * first dir with companies/manifest.yaml or
88
+ * .claude/settings.json.
89
+ * HQ_WORKFLOW_CODEX_BIN codex binary (default `codex`; tests inject a fake)
90
+ * HQ_WORKFLOW_GROK_BIN grok binary (default `grok`)
91
+ * HQ_WORKFLOW_CLAUDE_BIN claude binary (default `claude`)
92
+ * HQ_WORKFLOW_CODEX_PLAN_MODEL / HQ_WORKFLOW_CODEX_EXEC_MODEL
93
+ * codex tier models (defaults gpt-5.6-sol /
94
+ * gpt-5.6-terra)
95
+ * HQ_WORKFLOW_GROK_PLAN_MODEL / HQ_WORKFLOW_GROK_EXEC_MODEL
96
+ * grok tier models (default grok-4.6 for both)
97
+ * HQ_WORKFLOW_CLAUDE_PLAN_MODEL / HQ_WORKFLOW_CLAUDE_EXEC_MODEL
98
+ * claude tier models (defaults opus / sonnet)
99
+ * HQ_WORKFLOW_MODEL Global model pin overriding every tier map;
100
+ * empty string -> engine CLI default (no -m)
101
+ * HQ_WORKFLOW_EFFORT Default reasoning effort for codex and grok
102
+ * (default high; empty string -> engine CLI default)
103
+ * HQ_WORKFLOW_CLAUDE_EFFORT Default reasoning effort for claude, passed as
104
+ * `--effort` (default low; empty string -> CLI default)
105
+ * HQ_WORKFLOW_FAST_MODE Codex fast mode override (1/0). Per-tier
106
+ * default: exec on, plan off. Ignored by grok.
107
+ * HQ_WORKFLOW_REPAIR Repair passes for an off-contract reply
108
+ * (default 1; 0 disables). When an agent answers
109
+ * in prose instead of the schema's JSON, the
110
+ * engine is asked to restate that same reply as
111
+ * JSON — a reformat, not a re-run of the work.
112
+ * HQ_WORKFLOW_CPU_CHECK High-CPU governor on/off (default on)
113
+ * HQ_WORKFLOW_CPU_HIGH_THRESHOLD Busy fraction counting as high (0.85)
114
+ * HQ_WORKFLOW_CPU_BUSY_OVERRIDE Injected busy fraction (tests)
115
+ * HQ_WORKFLOW_GATES_DIR Gates root (default <hq-root>/workspace/gates;
116
+ * legacy CODEX_WORKFLOW_GATES_DIR honored)
117
+ * HQ_WORKFLOW_GATE_POLL_SECS Gate poll interval (default 5; legacy
118
+ * CODEX_WORKFLOW_GATE_POLL_SECS honored)
119
+ *
120
+ * Script API (mirrors the Workflow tool):
121
+ * agent(prompt, opts) -> Promise<string|object>
122
+ * opts.tier (REQUIRED): "plan" (analysis/planning — the flagship model)
123
+ * or "exec" (execution — the throughput model). agent() throws if
124
+ * missing/invalid so the model choice is never implicit.
125
+ * opts.engine: "codex" (default), "grok", or "claude"
126
+ * opts: label, phase, schema (ordinary JSON Schema; result parsed+returned
127
+ * as an object. Write it the normal way — optional properties simply
128
+ * stay out of `required`. On the codex engine it is rewritten into
129
+ * the provider's strict dialect on the wire and the answer is mapped
130
+ * back, so results are engine-neutral: see
131
+ * core/scripts/lib/codex-output-schema.mjs),
132
+ * model (explicit override), effort, fastMode (codex only),
133
+ * cd (task directory inside the HQ root, or a company repo symlink
134
+ * registered under repos/ / companies/manifest.yaml; injected into
135
+ * the prompt),
136
+ * timeoutSecs (soft), extraArgs (string[])
137
+ * A reply that will not parse, or that violates opts.schema, is not the
138
+ * end of the call: the engine is asked once to RESTATE its own reply as
139
+ * the requested JSON (a reformat — no tools, no re-work, nothing
140
+ * invented), because such an agent has almost always finished the work and
141
+ * only lost the envelope. HQ_WORKFLOW_REPAIR=0 disables it.
142
+ * Every successful call also records its result in the run dir keyed by
143
+ * its inputs, which is what --resume replays.
144
+ * parallel(thunks) -> barrier; a thrown thunk resolves to null
145
+ * pipeline(items, ...stages) -> no barrier; a throwing stage drops its item
146
+ * phase(title) / log(msg)
147
+ * gate(id, question, opts?) -> human pause (see above)
148
+ * workflow(ref, args?) -> nested script, one level deep
149
+ * args / budget (budget is a stub: spend is not tracked for CLI engines)
150
+ *
151
+ * The script's top-level return value prints to stdout as JSON.
152
+ */
153
+ type WorkflowRunnerChild = {
154
+ pid?: number;
155
+ unref(): void;
156
+ };
157
+ type WorkflowRunnerSpawnOptions = {
158
+ detached: true;
159
+ stdio: 'inherit';
160
+ env: NodeJS.ProcessEnv;
161
+ windowsHide?: true;
162
+ };
163
+ type WorkflowRunnerSpawner = (executable: string, argv: string[], options: WorkflowRunnerSpawnOptions) => WorkflowRunnerChild;
164
+ /** Restart this same CLI build with the pinned runner's detached lifecycle. */
165
+ export declare function restartWorkflowRunner(input: {
166
+ executable: string;
167
+ argv: string[];
168
+ env: NodeJS.ProcessEnv;
169
+ platform: NodeJS.Platform;
170
+ spawnProcess: WorkflowRunnerSpawner;
171
+ }): WorkflowRunnerChild;
172
+ /** Execute the native runner behind the hq core command route. */
173
+ export declare function runWorkflowRunnerNative(argv: string[], hqRoot: string): Promise<number>;
174
+ export {};
175
+ //# sourceMappingURL=core-pipeline-workflow-runner-native.d.ts.map