@indigoai-us/hq-cli 5.345.10 → 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 +3 -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/lib/checkpoint-ontology/merge-copies.d.ts +4 -3
- 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/policy.d.ts +0 -7
- package/dist/lib/daemon/ops/policy.js +1 -1
- package/dist/lib/doctor/checks/sync-health.d.ts +0 -2
- package/dist/lib/doctor/checks/sync-health.js +1 -1
- 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/compaction.d.ts +2 -1
- 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/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-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/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/throttle.d.ts +0 -1
- package/dist/lib/lanes/throttle.js +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/contract.d.ts +2 -3
- package/dist/lib/work-context/contract.js +1 -1
- 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/resident-package-preload.d.ts +0 -5
- package/dist/utils/resident-package-preload.js +1 -1
- package/dist/utils/version-gate.d.ts +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
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
|
+
|
|
5
8
|
## [5.345.10] — 2026-10-05
|
|
6
9
|
- Keep a healthy recorded Claude account for lane messages when every worker-profile-pinned account is unavailable.
|
|
7
10
|
|
|
@@ -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);
|
|
@@ -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
|
|
@@ -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);
|
|
@@ -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}`;
|
|
@@ -105,8 +105,6 @@ export interface SyncHealthDeps {
|
|
|
105
105
|
* outside `companies/`.
|
|
106
106
|
*/
|
|
107
107
|
export declare function isSafeCompanySlug(slug: string): boolean;
|
|
108
|
-
/** True when `hqRoot/companies/<slug>` exists as a directory. Never throws. */
|
|
109
|
-
export declare function defaultLocalCompanyExists(hqRoot: string, slug: string): boolean;
|
|
110
108
|
/** True when this journal slug names a company rather than the personal tree. */
|
|
111
109
|
export declare function isCompanyJournalSlug(slug: string): boolean;
|
|
112
110
|
/** Company slug from a `sync.journal.<slug>` check id, or null if not one. */
|
|
@@ -68,7 +68,7 @@ export function isSafeCompanySlug(slug) {
|
|
|
68
68
|
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(slug);
|
|
69
69
|
}
|
|
70
70
|
/** True when `hqRoot/companies/<slug>` exists as a directory. Never throws. */
|
|
71
|
-
|
|
71
|
+
function defaultLocalCompanyExists(hqRoot, slug) {
|
|
72
72
|
if (!isSafeCompanySlug(slug))
|
|
73
73
|
return false;
|
|
74
74
|
try {
|
|
@@ -6,8 +6,6 @@ export interface AdmissionHost {
|
|
|
6
6
|
}
|
|
7
7
|
export type AdmissionCapReason = "provider_cap" | "account_cap" | "profile_cap";
|
|
8
8
|
export declare const ADMISSION_LOCK_STALE_MS = 30000;
|
|
9
|
-
export declare const ADMISSION_LOCK_TIMEOUT_MS = 5000;
|
|
10
|
-
export declare const ADMISSION_RESERVATION_GRACE_MS = 30000;
|
|
11
9
|
export declare function withLaneAdmissionLock<T>(hqRoot: string, provider: LaneRecord["provider"], fn: () => Promise<T>, sleep?: (ms: number) => Promise<void>): Promise<T>;
|
|
12
10
|
export declare function withAllLaneAdmissionLocks<T>(hqRoot: string, fn: () => Promise<T>, sleep?: (ms: number) => Promise<void>): Promise<T>;
|
|
13
11
|
export declare function laneRunsOnHost(lane: LaneRecord, host: AdmissionHost): boolean;
|
|
@@ -5,8 +5,8 @@ import { LanesError } from "./errors.js";
|
|
|
5
5
|
import { quotaBlockFor } from "./quota.js";
|
|
6
6
|
import { isTerminalLaneState } from "./types.js";
|
|
7
7
|
export const ADMISSION_LOCK_STALE_MS = 30_000;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const ADMISSION_LOCK_TIMEOUT_MS = 5_000;
|
|
9
|
+
const ADMISSION_RESERVATION_GRACE_MS = 30_000;
|
|
10
10
|
function defaultAdmissionSleep(ms) {
|
|
11
11
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
12
|
}
|
|
@@ -3,7 +3,7 @@ export interface AutopilotMetricsLead {
|
|
|
3
3
|
lane_id: string;
|
|
4
4
|
project_id: string;
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
interface AutopilotMetricsLane {
|
|
7
7
|
lane_id: string;
|
|
8
8
|
project_id: string;
|
|
9
9
|
story_id: string;
|
|
@@ -67,7 +67,7 @@ export interface BuildAutopilotMetricsReportInput {
|
|
|
67
67
|
nudgeDefects: readonly AutopilotMetricsDefect[];
|
|
68
68
|
seniorResumes: readonly AutopilotMetricsResume[];
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
interface AutopilotMetricsDay {
|
|
71
71
|
team: string;
|
|
72
72
|
day: string;
|
|
73
73
|
operator_nudges: number;
|
|
@@ -76,7 +76,7 @@ export interface AutopilotMetricsDay {
|
|
|
76
76
|
review_latency_minutes_average: number | null;
|
|
77
77
|
idle_slot_minutes_ready_work: number;
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
interface AutopilotReviewLatency {
|
|
80
80
|
team: string;
|
|
81
81
|
lane_id: string;
|
|
82
82
|
story_id: string;
|
|
@@ -85,7 +85,7 @@ export interface AutopilotReviewLatency {
|
|
|
85
85
|
minutes: number;
|
|
86
86
|
end_event: "review_record" | "senior_resume" | "story_closed";
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
interface AutopilotNudgeDefect extends AutopilotMetricsDefect {
|
|
89
89
|
wake: null;
|
|
90
90
|
}
|
|
91
91
|
export interface AutopilotMetricsReport {
|
|
@@ -96,4 +96,5 @@ export interface AutopilotMetricsReport {
|
|
|
96
96
|
nudge_defects: AutopilotNudgeDefect[];
|
|
97
97
|
}
|
|
98
98
|
export declare function buildAutopilotMetricsReport(input: BuildAutopilotMetricsReportInput): AutopilotMetricsReport;
|
|
99
|
+
export {};
|
|
99
100
|
//# sourceMappingURL=autopilot-metrics.d.ts.map
|
|
@@ -65,7 +65,7 @@ export declare function probeProviderCompactions(transcriptPath: string | null,
|
|
|
65
65
|
export declare function findSessionTranscript(home: string, sessionId: string): string | null;
|
|
66
66
|
/** Count compact boundaries in a transcript. Other lines are never parsed. */
|
|
67
67
|
export declare function probeCompactBoundaries(transcriptPath: string | null): CompactBoundaryProbe;
|
|
68
|
-
|
|
68
|
+
interface CompactionCommandResult {
|
|
69
69
|
status: number | null;
|
|
70
70
|
error?: string;
|
|
71
71
|
}
|
|
@@ -107,4 +107,5 @@ export declare function compactLaneSession(input: CompactLaneSessionInput): Lane
|
|
|
107
107
|
* compaction's `resume_at`.
|
|
108
108
|
*/
|
|
109
109
|
export declare function compactionAfterUsage(lane: LaneRecord): LaneRunUsage | null;
|
|
110
|
+
export {};
|
|
110
111
|
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -69,8 +69,6 @@ export type LaneDeliveryMechanism = (typeof LANE_DELIVERY_MECHANISMS)[number];
|
|
|
69
69
|
/** Additional presentation-only result used by `hq lanes show`. */
|
|
70
70
|
export type LaneShowDeliveryMechanism = LaneDeliveryMechanism | "questions";
|
|
71
71
|
export type DeliveryLane = Pick<LaneRecord, "state" | "provider" | "provider_session_id" | "terminal_reason" | "envelope_repair">;
|
|
72
|
-
/** Only the terminal result of a failed automatic envelope repair is recoverable. */
|
|
73
|
-
export declare function isFailedEnvelopeRepairLane(lane: DeliveryLane): boolean;
|
|
74
72
|
/**
|
|
75
73
|
* `dropbox`: a process is (or is about to be) alive to drain the inbox.
|
|
76
74
|
* `resume`: the process has exited, the provider can resume, the state allows
|
|
@@ -88,7 +88,7 @@ export function isResumeCommandState(state) {
|
|
|
88
88
|
}
|
|
89
89
|
export const LANE_DELIVERY_MECHANISMS = ["dropbox", "resume", "none"];
|
|
90
90
|
/** Only the terminal result of a failed automatic envelope repair is recoverable. */
|
|
91
|
-
|
|
91
|
+
function isFailedEnvelopeRepairLane(lane) {
|
|
92
92
|
return (lane.state === "failed" &&
|
|
93
93
|
lane.terminal_reason === ENVELOPE_INVALID_REASON &&
|
|
94
94
|
lane.envelope_repair?.attempted === true &&
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
import type { LaneProvider } from "./types.js";
|
|
21
21
|
export declare const DRAIN_HOOK_BASENAME = "hq-lanes-drain";
|
|
22
22
|
export declare const DRAIN_HOOK_TIMEOUT_SECONDS = 30;
|
|
23
|
-
export declare function drainHookEntryPath(): string;
|
|
24
23
|
export declare function lanesHookAssetsDir(): string;
|
|
25
24
|
export declare const DRAIN_HOOK_REGISTRATION_KINDS: readonly ["hooks_dir", "settings_json", "config_toml"];
|
|
26
25
|
export type DrainHookRegistrationKind = (typeof DRAIN_HOOK_REGISTRATION_KINDS)[number];
|
|
@@ -28,7 +28,7 @@ export const DRAIN_HOOK_TIMEOUT_SECONDS = 30;
|
|
|
28
28
|
function shellQuote(value) {
|
|
29
29
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
function drainHookEntryPath() {
|
|
32
32
|
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../dist/lanes-drain-hook.js");
|
|
33
33
|
}
|
|
34
34
|
export function lanesHookAssetsDir() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
interface MergeCommandTarget {
|
|
2
2
|
kind: "pr" | "api" | "graphql" | "git";
|
|
3
3
|
repo: string | null;
|
|
4
4
|
pr: number | null;
|
|
@@ -12,4 +12,5 @@ export interface MergeCommandParseResult {
|
|
|
12
12
|
}
|
|
13
13
|
export declare function canonicalRepo(raw: string): string;
|
|
14
14
|
export declare function parseMergeCommands(command: string): MergeCommandParseResult;
|
|
15
|
+
export {};
|
|
15
16
|
//# sourceMappingURL=merge-command.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanesError } from "./errors.js";
|
|
2
2
|
import { isTerminalLaneState } from "./types.js";
|
|
3
|
-
|
|
3
|
+
const DEFAULT_ORPHAN_MIN_AGE_MINUTES = 30;
|
|
4
4
|
export const DEFAULT_ORPHAN_USER_IDLE_HOURS = 72;
|
|
5
5
|
const LIVE_LANE_STATES = new Set(["running", "queued", "blocked", "awaiting_input"]);
|
|
6
6
|
export function parseOrphanMinAge(value) {
|
|
@@ -18,14 +18,14 @@ export interface OutpostWorktreePrunerOptions {
|
|
|
18
18
|
/** Test seam for /proc reads; production uses the host filesystem. */
|
|
19
19
|
processPathReader?: ProcessPathReader;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
interface ProcessPathReader {
|
|
22
22
|
readdirSync(path: string): string[];
|
|
23
23
|
readlinkSync(path: string): string;
|
|
24
24
|
uid(path: string): number;
|
|
25
25
|
/** Test seam for read-only process identity checks used by the cwd exception. */
|
|
26
26
|
readFileSync?(path: string): string;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
interface PackageStorePruneResult {
|
|
29
29
|
attempted: boolean;
|
|
30
30
|
reason?: string;
|
|
31
31
|
bytes_freed?: number;
|
|
@@ -58,4 +58,5 @@ export interface OutpostWorktreePrunerResult {
|
|
|
58
58
|
*/
|
|
59
59
|
export declare function runOutpostWorktreePruner(options: OutpostWorktreePrunerOptions): OutpostWorktreePrunerResult;
|
|
60
60
|
export declare const OUTPOST_WORKTREE_PRUNER_DEFAULT_MIN_AGE_DAYS = 14;
|
|
61
|
+
export {};
|
|
61
62
|
//# sourceMappingURL=outpost-worktree-pruner.d.ts.map
|
|
@@ -38,7 +38,6 @@ export interface ProviderRejection {
|
|
|
38
38
|
event: "codex.turn.failed" | "claude.result.is_error" | "claude.result.login_failure" | "grok.error";
|
|
39
39
|
}
|
|
40
40
|
export declare function isProviderLoginFailure(failure: ProviderRejection | null): boolean;
|
|
41
|
-
export declare function capMessage(message: string): string;
|
|
42
41
|
/**
|
|
43
42
|
* Whether a later run could succeed without the operator changing anything.
|
|
44
43
|
* A 400 model rejection cannot; a request timeout, a too-early, or a server
|
|
@@ -100,7 +100,7 @@ function statusOf(value) {
|
|
|
100
100
|
? value
|
|
101
101
|
: null;
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
function capMessage(message) {
|
|
104
104
|
return message.length > PROVIDER_REJECTION_MESSAGE_CAP
|
|
105
105
|
? `${message.slice(0, PROVIDER_REJECTION_MESSAGE_CAP)}…`
|
|
106
106
|
: message;
|
|
@@ -26,8 +26,6 @@ export declare function providerCommandOnPath(command: string, pathEnv: string |
|
|
|
26
26
|
/** Per-provider model flag. A missing entry means --model is refused. */
|
|
27
27
|
export declare const PROVIDER_MODEL_FLAG: Record<LaneProvider, string>;
|
|
28
28
|
export declare const CLAUDE_AUTO_COMPACT_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
29
|
-
/** Codex CLI overrides required for its ChatGPT fast service tier. */
|
|
30
|
-
export declare const CODEX_FAST_MODE_FLAGS: readonly ["-c", "service_tier=\"fast\"", "--enable", "fast_mode"];
|
|
31
29
|
export declare function parseCliModel(raw: string | undefined): string | undefined;
|
|
32
30
|
export declare function resolveLaneModel(input: {
|
|
33
31
|
cliModel?: string;
|
|
@@ -39,14 +37,12 @@ type AutomaticAccountChangeReason = Exclude<AccountHistoryEntry["reason"], "oper
|
|
|
39
37
|
/** Change account only after a provider/runtime account failure, then re-admit. */
|
|
40
38
|
export declare function retryLaneOnAlternateAccount(hqRoot: string, lane: LaneRecord, reason: Extract<AutomaticAccountChangeReason, "usage_limit" | "account_unavailable">, writer?: "watcher" | "reconcile", deps?: SpawnLaneDeps): Promise<LaneRecord>;
|
|
41
39
|
export declare function appendModelFlag(provider: LaneProvider, args: string[], model: string | undefined): string[];
|
|
42
|
-
/** Add Codex fast-mode flags before the prompt/positional separator. */
|
|
43
|
-
export declare function appendFastModeFlags(provider: LaneProvider, args: string[], enabled: boolean | undefined): string[];
|
|
44
40
|
export interface ProviderProfileLaunch {
|
|
45
41
|
systemPrompt: string;
|
|
46
42
|
settingsPath?: string;
|
|
47
43
|
ignoredFields?: readonly string[];
|
|
48
44
|
}
|
|
49
|
-
|
|
45
|
+
type DetachedStdio = ["ignore", number, number];
|
|
50
46
|
export interface DetachedSpawnOptions {
|
|
51
47
|
detached: true;
|
|
52
48
|
windowsHide: true;
|
|
@@ -120,7 +116,6 @@ export interface PidLivenessProbe {
|
|
|
120
116
|
}
|
|
121
117
|
export declare function missingPidProbe(): PidLivenessProbe;
|
|
122
118
|
export declare function defaultPidIsAlive(pid: number): boolean;
|
|
123
|
-
export declare const STOP_TERM_WAIT_MS = 500;
|
|
124
119
|
export declare function parseSpawnTerminalReason(value: string): SpawnTerminalReason;
|
|
125
120
|
export declare function laneRunDir(hqRoot: string, laneId: string): string;
|
|
126
121
|
export declare function watcherMainPath(): string;
|
|
@@ -130,7 +125,6 @@ export declare function readProcStarttimeDetailed(pid: number): {
|
|
|
130
125
|
error: string | null;
|
|
131
126
|
};
|
|
132
127
|
export declare function readProcStarttime(pid: number): number | null;
|
|
133
|
-
export declare function formatPidRecord(rec: PidRecord): string;
|
|
134
128
|
export declare function parsePidRecord(text: string): PidRecord | null;
|
|
135
129
|
export declare function readPidRecord(filePath: string): PidRecord | null;
|
|
136
130
|
export declare function writePidRecord(filePath: string, rec: PidRecord): void;
|
package/dist/lib/lanes/spawn.js
CHANGED
|
@@ -148,7 +148,7 @@ export const PROVIDER_MODEL_FLAG = {
|
|
|
148
148
|
};
|
|
149
149
|
export const CLAUDE_AUTO_COMPACT_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
150
150
|
/** Codex CLI overrides required for its ChatGPT fast service tier. */
|
|
151
|
-
|
|
151
|
+
const CODEX_FAST_MODE_FLAGS = [
|
|
152
152
|
"-c",
|
|
153
153
|
'service_tier="fast"',
|
|
154
154
|
"--enable",
|
|
@@ -625,7 +625,7 @@ export function appendModelFlag(provider, args, model) {
|
|
|
625
625
|
return [...args, flag, model];
|
|
626
626
|
}
|
|
627
627
|
/** Add Codex fast-mode flags before the prompt/positional separator. */
|
|
628
|
-
|
|
628
|
+
function appendFastModeFlags(provider, args, enabled) {
|
|
629
629
|
if (provider !== "codex" || enabled !== true)
|
|
630
630
|
return args;
|
|
631
631
|
const flags = [...CODEX_FAST_MODE_FLAGS];
|
|
@@ -719,7 +719,7 @@ export function defaultPidIsAlive(pid) {
|
|
|
719
719
|
throw err;
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
|
-
|
|
722
|
+
const STOP_TERM_WAIT_MS = 500;
|
|
723
723
|
const defaultSpawnProcess = (command, args, options) => spawn(command, args, options);
|
|
724
724
|
function defaultKillProcess(pid, signal = "SIGTERM") {
|
|
725
725
|
process.kill(pid, signal);
|
|
@@ -787,7 +787,7 @@ export function readProcStarttimeDetailed(pid) {
|
|
|
787
787
|
export function readProcStarttime(pid) {
|
|
788
788
|
return readProcStarttimeDetailed(pid).starttime;
|
|
789
789
|
}
|
|
790
|
-
|
|
790
|
+
function formatPidRecord(rec) {
|
|
791
791
|
return rec.starttime !== undefined ? `${rec.pid} ${rec.starttime}\n` : `${rec.pid}\n`;
|
|
792
792
|
}
|
|
793
793
|
export function parsePidRecord(text) {
|
|
@@ -13,7 +13,6 @@ import * as fs from "node:fs";
|
|
|
13
13
|
import * as os from "node:os";
|
|
14
14
|
import type { ThrottleConfig } from "./types.js";
|
|
15
15
|
export declare const CPU_SAMPLE_MS = 5000;
|
|
16
|
-
export declare const CPU_CUMULATIVE_MAX_AGE_MS: number;
|
|
17
16
|
export declare const STARVATION_MAX_DEFERRALS = 10;
|
|
18
17
|
export declare const STARVATION_MAX_MS: number;
|
|
19
18
|
export declare const PROC_MEMINFO = "/proc/meminfo";
|
|
@@ -16,7 +16,7 @@ import { DEFAULT_CPU_BUSY_PAUSE, DEFAULT_CPU_BUSY_RESUME, DEFAULT_MIN_AVAILABLE_
|
|
|
16
16
|
// Reconcile normally measures the interval between cumulative CPU snapshots.
|
|
17
17
|
// A five-second window establishes a baseline or recovers from stale counters.
|
|
18
18
|
export const CPU_SAMPLE_MS = 5_000;
|
|
19
|
-
|
|
19
|
+
const CPU_CUMULATIVE_MAX_AGE_MS = 5 * 60 * 1000;
|
|
20
20
|
export const STARVATION_MAX_DEFERRALS = 10;
|
|
21
21
|
export const STARVATION_MAX_MS = 30 * 60 * 1000;
|
|
22
22
|
export const PROC_MEMINFO = "/proc/meminfo";
|
|
@@ -42,8 +42,6 @@ import { type EnvelopeRepairSpawnInput, type SpawnLaneDeps } from "./spawn.js";
|
|
|
42
42
|
export declare const SILENCE_MS: number;
|
|
43
43
|
export declare const WATCHER_POLL_MS = 5000;
|
|
44
44
|
export declare const ENVELOPE_REPAIR_CONTINUE_TEXT = "continue the task; the previous turn ended without an envelope.";
|
|
45
|
-
/** Synced last_host_report_at cadence. Reconcile dead-host TTL is 20 minutes. */
|
|
46
|
-
export declare const WATCHER_HEARTBEAT_MS: number;
|
|
47
45
|
/**
|
|
48
46
|
* Cap on logs/watcher.out. A decision line is typically under 300 bytes, so
|
|
49
47
|
* 256 KiB holds hundreds of transitions. A stuck lane cannot fill the disk:
|
|
@@ -164,13 +162,6 @@ export declare function stalledReason(silenceMs: number): string;
|
|
|
164
162
|
export declare function markLaneStalled(hqRoot: string, laneId: string, at: string, reason: string): LaneRecord;
|
|
165
163
|
export declare function clearLaneStalled(hqRoot: string, laneId: string): LaneRecord;
|
|
166
164
|
export declare function applyTerminalToLane(hqRoot: string, laneId: string, classification: TerminalClassification, opts?: ApplyTerminalOpts): LaneRecord;
|
|
167
|
-
/** Terminal write outcome for emitters: only the CAS winner may publish mesh effects. */
|
|
168
|
-
export declare function applyTerminalToLaneWithResult(hqRoot: string, laneId: string, classification: TerminalClassification, opts?: ApplyTerminalOpts): {
|
|
169
|
-
record: LaneRecord;
|
|
170
|
-
changed: boolean;
|
|
171
|
-
envelope?: LaneEnvelope;
|
|
172
|
-
classification: TerminalClassification;
|
|
173
|
-
};
|
|
174
165
|
export declare function isPidAlive(pid: number): boolean;
|
|
175
166
|
export interface LatestEnvelope {
|
|
176
167
|
envelope: LaneEnvelope;
|
|
@@ -63,7 +63,7 @@ export const SILENCE_MS = 20 * 60 * 1000;
|
|
|
63
63
|
export const WATCHER_POLL_MS = 5_000;
|
|
64
64
|
export const ENVELOPE_REPAIR_CONTINUE_TEXT = "continue the task; the previous turn ended without an envelope.";
|
|
65
65
|
/** Synced last_host_report_at cadence. Reconcile dead-host TTL is 20 minutes. */
|
|
66
|
-
|
|
66
|
+
const WATCHER_HEARTBEAT_MS = 60 * 1000;
|
|
67
67
|
/**
|
|
68
68
|
* Cap on logs/watcher.out. A decision line is typically under 300 bytes, so
|
|
69
69
|
* 256 KiB holds hundreds of transitions. A stuck lane cannot fill the disk:
|
|
@@ -333,7 +333,7 @@ export function applyTerminalToLane(hqRoot, laneId, classification, opts = {}) {
|
|
|
333
333
|
return applyTerminalToLaneWithResult(hqRoot, laneId, classification, opts).record;
|
|
334
334
|
}
|
|
335
335
|
/** Terminal write outcome for emitters: only the CAS winner may publish mesh effects. */
|
|
336
|
-
|
|
336
|
+
function applyTerminalToLaneWithResult(hqRoot, laneId, classification, opts = {}) {
|
|
337
337
|
const at = opts.at ?? new Date().toISOString();
|
|
338
338
|
const envelopeRef = opts.envelopeRef ?? "envelopes/unknown.json";
|
|
339
339
|
const existing = readLane(hqRoot, laneId);
|
|
@@ -6,9 +6,6 @@
|
|
|
6
6
|
* Windows: Scheduled Task ai.getindigo.hq-work-mesh-listen
|
|
7
7
|
*/
|
|
8
8
|
export type LegacyListenPlatform = "darwin" | "linux" | "win32" | "other";
|
|
9
|
-
export declare const LEGACY_LISTEN_LABEL = "ai.getindigo.hq-work-mesh-listen";
|
|
10
|
-
export declare const LEGACY_LISTEN_SYSTEMD_UNIT = "hq-work-mesh-listen.service";
|
|
11
|
-
export declare const LEGACY_LISTEN_TASK = "ai.getindigo.hq-work-mesh-listen";
|
|
12
9
|
export declare const LEGACY_LISTENER_DOCTOR_LINE = "legacy listener still installed";
|
|
13
10
|
export interface CommandResult {
|
|
14
11
|
status: number | null;
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path from "node:path";
|
|
10
10
|
import { spawnSync } from "node:child_process";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const LEGACY_LISTEN_LABEL = "ai.getindigo.hq-work-mesh-listen";
|
|
12
|
+
const LEGACY_LISTEN_SYSTEMD_UNIT = "hq-work-mesh-listen.service";
|
|
13
|
+
const LEGACY_LISTEN_TASK = LEGACY_LISTEN_LABEL;
|
|
14
14
|
export const LEGACY_LISTENER_DOCTOR_LINE = "legacy listener still installed";
|
|
15
15
|
export function legacyListenPlistPath(home) {
|
|
16
16
|
return path.join(home, "Library", "LaunchAgents", `${LEGACY_LISTEN_LABEL}.plist`);
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Local Work Mesh Live paths under ~/.hq/work-mesh/.
|
|
3
3
|
* Injectable root for tests (never touch the real HOME in unit tests).
|
|
4
4
|
*/
|
|
5
|
-
export declare const WORK_MESH_DIRNAME = "work-mesh";
|
|
6
5
|
export declare function workMeshRoot(home?: string, env?: NodeJS.ProcessEnv): string;
|
|
7
6
|
export declare function workMeshSpoolPath(root?: string): string;
|
|
8
7
|
export declare function workMeshHeldPath(root?: string): string;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
-
|
|
7
|
+
const WORK_MESH_DIRNAME = "work-mesh";
|
|
8
8
|
export function workMeshRoot(home = os.homedir(), env = process.env) {
|
|
9
9
|
const override = env.HQ_WORK_MESH_ROOT?.trim();
|
|
10
10
|
if (override)
|
|
@@ -19,8 +19,6 @@ export declare function ensureSpoolFile(filePath: string): void;
|
|
|
19
19
|
export declare function appendJsonlLine(filePath: string, line: string): void;
|
|
20
20
|
export declare function appendSpoolLine(line: string, root?: string): string;
|
|
21
21
|
export declare function appendHeldLine(line: string, root?: string): string;
|
|
22
|
-
/** Append a held envelope only when its eventId is not already held. */
|
|
23
|
-
export declare function appendHeldLineIfAbsent(line: string, root?: string): boolean;
|
|
24
22
|
/** Append a deduplicated held batch under one file lock and one write. */
|
|
25
23
|
export declare function appendHeldLinesIfAbsent(lines: string[], root?: string): number;
|
|
26
24
|
export declare function appendDeadLetterLine(line: string, root?: string): string;
|
|
@@ -36,12 +34,6 @@ export interface ClaimResult {
|
|
|
36
34
|
export declare function claimJsonlByRename(sourcePath: string, claimPath: string): ClaimResult;
|
|
37
35
|
export declare function claimSpool(root: string, ts?: string): ClaimResult;
|
|
38
36
|
export declare function claimHeld(root: string, ts?: string): ClaimResult;
|
|
39
|
-
/**
|
|
40
|
-
* List orphan claim files left by a crash mid-flush.
|
|
41
|
-
* Process these before claiming live spool/held (idempotent).
|
|
42
|
-
*/
|
|
43
|
-
export declare function listOrphanClaimFiles(root: string): string[];
|
|
44
|
-
export declare function readClaimFileLines(claimPath: string): string[];
|
|
45
37
|
/**
|
|
46
38
|
* Recover orphaned claim files: read their lines and return paths to unlink
|
|
47
39
|
* after the flush dispositions them.
|
|
@@ -70,7 +70,7 @@ export function appendHeldLine(line, root) {
|
|
|
70
70
|
return held;
|
|
71
71
|
}
|
|
72
72
|
/** Append a held envelope only when its eventId is not already held. */
|
|
73
|
-
|
|
73
|
+
function appendHeldLineIfAbsent(line, root) {
|
|
74
74
|
return appendHeldLinesIfAbsent([line], root) === 1;
|
|
75
75
|
}
|
|
76
76
|
/** Append a deduplicated held batch under one file lock and one write. */
|
|
@@ -266,7 +266,7 @@ const ORPHAN_CLAIM_RE = /^(spool|held)\..+\.claimed$/;
|
|
|
266
266
|
* List orphan claim files left by a crash mid-flush.
|
|
267
267
|
* Process these before claiming live spool/held (idempotent).
|
|
268
268
|
*/
|
|
269
|
-
|
|
269
|
+
function listOrphanClaimFiles(root) {
|
|
270
270
|
if (!fs.existsSync(root))
|
|
271
271
|
return [];
|
|
272
272
|
const names = fs.readdirSync(root);
|
|
@@ -278,7 +278,7 @@ export function listOrphanClaimFiles(root) {
|
|
|
278
278
|
}
|
|
279
279
|
return out.sort();
|
|
280
280
|
}
|
|
281
|
-
|
|
281
|
+
function readClaimFileLines(claimPath) {
|
|
282
282
|
if (!fs.existsSync(claimPath))
|
|
283
283
|
return [];
|
|
284
284
|
try {
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
declare const BOARD_STORY_STATUSES: readonly ["queued", "in_progress", "review", "done"];
|
|
2
2
|
export type BoardStoryStatus = (typeof BOARD_STORY_STATUSES)[number];
|
|
3
|
-
/**
|
|
4
|
-
* The ledger has more states than the Board. `blocked` and the review states
|
|
5
|
-
* need attention, while `dropped` is terminal; the Board has only one terminal
|
|
6
|
-
* column (`done`).
|
|
7
|
-
*/
|
|
8
|
-
export declare const LEDGER_STATE_TO_BOARD_STATUS: Readonly<Record<string, BoardStoryStatus>>;
|
|
9
3
|
export declare function mapSourceStoryStatus(story: {
|
|
10
4
|
status?: unknown;
|
|
11
5
|
state?: unknown;
|
|
@@ -19,4 +13,5 @@ export declare function mapReaderStoryStatus(story: {
|
|
|
19
13
|
status?: unknown;
|
|
20
14
|
state?: unknown;
|
|
21
15
|
}): string | undefined;
|
|
16
|
+
export {};
|
|
22
17
|
//# sourceMappingURL=story-status.d.ts.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
const BOARD_STORY_STATUSES = ["queued", "in_progress", "review", "done"];
|
|
2
2
|
const boardStoryStatusSet = new Set(BOARD_STORY_STATUSES);
|
|
3
3
|
/**
|
|
4
4
|
* The ledger has more states than the Board. `blocked` and the review states
|
|
5
5
|
* need attention, while `dropped` is terminal; the Board has only one terminal
|
|
6
6
|
* column (`done`).
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
const LEDGER_STATE_TO_BOARD_STATUS = {
|
|
9
9
|
todo: "queued",
|
|
10
10
|
in_progress: "in_progress",
|
|
11
11
|
in_review: "review",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { FlagClient, FlagClientOptions } from "@indigoai-us/hq-flags-client";
|
|
2
2
|
export declare const SYNC_INVALID_ENTITY_WARNING_FLAG = "sync.warn-invalid-ontology-entities";
|
|
3
3
|
export declare const SYNC_INVALID_ENTITY_WARNING_FALLBACK = false;
|
|
4
|
-
export declare const SYNC_INVALID_ENTITY_WARNING_TIMEOUT_MS = 1500;
|
|
5
4
|
type FlagClientLike = Pick<FlagClient, "ready" | "isEnabled" | "close">;
|
|
6
5
|
export interface InvalidEntityFrontmatter {
|
|
7
6
|
path: string;
|
|
@@ -6,7 +6,7 @@ import * as yaml from "js-yaml";
|
|
|
6
6
|
import { resolveFlagRegistryEndpoint } from "./flag-registry-endpoint.js";
|
|
7
7
|
export const SYNC_INVALID_ENTITY_WARNING_FLAG = "sync.warn-invalid-ontology-entities";
|
|
8
8
|
export const SYNC_INVALID_ENTITY_WARNING_FALLBACK = false;
|
|
9
|
-
|
|
9
|
+
const SYNC_INVALID_ENTITY_WARNING_TIMEOUT_MS = 1500;
|
|
10
10
|
const ENTITY_TYPES = new Set([
|
|
11
11
|
"person", "project", "company", "concept", "product", "tool",
|
|
12
12
|
"tool/technology", "model", "platform", "contact", "deal", "contract",
|
|
@@ -10,9 +10,5 @@ export declare function resolveRealTarget(target: string): string;
|
|
|
10
10
|
* Ensure parent dir exists as a real directory (not a symlink), mode 0700.
|
|
11
11
|
*/
|
|
12
12
|
export declare function ensureOwnerDir(dir: string): string;
|
|
13
|
-
/**
|
|
14
|
-
* Atomically replace target with data at mode 0600 (same-dir tmp + rename).
|
|
15
|
-
*/
|
|
16
|
-
export declare function atomicWriteFile(target: string, data: string | Buffer): void;
|
|
17
13
|
export declare function atomicWriteJson(target: string, value: unknown): void;
|
|
18
14
|
//# sourceMappingURL=atomic.d.ts.map
|
|
@@ -87,7 +87,7 @@ export function ensureOwnerDir(dir) {
|
|
|
87
87
|
/**
|
|
88
88
|
* Atomically replace target with data at mode 0600 (same-dir tmp + rename).
|
|
89
89
|
*/
|
|
90
|
-
|
|
90
|
+
function atomicWriteFile(target, data) {
|
|
91
91
|
const realTarget = resolveRealTarget(target);
|
|
92
92
|
const dir = ensureOwnerDir(path.dirname(realTarget));
|
|
93
93
|
const finalPath = path.join(dir, path.basename(realTarget));
|
|
@@ -21,9 +21,7 @@ export type LifecycleState = "open" | "terminal";
|
|
|
21
21
|
export type ContextResultKind = "bound" | "needs_company" | "company_conflict" | "needs_project" | "needs_task" | "queued" | "untracked" | "migration_pending" | "incompatible" | "error";
|
|
22
22
|
export declare const CLASSIFICATION_STATES: readonly ClassificationState[];
|
|
23
23
|
export declare const CONTEXT_RESULT_KINDS: readonly ContextResultKind[];
|
|
24
|
-
|
|
25
|
-
export declare const LOCAL_ONLY_CLASSIFICATION: ReadonlySet<ClassificationState>;
|
|
26
|
-
export interface SessionIdentity {
|
|
24
|
+
interface SessionIdentity {
|
|
27
25
|
sessionId: string;
|
|
28
26
|
providerSessionId?: string;
|
|
29
27
|
harness?: string;
|
|
@@ -91,4 +89,5 @@ export declare function normalizeTaskId(input: {
|
|
|
91
89
|
export declare function isLocalOnlyClassification(state: ClassificationState): boolean;
|
|
92
90
|
/** Content classes prohibited in durable work-context state. */
|
|
93
91
|
export declare const WORK_CONTEXT_PROHIBITED_CONTENT_CLASSES: readonly ["prompts", "model_output", "transcripts", "message_bodies", "tokens", "credentials"];
|
|
92
|
+
export {};
|
|
94
93
|
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -34,7 +34,7 @@ export const CONTEXT_RESULT_KINDS = [
|
|
|
34
34
|
"error",
|
|
35
35
|
];
|
|
36
36
|
/** Local-only classification: no tenant read or write. */
|
|
37
|
-
|
|
37
|
+
const LOCAL_ONLY_CLASSIFICATION = new Set(["needs_company", "company_conflict", "untracked"]);
|
|
38
38
|
/**
|
|
39
39
|
* Normalize taskId / storyId ingress. taskId is canonical; storyId is alias.
|
|
40
40
|
* Conflicting dual aliases are rejected.
|
|
@@ -11,13 +11,7 @@ import { type ContextResult } from "./contract.js";
|
|
|
11
11
|
export declare const PREFLIGHT_CONTRACT_VERSION: 1;
|
|
12
12
|
/** Classifications reconcile actually returns on the offline preflight path. */
|
|
13
13
|
export declare const OFFLINE_PREFLIGHT_CLASSIFICATIONS: readonly ["unresolved", "needs_company", "company_conflict", "needs_project", "needs_task", "bound", "untracked"];
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* One representative result per emitted classification, using the kind and
|
|
17
|
-
* delivery the offline path actually returns (company-resolved results are
|
|
18
|
-
* kind "queued" / delivery "queued"; local-only results are delivery "clean").
|
|
19
|
-
*/
|
|
20
|
-
export declare function preflightFixtureFor(classification: OfflinePreflightClassification): ContextResult;
|
|
14
|
+
type OfflinePreflightClassification = (typeof OFFLINE_PREFLIGHT_CLASSIFICATIONS)[number];
|
|
21
15
|
export interface PreflightFixtureFile {
|
|
22
16
|
contractVersion: typeof PREFLIGHT_CONTRACT_VERSION;
|
|
23
17
|
source: "hq-cli contracts/preflight/v1/fixtures.json";
|
|
@@ -25,4 +19,5 @@ export interface PreflightFixtureFile {
|
|
|
25
19
|
fixtures: ContextResult[];
|
|
26
20
|
}
|
|
27
21
|
export declare function buildPreflightFixtures(): PreflightFixtureFile;
|
|
22
|
+
export {};
|
|
28
23
|
//# sourceMappingURL=preflight-contract.d.ts.map
|
|
@@ -37,7 +37,7 @@ function base(classification, kind, delivery) {
|
|
|
37
37
|
* delivery the offline path actually returns (company-resolved results are
|
|
38
38
|
* kind "queued" / delivery "queued"; local-only results are delivery "clean").
|
|
39
39
|
*/
|
|
40
|
-
|
|
40
|
+
function preflightFixtureFor(classification) {
|
|
41
41
|
switch (classification) {
|
|
42
42
|
case "unresolved":
|
|
43
43
|
return base("unresolved", "queued", "queued");
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* (no git subprocess), normalises to owner/name, and matches against
|
|
6
6
|
* companies/manifest.yaml repos. Zero or multiple matches → no signal.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
interface CompaniesManifestEntry {
|
|
9
9
|
repos?: unknown;
|
|
10
10
|
[k: string]: unknown;
|
|
11
11
|
}
|
|
@@ -57,4 +57,5 @@ export declare function deriveRemoteOwnerSlug(opts: {
|
|
|
57
57
|
/** Injectable manifest reader (tests). */
|
|
58
58
|
readManifest?: (hqRoot: string) => CompaniesManifestMap | null;
|
|
59
59
|
}): string | null;
|
|
60
|
+
export {};
|
|
60
61
|
//# sourceMappingURL=repo-remote.d.ts.map
|
package/dist/utils/manifest.d.ts
CHANGED
|
@@ -14,8 +14,6 @@ export declare function findHqRoot(): string;
|
|
|
14
14
|
* Exported for tests.
|
|
15
15
|
*/
|
|
16
16
|
export declare function getManifestPath(hqRoot: string): string;
|
|
17
|
-
export declare function getLockPath(hqRoot: string): string;
|
|
18
|
-
export declare function getStatePath(hqRoot: string): string;
|
|
19
17
|
export declare function getModulesDir(hqRoot: string): string;
|
|
20
18
|
export declare function readManifest(hqRoot: string): ModulesManifest | null;
|
|
21
19
|
export declare function writeManifest(hqRoot: string, manifest: ModulesManifest): void;
|
package/dist/utils/manifest.js
CHANGED
|
@@ -37,10 +37,10 @@ export function getManifestPath(hqRoot) {
|
|
|
37
37
|
return flat;
|
|
38
38
|
return nested; // default for fresh HQs — see getModulesDir()
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
function getLockPath(hqRoot) {
|
|
41
41
|
return path.join(hqRoot, LOCK_FILE);
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
function getStatePath(hqRoot) {
|
|
44
44
|
return path.join(hqRoot, STATE_FILE);
|
|
45
45
|
}
|
|
46
46
|
export function getModulesDir(hqRoot) {
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
export type ResidentPackagePath = "agent-kit" | "agent-mcp" | "auth-login" | "agents-terminal" | "bot" | "bot-logs-follow" | "childWrapper" | "coreJobRun" | "daemon-call" | "login" | "mcp" | "daemon" | "daemon-logs-follow" | "mesh-daemon" | "lanes-watch" | "monitor-wait" | "monitor-run" | "agents-message-wait" | "integrations-oauth-wait" | "outpost-wait" | "secrets-sandbox" | "pkg-update" | "pack-install";
|
|
2
2
|
/** Runtime modules that resident commands may need after a wait starts. */
|
|
3
3
|
export declare const RESIDENT_PACKAGE_MODULES: Record<ResidentPackagePath, readonly string[]>;
|
|
4
|
-
export declare class ResidentPackagePreloadError extends Error {
|
|
5
|
-
readonly moduleSpecifier: string;
|
|
6
|
-
readonly errorClass: string;
|
|
7
|
-
constructor(moduleSpecifier: string, errorClass: string);
|
|
8
|
-
}
|
|
9
4
|
/** Report only bounded runtime metadata; never include an exception message or path. */
|
|
10
5
|
export declare function reportResidentPackagePreloadFailure(error: unknown): void;
|
|
11
6
|
/** Resolve every lazy package module before a resident command releases its lease. */
|
|
@@ -311,7 +311,7 @@ const LOADERS = {
|
|
|
311
311
|
() => import("@indigoai-us/hq-cloud"),
|
|
312
312
|
],
|
|
313
313
|
};
|
|
314
|
-
|
|
314
|
+
class ResidentPackagePreloadError extends Error {
|
|
315
315
|
moduleSpecifier;
|
|
316
316
|
errorClass;
|
|
317
317
|
constructor(moduleSpecifier, errorClass) {
|
|
@@ -33,7 +33,7 @@ export type VersionGatePhase = "preflight" | "lock_acquired" | "installer_runnin
|
|
|
33
33
|
/** The last closed version-gate phase observed in this process. */
|
|
34
34
|
export declare function getVersionGatePhase(): VersionGatePhase;
|
|
35
35
|
/** Which package manager owns the running global install. */
|
|
36
|
-
|
|
36
|
+
type InstallManager = "npm" | "pnpm" | "bun";
|
|
37
37
|
export interface VersionCheckResponse {
|
|
38
38
|
clientId: string;
|
|
39
39
|
currentVersion: string;
|
|
@@ -233,7 +233,7 @@ export declare function buildBunInstallArgv(): string[];
|
|
|
233
233
|
* Filesystem surface used by {@link cleanStalePartialInstall}. Injected so the
|
|
234
234
|
* cleanup logic is unit-testable without touching a real global prefix.
|
|
235
235
|
*/
|
|
236
|
-
|
|
236
|
+
interface StaleInstallFs {
|
|
237
237
|
readdirSync: (dir: string) => string[];
|
|
238
238
|
existsSync: (target: string) => boolean;
|
|
239
239
|
readFileSync: (target: string, encoding: "utf-8") => string;
|