@indigoai-us/hq-cli 5.293.0 → 5.294.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.
- package/CHANGELOG.md +14 -0
- package/assets/scaffold/core/scripts/outpost-jobs-reconcile.sh +5 -1
- package/dist/command-catalog.generated.d.ts +42 -24
- package/dist/command-catalog.generated.js +53 -30
- package/dist/commands/core-command-catalog.js +3 -2
- package/dist/commands/core-delegate-w1b.d.ts +2 -0
- package/dist/commands/core-delegate-w1b.js +28 -2
- package/dist/commands/core-delegate.d.ts +3 -1
- package/dist/commands/core-delegate.js +35 -5
- package/dist/commands/core-handoff-fast.d.ts +18 -0
- package/dist/commands/core-handoff-fast.js +103 -0
- package/dist/commands/core-handoff-open-steps.d.ts +21 -0
- package/dist/commands/core-handoff-open-steps.js +264 -0
- package/dist/commands/core-handoff.d.ts +4 -2
- package/dist/commands/core-handoff.js +22 -249
- package/dist/commands/core-jobs-native.d.ts +2 -0
- package/dist/commands/core-jobs-native.js +22 -11
- package/dist/commands/core-knowledge-prefs.d.ts +2 -0
- package/dist/commands/core-knowledge-prefs.js +13 -1
- package/dist/commands/core-ontology-native.d.ts +2 -0
- package/dist/commands/core-ontology-native.js +22 -2
- package/dist/commands/core-policy.d.ts +2 -0
- package/dist/commands/core-policy.js +18 -1
- package/dist/commands/core.js +2 -1
- package/dist/commands/daemon.d.ts +2 -1
- package/dist/commands/daemon.js +22 -7
- package/dist/commands/lanes-autopilot.d.ts +11 -0
- package/dist/commands/lanes-autopilot.js +336 -0
- package/dist/commands/lanes-questions.js +8 -5
- package/dist/commands/lanes-shared.d.ts +17 -0
- package/dist/commands/lanes-stories.d.ts +14 -0
- package/dist/commands/lanes-stories.js +308 -0
- package/dist/commands/lanes.js +39 -309
- package/dist/fast-core.js +53 -25
- package/dist/fast-scaffold.d.ts +15 -2
- package/dist/fast-scaffold.js +167 -7
- package/dist/lib/core-utils/worktree-resume.d.ts +2 -0
- package/dist/lib/core-utils/worktree-resume.js +16 -0
- package/dist/lib/daemon/migrate.d.ts +8 -1
- package/dist/lib/daemon/migrate.js +19 -7
- package/dist/lib/lanes/autopilot-metrics.d.ts +99 -0
- package/dist/lib/lanes/autopilot-metrics.js +301 -0
- package/dist/lib/lanes/store.d.ts +2 -0
- package/dist/lib/lanes/store.js +32 -3
- package/dist/native-fast-route.d.ts +3 -1
- package/dist/native-fast-route.js +10 -8
- package/dist/utils/contribution-table.d.ts +1 -1
- package/dist/utils/fast-stream-errors.d.ts +12 -0
- package/dist/utils/fast-stream-errors.js +18 -0
- package/dist/utils/scaffold-fast-import-guard.d.ts +2 -2
- package/dist/utils/scaffold-fast-import-guard.js +6 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.294.0] — 2026-09-30
|
|
6
|
+
|
|
7
|
+
- Split the lane story command handlers into a dedicated module without changing behavior.
|
|
8
|
+
- On a box, `sudo hq daemon migrate --apply` now finds the login user's own systemd user units (hq-mesh-daemon, hq-lanes-reconcile and the rest) and stops them through that user's systemd manager. `sudo hq daemon uninstall --restore-legacy` restarts them the same way. Before, root looked only in its own home and could not reach the login user's manager.
|
|
9
|
+
|
|
5
10
|
## [5.293.0] — 2026-09-30
|
|
6
11
|
- [HQ-CLI-HOOK-TIMEOUT-KIND] Group hook timeout events by normalized kind (`warning` or `exceeded`) across scripts; keep script and platform tags for triage. Existing per-script issues will stop receiving new events, and the lead handles their status.
|
|
7
12
|
- `hq lanes move` now reports an already-on-target no-op without dispatching or changing the queued lane.
|
|
13
|
+
- Keep bundled scheduled-job reconciliation units on the live scaffold runner, and preserve caller spelling in job-validation paths.
|
|
8
14
|
- On Linux, `hq daemon run` sets XDG_RUNTIME_DIR for its services when the system unit left it unset, so `systemctl --user` from jobs-reconcile no longer fails with "Failed to connect to bus: No medium found".
|
|
9
15
|
|
|
10
16
|
- With the default-off lanes.keep-alive-resume-blocked gate enabled, reconcile
|
|
@@ -18,13 +24,21 @@
|
|
|
18
24
|
- Preserve empty directory paths and modes in recorded corpus cases. The recorder rejects tree entries the case format cannot replay, and CI checks committed snapshots after a clean Git archive extraction.
|
|
19
25
|
- Cross-Outpost resume and hire-grant dispatch verify the senior from the
|
|
20
26
|
senior's owning Outpost before signing the caller's grant context.
|
|
27
|
+
- Run the no-Hermes source guard with the required Changelog gate in one runner job.
|
|
21
28
|
|
|
22
29
|
### Added
|
|
23
30
|
|
|
31
|
+
- Add the read-only `hq lanes autopilot report` metrics command for operator nudges, review latency, idle capacity with ready work, and nudge defects.
|
|
32
|
+
|
|
24
33
|
- Add `hq lanes ask --priority P0|P1|P2` and show question urgency in the queue; warn when omitted during the compatibility release.
|
|
34
|
+
- Route ported native hq core commands through the fast-startup gate while preserving each family's bundled shell fallback.
|
|
25
35
|
|
|
26
36
|
### Fixed
|
|
27
37
|
|
|
38
|
+
- Skip malformed remote lane mirrors with a lane and field warning while
|
|
39
|
+
keeping local lane validation strict. Refresh mirror queue reason and details
|
|
40
|
+
from one owner snapshot.
|
|
41
|
+
- Primary-side Outpost question show and answer skip the current Outpost during owner lookup. Remote answers require the lane senior; when the owner is reachable, an unrelated unavailable Outpost is returned as `lookup_errors` without blocking the answer.
|
|
28
42
|
- CI-only: keep the same-binary Node control case measured without applying performance regression thresholds.
|
|
29
43
|
- Fix npm global self-updates, which have failed with MODULE_NOT_FOUND since 5.290.0. The update moved the hq-cli package aside and then started its installer through a supervisor script inside that package. It now runs the installer through a copy of the supervisor outside the package.
|
|
30
44
|
|
|
@@ -39,7 +39,6 @@ set -euo pipefail
|
|
|
39
39
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
40
40
|
HQ_ROOT="${HQ_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
41
41
|
VALIDATE="$SCRIPT_DIR/jobs-validate.sh"
|
|
42
|
-
RUNNER="$SCRIPT_DIR/hq-job-run.sh"
|
|
43
42
|
PROBE="$SCRIPT_DIR/hq-job-probe.sh"
|
|
44
43
|
|
|
45
44
|
DRY_RUN=0
|
|
@@ -99,6 +98,11 @@ while [ $# -gt 0 ]; do
|
|
|
99
98
|
esac
|
|
100
99
|
done
|
|
101
100
|
|
|
101
|
+
# The shell script is also bundled inside hq-cli. Its own SCRIPT_DIR then
|
|
102
|
+
# points into the npm package, while job units must always target the live
|
|
103
|
+
# scaffold forwarder so they survive CLI upgrades and Node switches.
|
|
104
|
+
RUNNER="$HQ_ROOT/core/scripts/hq-job-run.sh"
|
|
105
|
+
|
|
102
106
|
command -v yq >/dev/null 2>&1 || die "yq is required (mikefarah/yq)"
|
|
103
107
|
command -v jq >/dev/null 2>&1 || die "jq is required"
|
|
104
108
|
[ -x "$VALIDATE" ] || [ -f "$VALIDATE" ] || die "missing jobs-validate.sh"
|
|
@@ -7769,6 +7769,48 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
7769
7769
|
readonly description: "Print the KR freshness report as JSON";
|
|
7770
7770
|
}];
|
|
7771
7771
|
readonly subcommands: readonly [];
|
|
7772
|
+
}, {
|
|
7773
|
+
readonly name: "autopilot";
|
|
7774
|
+
readonly description: "Run lead autopilot checks and report follow-through metrics";
|
|
7775
|
+
readonly aliases: readonly [];
|
|
7776
|
+
readonly hidden: false;
|
|
7777
|
+
readonly usage: "[options] [command]";
|
|
7778
|
+
readonly arguments: readonly [];
|
|
7779
|
+
readonly options: readonly [];
|
|
7780
|
+
readonly subcommands: readonly [{
|
|
7781
|
+
readonly name: "report";
|
|
7782
|
+
readonly description: "Report operator nudges, review latency, and idle slots with ready work";
|
|
7783
|
+
readonly aliases: readonly [];
|
|
7784
|
+
readonly hidden: false;
|
|
7785
|
+
readonly usage: "[options]";
|
|
7786
|
+
readonly arguments: readonly [];
|
|
7787
|
+
readonly options: readonly [{
|
|
7788
|
+
readonly flags: "--since <iso>";
|
|
7789
|
+
readonly description: "Include activity since this ISO timestamp";
|
|
7790
|
+
}, {
|
|
7791
|
+
readonly flags: "--days <n>";
|
|
7792
|
+
readonly description: "Include the most recent number of days";
|
|
7793
|
+
}, {
|
|
7794
|
+
readonly flags: "--json";
|
|
7795
|
+
readonly description: "Print JSON";
|
|
7796
|
+
}];
|
|
7797
|
+
readonly subcommands: readonly [];
|
|
7798
|
+
}, {
|
|
7799
|
+
readonly name: "run";
|
|
7800
|
+
readonly description: "Run one lead autopilot check pass";
|
|
7801
|
+
readonly aliases: readonly [];
|
|
7802
|
+
readonly hidden: false;
|
|
7803
|
+
readonly usage: "[options]";
|
|
7804
|
+
readonly arguments: readonly [];
|
|
7805
|
+
readonly options: readonly [{
|
|
7806
|
+
readonly flags: "--dry-run";
|
|
7807
|
+
readonly description: "Report proposed wakes without writing them";
|
|
7808
|
+
}, {
|
|
7809
|
+
readonly flags: "--json";
|
|
7810
|
+
readonly description: "Emit JSON on stdout (default)";
|
|
7811
|
+
}];
|
|
7812
|
+
readonly subcommands: readonly [];
|
|
7813
|
+
}];
|
|
7772
7814
|
}, {
|
|
7773
7815
|
readonly name: "create";
|
|
7774
7816
|
readonly description: "Register a lane, run admission, and return immediately";
|
|
@@ -8992,30 +9034,6 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
8992
9034
|
readonly description: "JSON on stdout (always)";
|
|
8993
9035
|
}];
|
|
8994
9036
|
readonly subcommands: readonly [];
|
|
8995
|
-
}, {
|
|
8996
|
-
readonly name: "autopilot";
|
|
8997
|
-
readonly description: "Check registered team leads and wake them for ready work";
|
|
8998
|
-
readonly aliases: readonly [];
|
|
8999
|
-
readonly hidden: false;
|
|
9000
|
-
readonly usage: "[options] [command]";
|
|
9001
|
-
readonly arguments: readonly [];
|
|
9002
|
-
readonly options: readonly [];
|
|
9003
|
-
readonly subcommands: readonly [{
|
|
9004
|
-
readonly name: "run";
|
|
9005
|
-
readonly description: "Run one lead autopilot check pass";
|
|
9006
|
-
readonly aliases: readonly [];
|
|
9007
|
-
readonly hidden: false;
|
|
9008
|
-
readonly usage: "[options]";
|
|
9009
|
-
readonly arguments: readonly [];
|
|
9010
|
-
readonly options: readonly [{
|
|
9011
|
-
readonly flags: "--dry-run";
|
|
9012
|
-
readonly description: "Report proposed wakes without writing them";
|
|
9013
|
-
}, {
|
|
9014
|
-
readonly flags: "--json";
|
|
9015
|
-
readonly description: "Emit JSON on stdout (default)";
|
|
9016
|
-
}];
|
|
9017
|
-
readonly subcommands: readonly [];
|
|
9018
|
-
}];
|
|
9019
9037
|
}, {
|
|
9020
9038
|
readonly name: "reconcile";
|
|
9021
9039
|
readonly description: "Run one machine-owned reconcile pass and exit";
|
|
@@ -10013,6 +10013,59 @@ export const COMMAND_CATALOG = [
|
|
|
10013
10013
|
],
|
|
10014
10014
|
"subcommands": []
|
|
10015
10015
|
},
|
|
10016
|
+
{
|
|
10017
|
+
"name": "autopilot",
|
|
10018
|
+
"description": "Run lead autopilot checks and report follow-through metrics",
|
|
10019
|
+
"aliases": [],
|
|
10020
|
+
"hidden": false,
|
|
10021
|
+
"usage": "[options] [command]",
|
|
10022
|
+
"arguments": [],
|
|
10023
|
+
"options": [],
|
|
10024
|
+
"subcommands": [
|
|
10025
|
+
{
|
|
10026
|
+
"name": "report",
|
|
10027
|
+
"description": "Report operator nudges, review latency, and idle slots with ready work",
|
|
10028
|
+
"aliases": [],
|
|
10029
|
+
"hidden": false,
|
|
10030
|
+
"usage": "[options]",
|
|
10031
|
+
"arguments": [],
|
|
10032
|
+
"options": [
|
|
10033
|
+
{
|
|
10034
|
+
"flags": "--since <iso>",
|
|
10035
|
+
"description": "Include activity since this ISO timestamp"
|
|
10036
|
+
},
|
|
10037
|
+
{
|
|
10038
|
+
"flags": "--days <n>",
|
|
10039
|
+
"description": "Include the most recent number of days"
|
|
10040
|
+
},
|
|
10041
|
+
{
|
|
10042
|
+
"flags": "--json",
|
|
10043
|
+
"description": "Print JSON"
|
|
10044
|
+
}
|
|
10045
|
+
],
|
|
10046
|
+
"subcommands": []
|
|
10047
|
+
},
|
|
10048
|
+
{
|
|
10049
|
+
"name": "run",
|
|
10050
|
+
"description": "Run one lead autopilot check pass",
|
|
10051
|
+
"aliases": [],
|
|
10052
|
+
"hidden": false,
|
|
10053
|
+
"usage": "[options]",
|
|
10054
|
+
"arguments": [],
|
|
10055
|
+
"options": [
|
|
10056
|
+
{
|
|
10057
|
+
"flags": "--dry-run",
|
|
10058
|
+
"description": "Report proposed wakes without writing them"
|
|
10059
|
+
},
|
|
10060
|
+
{
|
|
10061
|
+
"flags": "--json",
|
|
10062
|
+
"description": "Emit JSON on stdout (default)"
|
|
10063
|
+
}
|
|
10064
|
+
],
|
|
10065
|
+
"subcommands": []
|
|
10066
|
+
}
|
|
10067
|
+
]
|
|
10068
|
+
},
|
|
10016
10069
|
{
|
|
10017
10070
|
"name": "create",
|
|
10018
10071
|
"description": "Register a lane, run admission, and return immediately",
|
|
@@ -11608,36 +11661,6 @@ export const COMMAND_CATALOG = [
|
|
|
11608
11661
|
],
|
|
11609
11662
|
"subcommands": []
|
|
11610
11663
|
},
|
|
11611
|
-
{
|
|
11612
|
-
"name": "autopilot",
|
|
11613
|
-
"description": "Check registered team leads and wake them for ready work",
|
|
11614
|
-
"aliases": [],
|
|
11615
|
-
"hidden": false,
|
|
11616
|
-
"usage": "[options] [command]",
|
|
11617
|
-
"arguments": [],
|
|
11618
|
-
"options": [],
|
|
11619
|
-
"subcommands": [
|
|
11620
|
-
{
|
|
11621
|
-
"name": "run",
|
|
11622
|
-
"description": "Run one lead autopilot check pass",
|
|
11623
|
-
"aliases": [],
|
|
11624
|
-
"hidden": false,
|
|
11625
|
-
"usage": "[options]",
|
|
11626
|
-
"arguments": [],
|
|
11627
|
-
"options": [
|
|
11628
|
-
{
|
|
11629
|
-
"flags": "--dry-run",
|
|
11630
|
-
"description": "Report proposed wakes without writing them"
|
|
11631
|
-
},
|
|
11632
|
-
{
|
|
11633
|
-
"flags": "--json",
|
|
11634
|
-
"description": "Emit JSON on stdout (default)"
|
|
11635
|
-
}
|
|
11636
|
-
],
|
|
11637
|
-
"subcommands": []
|
|
11638
|
-
}
|
|
11639
|
-
]
|
|
11640
|
-
},
|
|
11641
11664
|
{
|
|
11642
11665
|
"name": "reconcile",
|
|
11643
11666
|
"description": "Run one machine-owned reconcile pass and exit",
|
|
@@ -46,8 +46,9 @@ export function fastScaffoldListingMismatches(listing, fastScripts) {
|
|
|
46
46
|
else if (fast.kind === "shell" && listed.asset !== fast.asset) {
|
|
47
47
|
mismatches.push(`${fast.name} lists ${listed.asset ?? "no asset"}, fast path uses ${fast.asset ?? "no asset"}`);
|
|
48
48
|
}
|
|
49
|
-
else if (fast.kind === "native" && (listed.execution !== "native" ||
|
|
50
|
-
|
|
49
|
+
else if (fast.kind === "native" && (listed.execution !== "native" ||
|
|
50
|
+
(fast.asset === undefined ? listed.asset !== undefined : listed.asset !== fast.asset))) {
|
|
51
|
+
mismatches.push(`${fast.name} has fast-route metadata that differs from the native command catalog`);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
return mismatches;
|
|
@@ -3,6 +3,8 @@ import { Command } from "commander";
|
|
|
3
3
|
import { type DelegateContext } from "./core-delegate.js";
|
|
4
4
|
type W1bName = "bundle" | "grant" | "publish" | "send" | "verify";
|
|
5
5
|
export declare function runNativeDelegateW1b(name: W1bName, args: string[], context: DelegateContext): number;
|
|
6
|
+
/** Fast-entry adapter; the shared family flag is resolved before this module loads. */
|
|
7
|
+
export declare function runDelegateW1bFast(args: readonly string[], _stdin: string, _cwd: string, hqRoot: string | undefined, commandName: string): number;
|
|
6
8
|
export declare function registerCoreDelegateW1b(delegate: Command, core: Command): void;
|
|
7
9
|
export {};
|
|
8
10
|
//# sourceMappingURL=core-delegate-w1b.d.ts.map
|
|
@@ -5,7 +5,6 @@ import * as os from "node:os";
|
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { serializeJqJson } from "../lib/core-utils/jq-json-serializer.js";
|
|
7
7
|
import { matchingSecretPatterns } from "../lib/core-utils/secret-patterns.js";
|
|
8
|
-
import { resolveProcessFlagGate } from "../lib/flag-registry.js";
|
|
9
8
|
import { describeCoreCommand } from "./core-command-catalog.js";
|
|
10
9
|
import { isRecord, jsonAt, jqFallback, jqRawPath, jqRawPaths, moveFile, readJsonFile, subprocess, writeJsonAtomically, } from "./core-delegate.js";
|
|
11
10
|
import { resolveLiveRoot } from "../utils/hq-roots.js";
|
|
@@ -1004,6 +1003,32 @@ export function runNativeDelegateW1b(name, args, context) {
|
|
|
1004
1003
|
case "verify": return runVerify(args, context);
|
|
1005
1004
|
}
|
|
1006
1005
|
}
|
|
1006
|
+
/** Fast-entry adapter; the shared family flag is resolved before this module loads. */
|
|
1007
|
+
export function runDelegateW1bFast(args, _stdin, _cwd, hqRoot, commandName) {
|
|
1008
|
+
const root = hqRoot ?? resolveLiveRoot();
|
|
1009
|
+
const context = { cwd: root, root };
|
|
1010
|
+
const saved = new Map();
|
|
1011
|
+
for (const key of ["HQ_ROOT", "CLAUDE_PROJECT_DIR", "PWD"])
|
|
1012
|
+
saved.set(key, process.env[key]);
|
|
1013
|
+
process.env.HQ_ROOT = root;
|
|
1014
|
+
process.env.CLAUDE_PROJECT_DIR = root;
|
|
1015
|
+
process.env.PWD = root;
|
|
1016
|
+
let code;
|
|
1017
|
+
try {
|
|
1018
|
+
code = runNativeDelegateW1b(commandName, [...args], context);
|
|
1019
|
+
}
|
|
1020
|
+
finally {
|
|
1021
|
+
for (const [key, value] of saved) {
|
|
1022
|
+
if (value === undefined)
|
|
1023
|
+
delete process.env[key];
|
|
1024
|
+
else
|
|
1025
|
+
process.env[key] = value;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (code !== 0)
|
|
1029
|
+
process.exitCode = code;
|
|
1030
|
+
return code;
|
|
1031
|
+
}
|
|
1007
1032
|
export function registerCoreDelegateW1b(delegate, core) {
|
|
1008
1033
|
for (const name of ["bundle", "grant", "publish", "send", "verify"]) {
|
|
1009
1034
|
const command = delegate.command(name)
|
|
@@ -1012,10 +1037,11 @@ export function registerCoreDelegateW1b(delegate, core) {
|
|
|
1012
1037
|
.allowExcessArguments()
|
|
1013
1038
|
.helpOption(false)
|
|
1014
1039
|
.argument("[args...]", "arguments accepted for shell ABI compatibility")
|
|
1015
|
-
.action((args = []) => {
|
|
1040
|
+
.action(async (args = []) => {
|
|
1016
1041
|
const options = core.opts();
|
|
1017
1042
|
const root = resolveLiveRoot({ hqRoot: options.hqRoot });
|
|
1018
1043
|
const context = { cwd: root, root };
|
|
1044
|
+
const { resolveProcessFlagGate } = await import("../lib/flag-registry.js");
|
|
1019
1045
|
if (!resolveProcessFlagGate(FLAG, { fallback: false }, () => false)) {
|
|
1020
1046
|
const result = runBundledScript({ asset: ASSETS[name], args, cwd: root, hqRoot: root });
|
|
1021
1047
|
if (result.code !== 0)
|
|
@@ -28,7 +28,9 @@ export declare function jqRawPaths(value: unknown, dottedPaths: string[], fallba
|
|
|
28
28
|
export declare function requireRecord(value: unknown, property: string): JsonRecord;
|
|
29
29
|
export declare function moveFile(source: string, target: string): void;
|
|
30
30
|
export declare function writeJsonAtomically(target: string, value: unknown, siblingTemp?: boolean): void;
|
|
31
|
+
/** Fast-entry adapter; family gating and shell fallback happen before import. */
|
|
32
|
+
export declare function runDelegateFast(args: readonly string[], _stdin: string, cwd: string, hqRoot: string | undefined, commandName: string): number;
|
|
31
33
|
/** Register the Wave 1a delegate commands and preserve the shell rollback path. */
|
|
32
|
-
export declare function registerCoreDelegateCommand(core: Command): void;
|
|
34
|
+
export declare function registerCoreDelegateCommand(core: Command, registerWave1b?: (delegate: Command, core: Command) => void): void;
|
|
33
35
|
export {};
|
|
34
36
|
//# sourceMappingURL=core-delegate.d.ts.map
|
|
@@ -4,11 +4,9 @@ import * as fs from "node:fs";
|
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { serializeJqJson } from "../lib/core-utils/jq-json-serializer.js";
|
|
7
|
-
import { resolveProcessFlagGate } from "../lib/flag-registry.js";
|
|
8
7
|
import { describeCoreCommand } from "./core-command-catalog.js";
|
|
9
8
|
import { resolveLiveRoot } from "../utils/hq-roots.js";
|
|
10
9
|
import { runBundledScript } from "../utils/run-bundled-script.js";
|
|
11
|
-
import { registerCoreDelegateW1b } from "./core-delegate-w1b.js";
|
|
12
10
|
export const CORE_NATIVE_DELEGATE_FLAG = "core-native-delegate";
|
|
13
11
|
const SCRIPT_ASSETS = {
|
|
14
12
|
resolve: "core/scripts/hq-delegate-resolve.sh",
|
|
@@ -936,8 +934,39 @@ function runNative(name, args, context) {
|
|
|
936
934
|
case "transfer": return runTransfer(args, context);
|
|
937
935
|
}
|
|
938
936
|
}
|
|
937
|
+
/** Fast-entry adapter; family gating and shell fallback happen before import. */
|
|
938
|
+
export function runDelegateFast(args, _stdin, cwd, hqRoot, commandName) {
|
|
939
|
+
const name = commandName;
|
|
940
|
+
const context = name === "pickup"
|
|
941
|
+
? { cwd }
|
|
942
|
+
: (() => { const root = hqRoot ?? resolveLiveRoot(); return { cwd: root, root }; })();
|
|
943
|
+
const savedEnvironment = new Map();
|
|
944
|
+
if (context.root) {
|
|
945
|
+
for (const key of ["HQ_ROOT", "CLAUDE_PROJECT_DIR", "PWD"]) {
|
|
946
|
+
savedEnvironment.set(key, process.env[key]);
|
|
947
|
+
}
|
|
948
|
+
process.env.HQ_ROOT = context.root;
|
|
949
|
+
process.env.CLAUDE_PROJECT_DIR = context.root;
|
|
950
|
+
process.env.PWD = context.cwd;
|
|
951
|
+
}
|
|
952
|
+
let code;
|
|
953
|
+
try {
|
|
954
|
+
code = runNative(name, [...args], context);
|
|
955
|
+
}
|
|
956
|
+
finally {
|
|
957
|
+
for (const [key, value] of savedEnvironment) {
|
|
958
|
+
if (value === undefined)
|
|
959
|
+
delete process.env[key];
|
|
960
|
+
else
|
|
961
|
+
process.env[key] = value;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
if (code !== 0)
|
|
965
|
+
process.exitCode = code;
|
|
966
|
+
return code;
|
|
967
|
+
}
|
|
939
968
|
/** Register the Wave 1a delegate commands and preserve the shell rollback path. */
|
|
940
|
-
export function registerCoreDelegateCommand(core) {
|
|
969
|
+
export function registerCoreDelegateCommand(core, registerWave1b) {
|
|
941
970
|
const delegate = core.command("delegate").description("Delegation handover helpers");
|
|
942
971
|
for (const name of ["resolve", "pickup", "repo", "secrets", "transfer"]) {
|
|
943
972
|
const rootMode = name === "pickup" ? "cwd" : "live";
|
|
@@ -947,11 +976,12 @@ export function registerCoreDelegateCommand(core) {
|
|
|
947
976
|
.allowExcessArguments()
|
|
948
977
|
.helpOption(false)
|
|
949
978
|
.argument("[args...]", "arguments accepted for shell ABI compatibility")
|
|
950
|
-
.action((args = []) => {
|
|
979
|
+
.action(async (args = []) => {
|
|
951
980
|
const scope = core.opts();
|
|
952
981
|
const context = rootMode === "cwd"
|
|
953
982
|
? { cwd: process.cwd() }
|
|
954
983
|
: (() => { const root = resolveLiveRoot({ hqRoot: scope.hqRoot }); return { cwd: root, root }; })();
|
|
984
|
+
const { resolveProcessFlagGate } = await import("../lib/flag-registry.js");
|
|
955
985
|
if (!resolveProcessFlagGate(CORE_NATIVE_DELEGATE_FLAG, { fallback: false }, () => false)) {
|
|
956
986
|
const result = runBundledScript({ asset: SCRIPT_ASSETS[name], args, cwd: context.cwd, hqRoot: context.root });
|
|
957
987
|
if (result.code !== 0)
|
|
@@ -984,6 +1014,6 @@ export function registerCoreDelegateCommand(core) {
|
|
|
984
1014
|
});
|
|
985
1015
|
describeCoreCommand(command, { execution: "native", asset: SCRIPT_ASSETS[name], root: rootMode });
|
|
986
1016
|
}
|
|
987
|
-
|
|
1017
|
+
registerWave1b?.(delegate, core);
|
|
988
1018
|
}
|
|
989
1019
|
//# sourceMappingURL=core-delegate.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Lightweight entry adapters for the fast handoff routes. */
|
|
2
|
+
type RunResult = {
|
|
3
|
+
code: number;
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* `handoff finalize --help` is historically an unknown-argument error. Keep
|
|
9
|
+
* that fast error path out of the large handoff implementation module.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handoffFinalizeHelpResult(args: readonly string[], root: string, tmpRoot?: string): RunResult | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Keep cheap help/launch paths in this small module. Commands that do the
|
|
14
|
+
* actual handoff work load the existing implementation only when invoked.
|
|
15
|
+
*/
|
|
16
|
+
export declare function runHandoffFastEntry(args: readonly string[], stdin: string, cwd: string, hqRoot: string | undefined, commandName: string): Promise<number>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=core-handoff-fast.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Lightweight entry adapters for the fast handoff routes. */
|
|
2
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
/**
|
|
6
|
+
* `handoff finalize --help` is historically an unknown-argument error. Keep
|
|
7
|
+
* that fast error path out of the large handoff implementation module.
|
|
8
|
+
*/
|
|
9
|
+
export function handoffFinalizeHelpResult(args, root, tmpRoot = "/tmp") {
|
|
10
|
+
if (args[0] !== "--help")
|
|
11
|
+
return undefined;
|
|
12
|
+
const absoluteRoot = fs.realpathSync(root);
|
|
13
|
+
const rootEnvironment = {
|
|
14
|
+
...process.env,
|
|
15
|
+
HQ_ROOT: absoluteRoot,
|
|
16
|
+
CLAUDE_PROJECT_DIR: absoluteRoot,
|
|
17
|
+
PWD: absoluteRoot,
|
|
18
|
+
};
|
|
19
|
+
const probe = spawnSync("git", ["rev-parse", "--git-common-dir"], {
|
|
20
|
+
cwd: absoluteRoot,
|
|
21
|
+
env: { ...rootEnvironment, LC_ALL: "C" },
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
24
|
+
});
|
|
25
|
+
if (!probe.error && probe.status === 0) {
|
|
26
|
+
// The result only determines whether later finalize work stages files. The
|
|
27
|
+
// unknown --help argument returns before that work starts.
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const output = `${String(probe.stdout ?? "")}${String(probe.stderr ?? "")}`.trimEnd();
|
|
31
|
+
const checkoutMarker = path.join(absoluteRoot, ".git");
|
|
32
|
+
if (fs.existsSync(checkoutMarker) || fs.lstatSync(checkoutMarker, { throwIfNoEntry: false })
|
|
33
|
+
|| !output.includes("not a git repository")) {
|
|
34
|
+
return {
|
|
35
|
+
code: 4,
|
|
36
|
+
stdout: "",
|
|
37
|
+
stderr: `handoff-finalize: Git checkout probe failed (exit ${probe.status ?? 127}): ${output}\n`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const gitPidFile = path.join(tmpRoot, "handoff-git-bg.pid");
|
|
42
|
+
if (fs.existsSync(gitPidFile)) {
|
|
43
|
+
try {
|
|
44
|
+
fs.rmSync(gitPidFile, { force: true });
|
|
45
|
+
}
|
|
46
|
+
catch { /* legacy cleanup is best-effort */ }
|
|
47
|
+
}
|
|
48
|
+
return { code: 2, stdout: "", stderr: "Unknown arg: --help\n" };
|
|
49
|
+
}
|
|
50
|
+
async function launchHandoffPost(args, root) {
|
|
51
|
+
return await new Promise((resolve) => {
|
|
52
|
+
try {
|
|
53
|
+
const child = spawn("hq", ["core", "--hq-root", root, "handoff", "post", ...args], {
|
|
54
|
+
cwd: root,
|
|
55
|
+
env: {
|
|
56
|
+
...process.env,
|
|
57
|
+
HQ_ROOT: root,
|
|
58
|
+
CLAUDE_PROJECT_DIR: root,
|
|
59
|
+
PWD: root,
|
|
60
|
+
HQ_NATIVE_HANDOFF_POST_CHILD: "1",
|
|
61
|
+
},
|
|
62
|
+
detached: true,
|
|
63
|
+
stdio: "ignore",
|
|
64
|
+
});
|
|
65
|
+
child.once("error", (error) => {
|
|
66
|
+
process.stderr.write(`${error.message}\n`);
|
|
67
|
+
resolve(127);
|
|
68
|
+
});
|
|
69
|
+
child.once("spawn", () => {
|
|
70
|
+
child.unref();
|
|
71
|
+
resolve(0);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
76
|
+
process.stderr.write(`${message}\n`);
|
|
77
|
+
resolve(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Keep cheap help/launch paths in this small module. Commands that do the
|
|
83
|
+
* actual handoff work load the existing implementation only when invoked.
|
|
84
|
+
*/
|
|
85
|
+
export async function runHandoffFastEntry(args, stdin, cwd, hqRoot, commandName) {
|
|
86
|
+
const root = hqRoot ?? cwd;
|
|
87
|
+
if (commandName === "post" && process.env.HQ_NATIVE_HANDOFF_POST_CHILD !== "1") {
|
|
88
|
+
return await launchHandoffPost(args, root);
|
|
89
|
+
}
|
|
90
|
+
if (commandName === "finalize") {
|
|
91
|
+
const helpResult = handoffFinalizeHelpResult(args, root);
|
|
92
|
+
if (helpResult) {
|
|
93
|
+
if (helpResult.stdout)
|
|
94
|
+
process.stdout.write(helpResult.stdout);
|
|
95
|
+
if (helpResult.stderr)
|
|
96
|
+
process.stderr.write(helpResult.stderr);
|
|
97
|
+
return helpResult.code;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const handoff = await import("./core-handoff.js");
|
|
101
|
+
return await handoff.runHandoffFast(args, stdin, cwd, root, commandName);
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=core-handoff-fast.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Lightweight native handler for the handoff open-steps helper. */
|
|
2
|
+
type RunResult = {
|
|
3
|
+
code: number;
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
};
|
|
7
|
+
type HandoffContext = {
|
|
8
|
+
root: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
now?: () => Date;
|
|
11
|
+
};
|
|
12
|
+
export declare function prettyJson(value: unknown): string;
|
|
13
|
+
export declare function compactJson(value: unknown): string;
|
|
14
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
15
|
+
export declare function jqTruthy(value: unknown): boolean;
|
|
16
|
+
export declare function shellDate(date: Date): string;
|
|
17
|
+
export declare function runHandoffOpenSteps(args: string[], context: HandoffContext): RunResult;
|
|
18
|
+
/** Fast-entry adapter for the lightweight open-steps implementation. */
|
|
19
|
+
export declare function runHandoffOpenStepsFast(args: readonly string[], _stdin: string, cwd: string, hqRoot: string | undefined): number;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=core-handoff-open-steps.d.ts.map
|