@indigoai-us/hq-cli 5.345.55 → 5.345.57
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 +18 -0
- package/assets/scaffold/core/scripts/derive-trigger-facts.sh +10 -1
- package/assets/scaffold/core/scripts/jobs-validate.sh +2 -1
- package/assets/scaffold/core/scripts/session-title.sh +18 -15
- package/dist/command-catalog.generated.d.ts +124 -0
- package/dist/command-catalog.generated.js +155 -0
- package/dist/commands/core-delegate-w1b.js +18 -5
- package/dist/commands/core-derive-trigger-facts-command.js +14 -0
- package/dist/commands/core-derive-trigger-facts-native.d.ts +1 -0
- package/dist/commands/core-derive-trigger-facts-native.js +20 -1
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +15 -2
- package/dist/commands/lanes-checks.d.ts +3 -0
- package/dist/commands/lanes-checks.js +34 -0
- package/dist/commands/lanes-loop.d.ts +12 -0
- package/dist/commands/lanes-loop.js +214 -0
- package/dist/commands/lanes-questions.js +37 -11
- package/dist/commands/lanes-resume.js +19 -1
- package/dist/commands/lanes-session-start.d.ts +2 -7
- package/dist/commands/lanes-session-start.js +9 -29
- package/dist/commands/lanes-shared.d.ts +14 -2
- package/dist/commands/lanes.d.ts +3 -1
- package/dist/commands/lanes.js +376 -35
- package/dist/commands/members.d.ts +4 -0
- package/dist/commands/members.js +23 -2
- package/dist/lanes-drain-hook.js +6 -2
- package/dist/lib/doctor/checks/sync-health.d.ts +2 -0
- package/dist/lib/doctor/checks/sync-health.js +47 -23
- package/dist/lib/lanes/delivery.d.ts +3 -0
- package/dist/lib/lanes/delivery.js +5 -0
- package/dist/lib/lanes/dropbox.d.ts +7 -2
- package/dist/lib/lanes/dropbox.js +157 -10
- package/dist/lib/lanes/flag-keys.d.ts +12 -0
- package/dist/lib/lanes/flag-keys.js +12 -0
- package/dist/lib/lanes/hooks-install.d.ts +14 -11
- package/dist/lib/lanes/hooks-install.js +70 -50
- package/dist/lib/lanes/loop.d.ts +158 -0
- package/dist/lib/lanes/loop.js +743 -0
- package/dist/lib/lanes/outpost-dispatch.d.ts +9 -1
- package/dist/lib/lanes/outpost-dispatch.js +21 -7
- package/dist/lib/lanes/reaper.d.ts +58 -0
- package/dist/lib/lanes/reaper.js +403 -0
- package/dist/lib/lanes/reconcile.d.ts +19 -0
- package/dist/lib/lanes/reconcile.js +173 -6
- package/dist/lib/lanes/spawn.d.ts +4 -0
- package/dist/lib/lanes/spawn.js +41 -9
- package/dist/lib/lanes/status-fields.d.ts +12 -0
- package/dist/lib/lanes/status-fields.js +189 -0
- package/dist/lib/lanes/store.js +49 -2
- package/dist/lib/lanes/types.d.ts +18 -0
- package/dist/lib/lanes/types.js +3 -3
- package/dist/lib/lanes/watcher.js +3 -0
- package/dist/lib/lanes/worker-continuity.d.ts +18 -0
- package/dist/lib/lanes/worker-continuity.js +81 -0
- package/dist/lib/lanes/worker-process.d.ts +4 -0
- package/dist/lib/lanes/worker-process.js +77 -0
- package/dist/main.js +9 -3
- package/dist/utils/cli-telemetry.d.ts +4 -1
- package/dist/utils/cli-telemetry.js +8 -0
- package/dist/utils/jq-windows-compat.d.ts +13 -0
- package/dist/utils/jq-windows-compat.js +48 -0
- package/dist/utils/run-bundled-script.d.ts +3 -0
- package/dist/utils/run-bundled-script.js +9 -80
- package/dist/utils/windows-bash.d.ts +5 -0
- package/dist/utils/windows-bash.js +75 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.345.57] — 2026-10-09
|
|
6
|
+
- Add `hq lanes create --loop` and `hq lanes enqueue` for persistent worker lanes that process FIFO phase envelopes, return generic results or section 8 handoffs, reuse sessions per story, retry one stall, and park a second stall for the senior. Loop behavior uses the default-on `lanes.conduct-loop` hq-flags kill switch. See `docs/lanes.md` for command output and exit codes.
|
|
7
|
+
|
|
8
|
+
- Add six-hour escalation for continuously blocked lanes, including durable cross-host inbox delivery and per-lane escalation history.
|
|
9
|
+
- Lane questions addressed to the current operator session record session-specific visibility on the owning host; unanswered questions cannot age past that session before it sees them, and reparenting to a different audience clears the marker. Visibility is separate from answer delivery so conflict-sidecar merging cannot suppress answer delivery. Outpost question show and answer lookups ignore malformed rows for unrelated question ids while still validating the requested record.
|
|
10
|
+
|
|
11
|
+
## [5.345.56] — 2026-10-09
|
|
12
|
+
- Add `hq lanes reap` to report local lanes whose session senior is confirmed ended, clear stale pid markers on request, and keep process-tree stopping behind the `lanes.reap-stop` hq-flags key. SessionStart runs the report-only sweep detached and stores its report in host-specific user state.
|
|
13
|
+
- Record privacy-limited `hq members invite` success and failure outcomes through the existing CLI feature telemetry event.
|
|
14
|
+
|
|
15
|
+
- Continue a senior's most recent same-company, same-provider worker lane on `hq lanes create`, refuse live duplicate worker lanes, and filter `hq lanes list` by worker.
|
|
16
|
+
|
|
17
|
+
- Pass jq diagnostic filters to Windows batch wrappers as single-line arguments so malformed-ACL parity reports the original jq diagnostic instead of failing on an invalid command line.
|
|
18
|
+
- Keep the bundled derive-trigger-facts helper's closed-stdin error prompt on macOS instead of blocking the hook call.
|
|
19
|
+
- Native delegate diagnostics match the bundled helper's Git Bash jq byte handling, including jq.exe CRLF output when `--binary` is unavailable.
|
|
20
|
+
- Lane drop-box hooks deliver queued messages after tool calls and at a deliverable Stop event. Lane list and show JSON include bounded output, PR, inbox, elapsed time, and worker exit fields.
|
|
21
|
+
- hq doctor now finds a company's sync manifest status instead of reporting the company as unresolved.
|
|
22
|
+
|
|
5
23
|
## [5.345.55] — 2026-10-08
|
|
6
24
|
- Added `hq daemon sync conflicts acknowledge <id>` so the desktop can clear a parked-conflict notice without writing runner-owned sync state.
|
|
7
25
|
- Add `hq import scan`, which runs the HQ import-context scanner on this
|
|
@@ -65,7 +65,16 @@ case "${OSTYPE:-}" in
|
|
|
65
65
|
STDIN_JSON="${STDIN_JSON%$'\n'}"
|
|
66
66
|
done
|
|
67
67
|
;;
|
|
68
|
-
*)
|
|
68
|
+
*)
|
|
69
|
+
# Bash 3.2 on macOS can block while opening /dev/stdin when fd 0 is closed.
|
|
70
|
+
# Detect that case with a builtin redirection so the existing fail-closed
|
|
71
|
+
# behavior returns promptly on every POSIX host.
|
|
72
|
+
if [[ ! -e /dev/stdin ]]; then
|
|
73
|
+
printf '%s: line 68: /dev/stdin: No such file or directory\n' "$0" >&2
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
STDIN_JSON="$(</dev/stdin)" || STDIN_JSON='{}'
|
|
77
|
+
;;
|
|
69
78
|
esac
|
|
70
79
|
[ -n "$STDIN_JSON" ] || STDIN_JSON='{}'
|
|
71
80
|
JQ="$(command -v jq || true)"
|
|
@@ -219,7 +219,8 @@ validate_job_file() {
|
|
|
219
219
|
err "$file" "yaml" "failed to parse YAML"
|
|
220
220
|
return
|
|
221
221
|
fi
|
|
222
|
-
|
|
222
|
+
# Use jq's exit status instead of its text output: jq.exe writes CRLF on Windows.
|
|
223
|
+
if ! jq -es 'length == 1 and (.[0] | type == "object")' <<<"$json" >/dev/null; then
|
|
223
224
|
err "$file" "yaml" "job root must be a mapping"
|
|
224
225
|
return
|
|
225
226
|
fi
|
|
@@ -38,13 +38,14 @@ done
|
|
|
38
38
|
|
|
39
39
|
command -v node >/dev/null 2>&1 || exit 0
|
|
40
40
|
|
|
41
|
-
HQ_ROOT="$HQ_ROOT" SESSION_ID="$SESSION_ID"
|
|
41
|
+
HQ_ROOT="$HQ_ROOT" SESSION_ID="$SESSION_ID" SESSION_CWD="$SESSION_CWD" \
|
|
42
|
+
MSYS2_ARG_CONV_EXCL="*" node - "$COMMAND" <<'JS'
|
|
42
43
|
const fs = require("fs");
|
|
43
44
|
const path = require("path");
|
|
44
45
|
|
|
45
46
|
const hq = process.env.HQ_ROOT || "";
|
|
46
47
|
const sid = process.env.SESSION_ID || "default";
|
|
47
|
-
let command = (process.
|
|
48
|
+
let command = (process.argv[2] || "").trim().replace(/^\/+/, "");
|
|
48
49
|
|
|
49
50
|
const key = sid.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
|
|
50
51
|
const state = path.join(hq, ".claude", "state");
|
|
@@ -133,12 +134,12 @@ if (project) {
|
|
|
133
134
|
if (matchesProject) {
|
|
134
135
|
const st = p.state || "";
|
|
135
136
|
if (st === "IN_PROGRESS") {
|
|
136
|
-
emoji = "
|
|
137
|
+
emoji = "\u25b6\ufe0f";
|
|
137
138
|
} else if (st === "COMPLETED") {
|
|
138
139
|
const ts = p.updatedAt || p.updated_at || "";
|
|
139
140
|
const t = new Date(ts);
|
|
140
141
|
if (!isNaN(t.getTime()) && (Date.now() - t.getTime()) / 1000 < 86400) {
|
|
141
|
-
emoji = "
|
|
142
|
+
emoji = "\u2705"; // only recent completions
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
break;
|
|
@@ -171,15 +172,15 @@ if (project) {
|
|
|
171
172
|
// while /handoff runs; only the model can know when it finished, so it sets 📤.
|
|
172
173
|
// Both are distinct from ✅ "the work shipped" and 🤝 "a person owns it now".
|
|
173
174
|
const MODES = [
|
|
174
|
-
[/^(brainstorm|idea|dream|discover|strategize)$/, "
|
|
175
|
-
[/^(plan|prd|deep-plan|storyboard|architect|review-plan|codebase-design)$/, "
|
|
176
|
-
[/^(run-project|execute-task|ship|land|land-batch|run-pipeline|orchestrate|tdd|deploy)$/, "
|
|
177
|
-
[/^(review|code-review|security-review)$/, "
|
|
178
|
-
[/^(quality-gate|smoke|verify|diagnose|investigate)$/, "
|
|
179
|
-
[/^(handoff|checkpoint-handoff|retro)$/, "
|
|
180
|
-
[/^(delegate|new-hire|new-agent|promote)$/, "
|
|
181
|
-
[/^(dm|hq-slack|meeting-notes|work-broadcast|signals|hq-share)$/, "
|
|
182
|
-
[/^(schedule|job|loop)$/, "
|
|
175
|
+
[/^(brainstorm|idea|dream|discover|strategize)$/, "\u{1f4ad}"],
|
|
176
|
+
[/^(plan|prd|deep-plan|storyboard|architect|review-plan|codebase-design)$/, "\u{1f4d0}"],
|
|
177
|
+
[/^(run-project|execute-task|ship|land|land-batch|run-pipeline|orchestrate|tdd|deploy)$/, "\u{26a1}"],
|
|
178
|
+
[/^(review|code-review|security-review)$/, "\u{1f440}"],
|
|
179
|
+
[/^(quality-gate|smoke|verify|diagnose|investigate)$/, "\u{1f9ea}"],
|
|
180
|
+
[/^(handoff|checkpoint-handoff|retro)$/, "\u{1f4dd}"],
|
|
181
|
+
[/^(delegate|new-hire|new-agent|promote)$/, "\u{1f91d}"],
|
|
182
|
+
[/^(dm|hq-slack|meeting-notes|work-broadcast|signals|hq-share)$/, "\u{1f4ac}"],
|
|
183
|
+
[/^(schedule|job|loop)$/, "\u{1f501}"],
|
|
183
184
|
];
|
|
184
185
|
|
|
185
186
|
const modeFor = (word) => {
|
|
@@ -192,7 +193,7 @@ if (!command) command = "chat";
|
|
|
192
193
|
// Precedence: a finished or running project outranks the command word — "it
|
|
193
194
|
// shipped" and "it is executing right now" beat "you typed /plan an hour ago".
|
|
194
195
|
// `emoji` is set above from orchestrator state (✅ recent completion, ▶️ running).
|
|
195
|
-
const mode = emoji === "
|
|
196
|
+
const mode = emoji === "\u25b6\ufe0f" ? "\u{26a1}" : (emoji || modeFor(command));
|
|
196
197
|
|
|
197
198
|
// --- company ---
|
|
198
199
|
// Always the first text token. Long slugs get an explicit short form from the
|
|
@@ -301,5 +302,7 @@ let title = compose(parts);
|
|
|
301
302
|
if (title.length > MAX && parts.length > 1) title = compose([parts[parts.length - 1]]);
|
|
302
303
|
if (title.length > MAX) title = title.slice(0, MAX - 1).replace(/\s+$/, "") + "…";
|
|
303
304
|
|
|
304
|
-
|
|
305
|
+
// The script is also run under Git Bash with LC_ALL=C from its caller. Write
|
|
306
|
+
// the protocol bytes explicitly so the host locale cannot replace UTF-8 glyphs.
|
|
307
|
+
process.stdout.write(Buffer.from(`${title}\n`, "utf8"));
|
|
305
308
|
JS
|
|
@@ -11008,6 +11008,38 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
11008
11008
|
readonly hidden: false;
|
|
11009
11009
|
}];
|
|
11010
11010
|
readonly subcommands: readonly [];
|
|
11011
|
+
}, {
|
|
11012
|
+
readonly name: "reap";
|
|
11013
|
+
readonly description: "Classify local lanes whose session senior has ended; report only by default";
|
|
11014
|
+
readonly aliases: readonly ["_reap"];
|
|
11015
|
+
readonly hidden: false;
|
|
11016
|
+
readonly helpOption: true;
|
|
11017
|
+
readonly helpCommand: false;
|
|
11018
|
+
readonly usage: "[options]";
|
|
11019
|
+
readonly helpText: readonly [];
|
|
11020
|
+
readonly arguments: readonly [];
|
|
11021
|
+
readonly options: readonly [{
|
|
11022
|
+
readonly flags: "--min-age <minutes>";
|
|
11023
|
+
readonly description: "Minimum lane age in minutes (default: 120)";
|
|
11024
|
+
readonly hidden: false;
|
|
11025
|
+
}, {
|
|
11026
|
+
readonly flags: "--apply-stale-state";
|
|
11027
|
+
readonly description: "Remove stale worker and watcher pid markers";
|
|
11028
|
+
readonly hidden: false;
|
|
11029
|
+
}, {
|
|
11030
|
+
readonly flags: "--stop";
|
|
11031
|
+
readonly description: "Stop candidate process trees when the hq-flags stop key is enabled";
|
|
11032
|
+
readonly hidden: false;
|
|
11033
|
+
}, {
|
|
11034
|
+
readonly flags: "--reason <text>";
|
|
11035
|
+
readonly description: "Required audit reason when --stop is set";
|
|
11036
|
+
readonly hidden: false;
|
|
11037
|
+
}, {
|
|
11038
|
+
readonly flags: "--json";
|
|
11039
|
+
readonly description: "Print machine-readable JSON (default)";
|
|
11040
|
+
readonly hidden: false;
|
|
11041
|
+
}];
|
|
11042
|
+
readonly subcommands: readonly [];
|
|
11011
11043
|
}, {
|
|
11012
11044
|
readonly name: "checks";
|
|
11013
11045
|
readonly description: "Evaluate tracker and lane health checks";
|
|
@@ -11618,6 +11650,14 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
11618
11650
|
readonly flags: "--worker <name>";
|
|
11619
11651
|
readonly description: "HQ worker or reusable profile id";
|
|
11620
11652
|
readonly hidden: false;
|
|
11653
|
+
}, {
|
|
11654
|
+
readonly flags: "--fresh-thread";
|
|
11655
|
+
readonly description: "Skip worker continuity and start a cold provider session";
|
|
11656
|
+
readonly hidden: false;
|
|
11657
|
+
}, {
|
|
11658
|
+
readonly flags: "--loop";
|
|
11659
|
+
readonly description: "Keep one worker lane registered to process queued phase envelopes";
|
|
11660
|
+
readonly hidden: false;
|
|
11621
11661
|
}, {
|
|
11622
11662
|
readonly flags: "--provider <name>";
|
|
11623
11663
|
readonly description: "claude | codex | grok";
|
|
@@ -11698,6 +11738,52 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
11698
11738
|
readonly hidden: false;
|
|
11699
11739
|
}];
|
|
11700
11740
|
readonly subcommands: readonly [];
|
|
11741
|
+
}, {
|
|
11742
|
+
readonly name: "_loop-worker";
|
|
11743
|
+
readonly description: "";
|
|
11744
|
+
readonly aliases: readonly [];
|
|
11745
|
+
readonly hidden: true;
|
|
11746
|
+
readonly helpOption: true;
|
|
11747
|
+
readonly helpCommand: false;
|
|
11748
|
+
readonly usage: "[options] <lane-id>";
|
|
11749
|
+
readonly helpText: readonly [];
|
|
11750
|
+
readonly arguments: readonly [{
|
|
11751
|
+
readonly name: "lane-id";
|
|
11752
|
+
readonly required: true;
|
|
11753
|
+
readonly variadic: false;
|
|
11754
|
+
readonly description: "Loop lane id";
|
|
11755
|
+
}];
|
|
11756
|
+
readonly options: readonly [{
|
|
11757
|
+
readonly flags: "--json";
|
|
11758
|
+
readonly description: "JSON on stdout (always)";
|
|
11759
|
+
readonly hidden: false;
|
|
11760
|
+
}];
|
|
11761
|
+
readonly subcommands: readonly [];
|
|
11762
|
+
}, {
|
|
11763
|
+
readonly name: "enqueue";
|
|
11764
|
+
readonly description: "Validate and queue one phase envelope for a loop lane";
|
|
11765
|
+
readonly aliases: readonly [];
|
|
11766
|
+
readonly hidden: false;
|
|
11767
|
+
readonly helpOption: true;
|
|
11768
|
+
readonly helpCommand: false;
|
|
11769
|
+
readonly usage: "[options] <lane-id>";
|
|
11770
|
+
readonly helpText: readonly [];
|
|
11771
|
+
readonly arguments: readonly [{
|
|
11772
|
+
readonly name: "lane-id";
|
|
11773
|
+
readonly required: true;
|
|
11774
|
+
readonly variadic: false;
|
|
11775
|
+
readonly description: "Loop lane id";
|
|
11776
|
+
}];
|
|
11777
|
+
readonly options: readonly [{
|
|
11778
|
+
readonly flags: "--envelope <file>";
|
|
11779
|
+
readonly description: "Generic phase or hq-phase-envelope/v1 JSON file";
|
|
11780
|
+
readonly hidden: false;
|
|
11781
|
+
}, {
|
|
11782
|
+
readonly flags: "--json";
|
|
11783
|
+
readonly description: "JSON on stdout (always)";
|
|
11784
|
+
readonly hidden: false;
|
|
11785
|
+
}];
|
|
11786
|
+
readonly subcommands: readonly [];
|
|
11701
11787
|
}, {
|
|
11702
11788
|
readonly name: "reparent-target";
|
|
11703
11789
|
readonly description: "";
|
|
@@ -11950,6 +12036,10 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
11950
12036
|
readonly flags: "--senior <ref>";
|
|
11951
12037
|
readonly description: "Filter by senior ref";
|
|
11952
12038
|
readonly hidden: false;
|
|
12039
|
+
}, {
|
|
12040
|
+
readonly flags: "--worker <id>";
|
|
12041
|
+
readonly description: "Filter by worker id";
|
|
12042
|
+
readonly hidden: false;
|
|
11953
12043
|
}, {
|
|
11954
12044
|
readonly flags: "--lane <id>";
|
|
11955
12045
|
readonly description: "Filter by lane id (repeatable)";
|
|
@@ -12566,6 +12656,40 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
12566
12656
|
readonly hidden: false;
|
|
12567
12657
|
}];
|
|
12568
12658
|
readonly subcommands: readonly [];
|
|
12659
|
+
}, {
|
|
12660
|
+
readonly name: "_enqueue-blocked-escalation";
|
|
12661
|
+
readonly description: "";
|
|
12662
|
+
readonly aliases: readonly [];
|
|
12663
|
+
readonly hidden: true;
|
|
12664
|
+
readonly helpOption: true;
|
|
12665
|
+
readonly helpCommand: false;
|
|
12666
|
+
readonly usage: "[options] <recipient-kind> <recipient-id>";
|
|
12667
|
+
readonly helpText: readonly [];
|
|
12668
|
+
readonly arguments: readonly [{
|
|
12669
|
+
readonly name: "recipient-kind";
|
|
12670
|
+
readonly required: true;
|
|
12671
|
+
readonly variadic: false;
|
|
12672
|
+
readonly description: "";
|
|
12673
|
+
}, {
|
|
12674
|
+
readonly name: "recipient-id";
|
|
12675
|
+
readonly required: true;
|
|
12676
|
+
readonly variadic: false;
|
|
12677
|
+
readonly description: "";
|
|
12678
|
+
}];
|
|
12679
|
+
readonly options: readonly [{
|
|
12680
|
+
readonly flags: "--text <text>";
|
|
12681
|
+
readonly description: "Escalation notice";
|
|
12682
|
+
readonly hidden: false;
|
|
12683
|
+
}, {
|
|
12684
|
+
readonly flags: "--message-id <id>";
|
|
12685
|
+
readonly description: "Idempotency key";
|
|
12686
|
+
readonly hidden: false;
|
|
12687
|
+
}, {
|
|
12688
|
+
readonly flags: "--json";
|
|
12689
|
+
readonly description: "JSON on stdout (always)";
|
|
12690
|
+
readonly hidden: false;
|
|
12691
|
+
}];
|
|
12692
|
+
readonly subcommands: readonly [];
|
|
12569
12693
|
}, {
|
|
12570
12694
|
readonly name: "_spawn-envelope-repair";
|
|
12571
12695
|
readonly description: "";
|
|
@@ -13374,6 +13374,47 @@ export const COMMAND_CATALOG = [
|
|
|
13374
13374
|
],
|
|
13375
13375
|
"subcommands": []
|
|
13376
13376
|
},
|
|
13377
|
+
{
|
|
13378
|
+
"name": "reap",
|
|
13379
|
+
"description": "Classify local lanes whose session senior has ended; report only by default",
|
|
13380
|
+
"aliases": [
|
|
13381
|
+
"_reap"
|
|
13382
|
+
],
|
|
13383
|
+
"hidden": false,
|
|
13384
|
+
"helpOption": true,
|
|
13385
|
+
"helpCommand": false,
|
|
13386
|
+
"usage": "[options]",
|
|
13387
|
+
"helpText": [],
|
|
13388
|
+
"arguments": [],
|
|
13389
|
+
"options": [
|
|
13390
|
+
{
|
|
13391
|
+
"flags": "--min-age <minutes>",
|
|
13392
|
+
"description": "Minimum lane age in minutes (default: 120)",
|
|
13393
|
+
"hidden": false
|
|
13394
|
+
},
|
|
13395
|
+
{
|
|
13396
|
+
"flags": "--apply-stale-state",
|
|
13397
|
+
"description": "Remove stale worker and watcher pid markers",
|
|
13398
|
+
"hidden": false
|
|
13399
|
+
},
|
|
13400
|
+
{
|
|
13401
|
+
"flags": "--stop",
|
|
13402
|
+
"description": "Stop candidate process trees when the hq-flags stop key is enabled",
|
|
13403
|
+
"hidden": false
|
|
13404
|
+
},
|
|
13405
|
+
{
|
|
13406
|
+
"flags": "--reason <text>",
|
|
13407
|
+
"description": "Required audit reason when --stop is set",
|
|
13408
|
+
"hidden": false
|
|
13409
|
+
},
|
|
13410
|
+
{
|
|
13411
|
+
"flags": "--json",
|
|
13412
|
+
"description": "Print machine-readable JSON (default)",
|
|
13413
|
+
"hidden": false
|
|
13414
|
+
}
|
|
13415
|
+
],
|
|
13416
|
+
"subcommands": []
|
|
13417
|
+
},
|
|
13377
13418
|
{
|
|
13378
13419
|
"name": "checks",
|
|
13379
13420
|
"description": "Evaluate tracker and lane health checks",
|
|
@@ -14116,6 +14157,16 @@ export const COMMAND_CATALOG = [
|
|
|
14116
14157
|
"description": "HQ worker or reusable profile id",
|
|
14117
14158
|
"hidden": false
|
|
14118
14159
|
},
|
|
14160
|
+
{
|
|
14161
|
+
"flags": "--fresh-thread",
|
|
14162
|
+
"description": "Skip worker continuity and start a cold provider session",
|
|
14163
|
+
"hidden": false
|
|
14164
|
+
},
|
|
14165
|
+
{
|
|
14166
|
+
"flags": "--loop",
|
|
14167
|
+
"description": "Keep one worker lane registered to process queued phase envelopes",
|
|
14168
|
+
"hidden": false
|
|
14169
|
+
},
|
|
14119
14170
|
{
|
|
14120
14171
|
"flags": "--provider <name>",
|
|
14121
14172
|
"description": "claude | codex | grok",
|
|
@@ -14216,6 +14267,63 @@ export const COMMAND_CATALOG = [
|
|
|
14216
14267
|
],
|
|
14217
14268
|
"subcommands": []
|
|
14218
14269
|
},
|
|
14270
|
+
{
|
|
14271
|
+
"name": "_loop-worker",
|
|
14272
|
+
"description": "",
|
|
14273
|
+
"aliases": [],
|
|
14274
|
+
"hidden": true,
|
|
14275
|
+
"helpOption": true,
|
|
14276
|
+
"helpCommand": false,
|
|
14277
|
+
"usage": "[options] <lane-id>",
|
|
14278
|
+
"helpText": [],
|
|
14279
|
+
"arguments": [
|
|
14280
|
+
{
|
|
14281
|
+
"name": "lane-id",
|
|
14282
|
+
"required": true,
|
|
14283
|
+
"variadic": false,
|
|
14284
|
+
"description": "Loop lane id"
|
|
14285
|
+
}
|
|
14286
|
+
],
|
|
14287
|
+
"options": [
|
|
14288
|
+
{
|
|
14289
|
+
"flags": "--json",
|
|
14290
|
+
"description": "JSON on stdout (always)",
|
|
14291
|
+
"hidden": false
|
|
14292
|
+
}
|
|
14293
|
+
],
|
|
14294
|
+
"subcommands": []
|
|
14295
|
+
},
|
|
14296
|
+
{
|
|
14297
|
+
"name": "enqueue",
|
|
14298
|
+
"description": "Validate and queue one phase envelope for a loop lane",
|
|
14299
|
+
"aliases": [],
|
|
14300
|
+
"hidden": false,
|
|
14301
|
+
"helpOption": true,
|
|
14302
|
+
"helpCommand": false,
|
|
14303
|
+
"usage": "[options] <lane-id>",
|
|
14304
|
+
"helpText": [],
|
|
14305
|
+
"arguments": [
|
|
14306
|
+
{
|
|
14307
|
+
"name": "lane-id",
|
|
14308
|
+
"required": true,
|
|
14309
|
+
"variadic": false,
|
|
14310
|
+
"description": "Loop lane id"
|
|
14311
|
+
}
|
|
14312
|
+
],
|
|
14313
|
+
"options": [
|
|
14314
|
+
{
|
|
14315
|
+
"flags": "--envelope <file>",
|
|
14316
|
+
"description": "Generic phase or hq-phase-envelope/v1 JSON file",
|
|
14317
|
+
"hidden": false
|
|
14318
|
+
},
|
|
14319
|
+
{
|
|
14320
|
+
"flags": "--json",
|
|
14321
|
+
"description": "JSON on stdout (always)",
|
|
14322
|
+
"hidden": false
|
|
14323
|
+
}
|
|
14324
|
+
],
|
|
14325
|
+
"subcommands": []
|
|
14326
|
+
},
|
|
14219
14327
|
{
|
|
14220
14328
|
"name": "reparent-target",
|
|
14221
14329
|
"description": "",
|
|
@@ -14526,6 +14634,11 @@ export const COMMAND_CATALOG = [
|
|
|
14526
14634
|
"description": "Filter by senior ref",
|
|
14527
14635
|
"hidden": false
|
|
14528
14636
|
},
|
|
14637
|
+
{
|
|
14638
|
+
"flags": "--worker <id>",
|
|
14639
|
+
"description": "Filter by worker id",
|
|
14640
|
+
"hidden": false
|
|
14641
|
+
},
|
|
14529
14642
|
{
|
|
14530
14643
|
"flags": "--lane <id>",
|
|
14531
14644
|
"description": "Filter by lane id (repeatable)",
|
|
@@ -15283,6 +15396,48 @@ export const COMMAND_CATALOG = [
|
|
|
15283
15396
|
],
|
|
15284
15397
|
"subcommands": []
|
|
15285
15398
|
},
|
|
15399
|
+
{
|
|
15400
|
+
"name": "_enqueue-blocked-escalation",
|
|
15401
|
+
"description": "",
|
|
15402
|
+
"aliases": [],
|
|
15403
|
+
"hidden": true,
|
|
15404
|
+
"helpOption": true,
|
|
15405
|
+
"helpCommand": false,
|
|
15406
|
+
"usage": "[options] <recipient-kind> <recipient-id>",
|
|
15407
|
+
"helpText": [],
|
|
15408
|
+
"arguments": [
|
|
15409
|
+
{
|
|
15410
|
+
"name": "recipient-kind",
|
|
15411
|
+
"required": true,
|
|
15412
|
+
"variadic": false,
|
|
15413
|
+
"description": ""
|
|
15414
|
+
},
|
|
15415
|
+
{
|
|
15416
|
+
"name": "recipient-id",
|
|
15417
|
+
"required": true,
|
|
15418
|
+
"variadic": false,
|
|
15419
|
+
"description": ""
|
|
15420
|
+
}
|
|
15421
|
+
],
|
|
15422
|
+
"options": [
|
|
15423
|
+
{
|
|
15424
|
+
"flags": "--text <text>",
|
|
15425
|
+
"description": "Escalation notice",
|
|
15426
|
+
"hidden": false
|
|
15427
|
+
},
|
|
15428
|
+
{
|
|
15429
|
+
"flags": "--message-id <id>",
|
|
15430
|
+
"description": "Idempotency key",
|
|
15431
|
+
"hidden": false
|
|
15432
|
+
},
|
|
15433
|
+
{
|
|
15434
|
+
"flags": "--json",
|
|
15435
|
+
"description": "JSON on stdout (always)",
|
|
15436
|
+
"hidden": false
|
|
15437
|
+
}
|
|
15438
|
+
],
|
|
15439
|
+
"subcommands": []
|
|
15440
|
+
},
|
|
15286
15441
|
{
|
|
15287
15442
|
"name": "_spawn-envelope-repair",
|
|
15288
15443
|
"description": "",
|
|
@@ -11,6 +11,8 @@ import { commandExists, delegateDiagnosticPath, isRecord, jsonAt, jqFallback, jq
|
|
|
11
11
|
import { resolveLiveRoot } from "../utils/hq-roots.js";
|
|
12
12
|
import { ACL_SOURCE_DISPLAY_LABELS } from "../utils/files-browse-acl.js";
|
|
13
13
|
import { runBundledScript } from "../utils/run-bundled-script.js";
|
|
14
|
+
import { resolveWindowsBash } from "../utils/windows-bash.js";
|
|
15
|
+
import { createShellCompatibleJqInvoker } from "../utils/jq-windows-compat.js";
|
|
14
16
|
const FLAG = "core-native-delegate";
|
|
15
17
|
const ASSETS = {
|
|
16
18
|
bundle: "core/scripts/hq-delegate-bundle.sh",
|
|
@@ -367,6 +369,13 @@ function runBundle(args, context, onMalformedWhoami) {
|
|
|
367
369
|
function runHq(args, context, stdout = "capture") {
|
|
368
370
|
return subprocess("hq", args, context.cwd, { stdout });
|
|
369
371
|
}
|
|
372
|
+
const runJq = createShellCompatibleJqInvoker((args, input, cwd, options) => subprocess("jq", args, cwd, { input, ...options }), process.platform, process.env, (cwd) => {
|
|
373
|
+
const bash = resolveWindowsBash(process.env).executable;
|
|
374
|
+
if (!bash)
|
|
375
|
+
return undefined;
|
|
376
|
+
const result = subprocess(bash, ["-c", "printf '%s' \"$OSTYPE\""], cwd, { stderr: "ignore" });
|
|
377
|
+
return result.code === 0 ? result.stdout?.trim() : undefined;
|
|
378
|
+
});
|
|
370
379
|
function commandSubstitutionBytes(value) {
|
|
371
380
|
const bytes = value.stdoutBytes ?? Buffer.from(value.stdout ?? "");
|
|
372
381
|
let end = bytes.length;
|
|
@@ -377,11 +386,15 @@ function commandSubstitutionBytes(value) {
|
|
|
377
386
|
function emitJqParseDiagnostic(input, args, context) {
|
|
378
387
|
if (!commandExists("jq", context.cwd))
|
|
379
388
|
return;
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
389
|
+
// cmd.exe cannot pass CR, LF, or NUL inside an argument. jq treats line
|
|
390
|
+
// breaks between tokens as whitespace, and these fixed filters contain no
|
|
391
|
+
// multiline string literals, so send the program as one argument on Windows.
|
|
392
|
+
const jqArgs = [...args];
|
|
393
|
+
const programIndex = jqArgs.length - 1;
|
|
394
|
+
if (programIndex >= 0)
|
|
395
|
+
jqArgs[programIndex] = (jqArgs[programIndex] ?? "").replace(/[\r\n\0]+/gu, " ");
|
|
396
|
+
const result = runJq(jqArgs, input, context.cwd, { stdout: "ignore", stderr: "pipe" });
|
|
397
|
+
const diagnostic = result.stderrBytes ?? Buffer.from(result.stderr ?? "");
|
|
385
398
|
if (diagnostic.length)
|
|
386
399
|
err(diagnostic);
|
|
387
400
|
}
|
|
@@ -13,6 +13,20 @@ export function registerCoreDeriveTriggerFactsCommand(core) {
|
|
|
13
13
|
.helpOption(false)
|
|
14
14
|
.argument("[args...]")
|
|
15
15
|
.action(async (args = [], _options, commandContext) => {
|
|
16
|
+
if (process.env.HQ_CORE_STDIN_CLOSED === "1") {
|
|
17
|
+
const root = liveRoot();
|
|
18
|
+
const result = runBundledScript({
|
|
19
|
+
asset: DERIVE_TRIGGER_FACTS_ASSET,
|
|
20
|
+
args: commandContext.args.length ? commandContext.args : args,
|
|
21
|
+
cwd: root,
|
|
22
|
+
hqRoot: root,
|
|
23
|
+
msysScriptPath: process.platform === "win32",
|
|
24
|
+
closeStdin: true,
|
|
25
|
+
});
|
|
26
|
+
if (result.code !== 0)
|
|
27
|
+
process.exit(result.code);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
16
30
|
if (!await coreNativeHookHelpersEnabled()) {
|
|
17
31
|
const root = liveRoot();
|
|
18
32
|
const stdin = process.platform === "win32" ? await readStdin() : undefined;
|
|
@@ -20,4 +20,5 @@ export declare function commandOnPath(command: string, env: Record<string, strin
|
|
|
20
20
|
/** Run the native handler contract, retaining exact bytes for differential tests. */
|
|
21
21
|
export declare function runDeriveTriggerFacts(options: DeriveTriggerRunOptions): DeriveTriggerRunResult;
|
|
22
22
|
export declare function runDeriveTriggerFactsFast(argv: readonly string[], stdin: string, cwd: string, hqRoot: string | undefined): number;
|
|
23
|
+
export declare function runDeriveTriggerFactsFastResult(argv: readonly string[], stdin: string, cwd: string, hqRoot: string | undefined): DeriveTriggerRunResult;
|
|
23
24
|
//# sourceMappingURL=core-derive-trigger-facts-native.d.ts.map
|
|
@@ -583,11 +583,30 @@ export function runDeriveTriggerFacts(options) {
|
|
|
583
583
|
}
|
|
584
584
|
}
|
|
585
585
|
export function runDeriveTriggerFactsFast(argv, stdin, cwd, hqRoot) {
|
|
586
|
-
const result =
|
|
586
|
+
const result = runDeriveTriggerFactsFastResult(argv, stdin, cwd, hqRoot);
|
|
587
587
|
if (result.stdout.length)
|
|
588
588
|
process.stdout.write(result.stdout);
|
|
589
589
|
if (result.stderr.length)
|
|
590
590
|
process.stderr.write(result.stderr);
|
|
591
591
|
return result.code;
|
|
592
592
|
}
|
|
593
|
+
export function runDeriveTriggerFactsFastResult(argv, stdin, cwd, hqRoot) {
|
|
594
|
+
if (process.env.HQ_CORE_STDIN_CLOSED === "1") {
|
|
595
|
+
const result = runBundledScript({
|
|
596
|
+
asset: DERIVE_TRIGGER_FACTS_ASSET,
|
|
597
|
+
args: [...argv],
|
|
598
|
+
cwd,
|
|
599
|
+
hqRoot: hqRoot ?? cwd,
|
|
600
|
+
msysScriptPath: process.platform === "win32",
|
|
601
|
+
closeStdin: true,
|
|
602
|
+
captureOutput: true,
|
|
603
|
+
});
|
|
604
|
+
return {
|
|
605
|
+
code: result.code,
|
|
606
|
+
stdout: result.stdout ?? Buffer.alloc(0),
|
|
607
|
+
stderr: result.stderr ?? Buffer.alloc(0),
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
return runDeriveTriggerFacts({ argv, stdin, cwd, hqRoot: hqRoot ?? cwd });
|
|
611
|
+
}
|
|
593
612
|
//# sourceMappingURL=core-derive-trigger-facts-native.js.map
|
|
@@ -119,6 +119,7 @@ export interface RunDoctorResult {
|
|
|
119
119
|
* read; all other default tiers remain local unless explicitly opted in.
|
|
120
120
|
*/
|
|
121
121
|
export declare function runDoctor(options?: RunDoctorOptions): Promise<RunDoctorResult>;
|
|
122
|
+
export declare function createClientHealthReasonCodeCompanyResolver(hqRoot: string): (companySlug: string | null) => Promise<boolean>;
|
|
122
123
|
export declare function createClientHealthCheckStatusCompanyResolver(hqRoot: string): (companySlug: string | null) => Promise<boolean>;
|
|
123
124
|
/** Register the top-level `hq doctor` command so it appears in `hq --help`. */
|
|
124
125
|
export declare function registerDoctorCommand(program: Command): void;
|
package/dist/commands/doctor.js
CHANGED
|
@@ -207,7 +207,14 @@ async function resolveClientHealthReasonCodesCheckIds(families, resolveForCompan
|
|
|
207
207
|
continue;
|
|
208
208
|
}
|
|
209
209
|
const scoped = /^sync\.(?:journal|manifest)\.(.+)$/.exec(result.checkId);
|
|
210
|
-
const
|
|
210
|
+
const companyUidScope = scoped
|
|
211
|
+
? /^company:(cmp_[A-Za-z0-9]{3,128})$/.exec(scoped[1])
|
|
212
|
+
: null;
|
|
213
|
+
const companySlug = companyUidScope
|
|
214
|
+
? `company:${companyUidScope[1]}`
|
|
215
|
+
: scoped && isCompanyJournalSlug(scoped[1])
|
|
216
|
+
? scoped[1]
|
|
217
|
+
: null;
|
|
211
218
|
const checkIds = checksByCompany.get(companySlug) ?? [];
|
|
212
219
|
checkIds.push(result.checkId);
|
|
213
220
|
checksByCompany.set(companySlug, checkIds);
|
|
@@ -254,12 +261,18 @@ async function resolveClientHealthCheckStatusCheckIds(families, resolveForCompan
|
|
|
254
261
|
}
|
|
255
262
|
return enabledChecks;
|
|
256
263
|
}
|
|
257
|
-
function createClientHealthReasonCodeCompanyResolver(hqRoot) {
|
|
264
|
+
export function createClientHealthReasonCodeCompanyResolver(hqRoot) {
|
|
258
265
|
const companies = readCompaniesManifestMap(hqRoot);
|
|
259
266
|
return async (companySlug) => {
|
|
260
267
|
if (companySlug === null) {
|
|
261
268
|
return isActiveCompanyClientHealthReasonCodesEnabled();
|
|
262
269
|
}
|
|
270
|
+
const scopedCompanyUid = /^company:(cmp_[A-Za-z0-9]{3,128})$/.exec(companySlug);
|
|
271
|
+
if (scopedCompanyUid) {
|
|
272
|
+
return clientHealthReasonCodesEnabledForCompany({
|
|
273
|
+
companyUid: scopedCompanyUid[1],
|
|
274
|
+
});
|
|
275
|
+
}
|
|
263
276
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(companySlug)) {
|
|
264
277
|
return false;
|
|
265
278
|
}
|
|
@@ -2,12 +2,15 @@ import type { Command } from "commander";
|
|
|
2
2
|
import { type TrackerCheckTeam } from "../lib/lanes/tracker-checks.js";
|
|
3
3
|
import { type TrackerKind, type TrackerRecord } from "../lib/lanes/tracker-store.js";
|
|
4
4
|
import type { LaneRecord, LaneCompanyRef, QuestionRecord } from "../lib/lanes/types.js";
|
|
5
|
+
import { type ReapDeps } from "../lib/lanes/reaper.js";
|
|
5
6
|
export interface LaneChecksDeps {
|
|
6
7
|
hqRoot: () => string;
|
|
7
8
|
resolveCompany: (company?: string) => Promise<LaneCompanyRef>;
|
|
8
9
|
now: () => Date;
|
|
9
10
|
stopLane?: (laneId: string, reason: string) => Promise<void>;
|
|
10
11
|
sessionState?: (root: string, sessionId: string, now: Date) => string | null;
|
|
12
|
+
stopEnabled?: (lane: LaneRecord) => Promise<boolean> | boolean;
|
|
13
|
+
reaperDeps?: Partial<ReapDeps>;
|
|
11
14
|
}
|
|
12
15
|
type WrapHandler = <Args extends unknown[]>(action: (...args: Args) => Promise<void>) => (...args: Args) => Promise<void>;
|
|
13
16
|
export interface ProjectMapping {
|