@deftai/directive 0.55.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/dist/bin.d.ts +3 -0
- package/dist/bin.js +5 -0
- package/dist/branch-parity.d.ts +47 -0
- package/dist/branch-parity.js +263 -0
- package/dist/cache-parity.d.ts +36 -0
- package/dist/cache-parity.js +165 -0
- package/dist/cache.d.ts +4 -0
- package/dist/cache.js +10 -0
- package/dist/capacity-backfill.d.ts +3 -0
- package/dist/capacity-backfill.js +9 -0
- package/dist/capacity-show.d.ts +3 -0
- package/dist/capacity-show.js +9 -0
- package/dist/check.d.ts +10 -0
- package/dist/check.js +60 -0
- package/dist/cli-router/index.d.ts +8 -0
- package/dist/cli-router/index.js +37 -0
- package/dist/cli-router/route-argv.d.ts +32 -0
- package/dist/cli-router/route-argv.js +226 -0
- package/dist/codebase-default-extractor.d.ts +3 -0
- package/dist/codebase-default-extractor.js +9 -0
- package/dist/codebase-map-fresh.d.ts +3 -0
- package/dist/codebase-map-fresh.js +9 -0
- package/dist/codebase-map.d.ts +3 -0
- package/dist/codebase-map.js +9 -0
- package/dist/codebase-parity.d.ts +30 -0
- package/dist/codebase-parity.js +294 -0
- package/dist/codebase-projection-registry.d.ts +3 -0
- package/dist/codebase-projection-registry.js +9 -0
- package/dist/codebase-provider.d.ts +3 -0
- package/dist/codebase-provider.js +9 -0
- package/dist/content-validate-cli/validate-links.d.ts +11 -0
- package/dist/content-validate-cli/validate-links.js +37 -0
- package/dist/content-validate-cli/validate-strategy-output.d.ts +13 -0
- package/dist/content-validate-cli/validate-strategy-output.js +56 -0
- package/dist/content-validate-cli/verify-capacity.d.ts +12 -0
- package/dist/content-validate-cli/verify-capacity.js +54 -0
- package/dist/dispatch.d.ts +26 -0
- package/dist/dispatch.js +569 -0
- package/dist/doctor-parity.d.ts +38 -0
- package/dist/doctor-parity.js +151 -0
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +10 -0
- package/dist/gates-cli/_helpers.d.ts +18 -0
- package/dist/gates-cli/_helpers.js +71 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +15 -0
- package/dist/init-cli/constants.d.ts +5 -0
- package/dist/init-cli/constants.js +5 -0
- package/dist/init-cli/init.d.ts +3 -0
- package/dist/init-cli/init.js +11 -0
- package/dist/init-cli/resolve-binary.d.ts +34 -0
- package/dist/init-cli/resolve-binary.js +78 -0
- package/dist/init-cli/run-deft-install.d.ts +23 -0
- package/dist/init-cli/run-deft-install.js +71 -0
- package/dist/init-cli/update.d.ts +3 -0
- package/dist/init-cli/update.js +11 -0
- package/dist/install-cli/coverage-map.d.ts +14 -0
- package/dist/install-cli/coverage-map.js +111 -0
- package/dist/intake-parity.d.ts +30 -0
- package/dist/intake-parity.js +203 -0
- package/dist/lifecycle-cli/coverage-map.d.ts +16 -0
- package/dist/lifecycle-cli/coverage-map.js +254 -0
- package/dist/lifecycle-cli/helpers.d.ts +8 -0
- package/dist/lifecycle-cli/helpers.js +20 -0
- package/dist/lifecycle-packs-parity.d.ts +30 -0
- package/dist/lifecycle-packs-parity.js +377 -0
- package/dist/orchestration-cli/coverage-map.d.ts +21 -0
- package/dist/orchestration-cli/coverage-map.js +225 -0
- package/dist/orchestration-cli/helpers.d.ts +11 -0
- package/dist/orchestration-cli/helpers.js +35 -0
- package/dist/orchestration-parity.d.ts +38 -0
- package/dist/orchestration-parity.js +364 -0
- package/dist/parity.d.ts +36 -0
- package/dist/parity.js +176 -0
- package/dist/platform-parity.d.ts +26 -0
- package/dist/platform-parity.js +309 -0
- package/dist/policy-parity.d.ts +35 -0
- package/dist/policy-parity.js +214 -0
- package/dist/policy.d.ts +27 -0
- package/dist/policy.js +316 -0
- package/dist/pr-closing-keywords-parity.d.ts +45 -0
- package/dist/pr-closing-keywords-parity.js +259 -0
- package/dist/pr-closing-keywords.d.ts +3 -0
- package/dist/pr-closing-keywords.js +10 -0
- package/dist/pr-merge-readiness-parity.d.ts +44 -0
- package/dist/pr-merge-readiness-parity.js +296 -0
- package/dist/pr-merge-readiness.d.ts +3 -0
- package/dist/pr-merge-readiness.js +10 -0
- package/dist/pr-monitor-parity.d.ts +44 -0
- package/dist/pr-monitor-parity.js +283 -0
- package/dist/pr-monitor.d.ts +3 -0
- package/dist/pr-monitor.js +10 -0
- package/dist/pr-protected-issues-parity.d.ts +41 -0
- package/dist/pr-protected-issues-parity.js +220 -0
- package/dist/pr-protected-issues.d.ts +3 -0
- package/dist/pr-protected-issues.js +10 -0
- package/dist/pr-wait-mergeable-parity.d.ts +45 -0
- package/dist/pr-wait-mergeable-parity.js +340 -0
- package/dist/pr-wait-mergeable.d.ts +3 -0
- package/dist/pr-wait-mergeable.js +10 -0
- package/dist/preflight-cache.d.ts +16 -0
- package/dist/preflight-cache.js +106 -0
- package/dist/preflight-gh.d.ts +12 -0
- package/dist/preflight-gh.js +188 -0
- package/dist/probe-session.d.ts +3 -0
- package/dist/probe-session.js +10 -0
- package/dist/release-e2e-parity.d.ts +31 -0
- package/dist/release-e2e-parity.js +114 -0
- package/dist/release-e2e.d.ts +3 -0
- package/dist/release-e2e.js +10 -0
- package/dist/release-parity.d.ts +40 -0
- package/dist/release-parity.js +223 -0
- package/dist/release-publish-parity.d.ts +36 -0
- package/dist/release-publish-parity.js +138 -0
- package/dist/release-publish.d.ts +3 -0
- package/dist/release-publish.js +10 -0
- package/dist/release-rollback-parity.d.ts +37 -0
- package/dist/release-rollback-parity.js +161 -0
- package/dist/release-rollback.d.ts +3 -0
- package/dist/release-rollback.js +10 -0
- package/dist/release.d.ts +3 -0
- package/dist/release.js +10 -0
- package/dist/render-cli/deft-ts-runner.d.ts +20 -0
- package/dist/render-cli/deft-ts-runner.js +35 -0
- package/dist/render-cli/prd-render-cli.d.ts +2 -0
- package/dist/render-cli/prd-render-cli.js +7 -0
- package/dist/render-cli/project-render-cli.d.ts +2 -0
- package/dist/render-cli/project-render-cli.js +6 -0
- package/dist/render-cli/spec-render-cli.d.ts +2 -0
- package/dist/render-cli/spec-render-cli.js +6 -0
- package/dist/render-cli/spec-validate-cli.d.ts +2 -0
- package/dist/render-cli/spec-validate-cli.js +6 -0
- package/dist/render-parity.d.ts +35 -0
- package/dist/render-parity.js +383 -0
- package/dist/scm-parity.d.ts +39 -0
- package/dist/scm-parity.js +181 -0
- package/dist/scope-lifecycle-parity.d.ts +35 -0
- package/dist/scope-lifecycle-parity.js +177 -0
- package/dist/scope-lifecycle.d.ts +4 -0
- package/dist/scope-lifecycle.js +29 -0
- package/dist/session-parity.d.ts +39 -0
- package/dist/session-parity.js +260 -0
- package/dist/slice-parity.d.ts +36 -0
- package/dist/slice-parity.js +304 -0
- package/dist/slice.d.ts +4 -0
- package/dist/slice.js +29 -0
- package/dist/story-ready-parity.d.ts +49 -0
- package/dist/story-ready-parity.js +254 -0
- package/dist/subagent-monitor.d.ts +3 -0
- package/dist/subagent-monitor.js +10 -0
- package/dist/swarm-parity.d.ts +28 -0
- package/dist/swarm-parity.js +326 -0
- package/dist/toolchain-check.d.ts +3 -0
- package/dist/toolchain-check.js +14 -0
- package/dist/triage-actions-parity.d.ts +33 -0
- package/dist/triage-actions-parity.js +201 -0
- package/dist/triage-actions.d.ts +17 -0
- package/dist/triage-actions.js +144 -0
- package/dist/triage-aux-a-parity.d.ts +35 -0
- package/dist/triage-aux-a-parity.js +172 -0
- package/dist/triage-aux-b-parity.d.ts +32 -0
- package/dist/triage-aux-b-parity.js +308 -0
- package/dist/triage-bootstrap-parity.d.ts +44 -0
- package/dist/triage-bootstrap-parity.js +226 -0
- package/dist/triage-bootstrap.d.ts +24 -0
- package/dist/triage-bootstrap.js +172 -0
- package/dist/triage-bulk.d.ts +17 -0
- package/dist/triage-bulk.js +154 -0
- package/dist/triage-classify-parity.d.ts +40 -0
- package/dist/triage-classify-parity.js +227 -0
- package/dist/triage-classify.d.ts +13 -0
- package/dist/triage-classify.js +76 -0
- package/dist/triage-help.d.ts +3 -0
- package/dist/triage-help.js +10 -0
- package/dist/triage-queue-parity.d.ts +59 -0
- package/dist/triage-queue-parity.js +363 -0
- package/dist/triage-queue.d.ts +17 -0
- package/dist/triage-queue.js +174 -0
- package/dist/triage-reconcile.d.ts +11 -0
- package/dist/triage-reconcile.js +76 -0
- package/dist/triage-refresh.d.ts +7 -0
- package/dist/triage-refresh.js +37 -0
- package/dist/triage-scope-drift.d.ts +12 -0
- package/dist/triage-scope-drift.js +117 -0
- package/dist/triage-scope-parity.d.ts +34 -0
- package/dist/triage-scope-parity.js +218 -0
- package/dist/triage-scope.d.ts +4 -0
- package/dist/triage-scope.js +29 -0
- package/dist/triage-smoketest.d.ts +3 -0
- package/dist/triage-smoketest.js +43 -0
- package/dist/triage-subscribe.d.ts +15 -0
- package/dist/triage-subscribe.js +157 -0
- package/dist/triage-summary-parity.d.ts +50 -0
- package/dist/triage-summary-parity.js +306 -0
- package/dist/triage-summary.d.ts +14 -0
- package/dist/triage-summary.js +77 -0
- package/dist/triage-welcome.d.ts +12 -0
- package/dist/triage-welcome.js +78 -0
- package/dist/ts-check-lane.d.ts +9 -0
- package/dist/ts-check-lane.js +49 -0
- package/dist/validate-content-parity.d.ts +33 -0
- package/dist/validate-content-parity.js +356 -0
- package/dist/vbrief-activate-parity.d.ts +39 -0
- package/dist/vbrief-activate-parity.js +216 -0
- package/dist/vbrief-activate.d.ts +3 -0
- package/dist/vbrief-activate.js +7 -0
- package/dist/vbrief-build-parity.d.ts +28 -0
- package/dist/vbrief-build-parity.js +399 -0
- package/dist/vbrief-build.d.ts +3 -0
- package/dist/vbrief-build.js +8 -0
- package/dist/vbrief-preflight-parity.d.ts +34 -0
- package/dist/vbrief-preflight-parity.js +163 -0
- package/dist/vbrief-preflight.d.ts +12 -0
- package/dist/vbrief-preflight.js +58 -0
- package/dist/vbrief-reconcile-parity.d.ts +22 -0
- package/dist/vbrief-reconcile-parity.js +600 -0
- package/dist/vbrief-reconcile.d.ts +3 -0
- package/dist/vbrief-reconcile.js +7 -0
- package/dist/vbrief-validate-parity.d.ts +27 -0
- package/dist/vbrief-validate-parity.js +122 -0
- package/dist/vbrief-validate.d.ts +3 -0
- package/dist/vbrief-validate.js +8 -0
- package/dist/vbrief-validation-parity.d.ts +28 -0
- package/dist/vbrief-validation-parity.js +645 -0
- package/dist/vbrief-validation.d.ts +3 -0
- package/dist/vbrief-validation.js +8 -0
- package/dist/verify-branch.d.ts +14 -0
- package/dist/verify-branch.js +81 -0
- package/dist/verify-encoding.d.ts +15 -0
- package/dist/verify-encoding.js +86 -0
- package/dist/verify-env-parity.d.ts +28 -0
- package/dist/verify-env-parity.js +272 -0
- package/dist/verify-hooks-installed.d.ts +10 -0
- package/dist/verify-hooks-installed.js +48 -0
- package/dist/verify-investigation.d.ts +3 -0
- package/dist/verify-investigation.js +10 -0
- package/dist/verify-judgment-gates.d.ts +3 -0
- package/dist/verify-judgment-gates.js +10 -0
- package/dist/verify-no-task-runtime.d.ts +3 -0
- package/dist/verify-no-task-runtime.js +16 -0
- package/dist/verify-session-ritual.d.ts +13 -0
- package/dist/verify-session-ritual.js +78 -0
- package/dist/verify-source-cli/rule-ownership-lint.d.ts +12 -0
- package/dist/verify-source-cli/rule-ownership-lint.js +61 -0
- package/dist/verify-source-cli/verify-content-manifest.d.ts +12 -0
- package/dist/verify-source-cli/verify-content-manifest.js +61 -0
- package/dist/verify-source-cli/verify-scm-boundary.d.ts +13 -0
- package/dist/verify-source-cli/verify-scm-boundary.js +66 -0
- package/dist/verify-source-cli/verify-stubs.d.ts +11 -0
- package/dist/verify-source-cli/verify-stubs.js +27 -0
- package/dist/verify-source-parity.d.ts +26 -0
- package/dist/verify-source-parity.js +178 -0
- package/dist/verify-story-ready.d.ts +16 -0
- package/dist/verify-story-ready.js +138 -0
- package/dist/verify-tools.d.ts +13 -0
- package/dist/verify-tools.js +67 -0
- package/dist/verify-wip-cap.d.ts +13 -0
- package/dist/verify-wip-cap.js +62 -0
- package/dist/wip-cap-parity.d.ts +39 -0
- package/dist/wip-cap-parity.js +209 -0
- package/package.json +50 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { listProject, validateProject } from "../../core/dist/triage/classify/index.js";
|
|
6
|
+
/** Parse triage-classify CLI args, mirroring the Python argparse surface. */
|
|
7
|
+
export function parseArgs(argv) {
|
|
8
|
+
const parsed = {
|
|
9
|
+
projectRoot: ".",
|
|
10
|
+
doList: false,
|
|
11
|
+
doValidate: false,
|
|
12
|
+
};
|
|
13
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
14
|
+
const arg = argv[i];
|
|
15
|
+
if (arg === "--list") {
|
|
16
|
+
parsed.doList = true;
|
|
17
|
+
}
|
|
18
|
+
else if (arg === "--validate") {
|
|
19
|
+
parsed.doValidate = true;
|
|
20
|
+
}
|
|
21
|
+
else if (arg === "--project-root") {
|
|
22
|
+
const value = argv[i + 1];
|
|
23
|
+
if (value === undefined) {
|
|
24
|
+
return { ...parsed, error: "argument --project-root: expected one argument" };
|
|
25
|
+
}
|
|
26
|
+
parsed.projectRoot = value;
|
|
27
|
+
i += 1;
|
|
28
|
+
}
|
|
29
|
+
else if (arg?.startsWith("--project-root=")) {
|
|
30
|
+
parsed.projectRoot = arg.slice("--project-root=".length);
|
|
31
|
+
}
|
|
32
|
+
else if (arg === "--help" || arg === "-h") {
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
else if (arg?.startsWith("-")) {
|
|
36
|
+
return { ...parsed, error: `unrecognized arguments: ${arg}` };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return parsed;
|
|
40
|
+
}
|
|
41
|
+
/** Run the CLI and return the process exit code. */
|
|
42
|
+
export function run(argv) {
|
|
43
|
+
const args = parseArgs(argv);
|
|
44
|
+
if (args.error !== undefined) {
|
|
45
|
+
process.stderr.write(`ERR: ${args.error}\n`);
|
|
46
|
+
return 2;
|
|
47
|
+
}
|
|
48
|
+
const projectRoot = resolve(args.projectRoot);
|
|
49
|
+
try {
|
|
50
|
+
const st = statSync(projectRoot);
|
|
51
|
+
if (!st.isDirectory()) {
|
|
52
|
+
process.stderr.write(`ERR: --project-root ${projectRoot} does not exist or is not a directory.\n`);
|
|
53
|
+
return 2;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
process.stderr.write(`ERR: --project-root ${projectRoot} does not exist or is not a directory.\n`);
|
|
58
|
+
return 2;
|
|
59
|
+
}
|
|
60
|
+
if (args.doValidate) {
|
|
61
|
+
const result = validateProject(projectRoot);
|
|
62
|
+
if (result.stdout.length > 0) {
|
|
63
|
+
process.stdout.write(result.stdout);
|
|
64
|
+
}
|
|
65
|
+
if (result.stderr.length > 0) {
|
|
66
|
+
process.stderr.write(result.stderr);
|
|
67
|
+
}
|
|
68
|
+
return result.code;
|
|
69
|
+
}
|
|
70
|
+
process.stdout.write(listProject(projectRoot));
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
74
|
+
process.exit(run(process.argv.slice(2)));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=triage-classify.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { runHelp } from "../../core/dist/triage/help/index.js";
|
|
4
|
+
export function run(argv) {
|
|
5
|
+
return runHelp(argv);
|
|
6
|
+
}
|
|
7
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
8
|
+
process.exit(run(process.argv.slice(2)));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=triage-help.js.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export interface CommandCapture {
|
|
3
|
+
readonly exitCode: number;
|
|
4
|
+
readonly stdout: string;
|
|
5
|
+
readonly stderr: string;
|
|
6
|
+
}
|
|
7
|
+
export interface QueueFixtureIssue {
|
|
8
|
+
readonly number: number;
|
|
9
|
+
readonly title?: string;
|
|
10
|
+
readonly state?: string;
|
|
11
|
+
readonly labels?: readonly string[];
|
|
12
|
+
readonly updatedAt?: string;
|
|
13
|
+
readonly createdAt?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface QueueAuditEntry {
|
|
16
|
+
readonly issueNumber: number;
|
|
17
|
+
readonly decision: string;
|
|
18
|
+
readonly timestamp?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface QueueFixtureOptions {
|
|
21
|
+
readonly repo?: string;
|
|
22
|
+
readonly issues?: readonly QueueFixtureIssue[];
|
|
23
|
+
readonly auditEntries?: readonly QueueAuditEntry[];
|
|
24
|
+
readonly rankingLabels?: readonly string[];
|
|
25
|
+
readonly activeIssueNumbers?: readonly number[];
|
|
26
|
+
readonly sliceRecords?: readonly Record<string, unknown>[];
|
|
27
|
+
readonly blockedIssueNumbers?: readonly number[];
|
|
28
|
+
}
|
|
29
|
+
export interface ParityCase {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly argv: readonly string[];
|
|
32
|
+
readonly fixture?: QueueFixtureOptions;
|
|
33
|
+
readonly skipFixture?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface ParityDiff {
|
|
36
|
+
readonly caseName: string;
|
|
37
|
+
readonly exitMismatch: boolean;
|
|
38
|
+
readonly stdoutMismatch: boolean;
|
|
39
|
+
readonly stderrMismatch: boolean;
|
|
40
|
+
readonly pythonExit: number;
|
|
41
|
+
readonly tsExit: number;
|
|
42
|
+
}
|
|
43
|
+
export interface ParityResult {
|
|
44
|
+
readonly ok: boolean;
|
|
45
|
+
readonly diffs: readonly ParityDiff[];
|
|
46
|
+
}
|
|
47
|
+
/** Strip volatile absolute paths before compare. */
|
|
48
|
+
export declare function normalizeOutput(text: string): string;
|
|
49
|
+
/** Build a throwaway project root with optional queue fixtures. */
|
|
50
|
+
export declare function buildFixtureRepo(options?: QueueFixtureOptions): string;
|
|
51
|
+
/** Diff one parity case between Python oracle and TS CLI. */
|
|
52
|
+
export declare function diffCase(python: CommandCapture, ts: CommandCapture, caseName: string): ParityDiff;
|
|
53
|
+
export declare const PARITY_CASES: readonly ParityCase[];
|
|
54
|
+
/** Augment argv with fixture audit/slices hooks when present. */
|
|
55
|
+
export declare function augmentParityArgv(testCase: ParityCase, root: string): readonly string[];
|
|
56
|
+
/** Run all parity cases; returns aggregate result. */
|
|
57
|
+
export declare function runParity(): ParityResult;
|
|
58
|
+
export declare function renderReport(result: ParityResult): string;
|
|
59
|
+
//# sourceMappingURL=triage-queue-parity.d.ts.map
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Golden-output parity harness (#1725): builds throwaway fixture repos, runs
|
|
4
|
+
* BOTH the Python oracle (`scripts/triage_queue.py queue`) and the ported TS
|
|
5
|
+
* triage:queue CLI, and diffs exit codes + stdout/stderr (cache-off).
|
|
6
|
+
*
|
|
7
|
+
* Exit codes: 0 parity / 1 divergence / 2 harness setup error.
|
|
8
|
+
*/
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
const DEFAULT_REPO = "owner/repo";
|
|
15
|
+
/** Strip volatile absolute paths before compare. */
|
|
16
|
+
export function normalizeOutput(text) {
|
|
17
|
+
return text.replace(/project_root=[^\s)]+/g, "project_root=<ROOT>");
|
|
18
|
+
}
|
|
19
|
+
function runCapture(cmd, args, cwd, env = {}) {
|
|
20
|
+
const merged = { ...process.env, ...env };
|
|
21
|
+
for (const key of Object.keys(merged)) {
|
|
22
|
+
if (merged[key] === undefined) {
|
|
23
|
+
delete merged[key];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const result = spawnSync(cmd, args, {
|
|
27
|
+
cwd,
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
env: merged,
|
|
30
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
status: result.status ?? 2,
|
|
34
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
35
|
+
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function writeCachedIssue(root, repo, issue) {
|
|
39
|
+
const parts = repo.split("/", 2);
|
|
40
|
+
const owner = parts[0];
|
|
41
|
+
const name = parts[1];
|
|
42
|
+
if (owner === undefined || name === undefined) {
|
|
43
|
+
throw new Error(`invalid repo slug: ${repo}`);
|
|
44
|
+
}
|
|
45
|
+
const dir = join(root, ".deft-cache", "github-issue", owner, name, String(issue.number));
|
|
46
|
+
mkdirSync(dir, { recursive: true });
|
|
47
|
+
const raw = {
|
|
48
|
+
number: issue.number,
|
|
49
|
+
title: issue.title ?? `Issue ${issue.number}`,
|
|
50
|
+
state: issue.state ?? "open",
|
|
51
|
+
labels: (issue.labels ?? []).map((label) => ({ name: label })),
|
|
52
|
+
updated_at: issue.updatedAt ?? "2026-05-17T20:00:00Z",
|
|
53
|
+
...(issue.createdAt !== undefined ? { created_at: issue.createdAt } : {}),
|
|
54
|
+
};
|
|
55
|
+
writeFileSync(join(dir, "raw.json"), `${JSON.stringify(raw)}\n`, { encoding: "utf8" });
|
|
56
|
+
}
|
|
57
|
+
function writeAuditLog(root, repo, entries) {
|
|
58
|
+
const dir = join(root, "vbrief", ".eval");
|
|
59
|
+
mkdirSync(dir, { recursive: true });
|
|
60
|
+
const lines = entries.map((entry) => JSON.stringify({
|
|
61
|
+
decision_id: `id-${entry.issueNumber}-${entry.decision}`,
|
|
62
|
+
timestamp: entry.timestamp ?? "2026-05-17T20:00:00Z",
|
|
63
|
+
repo,
|
|
64
|
+
issue_number: entry.issueNumber,
|
|
65
|
+
decision: entry.decision,
|
|
66
|
+
actor: "parity",
|
|
67
|
+
}));
|
|
68
|
+
writeFileSync(join(dir, "candidates.jsonl"), `${lines.join("\n")}\n`, { encoding: "utf8" });
|
|
69
|
+
}
|
|
70
|
+
function writeProjectDefinition(root, rankingLabels) {
|
|
71
|
+
const dir = join(root, "vbrief");
|
|
72
|
+
mkdirSync(dir, { recursive: true });
|
|
73
|
+
const plan = { title: "T", status: "running", items: [] };
|
|
74
|
+
if (rankingLabels !== undefined && rankingLabels.length > 0) {
|
|
75
|
+
plan.policy = { triageRankingLabels: [...rankingLabels] };
|
|
76
|
+
}
|
|
77
|
+
writeFileSync(join(dir, "PROJECT-DEFINITION.vbrief.json"), `${JSON.stringify({ vBRIEFInfo: { version: "0.6" }, plan }, null, 2)}\n`, { encoding: "utf8" });
|
|
78
|
+
}
|
|
79
|
+
function writeActiveScope(root, repo, issueNumber, filename) {
|
|
80
|
+
const dir = join(root, "vbrief", "active");
|
|
81
|
+
mkdirSync(dir, { recursive: true });
|
|
82
|
+
writeFileSync(join(dir, filename), `${JSON.stringify({
|
|
83
|
+
vBRIEFInfo: { version: "0.6" },
|
|
84
|
+
plan: {
|
|
85
|
+
title: "Active scope",
|
|
86
|
+
status: "running",
|
|
87
|
+
references: [
|
|
88
|
+
{
|
|
89
|
+
uri: `https://github.com/${repo}/issues/${issueNumber}`,
|
|
90
|
+
type: "x-vbrief/github-issue",
|
|
91
|
+
title: `Issue #${issueNumber}`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
})}\n`, { encoding: "utf8" });
|
|
96
|
+
}
|
|
97
|
+
function writeBlockedScope(root, repo, issueNumber, filename) {
|
|
98
|
+
const dir = join(root, "vbrief", "active");
|
|
99
|
+
mkdirSync(dir, { recursive: true });
|
|
100
|
+
writeFileSync(join(dir, filename), `${JSON.stringify({
|
|
101
|
+
vBRIEFInfo: { version: "0.6" },
|
|
102
|
+
plan: {
|
|
103
|
+
title: "Blocked scope",
|
|
104
|
+
status: "blocked",
|
|
105
|
+
references: [
|
|
106
|
+
{
|
|
107
|
+
uri: `https://github.com/${repo}/issues/${issueNumber}`,
|
|
108
|
+
type: "x-vbrief/github-issue",
|
|
109
|
+
title: `Issue #${issueNumber}`,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
})}\n`, { encoding: "utf8" });
|
|
114
|
+
}
|
|
115
|
+
function writeSliceRecords(root, records) {
|
|
116
|
+
const dir = join(root, "vbrief", ".eval");
|
|
117
|
+
mkdirSync(dir, { recursive: true });
|
|
118
|
+
writeFileSync(join(dir, "slices.jsonl"), `${records.map((record) => JSON.stringify(record)).join("\n")}\n`, { encoding: "utf8" });
|
|
119
|
+
}
|
|
120
|
+
/** Build a throwaway project root with optional queue fixtures. */
|
|
121
|
+
export function buildFixtureRepo(options = {}) {
|
|
122
|
+
const root = mkdtempSync(join(tmpdir(), "deft-triage-queue-parity-"));
|
|
123
|
+
const repo = options.repo ?? DEFAULT_REPO;
|
|
124
|
+
mkdirSync(join(root, "vbrief"), { recursive: true });
|
|
125
|
+
writeProjectDefinition(root, options.rankingLabels);
|
|
126
|
+
for (const issue of options.issues ?? []) {
|
|
127
|
+
writeCachedIssue(root, repo, issue);
|
|
128
|
+
}
|
|
129
|
+
if (options.auditEntries !== undefined && options.auditEntries.length > 0) {
|
|
130
|
+
writeAuditLog(root, repo, options.auditEntries);
|
|
131
|
+
}
|
|
132
|
+
for (const issueNumber of options.activeIssueNumbers ?? []) {
|
|
133
|
+
writeActiveScope(root, repo, issueNumber, `active-${issueNumber}.vbrief.json`);
|
|
134
|
+
}
|
|
135
|
+
for (const issueNumber of options.blockedIssueNumbers ?? []) {
|
|
136
|
+
writeBlockedScope(root, repo, issueNumber, `blocked-${issueNumber}.vbrief.json`);
|
|
137
|
+
}
|
|
138
|
+
if (options.sliceRecords !== undefined && options.sliceRecords.length > 0) {
|
|
139
|
+
writeSliceRecords(root, options.sliceRecords);
|
|
140
|
+
}
|
|
141
|
+
return root;
|
|
142
|
+
}
|
|
143
|
+
function resolveDeftRoot() {
|
|
144
|
+
if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
|
|
145
|
+
return resolve(process.env.DEFT_ROOT);
|
|
146
|
+
}
|
|
147
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
148
|
+
}
|
|
149
|
+
function runPythonQueue(deftRoot, _repo, argv) {
|
|
150
|
+
const cap = runCapture("uv", ["run", "python", join(deftRoot, "scripts", "triage_queue.py"), "queue", ...argv], deftRoot, { DEFT_TRIAGE_REPO: undefined, PYTHONUTF8: "1" });
|
|
151
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
152
|
+
}
|
|
153
|
+
function runTsQueue(deftRoot, _repo, argv) {
|
|
154
|
+
const cap = runCapture("node", [join(deftRoot, "packages", "cli", "dist", "triage-queue.js"), "queue", ...argv], deftRoot, { DEFT_TRIAGE_REPO: undefined });
|
|
155
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
156
|
+
}
|
|
157
|
+
/** Diff one parity case between Python oracle and TS CLI. */
|
|
158
|
+
export function diffCase(python, ts, caseName) {
|
|
159
|
+
const pyOut = normalizeOutput(python.stdout);
|
|
160
|
+
const tsOut = normalizeOutput(ts.stdout);
|
|
161
|
+
const pyErr = normalizeOutput(python.stderr);
|
|
162
|
+
const tsErr = normalizeOutput(ts.stderr);
|
|
163
|
+
return {
|
|
164
|
+
caseName,
|
|
165
|
+
exitMismatch: python.exitCode !== ts.exitCode,
|
|
166
|
+
stdoutMismatch: pyOut !== tsOut,
|
|
167
|
+
stderrMismatch: pyErr !== tsErr,
|
|
168
|
+
pythonExit: python.exitCode,
|
|
169
|
+
tsExit: ts.exitCode,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export const PARITY_CASES = [
|
|
173
|
+
{
|
|
174
|
+
name: "missing-repo",
|
|
175
|
+
argv: ["--project-root", "<ROOT>"],
|
|
176
|
+
skipFixture: true,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "empty-cache",
|
|
180
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
181
|
+
fixture: {},
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "group-order",
|
|
185
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
186
|
+
fixture: {
|
|
187
|
+
issues: [
|
|
188
|
+
{ number: 1, title: "Untriaged", updatedAt: "2026-05-17T12:00:00Z" },
|
|
189
|
+
{ number: 2, title: "Resume", updatedAt: "2026-05-17T11:00:00Z" },
|
|
190
|
+
{ number: 3, title: "Urgent", updatedAt: "2026-05-15T10:00:00Z" },
|
|
191
|
+
{ number: 4, title: "Other", updatedAt: "2026-05-14T10:00:00Z" },
|
|
192
|
+
],
|
|
193
|
+
auditEntries: [
|
|
194
|
+
{ issueNumber: 3, decision: "needs-ac", timestamp: "2026-05-15T11:00:00Z" },
|
|
195
|
+
{ issueNumber: 4, decision: "defer", timestamp: "2026-05-14T11:00:00Z" },
|
|
196
|
+
],
|
|
197
|
+
activeIssueNumbers: [2],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: "orphan-above-resume",
|
|
202
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
203
|
+
fixture: {
|
|
204
|
+
issues: [
|
|
205
|
+
{ number: 10, title: "Umbrella closed", state: "closed" },
|
|
206
|
+
{ number: 11, title: "Orphan child", state: "open", updatedAt: "2026-05-16T10:00:00Z" },
|
|
207
|
+
{ number: 12, title: "Resume child", state: "open", updatedAt: "2026-05-17T10:00:00Z" },
|
|
208
|
+
],
|
|
209
|
+
activeIssueNumbers: [12],
|
|
210
|
+
sliceRecords: [
|
|
211
|
+
{
|
|
212
|
+
slice_id: "slice-1",
|
|
213
|
+
umbrella: 10,
|
|
214
|
+
umbrella_url: "https://github.com/owner/repo/issues/10",
|
|
215
|
+
children: [
|
|
216
|
+
{ n: 11, url: "https://github.com/owner/repo/issues/11", wave: 1, role: "child" },
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "resume-eligible",
|
|
224
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
225
|
+
fixture: {
|
|
226
|
+
issues: [
|
|
227
|
+
{ number: 20, title: "Resume eligible", updatedAt: "2026-05-17T10:00:00Z" },
|
|
228
|
+
{ number: 21, title: "Untriaged", updatedAt: "2026-05-17T11:00:00Z" },
|
|
229
|
+
],
|
|
230
|
+
auditEntries: [
|
|
231
|
+
{ issueNumber: 20, decision: "resume-eligible", timestamp: "2026-05-17T09:00:00Z" },
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "ranking-labels",
|
|
237
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
238
|
+
fixture: {
|
|
239
|
+
rankingLabels: ["urgent", "breaking-change"],
|
|
240
|
+
issues: [
|
|
241
|
+
{ number: 30, title: "Unranked", updatedAt: "2026-05-17T10:00:00Z" },
|
|
242
|
+
{
|
|
243
|
+
number: 31,
|
|
244
|
+
title: "Breaking",
|
|
245
|
+
labels: ["breaking-change"],
|
|
246
|
+
updatedAt: "2026-05-15T10:00:00Z",
|
|
247
|
+
},
|
|
248
|
+
{ number: 32, title: "Urgent", labels: ["urgent"], updatedAt: "2026-05-16T10:00:00Z" },
|
|
249
|
+
],
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "limit-cap",
|
|
254
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "2"],
|
|
255
|
+
fixture: {
|
|
256
|
+
issues: [
|
|
257
|
+
{ number: 40, updatedAt: "2026-05-17T10:00:00Z" },
|
|
258
|
+
{ number: 41, updatedAt: "2026-05-16T10:00:00Z" },
|
|
259
|
+
{ number: 42, updatedAt: "2026-05-15T10:00:00Z" },
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: "blocked-demoted",
|
|
265
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0"],
|
|
266
|
+
fixture: {
|
|
267
|
+
issues: [
|
|
268
|
+
{ number: 50, title: "Blocked", updatedAt: "2026-05-17T10:00:00Z" },
|
|
269
|
+
{ number: 51, title: "Open", updatedAt: "2026-05-16T10:00:00Z" },
|
|
270
|
+
],
|
|
271
|
+
blockedIssueNumbers: [50],
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: "include-blocked",
|
|
276
|
+
argv: ["--project-root", "<ROOT>", "--repo", DEFAULT_REPO, "--limit", "0", "--include-blocked"],
|
|
277
|
+
fixture: {
|
|
278
|
+
issues: [
|
|
279
|
+
{ number: 60, title: "Blocked", updatedAt: "2026-05-17T10:00:00Z" },
|
|
280
|
+
{ number: 61, title: "Open", updatedAt: "2026-05-16T10:00:00Z" },
|
|
281
|
+
],
|
|
282
|
+
blockedIssueNumbers: [60],
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
/** Augment argv with fixture audit/slices hooks when present. */
|
|
287
|
+
export function augmentParityArgv(testCase, root) {
|
|
288
|
+
const argv = testCase.argv.map((arg) => (arg === "<ROOT>" ? root : arg));
|
|
289
|
+
if (testCase.skipFixture || testCase.fixture === undefined) {
|
|
290
|
+
return argv;
|
|
291
|
+
}
|
|
292
|
+
const extras = [];
|
|
293
|
+
if (testCase.fixture.auditEntries !== undefined && testCase.fixture.auditEntries.length > 0) {
|
|
294
|
+
extras.push("--audit-log", join(root, "vbrief", ".eval", "candidates.jsonl"));
|
|
295
|
+
}
|
|
296
|
+
if (testCase.fixture.sliceRecords !== undefined && testCase.fixture.sliceRecords.length > 0) {
|
|
297
|
+
extras.push("--slices-log", join(root, "vbrief", ".eval", "slices.jsonl"));
|
|
298
|
+
}
|
|
299
|
+
return [...argv, ...extras];
|
|
300
|
+
}
|
|
301
|
+
/** Run all parity cases; returns aggregate result. */
|
|
302
|
+
export function runParity() {
|
|
303
|
+
const deftRoot = resolveDeftRoot();
|
|
304
|
+
const diffs = [];
|
|
305
|
+
for (const testCase of PARITY_CASES) {
|
|
306
|
+
const pyRepo = testCase.skipFixture
|
|
307
|
+
? mkdtempSync(join(tmpdir(), "deft-triage-queue-parity-"))
|
|
308
|
+
: buildFixtureRepo(testCase.fixture);
|
|
309
|
+
const tsRepo = testCase.skipFixture
|
|
310
|
+
? mkdtempSync(join(tmpdir(), "deft-triage-queue-parity-"))
|
|
311
|
+
: buildFixtureRepo(testCase.fixture);
|
|
312
|
+
const pyArgv = augmentParityArgv(testCase, pyRepo);
|
|
313
|
+
const tsArgv = augmentParityArgv(testCase, tsRepo);
|
|
314
|
+
try {
|
|
315
|
+
const python = runPythonQueue(deftRoot, pyRepo, pyArgv);
|
|
316
|
+
const ts = runTsQueue(deftRoot, tsRepo, tsArgv);
|
|
317
|
+
diffs.push(diffCase(python, ts, testCase.name));
|
|
318
|
+
}
|
|
319
|
+
finally {
|
|
320
|
+
rmSync(pyRepo, { recursive: true, force: true });
|
|
321
|
+
rmSync(tsRepo, { recursive: true, force: true });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const ok = diffs.every((diff) => !diff.exitMismatch && !diff.stdoutMismatch && !diff.stderrMismatch);
|
|
325
|
+
return { ok, diffs };
|
|
326
|
+
}
|
|
327
|
+
export function renderReport(result) {
|
|
328
|
+
if (result.ok) {
|
|
329
|
+
return `triage:queue parity: CLEAN -- Python and TS agree on ${PARITY_CASES.length} cases.`;
|
|
330
|
+
}
|
|
331
|
+
const lines = ["triage:queue parity: DIVERGENCE"];
|
|
332
|
+
for (const diff of result.diffs) {
|
|
333
|
+
if (diff.exitMismatch || diff.stdoutMismatch || diff.stderrMismatch) {
|
|
334
|
+
lines.push(` case: ${diff.caseName}`);
|
|
335
|
+
if (diff.exitMismatch) {
|
|
336
|
+
lines.push(` exit: python=${diff.pythonExit} ts=${diff.tsExit}`);
|
|
337
|
+
}
|
|
338
|
+
if (diff.stdoutMismatch) {
|
|
339
|
+
lines.push(" stdout mismatch");
|
|
340
|
+
}
|
|
341
|
+
if (diff.stderrMismatch) {
|
|
342
|
+
lines.push(" stderr mismatch");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return lines.join("\n");
|
|
347
|
+
}
|
|
348
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
349
|
+
try {
|
|
350
|
+
const result = runParity();
|
|
351
|
+
if (result.ok) {
|
|
352
|
+
process.stdout.write(`${renderReport(result)}\n`);
|
|
353
|
+
process.exit(0);
|
|
354
|
+
}
|
|
355
|
+
process.stderr.write(`${renderReport(result)}\n`);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
catch (err) {
|
|
359
|
+
process.stderr.write(`triage:queue parity: harness error -- ${String(err)}\n`);
|
|
360
|
+
process.exit(2);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=triage-queue-parity.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
interface ParsedArgs {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
repo: string | null;
|
|
5
|
+
limit: number;
|
|
6
|
+
includeBlocked: boolean;
|
|
7
|
+
cacheRoot: string | null;
|
|
8
|
+
auditLog: string | null;
|
|
9
|
+
slicesLog: string | null;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Parse triage-queue CLI args for the queue subcommand. */
|
|
13
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
14
|
+
/** Run triage:queue and return process exit code. */
|
|
15
|
+
export declare function run(argv: string[]): number;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=triage-queue.d.ts.map
|