@on-par/factory-cli 0.0.0-stage → 0.9.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/LICENSE +21 -0
- package/README.md +23 -2
- package/dist/cli/admission.d.ts +17 -0
- package/dist/cli/admission.d.ts.map +1 -0
- package/dist/cli/admission.js +37 -0
- package/dist/cli/admission.js.map +1 -0
- package/dist/cli/branch-prefix.d.ts +8 -0
- package/dist/cli/branch-prefix.d.ts.map +1 -0
- package/dist/cli/branch-prefix.js +16 -0
- package/dist/cli/branch-prefix.js.map +1 -0
- package/dist/cli/classifier-backtest.d.ts +50 -0
- package/dist/cli/classifier-backtest.d.ts.map +1 -0
- package/dist/cli/classifier-backtest.js +112 -0
- package/dist/cli/classifier-backtest.js.map +1 -0
- package/dist/cli/cost-json.d.ts +37 -0
- package/dist/cli/cost-json.d.ts.map +1 -0
- package/dist/cli/cost-json.js +48 -0
- package/dist/cli/cost-json.js.map +1 -0
- package/dist/cli/daemon.d.ts +113 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +282 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/doctor.d.ts +127 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +400 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/feedback.d.ts +74 -0
- package/dist/cli/feedback.d.ts.map +1 -0
- package/dist/cli/feedback.js +180 -0
- package/dist/cli/feedback.js.map +1 -0
- package/dist/cli/filing.d.ts +22 -0
- package/dist/cli/filing.d.ts.map +1 -0
- package/dist/cli/filing.js +53 -0
- package/dist/cli/filing.js.map +1 -0
- package/dist/cli/first-run.d.ts +9 -0
- package/dist/cli/first-run.d.ts.map +1 -0
- package/dist/cli/first-run.js +34 -0
- package/dist/cli/first-run.js.map +1 -0
- package/dist/cli/help-groups.d.ts +17 -0
- package/dist/cli/help-groups.d.ts.map +1 -0
- package/dist/cli/help-groups.js +50 -0
- package/dist/cli/help-groups.js.map +1 -0
- package/dist/cli/hosted-queue.d.ts +45 -0
- package/dist/cli/hosted-queue.d.ts.map +1 -0
- package/dist/cli/hosted-queue.js +74 -0
- package/dist/cli/hosted-queue.js.map +1 -0
- package/dist/cli/hosted-runner.d.ts +44 -0
- package/dist/cli/hosted-runner.d.ts.map +1 -0
- package/dist/cli/hosted-runner.js +68 -0
- package/dist/cli/hosted-runner.js.map +1 -0
- package/dist/cli/hosted.d.ts +38 -0
- package/dist/cli/hosted.d.ts.map +1 -0
- package/dist/cli/hosted.js +82 -0
- package/dist/cli/hosted.js.map +1 -0
- package/dist/cli/index.d.ts +656 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4801 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-files.d.ts +8 -0
- package/dist/cli/init-files.d.ts.map +1 -0
- package/dist/cli/init-files.js +45 -0
- package/dist/cli/init-files.js.map +1 -0
- package/dist/cli/logs.d.ts +27 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +52 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/merge-scope.d.ts +7 -0
- package/dist/cli/merge-scope.d.ts.map +1 -0
- package/dist/cli/merge-scope.js +14 -0
- package/dist/cli/merge-scope.js.map +1 -0
- package/dist/cli/octokit.d.ts +43 -0
- package/dist/cli/octokit.d.ts.map +1 -0
- package/dist/cli/octokit.js +87 -0
- package/dist/cli/octokit.js.map +1 -0
- package/dist/cli/queue-add-json.d.ts +25 -0
- package/dist/cli/queue-add-json.d.ts.map +1 -0
- package/dist/cli/queue-add-json.js +24 -0
- package/dist/cli/queue-add-json.js.map +1 -0
- package/dist/cli/queue-clear.d.ts +15 -0
- package/dist/cli/queue-clear.d.ts.map +1 -0
- package/dist/cli/queue-clear.js +58 -0
- package/dist/cli/queue-clear.js.map +1 -0
- package/dist/cli/queue-list.d.ts +24 -0
- package/dist/cli/queue-list.d.ts.map +1 -0
- package/dist/cli/queue-list.js +25 -0
- package/dist/cli/queue-list.js.map +1 -0
- package/dist/cli/ready-check.d.ts +98 -0
- package/dist/cli/ready-check.d.ts.map +1 -0
- package/dist/cli/ready-check.js +169 -0
- package/dist/cli/ready-check.js.map +1 -0
- package/dist/cli/reset.d.ts +40 -0
- package/dist/cli/reset.d.ts.map +1 -0
- package/dist/cli/reset.js +215 -0
- package/dist/cli/reset.js.map +1 -0
- package/dist/cli/run-children.d.ts +24 -0
- package/dist/cli/run-children.d.ts.map +1 -0
- package/dist/cli/run-children.js +73 -0
- package/dist/cli/run-children.js.map +1 -0
- package/dist/cli/run-flags.d.ts +14 -0
- package/dist/cli/run-flags.d.ts.map +1 -0
- package/dist/cli/run-flags.js +43 -0
- package/dist/cli/run-flags.js.map +1 -0
- package/dist/cli/runs-diffstat.d.ts +43 -0
- package/dist/cli/runs-diffstat.d.ts.map +1 -0
- package/dist/cli/runs-diffstat.js +91 -0
- package/dist/cli/runs-diffstat.js.map +1 -0
- package/dist/cli/runs.d.ts +36 -0
- package/dist/cli/runs.d.ts.map +1 -0
- package/dist/cli/runs.js +102 -0
- package/dist/cli/runs.js.map +1 -0
- package/dist/cli/staleness.d.ts +30 -0
- package/dist/cli/staleness.d.ts.map +1 -0
- package/dist/cli/staleness.js +132 -0
- package/dist/cli/staleness.js.map +1 -0
- package/dist/cli/status-json.d.ts +45 -0
- package/dist/cli/status-json.d.ts.map +1 -0
- package/dist/cli/status-json.js +22 -0
- package/dist/cli/status-json.js.map +1 -0
- package/dist/cli/stop-resume-json.d.ts +18 -0
- package/dist/cli/stop-resume-json.d.ts.map +1 -0
- package/dist/cli/stop-resume-json.js +10 -0
- package/dist/cli/stop-resume-json.js.map +1 -0
- package/dist/cli/stop-sentinel.d.ts +23 -0
- package/dist/cli/stop-sentinel.d.ts.map +1 -0
- package/dist/cli/stop-sentinel.js +61 -0
- package/dist/cli/stop-sentinel.js.map +1 -0
- package/dist/cli/sweep-heartbeat.d.ts +33 -0
- package/dist/cli/sweep-heartbeat.d.ts.map +1 -0
- package/dist/cli/sweep-heartbeat.js +65 -0
- package/dist/cli/sweep-heartbeat.js.map +1 -0
- package/dist/cli/unpark.d.ts +28 -0
- package/dist/cli/unpark.d.ts.map +1 -0
- package/dist/cli/unpark.js +68 -0
- package/dist/cli/unpark.js.map +1 -0
- package/dist/cli/usage-json.d.ts +20 -0
- package/dist/cli/usage-json.d.ts.map +1 -0
- package/dist/cli/usage-json.js +36 -0
- package/dist/cli/usage-json.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -0
- package/dist/entry.d.ts +6 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +13 -0
- package/dist/entry.js.map +1 -0
- package/package.json +48 -4
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** One changed file. `added`/`deleted` are null for binary files. */
|
|
2
|
+
export interface RunDiffstatFileJson {
|
|
3
|
+
path: string;
|
|
4
|
+
added: number | null;
|
|
5
|
+
deleted: number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface RunDiffstatTotalsJson {
|
|
8
|
+
files: number;
|
|
9
|
+
added: number;
|
|
10
|
+
deleted: number;
|
|
11
|
+
}
|
|
12
|
+
export type RunDiffstatReason = 'branch-missing' | 'base-missing' | 'no-branch';
|
|
13
|
+
/**
|
|
14
|
+
* Machine-readable output of `factory runs --json --diffstat <issue>`.
|
|
15
|
+
* Additive changes only; bump schemaVersion on a breaking change.
|
|
16
|
+
* `files`/`totals` are null (with a `reason`) when the diff cannot be computed.
|
|
17
|
+
*/
|
|
18
|
+
export interface RunDiffstatJson {
|
|
19
|
+
schemaVersion: 1;
|
|
20
|
+
issue: number;
|
|
21
|
+
branch: string | null;
|
|
22
|
+
base: string;
|
|
23
|
+
files: RunDiffstatFileJson[] | null;
|
|
24
|
+
totals: RunDiffstatTotalsJson | null;
|
|
25
|
+
reason: RunDiffstatReason | null;
|
|
26
|
+
}
|
|
27
|
+
/** Runs `git <args>` in cwd without a shell. Resolves stdout; rejects on nonzero exit. */
|
|
28
|
+
export type DiffstatGit = (args: readonly string[], cwd: string) => Promise<string>;
|
|
29
|
+
/** Thrown when the issue has no readable run state. cmdRuns maps it to exit 1. */
|
|
30
|
+
export declare class NoRunError extends Error {
|
|
31
|
+
}
|
|
32
|
+
/** Parse the `--diffstat <issue>` value: a positive integer, else throw. */
|
|
33
|
+
export declare function parseDiffstatIssue(raw: string): number;
|
|
34
|
+
/** Parse `git diff --numstat -z --no-renames` output into file rows, in git's order. */
|
|
35
|
+
export declare function parseNumstat(raw: string): RunDiffstatFileJson[];
|
|
36
|
+
export declare function buildRunDiffstatJson(opts: {
|
|
37
|
+
runsDir: string;
|
|
38
|
+
repoRoot: string;
|
|
39
|
+
issue: number;
|
|
40
|
+
git?: DiffstatGit;
|
|
41
|
+
resolveBase?: (repoRoot: string) => Promise<string>;
|
|
42
|
+
}): Promise<RunDiffstatJson>;
|
|
43
|
+
//# sourceMappingURL=runs-diffstat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs-diffstat.d.ts","sourceRoot":"","sources":["../../src/cli/runs-diffstat.ts"],"names":[],"mappings":"AAKA,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEhF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,CAAC,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,mBAAmB,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAClC;AAED,0FAA0F;AAC1F,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEpF,kFAAkF;AAClF,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAmBxC,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAe/D;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD,GAAG,OAAO,CAAC,eAAe,CAAC,CA4C3B"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { defaultRemoteBase, readIssueRunState } from '@on-par/factory-core/internal';
|
|
4
|
+
/** Thrown when the issue has no readable run state. cmdRuns maps it to exit 1. */
|
|
5
|
+
export class NoRunError extends Error {
|
|
6
|
+
}
|
|
7
|
+
const defaultGit = (args, cwd) => new Promise((resolve, reject) => {
|
|
8
|
+
execFile('git', [...args], { cwd, timeout: 120_000, maxBuffer: 64 * 1024 * 1024, encoding: 'utf-8' }, (error, stdout, stderr) => {
|
|
9
|
+
if (error) {
|
|
10
|
+
const detail = String(stderr).trim();
|
|
11
|
+
reject(new Error(detail ? `${error.message}: ${detail}` : error.message));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
resolve(stdout);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
/** Parse the `--diffstat <issue>` value: a positive integer, else throw. */
|
|
18
|
+
export function parseDiffstatIssue(raw) {
|
|
19
|
+
const n = /^\d+$/.test(raw) ? Number(raw) : 0;
|
|
20
|
+
if (!Number.isSafeInteger(n) || n < 1) {
|
|
21
|
+
throw new Error(`invalid --diffstat '${raw}' — expected a positive issue number`);
|
|
22
|
+
}
|
|
23
|
+
return n;
|
|
24
|
+
}
|
|
25
|
+
/** Parse `git diff --numstat -z --no-renames` output into file rows, in git's order. */
|
|
26
|
+
export function parseNumstat(raw) {
|
|
27
|
+
const files = [];
|
|
28
|
+
for (const token of raw.split('\0')) {
|
|
29
|
+
if (token === '')
|
|
30
|
+
continue;
|
|
31
|
+
const first = token.indexOf('\t');
|
|
32
|
+
const second = first === -1 ? -1 : token.indexOf('\t', first + 1);
|
|
33
|
+
if (second === -1)
|
|
34
|
+
continue;
|
|
35
|
+
const count = (s) => (s === '-' ? null : Number(s));
|
|
36
|
+
files.push({
|
|
37
|
+
path: token.slice(second + 1),
|
|
38
|
+
added: count(token.slice(0, first)),
|
|
39
|
+
deleted: count(token.slice(first + 1, second)),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return files;
|
|
43
|
+
}
|
|
44
|
+
export async function buildRunDiffstatJson(opts) {
|
|
45
|
+
const { runsDir, repoRoot, issue, git = defaultGit, resolveBase = defaultRemoteBase } = opts;
|
|
46
|
+
const state = await readIssueRunState(join(runsDir, `issue-${issue}.json`));
|
|
47
|
+
if (state === null)
|
|
48
|
+
throw new NoRunError(`no run for issue #${issue}`);
|
|
49
|
+
const base = await resolveBase(repoRoot);
|
|
50
|
+
const branch = typeof state.branch === 'string' && state.branch !== '' ? state.branch : null;
|
|
51
|
+
const unavailable = (reason) => ({
|
|
52
|
+
schemaVersion: 1,
|
|
53
|
+
issue,
|
|
54
|
+
branch,
|
|
55
|
+
base,
|
|
56
|
+
files: null,
|
|
57
|
+
totals: null,
|
|
58
|
+
reason,
|
|
59
|
+
});
|
|
60
|
+
if (branch === null)
|
|
61
|
+
return unavailable('no-branch');
|
|
62
|
+
const resolves = async (ref) => {
|
|
63
|
+
try {
|
|
64
|
+
await git(['rev-parse', '--verify', '-q', `${ref}^{commit}`], repoRoot);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
if (!(await resolves(base)))
|
|
72
|
+
return unavailable('base-missing');
|
|
73
|
+
let ref = null;
|
|
74
|
+
for (const candidate of [`refs/heads/${branch}`, `refs/remotes/origin/${branch}`]) {
|
|
75
|
+
if (await resolves(candidate)) {
|
|
76
|
+
ref = candidate;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (ref === null)
|
|
81
|
+
return unavailable('branch-missing');
|
|
82
|
+
const raw = await git(['diff', '--numstat', '-z', '--no-renames', '--no-ext-diff', `${base}...${ref}`], repoRoot);
|
|
83
|
+
const files = parseNumstat(raw);
|
|
84
|
+
const totals = { files: files.length, added: 0, deleted: 0 };
|
|
85
|
+
for (const f of files) {
|
|
86
|
+
totals.added += f.added ?? 0;
|
|
87
|
+
totals.deleted += f.deleted ?? 0;
|
|
88
|
+
}
|
|
89
|
+
return { schemaVersion: 1, issue, branch, base, files, totals, reason: null };
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=runs-diffstat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs-diffstat.js","sourceRoot":"","sources":["../../src/cli/runs-diffstat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type FailurePhase, type RunStatus } from '@on-par/factory-core/internal';
|
|
2
|
+
/** Row cap when `--limit` is not given. */
|
|
3
|
+
export declare const DEFAULT_RUNS_LIMIT = 50;
|
|
4
|
+
/** One row of `factory runs --json` (#2271). Unknown values are null, never omitted. */
|
|
5
|
+
export interface RunsRowJson {
|
|
6
|
+
issue: number;
|
|
7
|
+
lane: string | null;
|
|
8
|
+
repo: string | null;
|
|
9
|
+
status: RunStatus | null;
|
|
10
|
+
phase: FailurePhase | null;
|
|
11
|
+
branch: string | null;
|
|
12
|
+
prNumber: number | null;
|
|
13
|
+
model: string | null;
|
|
14
|
+
attempts: number | null;
|
|
15
|
+
startedAt: string | null;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
/** `factory runs --json` payload (#2271). Additive changes only; bump schemaVersion on a breaking change. */
|
|
19
|
+
export interface RunsJson {
|
|
20
|
+
schemaVersion: 1;
|
|
21
|
+
runs: RunsRowJson[];
|
|
22
|
+
}
|
|
23
|
+
/** Parse `--limit`: absent → the default, otherwise a positive integer or an Error. */
|
|
24
|
+
export declare function parseRunsLimit(raw: string | undefined): number;
|
|
25
|
+
/**
|
|
26
|
+
* Merge `issue-<n>.json` (IssueRunState) and `issue-<n>.phase.json` (RunPhaseSnapshot)
|
|
27
|
+
* in `runsDir` into one row per issue, newest `updatedAt` first, capped at `limit`.
|
|
28
|
+
* A missing dir is an empty list; malformed files are skipped and named in `skipped`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildRunsJson(runsDir: string, { limit }?: {
|
|
31
|
+
limit?: number;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
json: RunsJson;
|
|
34
|
+
skipped: string[];
|
|
35
|
+
}>;
|
|
36
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/cli/runs.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,SAAS,EACf,MAAM,+BAA+B,CAAC;AAEvC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6GAA6G;AAC7G,MAAM,WAAW,QAAQ;IACvB,aAAa,EAAE,CAAC,CAAC;IACjB,IAAI,EAAE,WAAW,EAAE,CAAC;CACrB;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAI9D;AAUD;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,EAAE,KAA0B,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,OAAO,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA4EhD"}
|
package/dist/cli/runs.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readPhaseSnapshot } from '@on-par/factory-core';
|
|
4
|
+
import { readIssueRunState, } from '@on-par/factory-core/internal';
|
|
5
|
+
/** Row cap when `--limit` is not given. */
|
|
6
|
+
export const DEFAULT_RUNS_LIMIT = 50;
|
|
7
|
+
/** Parse `--limit`: absent → the default, otherwise a positive integer or an Error. */
|
|
8
|
+
export function parseRunsLimit(raw) {
|
|
9
|
+
if (raw === undefined)
|
|
10
|
+
return DEFAULT_RUNS_LIMIT;
|
|
11
|
+
if (/^\d+$/.test(raw) && Number(raw) >= 1)
|
|
12
|
+
return Number(raw);
|
|
13
|
+
throw new Error(`invalid --limit '${raw}' — expected a positive integer`);
|
|
14
|
+
}
|
|
15
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : null);
|
|
16
|
+
const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
|
|
17
|
+
function time(iso) {
|
|
18
|
+
const t = Date.parse(iso);
|
|
19
|
+
return Number.isNaN(t) ? -Infinity : t;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Merge `issue-<n>.json` (IssueRunState) and `issue-<n>.phase.json` (RunPhaseSnapshot)
|
|
23
|
+
* in `runsDir` into one row per issue, newest `updatedAt` first, capped at `limit`.
|
|
24
|
+
* A missing dir is an empty list; malformed files are skipped and named in `skipped`.
|
|
25
|
+
*/
|
|
26
|
+
export async function buildRunsJson(runsDir, { limit = DEFAULT_RUNS_LIMIT } = {}) {
|
|
27
|
+
let names;
|
|
28
|
+
try {
|
|
29
|
+
names = await readdir(runsDir);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err.code === 'ENOENT')
|
|
33
|
+
return { json: { schemaVersion: 1, runs: [] }, skipped: [] };
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
const byIssue = new Map();
|
|
37
|
+
for (const name of names) {
|
|
38
|
+
const phaseMatch = /^issue-(\d+)\.phase\.json$/.exec(name);
|
|
39
|
+
const runMatch = phaseMatch ? null : /^issue-(\d+)\.json$/.exec(name);
|
|
40
|
+
const match = phaseMatch ?? runMatch;
|
|
41
|
+
if (!match)
|
|
42
|
+
continue;
|
|
43
|
+
const issue = Number(match[1]);
|
|
44
|
+
const entry = byIssue.get(issue) ?? {};
|
|
45
|
+
if (phaseMatch)
|
|
46
|
+
entry.phase = name;
|
|
47
|
+
else
|
|
48
|
+
entry.run = name;
|
|
49
|
+
byIssue.set(issue, entry);
|
|
50
|
+
}
|
|
51
|
+
const issues = [...byIssue.keys()].sort((a, b) => a - b);
|
|
52
|
+
const skipped = [];
|
|
53
|
+
const rows = [];
|
|
54
|
+
const note = (name) => {
|
|
55
|
+
skipped.push(`factory: runs — skipped malformed ${name}`);
|
|
56
|
+
};
|
|
57
|
+
const loaded = await Promise.all(issues.map(async (issue) => {
|
|
58
|
+
const files = byIssue.get(issue) ?? {};
|
|
59
|
+
const bad = [];
|
|
60
|
+
let state = null;
|
|
61
|
+
let snapshot = null;
|
|
62
|
+
if (files.run !== undefined) {
|
|
63
|
+
state = await readIssueRunState(join(runsDir, files.run));
|
|
64
|
+
if (state === null || typeof state.updatedAt !== 'string') {
|
|
65
|
+
state = null;
|
|
66
|
+
bad.push(files.run);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (files.phase !== undefined) {
|
|
70
|
+
snapshot = await readPhaseSnapshot(join(runsDir, files.phase));
|
|
71
|
+
if (snapshot === null)
|
|
72
|
+
bad.push(files.phase);
|
|
73
|
+
}
|
|
74
|
+
return { issue, state, snapshot, bad };
|
|
75
|
+
}));
|
|
76
|
+
for (const { issue, state, snapshot, bad } of loaded) {
|
|
77
|
+
bad.forEach(note);
|
|
78
|
+
if (state === null && snapshot === null)
|
|
79
|
+
continue;
|
|
80
|
+
const updatedAt = state !== null && snapshot !== null
|
|
81
|
+
? time(snapshot.updatedAt) > time(state.updatedAt)
|
|
82
|
+
? snapshot.updatedAt
|
|
83
|
+
: state.updatedAt
|
|
84
|
+
: (state?.updatedAt ?? snapshot?.updatedAt ?? '');
|
|
85
|
+
rows.push({
|
|
86
|
+
issue,
|
|
87
|
+
lane: str(state?.lane),
|
|
88
|
+
repo: str(state?.repo),
|
|
89
|
+
status: str(state?.status),
|
|
90
|
+
phase: snapshot?.phase ?? null,
|
|
91
|
+
branch: str(state?.branch),
|
|
92
|
+
prNumber: num(state?.prNumber),
|
|
93
|
+
model: str(state?.model),
|
|
94
|
+
attempts: num(state?.attempts),
|
|
95
|
+
startedAt: str(state?.startedAt),
|
|
96
|
+
updatedAt,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
rows.sort((a, b) => time(b.updatedAt) - time(a.updatedAt) || b.issue - a.issue);
|
|
100
|
+
return { json: { schemaVersion: 1, runs: rows.slice(0, limit) }, skipped };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/cli/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface StalenessDeps {
|
|
2
|
+
exists: (p: string) => boolean;
|
|
3
|
+
readFile: (p: string) => string;
|
|
4
|
+
/** Absolute paths of all files under dir, recursive. */
|
|
5
|
+
listFiles: (dir: string) => string[];
|
|
6
|
+
mtimeMs: (p: string) => number;
|
|
7
|
+
}
|
|
8
|
+
export declare function defaultStalenessDeps(): StalenessDeps;
|
|
9
|
+
export declare function findWorkspaceRoot(startDir: string, deps: StalenessDeps): string | undefined;
|
|
10
|
+
export interface PackageStaleness {
|
|
11
|
+
pkg: string;
|
|
12
|
+
stale: boolean;
|
|
13
|
+
reason: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function checkDistFreshness(rootDir: string, deps: StalenessDeps): PackageStaleness[];
|
|
16
|
+
export declare function formatStaleDistMessage(stale: PackageStaleness[], rootDir: string): string;
|
|
17
|
+
export interface StalenessGuardOpts {
|
|
18
|
+
entryUrl: string;
|
|
19
|
+
env: NodeJS.ProcessEnv;
|
|
20
|
+
argv: string[];
|
|
21
|
+
error: (msg: string) => void;
|
|
22
|
+
warn: (msg: string) => void;
|
|
23
|
+
deps?: StalenessDeps;
|
|
24
|
+
}
|
|
25
|
+
export declare function runStalenessGuard(opts: StalenessGuardOpts): number | null;
|
|
26
|
+
export declare function distFreshnessProbe(entryUrl: string, deps?: StalenessDeps): (() => {
|
|
27
|
+
fresh: boolean;
|
|
28
|
+
detail: string;
|
|
29
|
+
}) | undefined;
|
|
30
|
+
//# sourceMappingURL=staleness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.d.ts","sourceRoot":"","sources":["../../src/cli/staleness.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,wDAAwD;IACxD,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAChC;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAUpD;AAID,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAgB3F;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAeD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,gBAAgB,EAAE,CAuC3F;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQzF;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAyBzE;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,aAAsC,GAC3C,CAAC,MAAM;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAexD"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// packages/cli/src/cli/staleness.ts — refuse to run from a dist/ older than src/
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
export function defaultStalenessDeps() {
|
|
6
|
+
return {
|
|
7
|
+
exists: (p) => existsSync(p),
|
|
8
|
+
readFile: (p) => readFileSync(p, 'utf-8'),
|
|
9
|
+
listFiles: (dir) => {
|
|
10
|
+
const entries = readdirSync(dir, { recursive: true, withFileTypes: true });
|
|
11
|
+
return entries.filter((e) => e.isFile()).map((e) => join(e.parentPath, e.name));
|
|
12
|
+
},
|
|
13
|
+
mtimeMs: (p) => statSync(p).mtimeMs,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const RUNTIME_PACKAGES = ['config', 'core', 'tui', 'cli'];
|
|
17
|
+
export function findWorkspaceRoot(startDir, deps) {
|
|
18
|
+
let dir = resolve(startDir);
|
|
19
|
+
for (;;) {
|
|
20
|
+
const pkgJsonPath = join(dir, 'package.json');
|
|
21
|
+
if (deps.exists(pkgJsonPath)) {
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(deps.readFile(pkgJsonPath));
|
|
24
|
+
if (parsed.workspaces !== undefined)
|
|
25
|
+
return dir;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// malformed package.json — not a match, keep walking
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const parent = dirname(dir);
|
|
32
|
+
if (parent === dir)
|
|
33
|
+
return undefined;
|
|
34
|
+
dir = parent;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isComparableSrcFile(path) {
|
|
38
|
+
return (path.endsWith('.ts') || path.endsWith('.tsx')) && !path.includes('.test.');
|
|
39
|
+
}
|
|
40
|
+
function newestMtime(files, deps) {
|
|
41
|
+
let newest = -Infinity;
|
|
42
|
+
for (const f of files) {
|
|
43
|
+
const mtime = deps.mtimeMs(f);
|
|
44
|
+
if (mtime > newest)
|
|
45
|
+
newest = mtime;
|
|
46
|
+
}
|
|
47
|
+
return newest;
|
|
48
|
+
}
|
|
49
|
+
export function checkDistFreshness(rootDir, deps) {
|
|
50
|
+
const results = [];
|
|
51
|
+
for (const pkg of RUNTIME_PACKAGES) {
|
|
52
|
+
const srcDir = join(rootDir, 'packages', pkg, 'src');
|
|
53
|
+
const distDir = join(rootDir, 'packages', pkg, 'dist');
|
|
54
|
+
if (!deps.exists(srcDir))
|
|
55
|
+
continue;
|
|
56
|
+
const srcFiles = deps.listFiles(srcDir).filter(isComparableSrcFile);
|
|
57
|
+
if (srcFiles.length === 0)
|
|
58
|
+
continue;
|
|
59
|
+
const newestSrc = newestMtime(srcFiles, deps);
|
|
60
|
+
if (!deps.exists(distDir)) {
|
|
61
|
+
results.push({ pkg, stale: true, reason: `${pkg}: dist/ missing` });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const distFiles = deps.listFiles(distDir);
|
|
65
|
+
if (distFiles.length === 0) {
|
|
66
|
+
results.push({ pkg, stale: true, reason: `${pkg}: dist/ empty` });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const newestDist = newestMtime(distFiles, deps);
|
|
70
|
+
if (newestSrc > newestDist) {
|
|
71
|
+
results.push({
|
|
72
|
+
pkg,
|
|
73
|
+
stale: true,
|
|
74
|
+
reason: `${pkg}: src is ${new Date(newestSrc).toISOString()} but dist is ${new Date(newestDist).toISOString()}`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
results.push({ pkg, stale: false, reason: `${pkg}: dist newer than src` });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return results;
|
|
82
|
+
}
|
|
83
|
+
export function formatStaleDistMessage(stale, rootDir) {
|
|
84
|
+
const lines = ['factory: compiled dist is stale — refusing to run old code'];
|
|
85
|
+
for (const s of stale) {
|
|
86
|
+
lines.push(` - ${s.reason}`);
|
|
87
|
+
}
|
|
88
|
+
lines.push(`fix: run 'npm run build' in ${rootDir}`);
|
|
89
|
+
lines.push('override: FACTORY_ALLOW_STALE=1 (runs anyway, at your own risk)');
|
|
90
|
+
return lines.join('\n');
|
|
91
|
+
}
|
|
92
|
+
const BYPASS_COMMANDS = new Set(['doctor', '--help', '-h', '--version', '-V']);
|
|
93
|
+
export function runStalenessGuard(opts) {
|
|
94
|
+
const deps = opts.deps ?? defaultStalenessDeps();
|
|
95
|
+
const entryPath = fileURLToPath(opts.entryUrl);
|
|
96
|
+
if (!entryPath.split(sep).includes('dist'))
|
|
97
|
+
return null;
|
|
98
|
+
const root = findWorkspaceRoot(dirname(entryPath), deps);
|
|
99
|
+
if (root === undefined)
|
|
100
|
+
return null;
|
|
101
|
+
const stale = checkDistFreshness(root, deps).filter((p) => p.stale);
|
|
102
|
+
if (stale.length === 0)
|
|
103
|
+
return null;
|
|
104
|
+
const message = formatStaleDistMessage(stale, root);
|
|
105
|
+
if (opts.env.FACTORY_ALLOW_STALE === '1') {
|
|
106
|
+
opts.warn(`factory: FACTORY_ALLOW_STALE=1 — running stale dist:\n${message}`);
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
if (opts.argv[2] !== undefined && BYPASS_COMMANDS.has(opts.argv[2])) {
|
|
110
|
+
opts.warn(message);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
opts.error(message);
|
|
114
|
+
return 2;
|
|
115
|
+
}
|
|
116
|
+
export function distFreshnessProbe(entryUrl, deps = defaultStalenessDeps()) {
|
|
117
|
+
const entryPath = fileURLToPath(entryUrl);
|
|
118
|
+
if (!entryPath.split(sep).includes('dist'))
|
|
119
|
+
return undefined;
|
|
120
|
+
const root = findWorkspaceRoot(dirname(entryPath), deps);
|
|
121
|
+
if (root === undefined)
|
|
122
|
+
return undefined;
|
|
123
|
+
return () => {
|
|
124
|
+
const results = checkDistFreshness(root, deps);
|
|
125
|
+
const stale = results.filter((r) => r.stale);
|
|
126
|
+
if (stale.length === 0) {
|
|
127
|
+
return { fresh: true, detail: 'dist newer than src' };
|
|
128
|
+
}
|
|
129
|
+
return { fresh: false, detail: stale.map((s) => s.reason).join('; ') };
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=staleness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.js","sourceRoot":"","sources":["../../src/cli/staleness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ActiveQueueClaim } from '@on-par/factory-core';
|
|
2
|
+
/** One open provider in `factory status --json` (#1101). */
|
|
3
|
+
export interface StatusBreakerProviderJson {
|
|
4
|
+
provider: string;
|
|
5
|
+
reason: string;
|
|
6
|
+
openedAt: string;
|
|
7
|
+
remainingSec: number;
|
|
8
|
+
}
|
|
9
|
+
/** Provider breaker state (state/breaker.json). `open` is true iff any provider is still open. */
|
|
10
|
+
export interface StatusBreakerJson {
|
|
11
|
+
open: boolean;
|
|
12
|
+
providers: StatusBreakerProviderJson[];
|
|
13
|
+
}
|
|
14
|
+
/** One fresh-heartbeat local queue claim. */
|
|
15
|
+
export interface StatusActiveRowJson {
|
|
16
|
+
lane: string;
|
|
17
|
+
issue: number;
|
|
18
|
+
phase: string;
|
|
19
|
+
ageSec: number;
|
|
20
|
+
}
|
|
21
|
+
/** `factory status --json` payload (#1101). No queue (#2268) or usage (#2270) section.
|
|
22
|
+
* Additive changes only; bump schemaVersion on a breaking change. */
|
|
23
|
+
export interface StatusJson {
|
|
24
|
+
schemaVersion: 1;
|
|
25
|
+
repo: string;
|
|
26
|
+
product: string | null;
|
|
27
|
+
stop: boolean;
|
|
28
|
+
breaker: StatusBreakerJson;
|
|
29
|
+
active: StatusActiveRowJson[];
|
|
30
|
+
}
|
|
31
|
+
/** Builds the `factory status --json` payload. An unparsable `lastActivityAt` reports `ageSec: 0`, never NaN. */
|
|
32
|
+
export declare function buildStatusJson(input: {
|
|
33
|
+
repo: string;
|
|
34
|
+
product: string | null;
|
|
35
|
+
stop: boolean;
|
|
36
|
+
breakers: ReadonlyArray<{
|
|
37
|
+
provider: string;
|
|
38
|
+
reason: string;
|
|
39
|
+
openedAt: string;
|
|
40
|
+
remainingMs: number;
|
|
41
|
+
}>;
|
|
42
|
+
active: ReadonlyArray<Pick<ActiveQueueClaim, 'lane' | 'issue' | 'phase' | 'lastActivityAt'>>;
|
|
43
|
+
now: number;
|
|
44
|
+
}): StatusJson;
|
|
45
|
+
//# sourceMappingURL=status-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-json.d.ts","sourceRoot":"","sources":["../../src/cli/status-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,4DAA4D;AAC5D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,kGAAkG;AAClG,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,yBAAyB,EAAE,CAAC;CACxC;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;sEACsE;AACtE,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,CAAC,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAED,iHAAiH;AACjH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrG,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC;IAC7F,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,UAAU,CAmBb"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Builds the `factory status --json` payload. An unparsable `lastActivityAt` reports `ageSec: 0`, never NaN. */
|
|
2
|
+
export function buildStatusJson(input) {
|
|
3
|
+
const providers = input.breakers.map((b) => ({
|
|
4
|
+
provider: b.provider,
|
|
5
|
+
reason: b.reason,
|
|
6
|
+
openedAt: b.openedAt,
|
|
7
|
+
remainingSec: Math.ceil(b.remainingMs / 1000),
|
|
8
|
+
}));
|
|
9
|
+
const active = input.active.map((c) => {
|
|
10
|
+
const ageSec = Math.floor((input.now - Date.parse(c.lastActivityAt)) / 1000);
|
|
11
|
+
return { lane: c.lane, issue: c.issue, phase: c.phase, ageSec: Number.isFinite(ageSec) ? Math.max(0, ageSec) : 0 };
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
schemaVersion: 1,
|
|
15
|
+
repo: input.repo,
|
|
16
|
+
product: input.product,
|
|
17
|
+
stop: input.stop,
|
|
18
|
+
breaker: { open: providers.length > 0, providers },
|
|
19
|
+
active,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=status-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-json.js","sourceRoot":"","sources":["../../src/cli/status-json.ts"],"names":[],"mappings":"AAmCA,iHAAiH;AACjH,MAAM,UAAU,eAAe,CAAC,KAO/B;IACC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC;KAC9C,CAAC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7E,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrH,CAAC,CAAC,CAAC;IACH,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,SAAS,EAAE;QAClD,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** `factory stop|resume --json` payload (#2276). Additive changes only; bump schemaVersion on a breaking change. */
|
|
2
|
+
export interface StopResumeJson {
|
|
3
|
+
schemaVersion: 1;
|
|
4
|
+
ok: true;
|
|
5
|
+
action: 'stop' | 'resume';
|
|
6
|
+
repo: string;
|
|
7
|
+
stopFlag: {
|
|
8
|
+
before: boolean;
|
|
9
|
+
after: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare function buildStopResumeJson(input: {
|
|
13
|
+
action: 'stop' | 'resume';
|
|
14
|
+
repo: string;
|
|
15
|
+
before: boolean;
|
|
16
|
+
after: boolean;
|
|
17
|
+
}): StopResumeJson;
|
|
18
|
+
//# sourceMappingURL=stop-resume-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-resume-json.d.ts","sourceRoot":"","sources":["../../src/cli/stop-resume-json.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/C;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,cAAc,CAQjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-resume-json.js","sourceRoot":"","sources":["../../src/cli/stop-resume-json.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,mBAAmB,CAAC,KAKnC;IACC,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;KACvD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DoctorCheck } from './doctor.js';
|
|
2
|
+
export interface StopFileDeps {
|
|
3
|
+
pathExists: (p: string) => boolean;
|
|
4
|
+
statMtimeMs: (p: string) => number;
|
|
5
|
+
now: () => number;
|
|
6
|
+
}
|
|
7
|
+
export declare function defaultStopFileDeps(): StopFileDeps;
|
|
8
|
+
export type StopSentinelStatus = {
|
|
9
|
+
present: false;
|
|
10
|
+
} | {
|
|
11
|
+
present: true;
|
|
12
|
+
ageMs: number;
|
|
13
|
+
writtenAt: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function readStopFileStatus(paths: {
|
|
16
|
+
stop: string;
|
|
17
|
+
}, deps?: Partial<StopFileDeps>): StopSentinelStatus;
|
|
18
|
+
/** Human-readable age like "3h 12m", "45s", or "820ms". */
|
|
19
|
+
export declare function formatStopFileAge(ms: number): string;
|
|
20
|
+
/** Message logged/printed by `factory run` when it skips a pass because STOP is present. */
|
|
21
|
+
export declare function stopSentinelRunSkipMessage(status: StopSentinelStatus): string;
|
|
22
|
+
export declare function stopSentinelCheck(status: StopSentinelStatus): DoctorCheck;
|
|
23
|
+
//# sourceMappingURL=stop-sentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-sentinel.d.ts","sourceRoot":"","sources":["../../src/cli/stop-sentinel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,wBAAgB,mBAAmB,IAAI,YAAY,CAMlD;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1G,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,kBAAkB,CAShH;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED,4FAA4F;AAC5F,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAO7E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,WAAW,CAezE"}
|