@indigoai-us/hq-cli 5.341.4 → 5.342.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 +10 -0
- package/dist/commands/agent-probe.d.ts +0 -2
- package/dist/commands/agent-probe.js +0 -13
- package/dist/commands/cloud.js +1 -0
- package/dist/commands/doctor.js +7 -2
- package/dist/commands/group-grants.d.ts +0 -1
- package/dist/commands/integrations-core.d.ts +1 -1
- package/dist/commands/integrations-core.js +97 -7
- package/dist/commands/integrations.js +2 -1
- package/dist/commands/lanes-hold.d.ts +0 -1
- package/dist/commands/lanes-hold.js +0 -3
- package/dist/lib/billing/plan-lock.d.ts +0 -10
- package/dist/lib/billing/plan-lock.js +0 -4
- package/dist/lib/install/claude-targets.d.ts +0 -1
- package/dist/lib/install/claude-targets.js +0 -3
- package/dist/lib/install/codex-pack-contributions.d.ts +0 -1
- package/dist/lib/install/codex-pack-contributions.js +1 -2
- package/dist/lib/lanes/autopilot.d.ts +0 -3
- package/dist/lib/lanes/autopilot.js +0 -3
- package/dist/lib/lanes/flag-keys.d.ts +0 -6
- package/dist/lib/lanes/flag-keys.js +0 -6
- package/dist/lib/lanes/index.d.ts +1 -1
- package/dist/lib/lanes/index.js +1 -1
- package/dist/lib/lanes/keep-alive.d.ts +0 -2
- package/dist/lib/lanes/keep-alive.js +0 -2
- package/dist/lib/lanes/kr-freshness.d.ts +0 -1
- package/dist/lib/lanes/kr-freshness.js +0 -1
- package/dist/lib/lanes/outpost-worktree-pruner.d.ts +0 -1
- package/dist/lib/lanes/outpost-worktree-pruner.js +0 -1
- package/dist/lib/lanes/questions.d.ts +0 -2
- package/dist/lib/lanes/questions.js +0 -8
- package/dist/lib/lanes/reconcile.js +32 -9
- package/dist/lib/lanes/reviews.d.ts +0 -1
- package/dist/lib/lanes/reviews.js +0 -3
- package/dist/lib/lanes/spawn.d.ts +0 -1
- package/dist/lib/lanes/spawn.js +0 -1
- package/dist/lib/mesh/live/flush.d.ts +0 -6
- package/dist/lib/onboarding/cli/prompts.d.ts +0 -4
- package/dist/lib/onboarding/cli/prompts.js +0 -9
- package/dist/lib/work-context/bind-best.d.ts +0 -4
- package/dist/lib/work-context/bind-best.js +0 -7
- package/dist/lib/work-context/outbox.d.ts +0 -6
- package/dist/lib/work-context/outbox.js +0 -61
- package/dist/lib/work-context/prd-sync.d.ts +0 -1
- package/dist/lib/work-context/prd-sync.js +0 -8
- package/dist/utils/git.d.ts +0 -1
- package/dist/utils/git.js +0 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.342.0] — 2026-10-04
|
|
6
|
+
|
|
7
|
+
- Keep `hq integrations call` alive through slow provider calls with bounded async-job polling, safe idempotent retry guidance on timeout, and validation of terminal responses.
|
|
8
|
+
|
|
9
|
+
- Let `hq sync now` skip unchanged server-owned cloud placeholders while keeping their warnings visible, so the sync can complete.
|
|
10
|
+
|
|
11
|
+
## [5.341.5] — 2026-10-04
|
|
12
|
+
- Reconcile can close an eligible done-story worker with a legacy missing `interrupted_at` when a matching watcher classification proves the interruption age.
|
|
13
|
+
- `hq doctor --verbose` now shows passing checks, including hqd runtime health details.
|
|
14
|
+
|
|
5
15
|
## [5.341.4] — 2026-10-03
|
|
6
16
|
- Prevent daemon restarts from waiting on stale or already-owned Claude bridge sessions, and keep captured startup diagnostics useful without exposing authorization credentials.
|
|
7
17
|
|
|
@@ -62,8 +62,6 @@ export interface ProbeDeps {
|
|
|
62
62
|
}
|
|
63
63
|
export declare function heartbeatAgeSeconds(paths: Pick<AgentKitPaths, "lastHeartbeatPath">, now?: () => Date): number | null;
|
|
64
64
|
export declare function runProbe(deps: ProbeDeps): Promise<ProbeResult>;
|
|
65
|
-
/** True when any inbox item (whatever its channel shape) carries the nonce. */
|
|
66
|
-
export declare function inboxContainsNonce(body: unknown, nonce: string): boolean;
|
|
67
65
|
export declare function formatHeartbeatAge(age: number | null): string;
|
|
68
66
|
/**
|
|
69
67
|
* Recipe contract: `PASS <check> <detail>` / `FAIL <check> <detail>` per
|
|
@@ -237,19 +237,6 @@ export async function runProbe(deps) {
|
|
|
237
237
|
}
|
|
238
238
|
return result;
|
|
239
239
|
}
|
|
240
|
-
/** True when any inbox item (whatever its channel shape) carries the nonce. */
|
|
241
|
-
export function inboxContainsNonce(body, nonce) {
|
|
242
|
-
const rec = body && typeof body === "object" ? body : {};
|
|
243
|
-
const messages = Array.isArray(rec.messages) ? rec.messages : [];
|
|
244
|
-
return messages.some((m) => {
|
|
245
|
-
try {
|
|
246
|
-
return JSON.stringify(m).includes(nonce);
|
|
247
|
-
}
|
|
248
|
-
catch {
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
240
|
export function formatHeartbeatAge(age) {
|
|
254
241
|
if (age === null)
|
|
255
242
|
return "never (kit heartbeat has not posted yet)";
|
package/dist/commands/cloud.js
CHANGED
|
@@ -1751,6 +1751,7 @@ async function runNowSingle(hqRoot, company, personal, message, onConflict, mode
|
|
|
1751
1751
|
hqRoot,
|
|
1752
1752
|
progressRecorder: trackingProgressRecorder(planLimitTracker, pushProgressCompany),
|
|
1753
1753
|
skipUnchanged: true,
|
|
1754
|
+
serverOwnedPathPolicy: "skip",
|
|
1754
1755
|
propagateDeletes: true,
|
|
1755
1756
|
propagateDeletePolicy: resolveDeletePolicy(),
|
|
1756
1757
|
...(onConflict ? { onConflict } : {}),
|
package/dist/commands/doctor.js
CHANGED
|
@@ -262,7 +262,7 @@ export function registerDoctorCommand(program) {
|
|
|
262
262
|
.addOption(new Option("--client-health-report", "Resolve the opt-in hq-flags gate used by the client-health report hook.").hideHelp())
|
|
263
263
|
.option("--yes", "Skip the interactive --fix confirmation (non-interactive use).")
|
|
264
264
|
.option("--force", "Let --fix run despite uncommitted changes under .claude/, .codex/, or .grok/.")
|
|
265
|
-
.action(async (opts) => {
|
|
265
|
+
.action(async (opts, command) => {
|
|
266
266
|
// `--fix` repairs the whole tree from its own allowlist and has no
|
|
267
267
|
// notion of a check family, so a scope passed alongside it could only
|
|
268
268
|
// be ignored. Ignoring it silently is the dangerous reading: an
|
|
@@ -336,7 +336,12 @@ export function registerDoctorCommand(program) {
|
|
|
336
336
|
: undefined;
|
|
337
337
|
const result = await runDoctor({
|
|
338
338
|
json,
|
|
339
|
-
|
|
339
|
+
// `src/main.ts` also declares --verbose on the root program. When
|
|
340
|
+
// Commander parses `hq doctor --verbose`, it can store the flag on
|
|
341
|
+
// the root command instead of the doctor command's local options.
|
|
342
|
+
// Read the merged option set so both the root diagnostic flag and
|
|
343
|
+
// this command's own option reach the text renderer.
|
|
344
|
+
verbose: command.optsWithGlobals().verbose === true,
|
|
340
345
|
color,
|
|
341
346
|
platform,
|
|
342
347
|
sessionId: opts.sessionId,
|
|
@@ -18,7 +18,6 @@ import { Command } from "commander";
|
|
|
18
18
|
* All require a Cognito idToken bearer; 403 (code FORBIDDEN) on authz failure.
|
|
19
19
|
*/
|
|
20
20
|
export declare const VALID_GRANT_ROLES: Set<string>;
|
|
21
|
-
export type GrantRole = "owner" | "admin" | "member" | "guest";
|
|
22
21
|
export interface GroupGrant {
|
|
23
22
|
groupId: string;
|
|
24
23
|
sourceCompanyUid: string;
|
|
@@ -248,7 +248,7 @@ export declare function resolveConnection(token: string, companyUid: string, app
|
|
|
248
248
|
}, recoveryOpts?: {
|
|
249
249
|
allowSingleRevoked?: boolean;
|
|
250
250
|
}): Promise<AdminConnection>;
|
|
251
|
-
export declare function callGateway(token: string, params: Record<string, unknown
|
|
251
|
+
export declare function callGateway(token: string, params: Record<string, unknown>, idempotencyKey?: string): Promise<GatewayMessage>;
|
|
252
252
|
/**
|
|
253
253
|
* Gateway results arrive MCP-style: `{ content: [{ type: "text", text }] }`
|
|
254
254
|
* where `text` is the provider's JSON. Unwrap to the inner payload; fall back
|
|
@@ -18,6 +18,8 @@ import { redactSensitiveUrls, redactUrlsInText } from "../utils/redact-url.js";
|
|
|
18
18
|
import { connectionHealthNotice } from "../lib/integrations/health.js";
|
|
19
19
|
import { bareProvider } from "../lib/integrations/provider-slug.js";
|
|
20
20
|
export { bareProvider } from "../lib/integrations/provider-slug.js";
|
|
21
|
+
const ASYNC_GATEWAY_POLL_INTERVAL_MS = 1_000;
|
|
22
|
+
const ASYNC_GATEWAY_DEADLINE_MS = 4 * 60_000 + 30_000;
|
|
21
23
|
export class IntegrationsCliError extends Error {
|
|
22
24
|
/**
|
|
23
25
|
* True when the error is the caller's request/state/permission (a client 4xx
|
|
@@ -397,7 +399,8 @@ export async function resolveConnection(token, companyUid, app, opts, recoveryOp
|
|
|
397
399
|
}
|
|
398
400
|
return selectConnection(connections, opts);
|
|
399
401
|
}
|
|
400
|
-
export async function callGateway(token, params) {
|
|
402
|
+
export async function callGateway(token, params, idempotencyKey) {
|
|
403
|
+
const deadline = Date.now() + ASYNC_GATEWAY_DEADLINE_MS;
|
|
401
404
|
const res = await vaultApiFetch({
|
|
402
405
|
token,
|
|
403
406
|
path: "/v1/integrations/mcp",
|
|
@@ -410,7 +413,23 @@ export async function callGateway(token, params) {
|
|
|
410
413
|
},
|
|
411
414
|
});
|
|
412
415
|
const message = (await res.json().catch(() => null));
|
|
413
|
-
|
|
416
|
+
let terminalMessage = message;
|
|
417
|
+
if (res.status === 202) {
|
|
418
|
+
const accepted = message;
|
|
419
|
+
const jobId = accepted && typeof accepted.jobId === "string" ? accepted.jobId : "";
|
|
420
|
+
if (accepted?.status !== "pending" || !/^imj_[A-Za-z0-9_-]+$/.test(jobId)) {
|
|
421
|
+
throw new IntegrationsCliError(`Integration gateway returned an invalid async job response (job id: ${jobId || "missing"}).`, { expected: false, status: 202 });
|
|
422
|
+
}
|
|
423
|
+
const companyUid = typeof params.companyUid === "string" ? params.companyUid : "";
|
|
424
|
+
if (!companyUid) {
|
|
425
|
+
throw new IntegrationsCliError(`Cannot poll integration job ${jobId}: the company id is missing.`, { expected: true });
|
|
426
|
+
}
|
|
427
|
+
if (!idempotencyKey) {
|
|
428
|
+
throw new IntegrationsCliError(`Integration gateway accepted async job ${jobId} without an idempotency key.`, { expected: false, status: 202 });
|
|
429
|
+
}
|
|
430
|
+
terminalMessage = await pollAsyncGatewayJob(token, companyUid, jobId, idempotencyKey, deadline);
|
|
431
|
+
}
|
|
432
|
+
if (res.status !== 202 && (!res.ok || !terminalMessage)) {
|
|
414
433
|
raiseIfUnauthorized(res);
|
|
415
434
|
raiseIfUpstreamUnavailable(res);
|
|
416
435
|
// Carry the HTTP status so a reportable transport failure (e.g. a 501 that
|
|
@@ -420,7 +439,7 @@ export async function callGateway(token, params) {
|
|
|
420
439
|
// `status`. This does not change the `expected` decision above.
|
|
421
440
|
throw new IntegrationsCliError(`Integration gateway request failed (HTTP ${res.status}).`, { expected: isClientError(res.status), status: res.status });
|
|
422
441
|
}
|
|
423
|
-
if (
|
|
442
|
+
if (terminalMessage?.error) {
|
|
424
443
|
// The gateway's error text is minted UPSTREAM (hq-pro, the integration
|
|
425
444
|
// factory, and beyond it the third-party provider), so it is untrusted:
|
|
426
445
|
// scrub credentials and bound the length here, at the throw site, because
|
|
@@ -429,16 +448,87 @@ export async function callGateway(token, params) {
|
|
|
429
448
|
// The chain is idempotent, so the unexpected path scrubbing again is a
|
|
430
449
|
// no-op. This preserves PR #298's user-visible diagnostic; it only makes
|
|
431
450
|
// it safe on the newly-expected path.
|
|
432
|
-
throw new IntegrationsCliError(redactErrorText(
|
|
451
|
+
throw new IntegrationsCliError(redactErrorText(terminalMessage.error.message ?? "") ||
|
|
433
452
|
"Integration gateway returned an error.", {
|
|
434
|
-
expected: isExpectedGatewayError(
|
|
453
|
+
expected: isExpectedGatewayError(terminalMessage.error.code),
|
|
435
454
|
// Carry the protocol code to the capture site as a bounded grouping
|
|
436
455
|
// discriminator (HQ-CLI collision, Sentry 7642756130). This does not
|
|
437
456
|
// alter the `expected` decision above; it only labels the error.
|
|
438
|
-
...(
|
|
457
|
+
...(terminalMessage.error.code !== undefined ? { rpcCode: terminalMessage.error.code } : {}),
|
|
439
458
|
});
|
|
440
459
|
}
|
|
441
|
-
return
|
|
460
|
+
return terminalMessage;
|
|
461
|
+
}
|
|
462
|
+
async function pollAsyncGatewayJob(token, companyUid, jobId, idempotencyKey, deadline) {
|
|
463
|
+
const jobPath = `/v1/integrations/mcp/jobs/${encodeURIComponent(jobId)}`;
|
|
464
|
+
while (Date.now() < deadline) {
|
|
465
|
+
const requestRemainingMs = deadline - Date.now();
|
|
466
|
+
if (requestRemainingMs <= 0)
|
|
467
|
+
break;
|
|
468
|
+
const controller = new AbortController();
|
|
469
|
+
const requestTimeout = setTimeout(() => controller.abort(), requestRemainingMs);
|
|
470
|
+
let res;
|
|
471
|
+
let poll;
|
|
472
|
+
try {
|
|
473
|
+
res = await vaultApiFetch({
|
|
474
|
+
token,
|
|
475
|
+
path: jobPath,
|
|
476
|
+
method: "GET",
|
|
477
|
+
query: { companyUid },
|
|
478
|
+
signal: controller.signal,
|
|
479
|
+
});
|
|
480
|
+
poll = (await res.json().catch(() => null));
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
if (!controller.signal.aborted)
|
|
484
|
+
throw error;
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
finally {
|
|
488
|
+
clearTimeout(requestTimeout);
|
|
489
|
+
}
|
|
490
|
+
if (!res.ok) {
|
|
491
|
+
raiseIfUnauthorized(res);
|
|
492
|
+
raiseIfUpstreamUnavailable(res);
|
|
493
|
+
if (res.status === 404) {
|
|
494
|
+
throw new IntegrationsCliError(`Integration job ${jobId} was not found or is no longer available.`, { expected: true, status: 404 });
|
|
495
|
+
}
|
|
496
|
+
throw new IntegrationsCliError(`Integration job ${jobId} polling failed (HTTP ${res.status}).`, { expected: isClientError(res.status), status: res.status });
|
|
497
|
+
}
|
|
498
|
+
if (!poll || typeof poll !== "object") {
|
|
499
|
+
throw new IntegrationsCliError(`Integration job ${jobId} returned an invalid poll response.`, { expected: true });
|
|
500
|
+
}
|
|
501
|
+
if (poll.status === "result" || poll.status === "error") {
|
|
502
|
+
const response = poll.response;
|
|
503
|
+
const isPlainObject = response !== null &&
|
|
504
|
+
typeof response === "object" &&
|
|
505
|
+
!Array.isArray(response) &&
|
|
506
|
+
(Object.getPrototypeOf(response) === Object.prototype || Object.getPrototypeOf(response) === null);
|
|
507
|
+
const responseRecord = isPlainObject ? response : undefined;
|
|
508
|
+
const hasResult = responseRecord ? Object.hasOwn(responseRecord, "result") : false;
|
|
509
|
+
const hasError = responseRecord ? Object.hasOwn(responseRecord, "error") : false;
|
|
510
|
+
const error = responseRecord?.error;
|
|
511
|
+
const validError = error !== null &&
|
|
512
|
+
typeof error === "object" &&
|
|
513
|
+
!Array.isArray(error) &&
|
|
514
|
+
(Object.getPrototypeOf(error) === Object.prototype || Object.getPrototypeOf(error) === null);
|
|
515
|
+
const hasJsonRpcOutcome = responseRecord?.jsonrpc === "2.0" &&
|
|
516
|
+
hasResult !== hasError &&
|
|
517
|
+
(!hasError || validError);
|
|
518
|
+
if (!hasJsonRpcOutcome) {
|
|
519
|
+
throw new IntegrationsCliError(`Integration job ${jobId} returned an invalid JSON-RPC response.`, { expected: false });
|
|
520
|
+
}
|
|
521
|
+
return response;
|
|
522
|
+
}
|
|
523
|
+
if (poll.status !== "pending") {
|
|
524
|
+
throw new IntegrationsCliError(`Integration job ${jobId} returned unknown status '${String(poll.status)}'.`, { expected: true });
|
|
525
|
+
}
|
|
526
|
+
const remainingMs = deadline - Date.now();
|
|
527
|
+
if (remainingMs <= 0)
|
|
528
|
+
break;
|
|
529
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(ASYNC_GATEWAY_POLL_INTERVAL_MS, remainingMs)));
|
|
530
|
+
}
|
|
531
|
+
throw new IntegrationsCliError(`Timed out waiting for integration job ${jobId}; the server job may still finish. To safely retry, rerun with --idempotency-key ${idempotencyKey}.`, { expected: true });
|
|
442
532
|
}
|
|
443
533
|
/**
|
|
444
534
|
* Gateway results arrive MCP-style: `{ content: [{ type: "text", text }] }`
|
|
@@ -338,6 +338,7 @@ export function registerIntegrationsCommand(program) {
|
|
|
338
338
|
const idempotencyKey = opts.idempotencyKey ?? `hq-cli-${randomUUID()}`;
|
|
339
339
|
const message = await callGateway(token, {
|
|
340
340
|
companyUid,
|
|
341
|
+
acceptAsync: true,
|
|
341
342
|
name: `${prefix}.mcp.tools.call`,
|
|
342
343
|
arguments: {
|
|
343
344
|
companyUid,
|
|
@@ -346,7 +347,7 @@ export function registerIntegrationsCommand(program) {
|
|
|
346
347
|
arguments: parsedArgs,
|
|
347
348
|
idempotencyKey,
|
|
348
349
|
},
|
|
349
|
-
});
|
|
350
|
+
}, idempotencyKey);
|
|
350
351
|
const payload = unwrapGatewayResult(message.result);
|
|
351
352
|
const queued = queuedOutcome(payload);
|
|
352
353
|
if (queued) {
|
|
@@ -35,7 +35,6 @@ export interface LaneRepoMergeHoldDeps {
|
|
|
35
35
|
mergeReviewEnabled?: (company: LaneCompanyRef) => boolean | Promise<boolean>;
|
|
36
36
|
}
|
|
37
37
|
type WrapHandler = <Args extends unknown[]>(action: (...args: Args) => Promise<void>) => (...args: Args) => Promise<void>;
|
|
38
|
-
export declare function repoMergeHoldPath(hqRoot: string, repo: string): string;
|
|
39
38
|
/** Serialize the read-modify-write cycle so concurrent set/release calls cannot overwrite each other. */
|
|
40
39
|
export declare function withRepoMergeHoldRecordLock<T>(recordPath: string, action: () => T | Promise<T>): Promise<T>;
|
|
41
40
|
export declare function registerLaneRepoMergeHoldCommand(lanes: Command, deps: LaneRepoMergeHoldDeps, wrap: WrapHandler): void;
|
|
@@ -23,9 +23,6 @@ function holdFilePath(hqRoot, repo) {
|
|
|
23
23
|
const [owner, repository] = canonicalRepo(repo).split("/");
|
|
24
24
|
return path.join(hqRoot, REPO_MERGE_HOLDS_REL, `${owner}__${repository}.json`);
|
|
25
25
|
}
|
|
26
|
-
export function repoMergeHoldPath(hqRoot, repo) {
|
|
27
|
-
return holdFilePath(hqRoot, repo);
|
|
28
|
-
}
|
|
29
26
|
function nonEmptyText(field, raw) {
|
|
30
27
|
const value = raw.trim();
|
|
31
28
|
if (!value)
|
|
@@ -28,18 +28,12 @@ export { parseFreeMonth, type PlanLimitFreeMonth };
|
|
|
28
28
|
* nag-only and never appear here.
|
|
29
29
|
*/
|
|
30
30
|
export declare const PLAN_LIMIT_REASONS: readonly ["users", "integrations", "secrets", "agents"];
|
|
31
|
-
/** @deprecated US-040 — alias of {@link PLAN_LIMIT_REASONS}. */
|
|
32
|
-
export declare const PLAN_LOCK_REASONS: readonly ["users", "integrations", "secrets", "agents"];
|
|
33
31
|
export type PlanLimitReason = (typeof PLAN_LIMIT_REASONS)[number];
|
|
34
|
-
/** @deprecated US-040 — alias of {@link PlanLimitReason}. */
|
|
35
|
-
export type PlanLockReason = PlanLimitReason;
|
|
36
32
|
/** Optional member decoration for the notice ("7 of 5 members"). */
|
|
37
33
|
export interface PlanLimitMembers {
|
|
38
34
|
used: number;
|
|
39
35
|
limit: number;
|
|
40
36
|
}
|
|
41
|
-
/** @deprecated US-040 — alias of {@link PlanLimitMembers}. */
|
|
42
|
-
export type PlanLockMembers = PlanLimitMembers;
|
|
43
37
|
export interface PlanLimitStatus {
|
|
44
38
|
companySlug: string;
|
|
45
39
|
companyUid?: string;
|
|
@@ -58,8 +52,6 @@ export interface PlanLimitStatus {
|
|
|
58
52
|
plan?: "free" | "paid" | "enterprise";
|
|
59
53
|
checkedAt: string;
|
|
60
54
|
}
|
|
61
|
-
/** @deprecated US-040 — alias of {@link PlanLimitStatus}. */
|
|
62
|
-
export type PlanLockStatus = PlanLimitStatus;
|
|
63
55
|
/** Starter member cap quoted when the server did not send a users.limit. */
|
|
64
56
|
export declare const STARTER_MEMBER_TARGET = 5;
|
|
65
57
|
/**
|
|
@@ -101,8 +93,6 @@ export declare function selectUsages(body: unknown): Partial<Record<PlanLimitRea
|
|
|
101
93
|
export declare function fetchPlanLimitStatus(token: string, companyRef: string, opts?: {
|
|
102
94
|
timeoutMs?: number;
|
|
103
95
|
}): Promise<PlanLimitStatus | null>;
|
|
104
|
-
/** @deprecated US-040 — alias of {@link fetchPlanLimitStatus}. */
|
|
105
|
-
export declare const fetchPlanLockStatus: typeof fetchPlanLimitStatus;
|
|
106
96
|
/** Why the workspace is over, one clause per reason. */
|
|
107
97
|
export declare function reasonLabel(reason: PlanLimitReason): string;
|
|
108
98
|
/**
|
|
@@ -40,8 +40,6 @@ export const PLAN_LIMIT_REASONS = [
|
|
|
40
40
|
"secrets",
|
|
41
41
|
"agents",
|
|
42
42
|
];
|
|
43
|
-
/** @deprecated US-040 — alias of {@link PLAN_LIMIT_REASONS}. */
|
|
44
|
-
export const PLAN_LOCK_REASONS = PLAN_LIMIT_REASONS;
|
|
45
43
|
/** Starter member cap quoted when the server did not send a users.limit. */
|
|
46
44
|
export const STARTER_MEMBER_TARGET = 5;
|
|
47
45
|
/**
|
|
@@ -266,8 +264,6 @@ export async function fetchPlanLimitStatus(token, companyRef, opts = {}) {
|
|
|
266
264
|
return null;
|
|
267
265
|
}
|
|
268
266
|
}
|
|
269
|
-
/** @deprecated US-040 — alias of {@link fetchPlanLimitStatus}. */
|
|
270
|
-
export const fetchPlanLockStatus = fetchPlanLimitStatus;
|
|
271
267
|
/** Why the workspace is over, one clause per reason. */
|
|
272
268
|
export function reasonLabel(reason) {
|
|
273
269
|
switch (reason) {
|
|
@@ -34,7 +34,6 @@ export declare function claudeMdBlock(hqRoot: string): string;
|
|
|
34
34
|
export declare function addClaudeMdBlock(current: string | null, hqRoot: string): string;
|
|
35
35
|
/** Strip the HQ block, plus the separator `addClaudeMdBlock` put before it. */
|
|
36
36
|
export declare function removeClaudeMdBlock(current: string): string;
|
|
37
|
-
export declare function hasClaudeMdBlock(current: string | null): boolean;
|
|
38
37
|
type Doc = Record<string, unknown>;
|
|
39
38
|
/**
|
|
40
39
|
* Add one HQ hook group per event; idempotent. An HQ entry for the other
|
|
@@ -90,9 +90,6 @@ export function removeClaudeMdBlock(current) {
|
|
|
90
90
|
start -= 1;
|
|
91
91
|
return current.slice(0, start) + current.slice(end);
|
|
92
92
|
}
|
|
93
|
-
export function hasClaudeMdBlock(current) {
|
|
94
|
-
return current !== null && current.includes(CLAUDE_MD_BEGIN) && current.includes(CLAUDE_MD_END);
|
|
95
|
-
}
|
|
96
93
|
function isHqHookEntry(entry, hqRoot) {
|
|
97
94
|
if (!entry || typeof entry !== 'object')
|
|
98
95
|
return false;
|
|
@@ -3,6 +3,5 @@ export declare function syncCodexPackSkills(packDir: string, packName: string, n
|
|
|
3
3
|
export declare function mergeCodexPackHooks(doc: Doc, packDir: string, items: string[]): Doc;
|
|
4
4
|
export declare function removeCodexPackHooks(doc: Doc, packDir: string, items: string[]): Doc;
|
|
5
5
|
export declare function syncCodexPackHooks(packDir: string, items: string[], remove?: boolean, home?: string, hqRoot?: string, packName?: string): void;
|
|
6
|
-
export declare function readCodexPackHooks(target: string): Doc;
|
|
7
6
|
export {};
|
|
8
7
|
//# sourceMappingURL=codex-pack-contributions.d.ts.map
|
|
@@ -2,7 +2,7 @@ import * as fs from 'node:fs';
|
|
|
2
2
|
import * as os from 'node:os';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { anywhereRuntimeEnabled } from '../../commands/anywhere-runtime-flag.js';
|
|
5
|
-
import { jsonFormat,
|
|
5
|
+
import { jsonFormat, writeConfigAtomic } from '../../commands/mcp-registration.js';
|
|
6
6
|
import { hookTargetFor } from '../../commands/install-global.js';
|
|
7
7
|
import { addCodexHooks, codexTargets, removeCodexHooks } from './codex-targets.js';
|
|
8
8
|
const configFormat = {
|
|
@@ -224,5 +224,4 @@ export function syncCodexPackHooks(packDir, items, remove = false, home = os.hom
|
|
|
224
224
|
env: { home },
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
|
-
export function readCodexPackHooks(target) { return readConfigDoc(target, configFormat).doc; }
|
|
228
227
|
//# sourceMappingURL=codex-pack-contributions.js.map
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { readLanesRegistryFlag } from "./registry-flag.js";
|
|
2
2
|
import type { LaneRecord } from "./types.js";
|
|
3
3
|
export declare const LEAD_AUTOPILOT_FLAG = "lanes.lead-autopilot";
|
|
4
|
-
export declare const LEAD_AUTOPILOT_DEFAULT_ENABLED = false;
|
|
5
4
|
export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = "lanes.autopilot-missed-deadline-escalation";
|
|
6
|
-
export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DEFAULT_ENABLED = false;
|
|
7
5
|
export declare const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DELAY_MS: number;
|
|
8
6
|
export declare const LEAD_AUTOPILOT_NUDGE_DEDUPE_FLAG = "lanes.autopilot-nudge-dedupe";
|
|
9
|
-
export declare const LEAD_AUTOPILOT_NUDGE_DEDUPE_DEFAULT_ENABLED = false;
|
|
10
7
|
export declare const LEAD_AUTOPILOT_NUDGE_REDELIVERY_DELAY_MS: number;
|
|
11
8
|
export declare const LEAD_AUTOPILOT_NUDGE_STATE_RETENTION_MS: number;
|
|
12
9
|
export declare const LEAD_AUTOPILOT_REVIEW_DELAY_MS: number;
|
|
@@ -11,12 +11,9 @@ import { resolveLaneCompany } from "./lane-company.js";
|
|
|
11
11
|
import { readLanesRegistryFlag } from "./registry-flag.js";
|
|
12
12
|
import { readAllLanes } from "./store.js";
|
|
13
13
|
export const LEAD_AUTOPILOT_FLAG = "lanes.lead-autopilot";
|
|
14
|
-
export const LEAD_AUTOPILOT_DEFAULT_ENABLED = false;
|
|
15
14
|
export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = LANE_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG;
|
|
16
|
-
export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DEFAULT_ENABLED = false;
|
|
17
15
|
export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DELAY_MS = 60 * 60_000;
|
|
18
16
|
export const LEAD_AUTOPILOT_NUDGE_DEDUPE_FLAG = LANE_AUTOPILOT_NUDGE_DEDUPE_FLAG;
|
|
19
|
-
export const LEAD_AUTOPILOT_NUDGE_DEDUPE_DEFAULT_ENABLED = false;
|
|
20
17
|
export const LEAD_AUTOPILOT_NUDGE_REDELIVERY_DELAY_MS = 30 * 60_000;
|
|
21
18
|
export const LEAD_AUTOPILOT_NUDGE_STATE_RETENTION_MS = 24 * 60 * 60_000;
|
|
22
19
|
const LEAD_AUTOPILOT_DELIVERED_ID_RETENTION_MS = 7 * 24 * 60 * 60_000;
|
|
@@ -8,16 +8,13 @@ export declare const LANE_ENVELOPE_REPAIR_CONTINUE_FLAG = "lanes.envelope-repair
|
|
|
8
8
|
export declare const LANE_HIRE_GRANT_FINISHED_LANES_FLAG = "lanes.hire-grant-count-live-only";
|
|
9
9
|
/** Skips owner refreshes during ordinary lane list polling when explicitly enabled. */
|
|
10
10
|
export declare const LANE_LIST_SKIP_REMOTE_REFRESH_FLAG = "lanes.list-skip-remote-refresh";
|
|
11
|
-
export declare const LANE_LIST_SKIP_REMOTE_REFRESH_DEFAULT_ENABLED = false;
|
|
12
11
|
/** Enables missed-deadline lead nudges and second-miss operator escalation. */
|
|
13
12
|
export declare const LANE_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = "lanes.autopilot-missed-deadline-escalation";
|
|
14
13
|
export declare const LANE_AUTOPILOT_NUDGE_DEDUPE_FLAG = "lanes.autopilot-nudge-dedupe";
|
|
15
14
|
/** Enables company-scoped lookup of a hostless lane ULID across Outpost indexes. */
|
|
16
15
|
export declare const LANE_MESSAGE_ROUTE_OWNER_HOST_FLAG = "lanes.message-route-owner-host";
|
|
17
|
-
export declare const LANE_MESSAGE_ROUTE_OWNER_HOST_DEFAULT_ENABLED = false;
|
|
18
16
|
/** Enables stale manager-status KPI reporting and one-time lead nudges. */
|
|
19
17
|
export declare const LEAD_AUTOPILOT_KPI_STALENESS_FLAG = "lanes.autopilot-kpi-staleness";
|
|
20
|
-
export declare const LEAD_AUTOPILOT_KPI_STALENESS_DEFAULT_ENABLED = false;
|
|
21
18
|
/** Skips malformed lead inputs individually instead of aborting the pass. */
|
|
22
19
|
export declare const LEAD_AUTOPILOT_PER_LEAD_ERRORS_FLAG = "lanes.autopilot-per-lead-errors";
|
|
23
20
|
export declare const LEAD_AUTOPILOT_PER_LEAD_ERRORS_DEFAULT_ENABLED = false;
|
|
@@ -26,11 +23,8 @@ export declare const LEAD_AUTOPILOT_KPI_STALENESS_BATCH_FLAG = "lanes.autopilot-
|
|
|
26
23
|
export declare const LEAD_AUTOPILOT_KPI_STALENESS_BATCH_DEFAULT_ENABLED = false;
|
|
27
24
|
/** Enables staleness notices for a registered lead's dashboard headline. */
|
|
28
25
|
export declare const LEAD_AUTOPILOT_HEADLINE_STALENESS_FLAG = "lanes.autopilot-headline-staleness";
|
|
29
|
-
export declare const LEAD_AUTOPILOT_HEADLINE_STALENESS_DEFAULT_ENABLED = false;
|
|
30
26
|
/** Lets an Outpost's autopilot wake leads created on that Outpost, which record a local host. */
|
|
31
27
|
export declare const LEAD_AUTOPILOT_OUTPOST_NATIVE_LEADS_FLAG = "lanes.autopilot-outpost-native-leads";
|
|
32
|
-
export declare const LEAD_AUTOPILOT_OUTPOST_NATIVE_LEADS_DEFAULT_ENABLED = false;
|
|
33
28
|
/** Allows applying an operator-reviewed repair of messages stranded in bare-ULID dropboxes. */
|
|
34
29
|
export declare const LANE_ORPHANED_BARE_ID_DROPBOX_REPAIR_FLAG = "lanes.orphaned-bare-id-dropbox-repair";
|
|
35
|
-
export declare const LANE_ORPHANED_BARE_ID_DROPBOX_REPAIR_DEFAULT_ENABLED = false;
|
|
36
30
|
//# sourceMappingURL=flag-keys.d.ts.map
|
|
@@ -8,16 +8,13 @@ export const LANE_ENVELOPE_REPAIR_CONTINUE_FLAG = "lanes.envelope-repair-continu
|
|
|
8
8
|
export const LANE_HIRE_GRANT_FINISHED_LANES_FLAG = "lanes.hire-grant-count-live-only";
|
|
9
9
|
/** Skips owner refreshes during ordinary lane list polling when explicitly enabled. */
|
|
10
10
|
export const LANE_LIST_SKIP_REMOTE_REFRESH_FLAG = "lanes.list-skip-remote-refresh";
|
|
11
|
-
export const LANE_LIST_SKIP_REMOTE_REFRESH_DEFAULT_ENABLED = false;
|
|
12
11
|
/** Enables missed-deadline lead nudges and second-miss operator escalation. */
|
|
13
12
|
export const LANE_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = "lanes.autopilot-missed-deadline-escalation";
|
|
14
13
|
export const LANE_AUTOPILOT_NUDGE_DEDUPE_FLAG = "lanes.autopilot-nudge-dedupe";
|
|
15
14
|
/** Enables company-scoped lookup of a hostless lane ULID across Outpost indexes. */
|
|
16
15
|
export const LANE_MESSAGE_ROUTE_OWNER_HOST_FLAG = "lanes.message-route-owner-host";
|
|
17
|
-
export const LANE_MESSAGE_ROUTE_OWNER_HOST_DEFAULT_ENABLED = false;
|
|
18
16
|
/** Enables stale manager-status KPI reporting and one-time lead nudges. */
|
|
19
17
|
export const LEAD_AUTOPILOT_KPI_STALENESS_FLAG = "lanes.autopilot-kpi-staleness";
|
|
20
|
-
export const LEAD_AUTOPILOT_KPI_STALENESS_DEFAULT_ENABLED = false;
|
|
21
18
|
/** Skips malformed lead inputs individually instead of aborting the pass. */
|
|
22
19
|
export const LEAD_AUTOPILOT_PER_LEAD_ERRORS_FLAG = "lanes.autopilot-per-lead-errors";
|
|
23
20
|
export const LEAD_AUTOPILOT_PER_LEAD_ERRORS_DEFAULT_ENABLED = false;
|
|
@@ -26,11 +23,8 @@ export const LEAD_AUTOPILOT_KPI_STALENESS_BATCH_FLAG = "lanes.autopilot-kpi-stal
|
|
|
26
23
|
export const LEAD_AUTOPILOT_KPI_STALENESS_BATCH_DEFAULT_ENABLED = false;
|
|
27
24
|
/** Enables staleness notices for a registered lead's dashboard headline. */
|
|
28
25
|
export const LEAD_AUTOPILOT_HEADLINE_STALENESS_FLAG = "lanes.autopilot-headline-staleness";
|
|
29
|
-
export const LEAD_AUTOPILOT_HEADLINE_STALENESS_DEFAULT_ENABLED = false;
|
|
30
26
|
/** Lets an Outpost's autopilot wake leads created on that Outpost, which record a local host. */
|
|
31
27
|
export const LEAD_AUTOPILOT_OUTPOST_NATIVE_LEADS_FLAG = "lanes.autopilot-outpost-native-leads";
|
|
32
|
-
export const LEAD_AUTOPILOT_OUTPOST_NATIVE_LEADS_DEFAULT_ENABLED = false;
|
|
33
28
|
/** Allows applying an operator-reviewed repair of messages stranded in bare-ULID dropboxes. */
|
|
34
29
|
export const LANE_ORPHANED_BARE_ID_DROPBOX_REPAIR_FLAG = "lanes.orphaned-bare-id-dropbox-repair";
|
|
35
|
-
export const LANE_ORPHANED_BARE_ID_DROPBOX_REPAIR_DEFAULT_ENABLED = false;
|
|
36
30
|
//# sourceMappingURL=flag-keys.js.map
|
|
@@ -28,7 +28,7 @@ export { MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONIT
|
|
|
28
28
|
export type { LiveMonitorEvidenceOptions, MonitorEngine, MonitorEvidence, MonitorEvidenceReader, MonitorTaskEvidence, } from "./monitor.js";
|
|
29
29
|
export { IMDS_HOST, IMDS_INSTANCE_ID_URL, IMDS_TIMEOUT_MS, IMDS_TOKEN_URL, defaultReadImdsInstanceId, resolveMachineIdentity, } from "./machine-identity.js";
|
|
30
30
|
export type { MachineIdentity, MachineIdentityDeps } from "./machine-identity.js";
|
|
31
|
-
export {
|
|
31
|
+
export { PID_LIVENESS_DECISIONS, PROVIDER_COMMAND, PROVIDER_MODEL_FLAG, SPAWN_TERMINAL_REASONS, ANSWERED_QUESTIONS_FILE, appendModelFlag, armLaneWatcher, buildProviderCommand, parseCliModel, resolveLaneModel, defaultProveDetached, isPidRecordAlive, laneRunDir, missingPidProbe, nextEnvelopePath, markSpawnFailure, parsePidRecord, parseProcStat, parseSpawnTerminalReason, probePidRecord, readPidRecord, readProcStarttime, readProcStarttimeDetailed, readSpawnManifest, resumePrompt, envelopeInstruction, spawnLaneWorker, stopLaneProcesses, watcherMainPath, workerEnv, } from "./spawn.js";
|
|
32
32
|
export type { DetachProof, DetachedSpawnOptions, KillProcessFn, PidLivenessDecision, PidLivenessProbe, PidRecord, ProveDetachedDeps, ProveDetachedFn, SpawnLaneDeps, SpawnProcessFn, SpawnTerminalReason, StopLaneDeps, StopLaneResult, } from "./spawn.js";
|
|
33
33
|
export { SILENCE_MS, WATCHER_DECISION_EVENTS, WATCHER_OUT_MAX_BYTES, WATCHER_POLL_MS, WATCHER_SIGNAL_KINDS, appendCappedLog, appendWatcherSignal, applyTerminalToLane, classifyLaneExit, clearLaneStalled, isPidAlive, laneIdentityFromRecord, markLaneStalled, notifySlotFreed, parseWatcherSignalKind, readLatestEnvelope, runWatcherLoop, stalledReason, tickWatcher, watcherEventsPath, watcherLastSignalPath, watcherOutLogPath, writeWatcherDecision, } from "./watcher.js";
|
|
34
34
|
export type { TerminalClassification, WatcherDecisionEvent, WatcherLoopDeps, WatcherSignal, WatcherSignalKind, WatcherTickInput, WatcherTickResult, } from "./watcher.js";
|
package/dist/lib/lanes/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export { LANES_STORE_REL, LANE_RECORDS_DIR, PENDING_INDEX_DIR, QUESTION_RECORDS_
|
|
|
16
16
|
export { DEFAULT_LANE_WATCH_INTERVAL_MS, MAX_LANE_WATCH_INTERVAL_MS, MAX_WATCHED_LANES, MAX_WATCH_OUTPUT_LINES, runLaneWatch, } from "./watch.js";
|
|
17
17
|
export { MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_TASK_OUTPUT_MAX_BYTES, MONITOR_TRANSCRIPT_MAX_BYTES, MONITOR_UNCOVERED_EXIT_CODE, coveredLaneIds, isMonitorTaskLive, monitorReminderText, parseCanonicalWatchCommand, parseMonitorTranscript, readLiveMonitorEvidence, } from "./monitor.js";
|
|
18
18
|
export { IMDS_HOST, IMDS_INSTANCE_ID_URL, IMDS_TIMEOUT_MS, IMDS_TOKEN_URL, defaultReadImdsInstanceId, resolveMachineIdentity, } from "./machine-identity.js";
|
|
19
|
-
export {
|
|
19
|
+
export { PID_LIVENESS_DECISIONS, PROVIDER_COMMAND, PROVIDER_MODEL_FLAG, SPAWN_TERMINAL_REASONS, ANSWERED_QUESTIONS_FILE, appendModelFlag, armLaneWatcher, buildProviderCommand, parseCliModel, resolveLaneModel, defaultProveDetached, isPidRecordAlive, laneRunDir, missingPidProbe, nextEnvelopePath, markSpawnFailure, parsePidRecord, parseProcStat, parseSpawnTerminalReason, probePidRecord, readPidRecord, readProcStarttime, readProcStarttimeDetailed, readSpawnManifest, resumePrompt, envelopeInstruction, spawnLaneWorker, stopLaneProcesses, watcherMainPath, workerEnv, } from "./spawn.js";
|
|
20
20
|
export { SILENCE_MS, WATCHER_DECISION_EVENTS, WATCHER_OUT_MAX_BYTES, WATCHER_POLL_MS, WATCHER_SIGNAL_KINDS, appendCappedLog, appendWatcherSignal, applyTerminalToLane, classifyLaneExit, clearLaneStalled, isPidAlive, laneIdentityFromRecord, markLaneStalled, notifySlotFreed, parseWatcherSignalKind, readLatestEnvelope, runWatcherLoop, stalledReason, tickWatcher, watcherEventsPath, watcherLastSignalPath, watcherOutLogPath, writeWatcherDecision, } from "./watcher.js";
|
|
21
21
|
export { ENVELOPE_INVALID_REASON, decideEnvelopeRepair, emitMeshSoft, envelopeQuestionIds, readLatestEnvelopeFile, readLatestEnvelopeRecord, } from "./watcher.js";
|
|
22
22
|
export { LANE_MESH_EVENTS, WIRE_EVENT_KINDS, createLaneMesh, emitLaneDecisionEvents, emitLaneProgressEvent, laneCanEmit, parseLaneMeshEvent, progressEventDue, toWireThreadEvent, } from "./mesh-events.js";
|
|
@@ -8,14 +8,12 @@ export declare const LEAD_LANE_KEEP_ALIVE_IMMEDIATE_FIRST_RESUME_FLAG = "lanes.k
|
|
|
8
8
|
export declare const LEAD_LANE_KEEP_ALIVE_IMMEDIATE_FIRST_RESUME_DEFAULT_ENABLED = false;
|
|
9
9
|
export declare const LEAD_LANE_KEEP_ALIVE_FIRST_RESUME_SETTLE_MS = 30000;
|
|
10
10
|
export declare const LEAD_LANE_KEEP_ALIVE_TERMINAL_TRIGGER_FLAG = "lanes.keep-alive-terminal-trigger";
|
|
11
|
-
export declare const LEAD_LANE_KEEP_ALIVE_TERMINAL_TRIGGER_DEFAULT_ENABLED = false;
|
|
12
11
|
export declare const LEAD_LANE_KEEP_ALIVE_BLOCKED_GRACE_MS: number;
|
|
13
12
|
/** Missing or unreadable registry values retain the legacy supersession behavior. */
|
|
14
13
|
export declare const LANE_SUPERSESSION_LINEAGE_AWARE_FLAG = "lanes.supersession-lineage-aware";
|
|
15
14
|
export declare const LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED = false;
|
|
16
15
|
/** Missing or unreadable registry values keep rejecting superseded messages. */
|
|
17
16
|
export declare const LANE_RUNNING_SUPERSEDED_MESSAGE_DELIVERY_FLAG = "lanes.running-superseded-message-delivery";
|
|
18
|
-
export declare const LANE_RUNNING_SUPERSEDED_MESSAGE_DELIVERY_DEFAULT_ENABLED = false;
|
|
19
17
|
export declare const LEAD_LANE_KEEP_ALIVE_MAX_RESUMES = 24;
|
|
20
18
|
export declare const LEAD_LANE_KEEP_ALIVE_BASE_BACKOFF_MS: number;
|
|
21
19
|
export declare const LEAD_LANE_KEEP_ALIVE_MAX_BACKOFF_MS: number;
|
|
@@ -13,14 +13,12 @@ export const LEAD_LANE_KEEP_ALIVE_IMMEDIATE_FIRST_RESUME_FLAG = "lanes.keep-aliv
|
|
|
13
13
|
export const LEAD_LANE_KEEP_ALIVE_IMMEDIATE_FIRST_RESUME_DEFAULT_ENABLED = false;
|
|
14
14
|
export const LEAD_LANE_KEEP_ALIVE_FIRST_RESUME_SETTLE_MS = 30_000;
|
|
15
15
|
export const LEAD_LANE_KEEP_ALIVE_TERMINAL_TRIGGER_FLAG = "lanes.keep-alive-terminal-trigger";
|
|
16
|
-
export const LEAD_LANE_KEEP_ALIVE_TERMINAL_TRIGGER_DEFAULT_ENABLED = false;
|
|
17
16
|
export const LEAD_LANE_KEEP_ALIVE_BLOCKED_GRACE_MS = 15 * 60 * 1000;
|
|
18
17
|
/** Missing or unreadable registry values retain the legacy supersession behavior. */
|
|
19
18
|
export const LANE_SUPERSESSION_LINEAGE_AWARE_FLAG = "lanes.supersession-lineage-aware";
|
|
20
19
|
export const LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED = false;
|
|
21
20
|
/** Missing or unreadable registry values keep rejecting superseded messages. */
|
|
22
21
|
export const LANE_RUNNING_SUPERSEDED_MESSAGE_DELIVERY_FLAG = "lanes.running-superseded-message-delivery";
|
|
23
|
-
export const LANE_RUNNING_SUPERSEDED_MESSAGE_DELIVERY_DEFAULT_ENABLED = false;
|
|
24
22
|
export const LEAD_LANE_KEEP_ALIVE_MAX_RESUMES = 24;
|
|
25
23
|
export const LEAD_LANE_KEEP_ALIVE_BASE_BACKOFF_MS = 5 * 60 * 1000;
|
|
26
24
|
export const LEAD_LANE_KEEP_ALIVE_MAX_BACKOFF_MS = 60 * 60 * 1000;
|
|
@@ -5,7 +5,6 @@ export declare const KR_FRESHNESS_FLAG = "lanes.kr-freshness";
|
|
|
5
5
|
export declare const KR_FRESHNESS_DEFAULT_HOURS = 6;
|
|
6
6
|
export declare const KR_FRESHNESS_LEDGER_REL: string;
|
|
7
7
|
export declare const KR_FRESHNESS_LEDGER_SCHEMA = "kr-freshness-ledger.v1";
|
|
8
|
-
export declare const KR_FRESHNESS_HISTORY_LIMIT = 50;
|
|
9
8
|
export type KrFreshnessVerdict = "moving" | "flat" | "stalled";
|
|
10
9
|
export interface KrFreshnessKpi {
|
|
11
10
|
name: string;
|
|
@@ -11,7 +11,6 @@ export const KR_FRESHNESS_FLAG = "lanes.kr-freshness";
|
|
|
11
11
|
export const KR_FRESHNESS_DEFAULT_HOURS = DEFAULT_KR_FRESHNESS_HOURS;
|
|
12
12
|
export const KR_FRESHNESS_LEDGER_REL = path.join("workspace", "lanes", "kpi-ledger");
|
|
13
13
|
export const KR_FRESHNESS_LEDGER_SCHEMA = "kr-freshness-ledger.v1";
|
|
14
|
-
export const KR_FRESHNESS_HISTORY_LIMIT = 50;
|
|
15
14
|
const MAX_STATUS_BYTES = 1024 * 1024;
|
|
16
15
|
const MAX_LEDGER_BYTES = 1024 * 1024;
|
|
17
16
|
const MAX_KPIS = 1000;
|
|
@@ -58,5 +58,4 @@ 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 declare const OUTPOST_WORKTREE_PRUNER_PRESSURE_THRESHOLD_PERCENT = 78;
|
|
62
61
|
//# sourceMappingURL=outpost-worktree-pruner.d.ts.map
|
|
@@ -1197,5 +1197,4 @@ export function runOutpostWorktreePruner(options) {
|
|
|
1197
1197
|
}
|
|
1198
1198
|
}
|
|
1199
1199
|
export const OUTPOST_WORKTREE_PRUNER_DEFAULT_MIN_AGE_DAYS = DEFAULT_MIN_AGE_DAYS;
|
|
1200
|
-
export const OUTPOST_WORKTREE_PRUNER_PRESSURE_THRESHOLD_PERCENT = PRESSURE_THRESHOLD_PERCENT;
|
|
1201
1200
|
//# sourceMappingURL=outpost-worktree-pruner.js.map
|
|
@@ -56,8 +56,6 @@ export declare function raiseLaneQuestion(input: RaiseLaneQuestionInput): Questi
|
|
|
56
56
|
* already settle; it is recorded as `question_kind: "continue"`.
|
|
57
57
|
*/
|
|
58
58
|
export declare function classifyQuestionKind(options: readonly string[]): QuestionKind | undefined;
|
|
59
|
-
/** The store a lane's question bodies live in, derived from the lane and never the reverse. */
|
|
60
|
-
export declare function questionBodyPathForLane(hqRoot: string, lane: Pick<LaneRecord, "company" | "mesh_company">, questionId: string): string;
|
|
61
59
|
/**
|
|
62
60
|
* Free-text notes the operator attached with `questions answer --notes`.
|
|
63
61
|
* Read from the lane's own store (spec §6.5): the company store for a company
|
|
@@ -248,14 +248,6 @@ export function classifyQuestionKind(options) {
|
|
|
248
248
|
const isContinueStop = folded.includes("continue") && folded.includes("stop") && folded[0] !== folded[1];
|
|
249
249
|
return isContinueStop ? "continue" : undefined;
|
|
250
250
|
}
|
|
251
|
-
/** The store a lane's question bodies live in, derived from the lane and never the reverse. */
|
|
252
|
-
export function questionBodyPathForLane(hqRoot, lane, questionId) {
|
|
253
|
-
return questionBodyAbsPath(hqRoot, {
|
|
254
|
-
company: lane.company,
|
|
255
|
-
question_id: questionId,
|
|
256
|
-
body: { store: bodyStoreForLane(lane), ref: "", digest: "" },
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
251
|
/**
|
|
260
252
|
* Free-text notes the operator attached with `questions answer --notes`.
|
|
261
253
|
* Read from the lane's own store (spec §6.5): the company store for a company
|
|
@@ -346,6 +346,9 @@ function laneStoryLedgerIsClosed(hqRoot, lane) {
|
|
|
346
346
|
}
|
|
347
347
|
return { closed: states.length > 0 && states.every((state) => state === "done" || state === "dropped"), states };
|
|
348
348
|
}
|
|
349
|
+
function resolveStoryCloseInterruptionAt(hqRoot, lane) {
|
|
350
|
+
return lane.interrupted_at ?? readLatestInterruptedClassificationAt(hqRoot, lane);
|
|
351
|
+
}
|
|
349
352
|
async function closeInterruptedDoneStoryWorkers(hqRoot, lanes, questions, summary, deps, now, enabledByCompany) {
|
|
350
353
|
if (deps.dryRun)
|
|
351
354
|
return;
|
|
@@ -353,11 +356,20 @@ async function closeInterruptedDoneStoryWorkers(hqRoot, lanes, questions, summar
|
|
|
353
356
|
const at = now.toISOString();
|
|
354
357
|
for (const lane of lanes) {
|
|
355
358
|
if (lane.depth < 1 || lane.state !== "interrupted" || lane.keep_alive === true ||
|
|
356
|
-
!laneRunsHere(lane, deps.host) ||
|
|
357
|
-
!Number.isFinite(Date.parse(lane.interrupted_at)) ||
|
|
358
|
-
nowMs - Date.parse(lane.interrupted_at) < INTERRUPTED_DONE_STORY_MIN_AGE_MS ||
|
|
359
|
+
!laneRunsHere(lane, deps.host) ||
|
|
359
360
|
hasPendingKeepAliveWork(hqRoot, lane, questions))
|
|
360
361
|
continue;
|
|
362
|
+
let interruptedAt;
|
|
363
|
+
try {
|
|
364
|
+
interruptedAt = resolveStoryCloseInterruptionAt(hqRoot, lane);
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
markDirty(summary, { kind: "lane", id: lane.lane_id, why: `story close interruption time read failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
if (!interruptedAt || !Number.isFinite(Date.parse(interruptedAt)) ||
|
|
371
|
+
nowMs - Date.parse(interruptedAt) < INTERRUPTED_DONE_STORY_MIN_AGE_MS)
|
|
372
|
+
continue;
|
|
361
373
|
let company;
|
|
362
374
|
try {
|
|
363
375
|
company = resolveLaneCompany(hqRoot, lane).company;
|
|
@@ -383,11 +395,13 @@ async function closeInterruptedDoneStoryWorkers(hqRoot, lanes, questions, summar
|
|
|
383
395
|
const currentCompany = resolveLaneCompany(hqRoot, current).company;
|
|
384
396
|
if (current.state !== "interrupted" || current.depth < 1 || current.keep_alive === true ||
|
|
385
397
|
!currentCompany || enabledByCompany.get(keepAliveCompanyKey(currentCompany)) !== true ||
|
|
386
|
-
!laneRunsHere(current, deps.host) ||
|
|
387
|
-
!Number.isFinite(Date.parse(current.interrupted_at)) ||
|
|
388
|
-
nowMs - Date.parse(current.interrupted_at) < INTERRUPTED_DONE_STORY_MIN_AGE_MS ||
|
|
398
|
+
!laneRunsHere(current, deps.host) ||
|
|
389
399
|
hasPendingKeepAliveWork(hqRoot, current, questions))
|
|
390
400
|
return false;
|
|
401
|
+
const currentInterruptedAt = resolveStoryCloseInterruptionAt(hqRoot, current);
|
|
402
|
+
if (!currentInterruptedAt || !Number.isFinite(Date.parse(currentInterruptedAt)) ||
|
|
403
|
+
nowMs - Date.parse(currentInterruptedAt) < INTERRUPTED_DONE_STORY_MIN_AGE_MS)
|
|
404
|
+
return false;
|
|
391
405
|
return laneStoryLedgerIsClosed(hqRoot, current).closed;
|
|
392
406
|
}, (current) => ({
|
|
393
407
|
...current,
|
|
@@ -1112,11 +1126,20 @@ export async function runPassBody(hqRoot, deps) {
|
|
|
1112
1126
|
const storyCloseCompanies = new Map();
|
|
1113
1127
|
for (const lane of lanes) {
|
|
1114
1128
|
if (lane.depth < 1 || lane.state !== "interrupted" || lane.keep_alive === true ||
|
|
1115
|
-
!laneRunsHere(lane, deps.host) ||
|
|
1116
|
-
!Number.isFinite(Date.parse(lane.interrupted_at)) ||
|
|
1117
|
-
nowMs - Date.parse(lane.interrupted_at) < INTERRUPTED_DONE_STORY_MIN_AGE_MS ||
|
|
1129
|
+
!laneRunsHere(lane, deps.host) ||
|
|
1118
1130
|
hasPendingKeepAliveWork(hqRoot, lane, questions) || laneStories(lane).length === 0)
|
|
1119
1131
|
continue;
|
|
1132
|
+
let interruptedAt;
|
|
1133
|
+
try {
|
|
1134
|
+
interruptedAt = resolveStoryCloseInterruptionAt(hqRoot, lane);
|
|
1135
|
+
}
|
|
1136
|
+
catch (err) {
|
|
1137
|
+
markDirty(summary, { kind: "lane", id: lane.lane_id, why: `story close interruption time read failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if (!interruptedAt || !Number.isFinite(Date.parse(interruptedAt)) ||
|
|
1141
|
+
nowMs - Date.parse(interruptedAt) < INTERRUPTED_DONE_STORY_MIN_AGE_MS)
|
|
1142
|
+
continue;
|
|
1120
1143
|
try {
|
|
1121
1144
|
const company = resolveLaneCompany(hqRoot, lane).company;
|
|
1122
1145
|
if (company)
|
|
@@ -31,7 +31,6 @@ export interface RecordLaneReviewInput {
|
|
|
31
31
|
}
|
|
32
32
|
export declare function canonicalLaneReviewRepo(raw: string): string;
|
|
33
33
|
export declare function parseLaneReviewPr(raw: string | number): number;
|
|
34
|
-
export declare function laneReviewPath(hqRoot: string, repo: string, pr: number): string;
|
|
35
34
|
export declare function readLaneReview(hqRoot: string, repo: string, pr: number): LaneReview | null;
|
|
36
35
|
export declare function listLaneReviews(hqRoot: string, reviewerLane?: string): LaneReviewListing;
|
|
37
36
|
export declare function recordLaneReview(hqRoot: string, input: RecordLaneReviewInput): Promise<LaneReview>;
|
|
@@ -48,9 +48,6 @@ function reviewPath(hqRoot, repo, pr) {
|
|
|
48
48
|
const [owner, name] = canonicalLaneReviewRepo(repo).split("/");
|
|
49
49
|
return path.join(hqRoot, LANE_REVIEWS_REL, `${owner}__${name}`, `${parseLaneReviewPr(pr)}.json`);
|
|
50
50
|
}
|
|
51
|
-
export function laneReviewPath(hqRoot, repo, pr) {
|
|
52
|
-
return reviewPath(hqRoot, repo, pr);
|
|
53
|
-
}
|
|
54
51
|
function isObject(value) {
|
|
55
52
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
56
53
|
}
|
|
@@ -123,7 +123,6 @@ export interface PidLivenessProbe {
|
|
|
123
123
|
export declare function missingPidProbe(): PidLivenessProbe;
|
|
124
124
|
export declare function defaultPidIsAlive(pid: number): boolean;
|
|
125
125
|
export declare const STOP_TERM_WAIT_MS = 500;
|
|
126
|
-
export declare const STOP_KILL_WAIT_MS = 200;
|
|
127
126
|
export declare function parseSpawnTerminalReason(value: string): SpawnTerminalReason;
|
|
128
127
|
export declare function laneRunDir(hqRoot: string, laneId: string): string;
|
|
129
128
|
export declare function watcherMainPath(): string;
|
package/dist/lib/lanes/spawn.js
CHANGED
|
@@ -657,7 +657,6 @@ export function defaultPidIsAlive(pid) {
|
|
|
657
657
|
}
|
|
658
658
|
}
|
|
659
659
|
export const STOP_TERM_WAIT_MS = 500;
|
|
660
|
-
export const STOP_KILL_WAIT_MS = 200;
|
|
661
660
|
const defaultSpawnProcess = (command, args, options) => spawn(command, args, options);
|
|
662
661
|
function defaultKillProcess(pid, signal = "SIGTERM") {
|
|
663
662
|
process.kill(pid, signal);
|
|
@@ -22,12 +22,6 @@ export declare const HELD_MAX_LINES = 20000;
|
|
|
22
22
|
*/
|
|
23
23
|
export declare const PROJECT_REBIND_INTERVAL_MS = 60000;
|
|
24
24
|
export type HeldReason = "STATE_ABSENT" | "NEEDS_COMPANY" | "COMPANY_CONFLICT" | "NEEDS_PROJECT" | "HELD_EXPIRED" | "HELD_OVERFLOW";
|
|
25
|
-
export interface HeldLineRecord {
|
|
26
|
-
/** Original spool event fields. */
|
|
27
|
-
event: Record<string, unknown>;
|
|
28
|
-
heldReason: HeldReason;
|
|
29
|
-
heldAt: string;
|
|
30
|
-
}
|
|
31
25
|
export interface FlushDeps {
|
|
32
26
|
workMeshRoot: string;
|
|
33
27
|
workContextRoot: string;
|
|
@@ -21,8 +21,4 @@ export declare function formatError(error: Error, checkpointPath: string): strin
|
|
|
21
21
|
* Validate a company slug: lowercase, alphanumeric + hyphens, 3-40 chars.
|
|
22
22
|
*/
|
|
23
23
|
export declare function validateSlug(slug: string): string | null;
|
|
24
|
-
/**
|
|
25
|
-
* Validate email format.
|
|
26
|
-
*/
|
|
27
|
-
export declare function validateEmail(email: string): string | null;
|
|
28
24
|
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -71,13 +71,4 @@ export function validateSlug(slug) {
|
|
|
71
71
|
}
|
|
72
72
|
return null;
|
|
73
73
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Validate email format.
|
|
76
|
-
*/
|
|
77
|
-
export function validateEmail(email) {
|
|
78
|
-
if (!email.includes("@") || !email.includes(".")) {
|
|
79
|
-
return "Invalid email format";
|
|
80
|
-
}
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
74
|
//# sourceMappingURL=prompts.js.map
|
|
@@ -59,8 +59,4 @@ export declare function listNeedsProjectSessions(workContextRoot: string): Array
|
|
|
59
59
|
reason?: string;
|
|
60
60
|
candidates: BindCandidate[];
|
|
61
61
|
}>;
|
|
62
|
-
export declare function formatProjectAsk(candidates: Array<{
|
|
63
|
-
projectId: string;
|
|
64
|
-
title?: string;
|
|
65
|
-
}>): string;
|
|
66
62
|
//# sourceMappingURL=bind-best.d.ts.map
|
|
@@ -334,11 +334,4 @@ export function listNeedsProjectSessions(workContextRoot) {
|
|
|
334
334
|
}
|
|
335
335
|
return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
|
|
336
336
|
}
|
|
337
|
-
export function formatProjectAsk(candidates) {
|
|
338
|
-
const parts = candidates.map((candidate, index) => {
|
|
339
|
-
const title = candidate.title?.trim() || candidate.projectId;
|
|
340
|
-
return `${index + 1}) ${candidate.projectId} ${title}`;
|
|
341
|
-
});
|
|
342
|
-
return `This session is not bound to a project. Best matches: ${parts.join(" ")}. Reply with a number, a project id, or \`new <slug>\`.`;
|
|
343
|
-
}
|
|
344
337
|
//# sourceMappingURL=bind-best.js.map
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { DeliveryState } from "./contract.js";
|
|
6
6
|
import { WORK_CONTEXT_CONTRACT_VERSION } from "./contract.js";
|
|
7
|
-
/** Fields allowed on a durable outbox operation (privacy allowlist). */
|
|
8
|
-
export declare const OUTBOX_ALLOWLIST: readonly ["contractVersion", "operationId", "clientOperationId", "sessionId", "harness", "companyUid", "companySlug", "projectId", "taskId", "companyConfidence", "kind", "digest", "delivery", "createdAt", "updatedAt", "attemptCount", "lastErrorCode", "lastErrorHttpStatus", "lastServerErrorCode", "receiptId", "destinationCompanyUid", "destinationCompanySlug", "nextAttemptAt"];
|
|
9
7
|
/** Base delay for outbox retry backoff (attempt 1 → 30s). */
|
|
10
8
|
export declare const OUTBOX_RETRY_BASE_MS = 30000;
|
|
11
9
|
/** Cap for outbox retry backoff (6 hours). */
|
|
@@ -154,8 +152,4 @@ export declare function replayOutbox(root: string, deliver: DeliverFn, opts?: {
|
|
|
154
152
|
quarantined: number;
|
|
155
153
|
skipped: number;
|
|
156
154
|
}>;
|
|
157
|
-
/** Remove acked ops older than retention (optional GC; not required by AC). */
|
|
158
|
-
export declare function removeAckedOutbox(root: string, olderThanMs: number, now?: number): number;
|
|
159
|
-
export declare function outboxFileExists(operationId: string, root: string): boolean;
|
|
160
|
-
export declare function quarantineCorruptOutboxFile(filePath: string, root: string): void;
|
|
161
155
|
//# sourceMappingURL=outbox.d.ts.map
|
|
@@ -11,32 +11,6 @@ import { NotTrackingError } from "./errors.js";
|
|
|
11
11
|
import { isWorkSessionDenialCode } from "../mesh/denial-codes.js";
|
|
12
12
|
import { readSessionState, stripRegisterReceiptEpisodes, updateSessionState, writeAcknowledgedRegisterBinding, } from "./state.js";
|
|
13
13
|
import { isSafeWorkContextSegment, workContextOutboxDir, workContextOutboxPath, } from "./paths.js";
|
|
14
|
-
/** Fields allowed on a durable outbox operation (privacy allowlist). */
|
|
15
|
-
export const OUTBOX_ALLOWLIST = [
|
|
16
|
-
"contractVersion",
|
|
17
|
-
"operationId",
|
|
18
|
-
"clientOperationId",
|
|
19
|
-
"sessionId",
|
|
20
|
-
"harness",
|
|
21
|
-
"companyUid",
|
|
22
|
-
"companySlug",
|
|
23
|
-
"projectId",
|
|
24
|
-
"taskId",
|
|
25
|
-
"companyConfidence",
|
|
26
|
-
"kind",
|
|
27
|
-
"digest",
|
|
28
|
-
"delivery",
|
|
29
|
-
"createdAt",
|
|
30
|
-
"updatedAt",
|
|
31
|
-
"attemptCount",
|
|
32
|
-
"lastErrorCode",
|
|
33
|
-
"lastErrorHttpStatus",
|
|
34
|
-
"lastServerErrorCode",
|
|
35
|
-
"receiptId",
|
|
36
|
-
"destinationCompanyUid",
|
|
37
|
-
"destinationCompanySlug",
|
|
38
|
-
"nextAttemptAt",
|
|
39
|
-
];
|
|
40
14
|
/** Base delay for outbox retry backoff (attempt 1 → 30s). */
|
|
41
15
|
export const OUTBOX_RETRY_BASE_MS = 30_000;
|
|
42
16
|
/** Cap for outbox retry backoff (6 hours). */
|
|
@@ -624,39 +598,4 @@ export async function replayOutbox(root, deliver, opts = {}) {
|
|
|
624
598
|
await Promise.all(workers);
|
|
625
599
|
return { delivered, queued, quarantined, skipped };
|
|
626
600
|
}
|
|
627
|
-
/** Remove acked ops older than retention (optional GC; not required by AC). */
|
|
628
|
-
export function removeAckedOutbox(root, olderThanMs, now = Date.now()) {
|
|
629
|
-
let removed = 0;
|
|
630
|
-
for (const op of listOutboxOperations(root)) {
|
|
631
|
-
if (op.delivery !== "acked" || !op.receiptId)
|
|
632
|
-
continue;
|
|
633
|
-
const age = now - Date.parse(op.updatedAt);
|
|
634
|
-
if (Number.isFinite(age) && age > olderThanMs) {
|
|
635
|
-
const filePath = workContextOutboxPath(op.operationId, root);
|
|
636
|
-
try {
|
|
637
|
-
fs.unlinkSync(filePath);
|
|
638
|
-
invalidateOutboxListCacheEntry(filePath);
|
|
639
|
-
removed += 1;
|
|
640
|
-
}
|
|
641
|
-
catch {
|
|
642
|
-
/* ignore */
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
return removed;
|
|
647
|
-
}
|
|
648
|
-
export function outboxFileExists(operationId, root) {
|
|
649
|
-
return fs.existsSync(workContextOutboxPath(operationId, root));
|
|
650
|
-
}
|
|
651
|
-
export function quarantineCorruptOutboxFile(filePath, root) {
|
|
652
|
-
const base = path.basename(filePath);
|
|
653
|
-
const dest = path.join(workContextOutboxDir(root), `.quarantine.${base}`);
|
|
654
|
-
try {
|
|
655
|
-
fs.renameSync(filePath, dest);
|
|
656
|
-
invalidateOutboxListCacheEntry(filePath);
|
|
657
|
-
}
|
|
658
|
-
catch {
|
|
659
|
-
/* ignore */
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
601
|
//# sourceMappingURL=outbox.js.map
|
|
@@ -26,7 +26,6 @@ export declare function prdPathIdentity(file: string): {
|
|
|
26
26
|
companySlug: string;
|
|
27
27
|
projectId: string;
|
|
28
28
|
} | null;
|
|
29
|
-
export declare function prdBelongsToProject(file: string, projectId: string, companySlug: string | undefined): boolean;
|
|
30
29
|
export declare function rebindSessionToProject(input: {
|
|
31
30
|
sessionId: string;
|
|
32
31
|
root: string;
|
|
@@ -49,14 +49,6 @@ function writeSnapshot(sessionId, root, snapshot) {
|
|
|
49
49
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
50
50
|
fs.writeFileSync(dest, `${JSON.stringify(snapshot)}\n`, { mode: 0o600 });
|
|
51
51
|
}
|
|
52
|
-
export function prdBelongsToProject(file, projectId, companySlug) {
|
|
53
|
-
if (!companySlug)
|
|
54
|
-
return false;
|
|
55
|
-
const identity = prdPathIdentity(file);
|
|
56
|
-
return Boolean(identity &&
|
|
57
|
-
identity.companySlug.toLowerCase() === companySlug.toLowerCase() &&
|
|
58
|
-
identity.projectId === projectId);
|
|
59
|
-
}
|
|
60
52
|
export function rebindSessionToProject(input) {
|
|
61
53
|
const nowIso = (input.now ?? (() => new Date()))().toISOString();
|
|
62
54
|
return updateSessionState(input.sessionId, input.root, (current) => {
|
package/dist/utils/git.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export declare function pullRepo(repoDir: string): Promise<void>;
|
|
|
4
4
|
export declare function getCurrentCommit(repoDir: string): Promise<string>;
|
|
5
5
|
export declare function checkoutCommit(repoDir: string, commitSha: string): Promise<void>;
|
|
6
6
|
export declare function isRepo(dir: string): Promise<boolean>;
|
|
7
|
-
export declare function getRemoteUrl(repoDir: string): Promise<string | null>;
|
|
8
7
|
export declare function isBehindRemote(repoDir: string): Promise<{
|
|
9
8
|
behind: boolean;
|
|
10
9
|
commits: number;
|
package/dist/utils/git.js
CHANGED
|
@@ -34,17 +34,6 @@ export async function isRepo(dir) {
|
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
export async function getRemoteUrl(repoDir) {
|
|
38
|
-
try {
|
|
39
|
-
const git = simpleGit(repoDir);
|
|
40
|
-
const remotes = await git.getRemotes(true);
|
|
41
|
-
const origin = remotes.find(r => r.name === 'origin');
|
|
42
|
-
return origin?.refs?.fetch ?? null;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
37
|
export async function isBehindRemote(repoDir) {
|
|
49
38
|
try {
|
|
50
39
|
const git = simpleGit(repoDir);
|