@indigoai-us/hq-cli 5.345.9 → 5.345.11
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 +6 -0
- package/assets/scaffold/core/scripts/hq-delegate-grant.sh +11 -4
- package/assets/scaffold/core/scripts/hq-delegate-send.sh +11 -4
- package/assets/scaffold/core/scripts/hq-job-probe.sh +11 -4
- package/assets/scaffold/core/scripts/jobs-validate.sh +11 -4
- package/assets/scaffold/core/scripts/session-journal.sh +3 -3
- package/dist/commands/core-delegate-w1b.js +4 -1
- package/dist/commands/core-hq-session-native.js +5 -1
- package/dist/commands/core-session-journal-native.js +2 -2
- package/dist/commands/core-session-project-native.js +2 -1
- package/dist/commands/lanes.js +52 -4
- package/dist/lib/bot/coding-tool-activity.d.ts +2 -8
- package/dist/lib/bot/coding-tool-activity.js +1 -5
- package/dist/lib/bot/setup-tool-offer.d.ts +0 -4
- package/dist/lib/bot/setup-tool-offer.js +2 -2
- package/dist/lib/checkpoint-ontology/merge-copies.d.ts +4 -3
- package/dist/lib/checkpoint-ontology/tree.d.ts +0 -1
- package/dist/lib/checkpoint-ontology/tree.js +1 -1
- package/dist/lib/core-utils/qmd-reindex-after-sync.d.ts +0 -2
- package/dist/lib/core-utils/qmd-reindex-after-sync.js +2 -2
- package/dist/lib/daemon/convergence.d.ts +0 -2
- package/dist/lib/daemon/convergence.js +2 -2
- package/dist/lib/daemon/flag-monitor.d.ts +0 -2
- package/dist/lib/daemon/flag-monitor.js +2 -2
- package/dist/lib/daemon/legacy-sync-env.d.ts +0 -1
- package/dist/lib/daemon/legacy-sync-env.js +1 -1
- package/dist/lib/daemon/ops/journal.d.ts +0 -1
- package/dist/lib/daemon/ops/journal.js +1 -1
- package/dist/lib/daemon/ops/mcp.d.ts +0 -1
- package/dist/lib/daemon/ops/mcp.js +1 -1
- package/dist/lib/daemon/ops/memory.d.ts +0 -2
- package/dist/lib/daemon/ops/memory.js +2 -2
- package/dist/lib/daemon/ops/policy.d.ts +0 -7
- package/dist/lib/daemon/ops/policy.js +1 -1
- package/dist/lib/daemon/supervisor.d.ts +0 -1
- package/dist/lib/daemon/supervisor.js +1 -1
- package/dist/lib/daemon/sync-runner-bundle.d.ts +2 -1
- package/dist/lib/daemon/sync-runner-bundle.js +1 -1
- package/dist/lib/daemon/sync-runner.d.ts +2 -1
- package/dist/lib/doctor/checks/runtime-probe.d.ts +2 -16
- package/dist/lib/doctor/checks/runtime-probe.js +2 -2
- package/dist/lib/doctor/checks/sync-health.d.ts +0 -2
- package/dist/lib/doctor/checks/sync-health.js +1 -1
- package/dist/lib/doctor/fix/json-output.d.ts +0 -1
- package/dist/lib/doctor/fix/json-output.js +1 -1
- package/dist/lib/doctor/platform.d.ts +5 -4
- package/dist/lib/lanes/admission.d.ts +0 -2
- package/dist/lib/lanes/admission.js +2 -2
- package/dist/lib/lanes/autopilot-metrics.d.ts +5 -4
- package/dist/lib/lanes/blocker-freshness.d.ts +0 -2
- package/dist/lib/lanes/blocker-freshness.js +2 -2
- package/dist/lib/lanes/compaction.d.ts +2 -1
- package/dist/lib/lanes/config.d.ts +1 -5
- package/dist/lib/lanes/config.js +4 -4
- package/dist/lib/lanes/delivery.d.ts +0 -2
- package/dist/lib/lanes/delivery.js +1 -1
- package/dist/lib/lanes/hooks-install.d.ts +0 -1
- package/dist/lib/lanes/hooks-install.js +1 -1
- package/dist/lib/lanes/keep-alive.d.ts +0 -4
- package/dist/lib/lanes/keep-alive.js +3 -3
- package/dist/lib/lanes/kr-freshness.d.ts +2 -4
- package/dist/lib/lanes/kr-freshness.js +4 -4
- package/dist/lib/lanes/merge-command.d.ts +2 -1
- package/dist/lib/lanes/orphans.d.ts +0 -1
- package/dist/lib/lanes/orphans.js +1 -1
- package/dist/lib/lanes/outpost-pruner-install.d.ts +0 -3
- package/dist/lib/lanes/outpost-pruner-install.js +3 -3
- package/dist/lib/lanes/outpost-worktree-pruner.d.ts +3 -2
- package/dist/lib/lanes/provider-rejection.d.ts +0 -1
- package/dist/lib/lanes/provider-rejection.js +1 -1
- package/dist/lib/lanes/reviews.d.ts +3 -4
- package/dist/lib/lanes/reviews.js +3 -3
- package/dist/lib/lanes/runaway-tool-guard.d.ts +1 -1
- package/dist/lib/lanes/spawn.d.ts +1 -7
- package/dist/lib/lanes/spawn.js +4 -4
- package/dist/lib/lanes/store.js +1 -1
- package/dist/lib/lanes/throttle.d.ts +0 -1
- package/dist/lib/lanes/throttle.js +1 -1
- package/dist/lib/lanes/types.d.ts +1 -1
- package/dist/lib/lanes/watcher.d.ts +0 -9
- package/dist/lib/lanes/watcher.js +2 -2
- package/dist/lib/mesh/live/daemon/legacy-listen.d.ts +0 -3
- package/dist/lib/mesh/live/daemon/legacy-listen.js +3 -3
- package/dist/lib/mesh/live/paths.d.ts +0 -1
- package/dist/lib/mesh/live/paths.js +1 -1
- package/dist/lib/mesh/live/spool.d.ts +0 -8
- package/dist/lib/mesh/live/spool.js +3 -3
- package/dist/lib/mesh/story-status.d.ts +2 -7
- package/dist/lib/mesh/story-status.js +2 -2
- package/dist/lib/sync-invalid-entity-warning.d.ts +0 -1
- package/dist/lib/sync-invalid-entity-warning.js +1 -1
- package/dist/lib/work-context/atomic.d.ts +0 -4
- package/dist/lib/work-context/atomic.js +1 -1
- package/dist/lib/work-context/bind-best.d.ts +0 -19
- package/dist/lib/work-context/bind-best.js +3 -3
- package/dist/lib/work-context/contract.d.ts +2 -3
- package/dist/lib/work-context/contract.js +1 -1
- package/dist/lib/work-context/organize.d.ts +3 -11
- package/dist/lib/work-context/organize.js +3 -3
- package/dist/lib/work-context/preflight-contract.d.ts +2 -7
- package/dist/lib/work-context/preflight-contract.js +1 -1
- package/dist/lib/work-context/repo-remote.d.ts +2 -1
- package/dist/utils/manifest.d.ts +0 -2
- package/dist/utils/manifest.js +2 -2
- package/dist/utils/pack-contributions.d.ts +1 -3
- package/dist/utils/pack-contributions.js +0 -5
- package/dist/utils/package-use-lease.d.ts +0 -7
- package/dist/utils/package-use-lease.js +1 -1
- package/dist/utils/resident-package-preload.d.ts +0 -5
- package/dist/utils/resident-package-preload.js +1 -1
- package/dist/utils/resolve-executable.d.ts +0 -1
- package/dist/utils/resolve-executable.js +1 -1
- package/dist/utils/version-gate.d.ts +4 -4
- package/dist/utils/version-gate.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.345.11] — 2026-10-05
|
|
6
|
+
- Fix Windows parity for delegate, scheduled job, and session helpers.
|
|
7
|
+
|
|
8
|
+
## [5.345.10] — 2026-10-05
|
|
9
|
+
- Keep a healthy recorded Claude account for lane messages when every worker-profile-pinned account is unavailable.
|
|
10
|
+
|
|
5
11
|
## [5.345.9] — 2026-10-05
|
|
6
12
|
- Lane messages to exited sessions now queue durably when provider admission is busy, so delivery succeeds and reconcile can resume them later.
|
|
7
13
|
- Keep the current sync runner until an hq-cloud version matching the configured pin is available.
|
|
@@ -35,11 +35,18 @@ die() { echo "hq-delegate-grant: $*" >&2; exit 1; }
|
|
|
35
35
|
|
|
36
36
|
command -v jq >/dev/null 2>&1 || die "jq is required but not installed"
|
|
37
37
|
|
|
38
|
-
# jq.exe
|
|
39
|
-
case "${OSTYPE:-}" in
|
|
40
|
-
msys*)
|
|
38
|
+
# jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
|
|
39
|
+
case "${OSTYPE:-}:${MSYSTEM:-}" in
|
|
40
|
+
msys*:*|*:MINGW*)
|
|
41
41
|
jq() {
|
|
42
|
-
|
|
42
|
+
local stdout_file stderr_file status
|
|
43
|
+
stdout_file="$(mktemp)" || return $?
|
|
44
|
+
stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
|
|
45
|
+
if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
|
|
46
|
+
command sed -b 's/\r$//' "$stdout_file"
|
|
47
|
+
command sed -b 's/\r$//' "$stderr_file" >&2
|
|
48
|
+
rm -f "$stdout_file" "$stderr_file"
|
|
49
|
+
return "$status"
|
|
43
50
|
}
|
|
44
51
|
;;
|
|
45
52
|
esac
|
|
@@ -40,11 +40,18 @@ die() { echo "hq-delegate-send: $*" >&2; exit 1; }
|
|
|
40
40
|
|
|
41
41
|
command -v jq >/dev/null 2>&1 || die "jq is required but not installed"
|
|
42
42
|
|
|
43
|
-
# jq.exe
|
|
44
|
-
case "${OSTYPE:-}" in
|
|
45
|
-
msys*)
|
|
43
|
+
# jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
|
|
44
|
+
case "${OSTYPE:-}:${MSYSTEM:-}" in
|
|
45
|
+
msys*:*|*:MINGW*)
|
|
46
46
|
jq() {
|
|
47
|
-
|
|
47
|
+
local stdout_file stderr_file status
|
|
48
|
+
stdout_file="$(mktemp)" || return $?
|
|
49
|
+
stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
|
|
50
|
+
if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
|
|
51
|
+
command sed -b 's/\r$//' "$stdout_file"
|
|
52
|
+
command sed -b 's/\r$//' "$stderr_file" >&2
|
|
53
|
+
rm -f "$stdout_file" "$stderr_file"
|
|
54
|
+
return "$status"
|
|
48
55
|
}
|
|
49
56
|
;;
|
|
50
57
|
esac
|
|
@@ -120,11 +120,18 @@ done
|
|
|
120
120
|
command -v yq >/dev/null 2>&1 || die "yq is required (mikefarah/yq)"
|
|
121
121
|
command -v jq >/dev/null 2>&1 || die "jq is required"
|
|
122
122
|
|
|
123
|
-
# jq.exe
|
|
124
|
-
case "${OSTYPE:-}" in
|
|
125
|
-
msys*)
|
|
123
|
+
# jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
|
|
124
|
+
case "${OSTYPE:-}:${MSYSTEM:-}" in
|
|
125
|
+
msys*:*|*:MINGW*)
|
|
126
126
|
jq() {
|
|
127
|
-
|
|
127
|
+
local stdout_file stderr_file status
|
|
128
|
+
stdout_file="$(mktemp)" || return $?
|
|
129
|
+
stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
|
|
130
|
+
if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
|
|
131
|
+
command sed -b 's/\r$//' "$stdout_file"
|
|
132
|
+
command sed -b 's/\r$//' "$stderr_file" >&2
|
|
133
|
+
rm -f "$stdout_file" "$stderr_file"
|
|
134
|
+
return "$status"
|
|
128
135
|
}
|
|
129
136
|
;;
|
|
130
137
|
esac
|
|
@@ -40,11 +40,18 @@ command -v jq >/dev/null 2>&1 || {
|
|
|
40
40
|
exit 2
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
# jq.exe
|
|
44
|
-
case "${OSTYPE:-}" in
|
|
45
|
-
msys*)
|
|
43
|
+
# jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
|
|
44
|
+
case "${OSTYPE:-}:${MSYSTEM:-}" in
|
|
45
|
+
msys*:*|*:MINGW*)
|
|
46
46
|
jq() {
|
|
47
|
-
|
|
47
|
+
local stdout_file stderr_file status
|
|
48
|
+
stdout_file="$(mktemp)" || return $?
|
|
49
|
+
stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
|
|
50
|
+
if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
|
|
51
|
+
command sed -b 's/\r$//' "$stdout_file"
|
|
52
|
+
command sed -b 's/\r$//' "$stderr_file" >&2
|
|
53
|
+
rm -f "$stdout_file" "$stderr_file"
|
|
54
|
+
return "$status"
|
|
48
55
|
}
|
|
49
56
|
;;
|
|
50
57
|
esac
|
|
@@ -36,8 +36,8 @@ journal_dir_for() {
|
|
|
36
36
|
warn() { echo "session-journal: $*" >&2; }
|
|
37
37
|
|
|
38
38
|
slugify() {
|
|
39
|
-
#
|
|
40
|
-
printf '%s' "$
|
|
39
|
+
# Win32 rejects newline file-name bytes; otherwise keep the POSIX slug pipeline.
|
|
40
|
+
local slug_input="$1"; if [[ "${OSTYPE:-}" == msys* ]] || [[ "${MSYSTEM:-}" == MINGW* ]]; then slug_input="${slug_input//$'\n'/-}"; fi; printf '%s' "$slug_input" \
|
|
41
41
|
| tr '[:upper:]' '[:lower:]' \
|
|
42
42
|
| sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' \
|
|
43
43
|
| cut -c1-40
|
|
@@ -161,7 +161,7 @@ next_seq() {
|
|
|
161
161
|
|
|
162
162
|
acquire_journal_write_lock() {
|
|
163
163
|
local lock="$1/.session-journal-write.lock" owner=0 i=0
|
|
164
|
-
while [ "$i" -lt 250 ]; do
|
|
164
|
+
while [[ "$i" -lt 250 || ( "${OSTYPE:-}" == msys* && "$i" -lt 1500 ) ]]; do
|
|
165
165
|
if mkdir "$lock" 2>/dev/null; then
|
|
166
166
|
printf '%s\n' "$$" > "$lock/pid" || { rm -rf "$lock"; return 1; }
|
|
167
167
|
JOURNAL_WRITE_LOCK="$lock"
|
|
@@ -373,7 +373,10 @@ function emitJqParseDiagnostic(input, args, context) {
|
|
|
373
373
|
if (!commandExists("jq", context.cwd))
|
|
374
374
|
return;
|
|
375
375
|
const result = subprocess("jq", args, context.cwd, { input, stdout: "ignore", stderr: "pipe" });
|
|
376
|
-
const
|
|
376
|
+
const rawDiagnostic = result.stderrBytes ?? Buffer.from(result.stderr ?? "");
|
|
377
|
+
const diagnostic = process.platform === "win32"
|
|
378
|
+
? Buffer.from(rawDiagnostic.toString("latin1").replace(/\r(?=\n|$)/g, ""), "latin1")
|
|
379
|
+
: rawDiagnostic;
|
|
377
380
|
if (diagnostic.length)
|
|
378
381
|
err(diagnostic);
|
|
379
382
|
}
|
|
@@ -243,7 +243,11 @@ function timestamp(date) {
|
|
|
243
243
|
}
|
|
244
244
|
function currentMetaPath(root, sessionOverride, deps) {
|
|
245
245
|
const id = sessionOverride || resolveSessionId(root, deps);
|
|
246
|
-
return id
|
|
246
|
+
return id
|
|
247
|
+
? process.platform === "win32"
|
|
248
|
+
? `${root}/workspace/sessions/${id}/meta.yaml`
|
|
249
|
+
: path.join(root, "workspace", "sessions", id, "meta.yaml")
|
|
250
|
+
: "";
|
|
247
251
|
}
|
|
248
252
|
function exactCompanyDir(root, slug, deps) {
|
|
249
253
|
if (!root || !slug)
|
|
@@ -23,7 +23,7 @@ const counterKey = (value) => {
|
|
|
23
23
|
key = "unscoped";
|
|
24
24
|
return key.length > 96 ? key.slice(0, 96) : key;
|
|
25
25
|
};
|
|
26
|
-
const slugify = (
|
|
26
|
+
const slugify = (input) => (process.platform === "win32" ? input.replaceAll("\n", "-") : input).toLowerCase()
|
|
27
27
|
.split("\n")
|
|
28
28
|
.map((line) => line.replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").replace(/-+$/, "").slice(0, 40))
|
|
29
29
|
.join("\n");
|
|
@@ -92,7 +92,7 @@ function processIsAlive(pid) {
|
|
|
92
92
|
function acquireJournalWriteLock(dir) {
|
|
93
93
|
const lock = path.join(dir, ".session-journal-write.lock");
|
|
94
94
|
const ownerFile = path.join(lock, "pid");
|
|
95
|
-
const deadline = Date.now() + 5_000;
|
|
95
|
+
const deadline = Date.now() + (process.platform === "win32" ? 30_000 : 5_000);
|
|
96
96
|
while (Date.now() < deadline) {
|
|
97
97
|
try {
|
|
98
98
|
fs.mkdirSync(lock);
|
|
@@ -252,7 +252,8 @@ export function runSessionProjectFast(argv, stdin, cwd, root, dependencies = {})
|
|
|
252
252
|
function acquireProjectWriteLock(prdPath) {
|
|
253
253
|
const lock = `${prdPath}.write-lock`;
|
|
254
254
|
const ownerFile = path.join(lock, "pid");
|
|
255
|
-
|
|
255
|
+
// Git Bash and Node process startup can stretch Windows lock contention beyond the short POSIX window.
|
|
256
|
+
const deadline = Date.now() + (process.platform === "win32" ? 30_000 : 5_000);
|
|
256
257
|
while (Date.now() < deadline) {
|
|
257
258
|
try {
|
|
258
259
|
fs.mkdirSync(lock);
|
package/dist/commands/lanes.js
CHANGED
|
@@ -6791,18 +6791,62 @@ async function selectAutomaticClaudeResumeAccount(ctx, lane, workerProfile, opti
|
|
|
6791
6791
|
(model === undefined || currentConfig.model === undefined || currentConfig.model === model ||
|
|
6792
6792
|
lane.account === recordedModelAccount))
|
|
6793
6793
|
return undefined;
|
|
6794
|
-
const
|
|
6794
|
+
const selectionInput = {
|
|
6795
6795
|
hosts: balanceHosts.snapshots,
|
|
6796
6796
|
targetHost: lane.host,
|
|
6797
6797
|
config,
|
|
6798
6798
|
quotaState: loadQuotaState(hqRoot),
|
|
6799
6799
|
recentUsageEnabled: await readClaudeAccountBalanceSignalsEnabled(ctx, lane.company ?? undefined),
|
|
6800
6800
|
now: ctx.now(),
|
|
6801
|
-
...(!repairUnavailableAccount && allowedAccounts !== undefined ? { allowedAccounts } : {}),
|
|
6802
6801
|
...(model !== undefined ? { model } : {}),
|
|
6803
6802
|
...(recordedModelAccount !== undefined ? { recordedModelAccount } : {}),
|
|
6804
6803
|
unavailableHosts: balanceHosts.unavailableHosts,
|
|
6805
|
-
}
|
|
6804
|
+
};
|
|
6805
|
+
let selected;
|
|
6806
|
+
let profilePinUnavailable = false;
|
|
6807
|
+
try {
|
|
6808
|
+
selected = selectClaudeAccount({
|
|
6809
|
+
...selectionInput,
|
|
6810
|
+
...(!repairUnavailableAccount && allowedAccounts !== undefined ? { allowedAccounts } : {}),
|
|
6811
|
+
});
|
|
6812
|
+
}
|
|
6813
|
+
catch (err) {
|
|
6814
|
+
const accountReasons = err instanceof LanesError &&
|
|
6815
|
+
err.error === "claude_account_balance_no_eligible_account" &&
|
|
6816
|
+
Array.isArray(err.details.account_reasons)
|
|
6817
|
+
? err.details.account_reasons.filter((reason) => reason !== null && typeof reason === "object" && !Array.isArray(reason))
|
|
6818
|
+
: [];
|
|
6819
|
+
const unavailablePinReasons = new Set(["disabled", "home_missing", "not_logged_in", "model_mismatch", "quota_held"]);
|
|
6820
|
+
const everyProfileAccountUnavailable = profilePin !== undefined && profilePin.length > 0 &&
|
|
6821
|
+
profilePin.every((account) => accountReasons.some((reason) => reason.account === account && typeof reason.reason === "string" && unavailablePinReasons.has(reason.reason)));
|
|
6822
|
+
if (!everyProfileAccountUnavailable || lane.account === undefined ||
|
|
6823
|
+
(lane.admission_accounts !== undefined && !lane.admission_accounts.includes(lane.account)))
|
|
6824
|
+
throw err;
|
|
6825
|
+
const recordedSelection = selectClaudeAccount({
|
|
6826
|
+
...selectionInput,
|
|
6827
|
+
allowedAccounts: [lane.account],
|
|
6828
|
+
});
|
|
6829
|
+
selected = {
|
|
6830
|
+
...recordedSelection,
|
|
6831
|
+
considered: recordedSelection.considered.map((entry) => {
|
|
6832
|
+
const pinnedReason = profilePin.includes(entry.account)
|
|
6833
|
+
? accountReasons.find((reason) => reason.account === entry.account)?.reason
|
|
6834
|
+
: undefined;
|
|
6835
|
+
return typeof pinnedReason === "string"
|
|
6836
|
+
? { ...entry, eligible: false, ineligible_reason: pinnedReason }
|
|
6837
|
+
: entry;
|
|
6838
|
+
}),
|
|
6839
|
+
skipped_accounts: [
|
|
6840
|
+
...recordedSelection.skipped_accounts.filter((entry) => !profilePin.includes(entry.account)),
|
|
6841
|
+
...profilePin.map((account) => ({
|
|
6842
|
+
account,
|
|
6843
|
+
host: lane.host,
|
|
6844
|
+
reason: String(accountReasons.find((entry) => entry.account === account)?.reason),
|
|
6845
|
+
})),
|
|
6846
|
+
],
|
|
6847
|
+
};
|
|
6848
|
+
profilePinUnavailable = true;
|
|
6849
|
+
}
|
|
6806
6850
|
const historyReason = lane.account === undefined
|
|
6807
6851
|
? "load_balance"
|
|
6808
6852
|
: currentConfig?.enabled !== true
|
|
@@ -6815,7 +6859,11 @@ async function selectAutomaticClaudeResumeAccount(ctx, lane, workerProfile, opti
|
|
|
6815
6859
|
? "usage_limit"
|
|
6816
6860
|
: "load_balance";
|
|
6817
6861
|
return {
|
|
6818
|
-
selection: {
|
|
6862
|
+
selection: {
|
|
6863
|
+
...selected,
|
|
6864
|
+
...(profilePinUnavailable ? { reason: "profile_pin_unavailable" } : {}),
|
|
6865
|
+
selected_at: ctx.now().toISOString(),
|
|
6866
|
+
},
|
|
6819
6867
|
historyReason,
|
|
6820
6868
|
...(preservedModel !== undefined ? { preservedModel } : {}),
|
|
6821
6869
|
};
|
|
@@ -45,7 +45,7 @@ export interface ActivityThreshold {
|
|
|
45
45
|
* at least `minDistinctDays` calendar days, within the last `windowDays` days.
|
|
46
46
|
*/
|
|
47
47
|
export declare const SIGNIFICANT_CODING_TOOL_ACTIVITY: Readonly<ActivityThreshold>;
|
|
48
|
-
|
|
48
|
+
interface ToolActivity {
|
|
49
49
|
/** Is the desktop app installed? */
|
|
50
50
|
installed: boolean;
|
|
51
51
|
/** App sessions used within the window (0 when the app is not installed). */
|
|
@@ -79,15 +79,8 @@ export interface DetectCodingToolActivityInput {
|
|
|
79
79
|
extraHqRoots?: string[];
|
|
80
80
|
threshold?: ActivityThreshold;
|
|
81
81
|
}
|
|
82
|
-
/** The desktop apps, by bundle id, and the bundle names they ship under. */
|
|
83
|
-
export declare const DESKTOP_APPS: Readonly<Record<CodingTool, {
|
|
84
|
-
bundleId: string;
|
|
85
|
-
bundles: readonly string[];
|
|
86
|
-
}>>;
|
|
87
82
|
/** `originator` the Codex app writes into its sessions' first line. */
|
|
88
83
|
export declare const CODEX_APP_ORIGINATOR = "Codex Desktop";
|
|
89
|
-
/** Claude Code's project folder name for a working directory. */
|
|
90
|
-
export declare function claudeProjectDirName(cwd: string): string;
|
|
91
84
|
/**
|
|
92
85
|
* Is `bundleId` this Info.plist's CFBundleIdentifier? An XML plist is read by
|
|
93
86
|
* key. A binary plist has no readable key/value pairing, so it matches when the
|
|
@@ -139,4 +132,5 @@ export declare function pickCodingTool(claude: {
|
|
|
139
132
|
}, threshold?: ActivityThreshold): CodingTool | null;
|
|
140
133
|
/** Look for the Claude and Codex desktop apps and their recent sessions, and pick one to offer, if any. */
|
|
141
134
|
export declare function detectCodingToolActivity(input: DetectCodingToolActivityInput): CodingToolActivity;
|
|
135
|
+
export {};
|
|
142
136
|
//# sourceMappingURL=coding-tool-activity.d.ts.map
|
|
@@ -48,7 +48,7 @@ export const SIGNIFICANT_CODING_TOOL_ACTIVITY = Object.freeze({
|
|
|
48
48
|
minDistinctDays: 3,
|
|
49
49
|
});
|
|
50
50
|
/** The desktop apps, by bundle id, and the bundle names they ship under. */
|
|
51
|
-
|
|
51
|
+
const DESKTOP_APPS = Object.freeze({
|
|
52
52
|
claude: { bundleId: "com.anthropic.claudefordesktop", bundles: ["Claude.app"] },
|
|
53
53
|
codex: { bundleId: "com.openai.codex", bundles: ["ChatGPT.app", "Codex.app"] },
|
|
54
54
|
});
|
|
@@ -65,10 +65,6 @@ const DAY_MS = 24 * 60 * 60 * 1000;
|
|
|
65
65
|
* many days older than the window, so a resumed session is still counted.
|
|
66
66
|
*/
|
|
67
67
|
const CODEX_FOLDER_MARGIN_DAYS = 31;
|
|
68
|
-
/** Claude Code's project folder name for a working directory. */
|
|
69
|
-
export function claudeProjectDirName(cwd) {
|
|
70
|
-
return path.resolve(cwd).replace(/[^a-zA-Z0-9]/g, "-");
|
|
71
|
-
}
|
|
72
68
|
function codexHome(home, env) {
|
|
73
69
|
const override = env.CODEX_HOME?.trim();
|
|
74
70
|
return override ? override : path.join(home, ".codex");
|
|
@@ -26,10 +26,6 @@ import type { CodingTool } from "./coding-tool-activity.js";
|
|
|
26
26
|
export declare const KEEP_GOING_HERE_REPLY = "Keep going here";
|
|
27
27
|
/** The hq-block kind the desktop app draws as the two-button card. */
|
|
28
28
|
export declare const CONTINUE_IN_TOOL_BLOCK_KIND = "continueInTool";
|
|
29
|
-
/** The desktop apps' product names. */
|
|
30
|
-
export declare const CODING_TOOL_NAMES: Readonly<Record<CodingTool, string>>;
|
|
31
|
-
/** The offer's one line. */
|
|
32
|
-
export declare function setupToolOfferLine(tool: CodingTool): string;
|
|
33
29
|
/**
|
|
34
30
|
* The opening of the app's welcome, kept when the offer replaces it: its
|
|
35
31
|
* first sentence (who the bot is and what setup covers). The rest of the
|
|
@@ -26,12 +26,12 @@ export const KEEP_GOING_HERE_REPLY = "Keep going here";
|
|
|
26
26
|
/** The hq-block kind the desktop app draws as the two-button card. */
|
|
27
27
|
export const CONTINUE_IN_TOOL_BLOCK_KIND = "continueInTool";
|
|
28
28
|
/** The desktop apps' product names. */
|
|
29
|
-
|
|
29
|
+
const CODING_TOOL_NAMES = Object.freeze({
|
|
30
30
|
claude: "Claude",
|
|
31
31
|
codex: "Codex",
|
|
32
32
|
});
|
|
33
33
|
/** The offer's one line. */
|
|
34
|
-
|
|
34
|
+
function setupToolOfferLine(tool) {
|
|
35
35
|
return `Looks like you use the ${CODING_TOOL_NAMES[tool]} app. Want to continue setup there?`;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -63,8 +63,8 @@ export declare const MERGE_LISTED_PAIRS_FLAG = "checkpoint.ontology.merge-listed
|
|
|
63
63
|
* carry the copy's `external_ids` and `web_domains` to the survivor.
|
|
64
64
|
*/
|
|
65
65
|
export declare const MERGE_REWRITE_REFS_FLAG = "checkpoint.ontology.merge-rewrite-refs";
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
type CopySkipReason = "no_original" | "original_invalid" | "identity_differs" | "not_in_duplicate_group" | "group_size" | "type_differs" | "names_differ" | "numbered_copy" | "not_listed" | "listed_conflict";
|
|
67
|
+
type PairKind = "numbered" | "variants" | "listed";
|
|
68
68
|
export interface CopySkip {
|
|
69
69
|
copy: string;
|
|
70
70
|
reason: CopySkipReason;
|
|
@@ -93,7 +93,7 @@ export interface ListedPair {
|
|
|
93
93
|
/** Provider -> resolution, applied only when `rewriteRefs` is on and the ids conflict. */
|
|
94
94
|
resolve_external_ids?: Record<string, ExternalIdResolution>;
|
|
95
95
|
}
|
|
96
|
-
|
|
96
|
+
interface CopyPlan extends CopyPair {
|
|
97
97
|
add_aliases: string[];
|
|
98
98
|
/** Copy names the original lacks that another entity already holds, so they do not move. */
|
|
99
99
|
dropped_aliases: string[];
|
|
@@ -196,4 +196,5 @@ export declare function findListedPairs(index: EntityIndex, only: ListedPair[]):
|
|
|
196
196
|
* local copy files only.
|
|
197
197
|
*/
|
|
198
198
|
export declare function mergeCopies(options: MergeCopiesOptions): Promise<MergeCopiesReport>;
|
|
199
|
+
export {};
|
|
199
200
|
//# sourceMappingURL=merge-copies.d.ts.map
|
|
@@ -25,7 +25,6 @@ export interface EntityIndex {
|
|
|
25
25
|
/** Files under `ontology/entities/` that fail validation. Never written. */
|
|
26
26
|
invalid: Set<string>;
|
|
27
27
|
}
|
|
28
|
-
export declare function emptyIndex(): EntityIndex;
|
|
29
28
|
/** Add one parsed entity to the index (also used for entities created mid-run). */
|
|
30
29
|
export declare function indexEntity(index: EntityIndex, entity: IndexedEntity): void;
|
|
31
30
|
/** Record that the entity at `rel` answers to `alias`. */
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { type EmbedLockDependencies } from "../search-index/embed-lock.js";
|
|
2
2
|
import { type LoadGateDependencies } from "../search-index/load-gate.js";
|
|
3
3
|
import { type UtilityIo } from "./common.js";
|
|
4
|
-
export declare const QMD_REINDEX_STARTUP_WARNING_FLAG = "qmd.reindex-startup-warning";
|
|
5
|
-
export declare const QMD_REINDEX_STARTUP_WARNING_FLAG_FALLBACK = false;
|
|
6
4
|
export type QmdReindexOptions = UtilityIo & {
|
|
7
5
|
cwd?: string;
|
|
8
6
|
/** Test seams; default to the real search-index implementations. */
|
|
@@ -20,8 +20,8 @@ import { resolveProcessFlagGate } from "../flag-registry.js";
|
|
|
20
20
|
import { qmdReindexSingleFlightEnabled } from "../search-index/reindex-single-flight-flag.js";
|
|
21
21
|
import { isQmdNativeBindingError, QMD_NATIVE_BINDING_REMEDY, } from "../../utils/qmd-native-binding-error.js";
|
|
22
22
|
import { ioFor, line } from "./common.js";
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const QMD_REINDEX_STARTUP_WARNING_FLAG = "qmd.reindex-startup-warning";
|
|
24
|
+
const QMD_REINDEX_STARTUP_WARNING_FLAG_FALLBACK = false;
|
|
25
25
|
function qmdStartupFailureWarningsEnabled() {
|
|
26
26
|
return resolveProcessFlagGate(QMD_REINDEX_STARTUP_WARNING_FLAG, { fallback: QMD_REINDEX_STARTUP_WARNING_FLAG_FALLBACK }, () => QMD_REINDEX_STARTUP_WARNING_FLAG_FALLBACK);
|
|
27
27
|
}
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
* on disk. Policy hq-self-updater-must-verify-convergence-after-install: the
|
|
8
8
|
* caller reports a mismatch as a failure; it is never swallowed.
|
|
9
9
|
*/
|
|
10
|
-
export declare const CONVERGENCE_TIMEOUT_MS = 10000;
|
|
11
|
-
export declare const CONVERGENCE_POLL_MS = 500;
|
|
12
10
|
export interface ConvergenceResult {
|
|
13
11
|
converged: boolean;
|
|
14
12
|
expected: string;
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { spawnSync } from "node:child_process";
|
|
11
11
|
import { hqdRequest } from "./protocol.js";
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const CONVERGENCE_TIMEOUT_MS = 10_000;
|
|
13
|
+
const CONVERGENCE_POLL_MS = 500;
|
|
14
14
|
/** Ping hqd over its socket and return the version it reports. */
|
|
15
15
|
export async function pingHqdVersion(socketPath, timeoutMs = 2_000) {
|
|
16
16
|
const result = (await hqdRequest("ping", {}, { socketPath, timeoutMs }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { performance } from "node:perf_hooks";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const HQ_ANYWHERE_FLAG_REFRESH_INTERVAL_MS = 30_000;
|
|
3
|
+
const HQ_ANYWHERE_FLAG_MAX_STALENESS_MS = 60_000;
|
|
4
4
|
/**
|
|
5
5
|
* Refreshes a long-running daemon's flag independently of incoming requests.
|
|
6
6
|
* A failed read keeps the last successful decision only until its 60s age limit.
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* sync limits. This module is deliberately tolerant: a bad or missing drop-in
|
|
5
5
|
* must never stop daemon planning.
|
|
6
6
|
*/
|
|
7
|
-
export declare const LEGACY_SYNC_DROPIN_DIR = "/etc/systemd/system/outpost-sync.service.d";
|
|
8
7
|
/** Read simple KEY=VALUE and quoted "KEY=VALUE" Environment directives. */
|
|
9
8
|
export declare function readLegacySyncEnv(platform: NodeJS.Platform, directory?: string): Record<string, string>;
|
|
10
9
|
//# sourceMappingURL=legacy-sync-env.d.ts.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
|
|
9
|
+
const LEGACY_SYNC_DROPIN_DIR = "/etc/systemd/system/outpost-sync.service.d";
|
|
10
10
|
function assignments(text, into) {
|
|
11
11
|
let inService = false;
|
|
12
12
|
for (const rawLine of text.split(/\r?\n/)) {
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
* <project>/journal/ is used, and one is opened (same template as
|
|
10
10
|
* `journal.sh open`) when none exists.
|
|
11
11
|
*/
|
|
12
|
-
export declare const JOURNAL_SECTIONS: Record<string, string>;
|
|
13
12
|
export declare class JournalOpError extends Error {
|
|
14
13
|
readonly code: string;
|
|
15
14
|
constructor(code: string, message: string);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as fs from "node:fs";
|
|
13
13
|
import * as path from "node:path";
|
|
14
14
|
const SLUG_RE = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
|
|
15
|
-
|
|
15
|
+
const JOURNAL_SECTIONS = {
|
|
16
16
|
decisions: "## Decisions",
|
|
17
17
|
open: "## Open threads",
|
|
18
18
|
findings: "## Findings",
|
|
@@ -12,7 +12,6 @@ export interface McpToolResult {
|
|
|
12
12
|
isError?: boolean;
|
|
13
13
|
}
|
|
14
14
|
export declare function jsonResult(value: unknown): McpToolResult;
|
|
15
|
-
export declare const HQ_MCP_HTTP_TIMEOUT_MS = 30000;
|
|
16
15
|
export declare function resolveHqMcpEndpoint(env?: NodeJS.ProcessEnv): URL;
|
|
17
16
|
export declare function defaultMcpToken(): Promise<string>;
|
|
18
17
|
export interface HqMcpBridgeOptions {
|
|
@@ -16,7 +16,7 @@ export function jsonResult(value) {
|
|
|
16
16
|
const structured = value && typeof value === "object" && !Array.isArray(value) ? value : { value };
|
|
17
17
|
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }], structuredContent: structured };
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
const HQ_MCP_HTTP_TIMEOUT_MS = 30_000;
|
|
20
20
|
export function resolveHqMcpEndpoint(env = process.env) {
|
|
21
21
|
try {
|
|
22
22
|
return resolveEndpoint(env);
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
* memory.get / memory.put ops (hq-anywhere US-009): session-scoped notes
|
|
3
3
|
* persisted at workspace/sessions/<sid>/hqd-memory.json under HQ_ROOT.
|
|
4
4
|
*/
|
|
5
|
-
export declare const MEMORY_FILE = "hqd-memory.json";
|
|
6
5
|
export declare class MemoryOpError extends Error {
|
|
7
6
|
readonly code: string;
|
|
8
7
|
constructor(code: string, message: string);
|
|
9
8
|
}
|
|
10
|
-
export declare function memoryPath(hqRoot: string, sessionId: string): string;
|
|
11
9
|
export declare function memoryPut(hqRoot: string, sessionId: string, key: string, value: unknown, now?: Date): {
|
|
12
10
|
key: string;
|
|
13
11
|
updatedAt: string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
const SESSION_RE = /^[A-Za-z0-9._-]+$/;
|
|
8
|
-
|
|
8
|
+
const MEMORY_FILE = "hqd-memory.json";
|
|
9
9
|
const MAX_VALUE_BYTES = 256 * 1024;
|
|
10
10
|
export class MemoryOpError extends Error {
|
|
11
11
|
code;
|
|
@@ -15,7 +15,7 @@ export class MemoryOpError extends Error {
|
|
|
15
15
|
this.name = "MemoryOpError";
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
function memoryPath(hqRoot, sessionId) {
|
|
19
19
|
if (!SESSION_RE.test(sessionId) || sessionId === "." || sessionId === "..") {
|
|
20
20
|
throw new MemoryOpError("bad_args", "sessionId may only contain letters, digits, '.', '_' and '-'");
|
|
21
21
|
}
|
|
@@ -61,13 +61,6 @@ export interface PolicyCheckResult {
|
|
|
61
61
|
version: number;
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
* The scope authorizer reads the session's company from
|
|
66
|
-
* workspace/sessions/<sid>/meta.yaml (or scope-capability.json). hqd binds a
|
|
67
|
-
* session id of its own per company + caller, so a check never borrows the
|
|
68
|
-
* binding of an unrelated session.
|
|
69
|
-
*/
|
|
70
|
-
export declare function bindCheckSession(hqRoot: string, company: string | undefined, callerSession: string | undefined, now: Date): string;
|
|
71
64
|
export interface PolicyCheckDeps {
|
|
72
65
|
hqRoot: string;
|
|
73
66
|
index: PolicyIndex;
|
|
@@ -160,7 +160,7 @@ function runScript(script, payload, env, cwd, timeoutMs) {
|
|
|
160
160
|
* session id of its own per company + caller, so a check never borrows the
|
|
161
161
|
* binding of an unrelated session.
|
|
162
162
|
*/
|
|
163
|
-
|
|
163
|
+
function bindCheckSession(hqRoot, company, callerSession, now) {
|
|
164
164
|
const caller = (callerSession ?? "default").replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 80) || "default";
|
|
165
165
|
const scope = company ?? "personal";
|
|
166
166
|
const sid = `hqd-${scope}-${caller}`;
|
|
@@ -26,7 +26,6 @@ import type { MachineType } from "./machine-type.js";
|
|
|
26
26
|
import type { ControlRequest } from "./requests.js";
|
|
27
27
|
import { syncPassResult } from "./sync-runner.js";
|
|
28
28
|
export declare const STOP_ESCALATION_MS = 10000;
|
|
29
|
-
export declare const CLI_UPDATE_SYNC_IDLE_MAX_MS: number;
|
|
30
29
|
export declare const CLI_UPDATE_SYNC_IDLE_KILL_GRACE_MS = 60000;
|
|
31
30
|
/** After a handoff, how long a replaced unit must stay up before the next one is replaced. */
|
|
32
31
|
export declare const HANDOFF_STAGGER_MS = 15000;
|
|
@@ -27,7 +27,7 @@ const BACKOFF_BASE_MS = 1_000;
|
|
|
27
27
|
const BACKOFF_MAX_MS = 60_000;
|
|
28
28
|
const HEALTHY_RUN_MS = 60_000;
|
|
29
29
|
export const STOP_ESCALATION_MS = 10_000;
|
|
30
|
-
|
|
30
|
+
const CLI_UPDATE_SYNC_IDLE_MAX_MS = 10 * 60_000;
|
|
31
31
|
export const CLI_UPDATE_SYNC_IDLE_KILL_GRACE_MS = 60_000;
|
|
32
32
|
const MESH_OWNER_RECHECK_MS = 15_000;
|
|
33
33
|
const MESH_OWNER_LOG_INTERVAL_MS = 10 * 60_000;
|
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
export declare const SYNC_RUNNER_BUNDLE_RUNNER_FILE = "bin/sync-runner.js";
|
|
4
4
|
export declare const SYNC_RUNNER_BUNDLE_METADATA_FILE = "package.json";
|
|
5
5
|
export declare const SYNC_RUNNER_BUNDLE_DIRECTORY = "hq-cloud-sync-runner";
|
|
6
|
-
|
|
6
|
+
declare const SYNC_RUNNER_BUNDLE_FORMAT_VERSION = 1;
|
|
7
7
|
/** Root directory where validated sync-runner bundles are selected. */
|
|
8
8
|
export declare function syncRunnerBundleStageRoot(daemonRoot: string): string;
|
|
9
9
|
/** package.json contract that the hq-cli build step emits beside the bundled bin directory. */
|
|
@@ -41,4 +41,5 @@ export declare function stagedSyncRunnerVersion(runnerPath: string): string;
|
|
|
41
41
|
* Only a completed, fsynced directory is returned; temp siblings are ignored.
|
|
42
42
|
*/
|
|
43
43
|
export declare function stageSyncRunnerBundle(options: StageSyncRunnerBundleOptions): StagedSyncRunnerBundle;
|
|
44
|
+
export {};
|
|
44
45
|
//# sourceMappingURL=sync-runner-bundle.d.ts.map
|
|
@@ -8,7 +8,7 @@ import { ensurePrivateDir } from "./paths.js";
|
|
|
8
8
|
export const SYNC_RUNNER_BUNDLE_RUNNER_FILE = "bin/sync-runner.js";
|
|
9
9
|
export const SYNC_RUNNER_BUNDLE_METADATA_FILE = "package.json";
|
|
10
10
|
export const SYNC_RUNNER_BUNDLE_DIRECTORY = "hq-cloud-sync-runner";
|
|
11
|
-
|
|
11
|
+
const SYNC_RUNNER_BUNDLE_FORMAT_VERSION = 1;
|
|
12
12
|
/** Root directory where validated sync-runner bundles are selected. */
|
|
13
13
|
export function syncRunnerBundleStageRoot(daemonRoot) {
|
|
14
14
|
return path.join(daemonRoot, "bundles", "sync-runner");
|