@deftai/directive 0.62.0 → 0.64.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/{branch-parity.d.ts → branch-fixtures.d.ts} +1 -3
- package/dist/{branch-parity.js → branch-fixtures.js} +3 -110
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +3 -1
- package/dist/orchestration-cli/coverage-map.js +1 -1
- package/dist/{policy-parity.d.ts → policy-fixtures.d.ts} +1 -3
- package/dist/{policy-parity.js → policy-fixtures.js} +4 -100
- package/dist/{release-e2e-parity.d.ts → release-e2e-fixtures.d.ts} +1 -3
- package/dist/release-e2e-fixtures.js +38 -0
- package/dist/{story-ready-parity.d.ts → story-ready-fixtures.d.ts} +1 -3
- package/dist/{story-ready-parity.js → story-ready-fixtures.js} +4 -121
- package/dist/{triage-aux-a-parity.d.ts → triage-aux-a-fixtures.d.ts} +1 -3
- package/dist/{triage-aux-a-parity.js → triage-aux-a-fixtures.js} +3 -73
- package/dist/{triage-aux-b-parity.d.ts → triage-aux-b-fixtures.d.ts} +1 -3
- package/dist/triage-aux-b-fixtures.js +167 -0
- package/dist/{triage-bootstrap-parity.d.ts → triage-bootstrap-fixtures.d.ts} +1 -3
- package/dist/{triage-bootstrap-parity.js → triage-bootstrap-fixtures.js} +4 -91
- package/dist/{triage-classify-parity.d.ts → triage-classify-fixtures.d.ts} +1 -3
- package/dist/{triage-classify-parity.js → triage-classify-fixtures.js} +4 -94
- package/dist/{triage-queue-parity.d.ts → triage-queue-fixtures.d.ts} +1 -3
- package/dist/{triage-queue-parity.js → triage-queue-fixtures.js} +4 -86
- package/dist/{triage-scope-parity.d.ts → triage-scope-fixtures.d.ts} +1 -3
- package/dist/{triage-scope-parity.js → triage-scope-fixtures.js} +4 -91
- package/dist/{vbrief-preflight-parity.d.ts → vbrief-preflight-fixtures.d.ts} +1 -3
- package/dist/vbrief-preflight-fixtures.js +79 -0
- package/dist/verify-source-cli/verify-cursor-tier1.d.ts +12 -0
- package/dist/verify-source-cli/verify-cursor-tier1.js +51 -0
- package/dist/{wip-cap-parity.d.ts → wip-cap-fixtures.d.ts} +1 -3
- package/dist/{wip-cap-parity.js → wip-cap-fixtures.js} +4 -91
- package/package.json +4 -15
- package/dist/cache-parity.d.ts +0 -36
- package/dist/cache-parity.js +0 -165
- package/dist/codebase-parity.d.ts +0 -31
- package/dist/codebase-parity.js +0 -303
- package/dist/doc-cli-parity.d.ts +0 -29
- package/dist/doc-cli-parity.js +0 -159
- package/dist/doctor-parity.d.ts +0 -42
- package/dist/doctor-parity.js +0 -157
- package/dist/intake-parity.d.ts +0 -30
- package/dist/intake-parity.js +0 -203
- package/dist/lifecycle-packs-parity.d.ts +0 -30
- package/dist/lifecycle-packs-parity.js +0 -377
- package/dist/orchestration-parity.d.ts +0 -38
- package/dist/orchestration-parity.js +0 -364
- package/dist/parity.d.ts +0 -36
- package/dist/parity.js +0 -176
- package/dist/platform-parity.d.ts +0 -26
- package/dist/platform-parity.js +0 -309
- package/dist/pr-closing-keywords-parity.d.ts +0 -45
- package/dist/pr-closing-keywords-parity.js +0 -259
- package/dist/pr-merge-readiness-parity.d.ts +0 -44
- package/dist/pr-merge-readiness-parity.js +0 -296
- package/dist/pr-monitor-parity.d.ts +0 -44
- package/dist/pr-monitor-parity.js +0 -283
- package/dist/pr-protected-issues-parity.d.ts +0 -41
- package/dist/pr-protected-issues-parity.js +0 -220
- package/dist/pr-wait-mergeable-parity.d.ts +0 -45
- package/dist/pr-wait-mergeable-parity.js +0 -340
- package/dist/release-e2e-parity.js +0 -114
- package/dist/release-parity.d.ts +0 -40
- package/dist/release-parity.js +0 -226
- package/dist/release-publish-parity.d.ts +0 -36
- package/dist/release-publish-parity.js +0 -138
- package/dist/release-rollback-parity.d.ts +0 -37
- package/dist/release-rollback-parity.js +0 -161
- package/dist/render-parity.d.ts +0 -36
- package/dist/render-parity.js +0 -385
- package/dist/scm-parity.d.ts +0 -39
- package/dist/scm-parity.js +0 -181
- package/dist/scope-lifecycle-parity.d.ts +0 -35
- package/dist/scope-lifecycle-parity.js +0 -177
- package/dist/session-parity.d.ts +0 -39
- package/dist/session-parity.js +0 -262
- package/dist/slice-parity.d.ts +0 -36
- package/dist/slice-parity.js +0 -304
- package/dist/swarm-parity.d.ts +0 -28
- package/dist/swarm-parity.js +0 -327
- package/dist/triage-actions-parity.d.ts +0 -36
- package/dist/triage-actions-parity.js +0 -357
- package/dist/triage-aux-b-parity.js +0 -308
- package/dist/triage-summary-parity.d.ts +0 -50
- package/dist/triage-summary-parity.js +0 -306
- package/dist/validate-content-parity.d.ts +0 -33
- package/dist/validate-content-parity.js +0 -356
- package/dist/vbrief-activate-parity.d.ts +0 -39
- package/dist/vbrief-activate-parity.js +0 -216
- package/dist/vbrief-build-parity.d.ts +0 -28
- package/dist/vbrief-build-parity.js +0 -399
- package/dist/vbrief-preflight-parity.js +0 -163
- package/dist/vbrief-reconcile-parity.d.ts +0 -23
- package/dist/vbrief-reconcile-parity.js +0 -609
- package/dist/vbrief-validate-parity.d.ts +0 -27
- package/dist/vbrief-validate-parity.js +0 -122
- package/dist/vbrief-validation-parity.d.ts +0 -28
- package/dist/vbrief-validation-parity.js +0 -645
- package/dist/verify-env-parity.d.ts +0 -28
- package/dist/verify-env-parity.js +0 -272
- package/dist/verify-source-parity.d.ts +0 -26
- package/dist/verify-source-parity.js +0 -178
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Golden-output parity harness (#1729): runs BOTH the Python oracle
|
|
4
|
-
* (`scripts/release_e2e.py`) and the ported TS release:e2e CLI with
|
|
5
|
-
* identical argv, then diffs exit codes and normalised stderr/stdout.
|
|
6
|
-
*/
|
|
7
|
-
import { spawnSync } from "node:child_process";
|
|
8
|
-
import { dirname, join, resolve } from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
export const PARITY_SCENARIOS = [
|
|
11
|
-
{ name: "help", argv: ["--help"], compareStdout: true },
|
|
12
|
-
{ name: "dry-run", argv: ["--dry-run"] },
|
|
13
|
-
{ name: "dry-run-keep-repo", argv: ["--dry-run", "--keep-repo"] },
|
|
14
|
-
{
|
|
15
|
-
name: "dry-run-project-root",
|
|
16
|
-
argv: ["--dry-run", "--owner", "deftai", "--project-root", "/tmp/deft-e2e-parity-root"],
|
|
17
|
-
},
|
|
18
|
-
];
|
|
19
|
-
/** Normalise volatile repo slugs and ISO dates in stderr while preserving semantics. */
|
|
20
|
-
export function normaliseStderr(text) {
|
|
21
|
-
return text
|
|
22
|
-
.replace(/deftai-release-test-\d{14}-[0-9a-f]{6}/g, "deftai-release-test-YYYYMMDDHHMMSS-uuid6")
|
|
23
|
-
.replace(/\d{4}-\d{2}-\d{2}/g, "YYYY-MM-DD");
|
|
24
|
-
}
|
|
25
|
-
function runCapture(cmd, args, cwd) {
|
|
26
|
-
const result = spawnSync(cmd, args, {
|
|
27
|
-
cwd,
|
|
28
|
-
encoding: "utf8",
|
|
29
|
-
env: {
|
|
30
|
-
...process.env,
|
|
31
|
-
DEFT_CACHE_DISABLE: "1",
|
|
32
|
-
PYTHONUTF8: "1",
|
|
33
|
-
},
|
|
34
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
35
|
-
});
|
|
36
|
-
return {
|
|
37
|
-
exitCode: result.status ?? 2,
|
|
38
|
-
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
39
|
-
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function resolveDeftRoot() {
|
|
43
|
-
if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
|
|
44
|
-
return resolve(process.env.DEFT_ROOT);
|
|
45
|
-
}
|
|
46
|
-
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
47
|
-
}
|
|
48
|
-
function runScenario(deftRoot, scenario) {
|
|
49
|
-
const argv = [...scenario.argv];
|
|
50
|
-
const py = runCapture("uv", ["run", "python", join(deftRoot, "scripts", "release_e2e.py"), ...argv], deftRoot);
|
|
51
|
-
const ts = runCapture("node", [join(deftRoot, "packages", "cli", "dist", "release-e2e.js"), ...argv], deftRoot);
|
|
52
|
-
const stream = scenario.compareStdout ? "stdout" : "stderr";
|
|
53
|
-
let pythonOutput = stream === "stdout" ? py.stdout : py.stderr;
|
|
54
|
-
let tsOutput = stream === "stdout" ? ts.stdout : ts.stderr;
|
|
55
|
-
if (stream === "stderr") {
|
|
56
|
-
pythonOutput = normaliseStderr(pythonOutput);
|
|
57
|
-
tsOutput = normaliseStderr(tsOutput);
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
name: scenario.name,
|
|
61
|
-
exitMismatch: py.exitCode !== ts.exitCode,
|
|
62
|
-
outputMismatch: pythonOutput !== tsOutput,
|
|
63
|
-
pythonExit: py.exitCode,
|
|
64
|
-
tsExit: ts.exitCode,
|
|
65
|
-
pythonOutput,
|
|
66
|
-
tsOutput,
|
|
67
|
-
stream,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
export function runParity() {
|
|
71
|
-
const deftRoot = resolveDeftRoot();
|
|
72
|
-
const diffs = PARITY_SCENARIOS.map((scenario) => runScenario(deftRoot, scenario));
|
|
73
|
-
const ok = diffs.every((d) => !d.exitMismatch && !d.outputMismatch);
|
|
74
|
-
return { ok, diffs };
|
|
75
|
-
}
|
|
76
|
-
export function renderReport(result) {
|
|
77
|
-
if (result.ok) {
|
|
78
|
-
return `release-e2e parity: CLEAN -- Python and TS agree on ${result.diffs.length} scenario(s).`;
|
|
79
|
-
}
|
|
80
|
-
const lines = ["release-e2e parity: DIVERGENCE"];
|
|
81
|
-
for (const d of result.diffs) {
|
|
82
|
-
if (d.exitMismatch || d.outputMismatch) {
|
|
83
|
-
lines.push(` scenario: ${d.name}`);
|
|
84
|
-
if (d.exitMismatch) {
|
|
85
|
-
lines.push(` exit mismatch: python=${d.pythonExit} ts=${d.tsExit}`);
|
|
86
|
-
}
|
|
87
|
-
if (d.outputMismatch) {
|
|
88
|
-
lines.push(` stream: ${d.stream}`);
|
|
89
|
-
lines.push(` python (${d.pythonOutput.length} bytes):`);
|
|
90
|
-
lines.push(d.pythonOutput);
|
|
91
|
-
lines.push(` ts (${d.tsOutput.length} bytes):`);
|
|
92
|
-
lines.push(d.tsOutput);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return lines.join("\n");
|
|
97
|
-
}
|
|
98
|
-
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
99
|
-
try {
|
|
100
|
-
const result = runParity();
|
|
101
|
-
if (result.ok) {
|
|
102
|
-
process.stdout.write(`${renderReport(result)}\n`);
|
|
103
|
-
process.exit(0);
|
|
104
|
-
}
|
|
105
|
-
process.stderr.write(`${renderReport(result)}\n`);
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
catch (err) {
|
|
109
|
-
const msg = String(err).replace(/\r?\n/g, " ");
|
|
110
|
-
process.stderr.write(`release-e2e parity: harness error -- ${msg}\n`);
|
|
111
|
-
process.exit(2);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
//# sourceMappingURL=release-e2e-parity.js.map
|
package/dist/release-parity.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
export declare const SAMPLE_CHANGELOG = " Changelog\n\nAll notable changes to the project.\n\n## [Unreleased]\n\n### Added\n- New release automation (#74)\n\n### Changed\n- Refactored module X\n\n### Fixed\n- Bug Y\n\n## [0.20.2] - 2026-04-24\n\n### Added\n- Prior change\n\n## [0.20.0] - 2026-04-23\n\n### Added\n- Older change\n\n[Unreleased]: https://github.com/deftai/directive/compare/v0.20.2...HEAD\n[0.20.2]: https://github.com/deftai/directive/compare/v0.20.0...v0.20.2\n[0.20.0]: https://github.com/deftai/directive/compare/v0.19.0...v0.20.0\n";
|
|
3
|
-
export interface ScenarioResult {
|
|
4
|
-
readonly name: string;
|
|
5
|
-
readonly exitCode: number;
|
|
6
|
-
readonly stdout: string;
|
|
7
|
-
readonly stderr: string;
|
|
8
|
-
}
|
|
9
|
-
export interface ParityScenario {
|
|
10
|
-
readonly name: string;
|
|
11
|
-
readonly argv: readonly string[];
|
|
12
|
-
readonly setup?: (root: string) => void;
|
|
13
|
-
readonly compareStdout?: boolean;
|
|
14
|
-
}
|
|
15
|
-
export interface ParityResult {
|
|
16
|
-
readonly ok: boolean;
|
|
17
|
-
readonly scenarios: Array<{
|
|
18
|
-
readonly name: string;
|
|
19
|
-
readonly exitMismatch: boolean;
|
|
20
|
-
readonly pythonExit: number;
|
|
21
|
-
readonly tsExit: number;
|
|
22
|
-
readonly outputMismatch: boolean;
|
|
23
|
-
readonly pythonOutput: string;
|
|
24
|
-
readonly tsOutput: string;
|
|
25
|
-
readonly stream: "stdout" | "stderr";
|
|
26
|
-
}>;
|
|
27
|
-
}
|
|
28
|
-
export declare const PARITY_SCENARIOS: readonly ParityScenario[];
|
|
29
|
-
/** Normalise volatile ISO dates in stderr while preserving semantics. */
|
|
30
|
-
export declare function normaliseStderr(text: string): string;
|
|
31
|
-
export declare function pickOutput(result: ScenarioResult, stream: "stdout" | "stderr"): string;
|
|
32
|
-
export declare function diffParity(python: ScenarioResult, ts: ScenarioResult, stream: "stdout" | "stderr"): {
|
|
33
|
-
exitMismatch: boolean;
|
|
34
|
-
outputMismatch: boolean;
|
|
35
|
-
pythonOutput: string;
|
|
36
|
-
tsOutput: string;
|
|
37
|
-
};
|
|
38
|
-
export declare function runParity(): ParityResult;
|
|
39
|
-
export declare function renderReport(result: ParityResult): string;
|
|
40
|
-
//# sourceMappingURL=release-parity.d.ts.map
|
package/dist/release-parity.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Golden-output parity harness (#1729): runs BOTH the Python oracle
|
|
4
|
-
* (`scripts/release.py`) and the ported TS release CLI with identical argv,
|
|
5
|
-
* then diffs exit codes and normalised stderr/stdout. Exit 0 only on
|
|
6
|
-
* byte-identical results (volatile ISO dates normalised in stderr).
|
|
7
|
-
*
|
|
8
|
-
* Exit codes: 0 parity / 1 divergence / 2 harness setup error.
|
|
9
|
-
*/
|
|
10
|
-
import { execFileSync, spawnSync } from "node:child_process";
|
|
11
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
-
import { tmpdir } from "node:os";
|
|
13
|
-
import { dirname, join, resolve } from "node:path";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
15
|
-
export const SAMPLE_CHANGELOG = ` Changelog
|
|
16
|
-
|
|
17
|
-
All notable changes to the project.
|
|
18
|
-
|
|
19
|
-
## [Unreleased]
|
|
20
|
-
|
|
21
|
-
### Added
|
|
22
|
-
- New release automation (#74)
|
|
23
|
-
|
|
24
|
-
### Changed
|
|
25
|
-
- Refactored module X
|
|
26
|
-
|
|
27
|
-
### Fixed
|
|
28
|
-
- Bug Y
|
|
29
|
-
|
|
30
|
-
## [0.20.2] - 2026-04-24
|
|
31
|
-
|
|
32
|
-
### Added
|
|
33
|
-
- Prior change
|
|
34
|
-
|
|
35
|
-
## [0.20.0] - 2026-04-23
|
|
36
|
-
|
|
37
|
-
### Added
|
|
38
|
-
- Older change
|
|
39
|
-
|
|
40
|
-
[Unreleased]: https://github.com/deftai/directive/compare/v0.20.2...HEAD
|
|
41
|
-
[0.20.2]: https://github.com/deftai/directive/compare/v0.20.0...v0.20.2
|
|
42
|
-
[0.20.0]: https://github.com/deftai/directive/compare/v0.19.0...v0.20.0
|
|
43
|
-
`;
|
|
44
|
-
export const PARITY_SCENARIOS = [
|
|
45
|
-
{ name: "invalid-version", argv: ["not-a-version"] },
|
|
46
|
-
{
|
|
47
|
-
name: "dry-run-fixture",
|
|
48
|
-
argv: [
|
|
49
|
-
"0.21.0",
|
|
50
|
-
"--dry-run",
|
|
51
|
-
"--skip-tag",
|
|
52
|
-
"--skip-release",
|
|
53
|
-
"--repo",
|
|
54
|
-
"deftai/directive",
|
|
55
|
-
"--allow-vbrief-drift",
|
|
56
|
-
"--skip-ci",
|
|
57
|
-
],
|
|
58
|
-
setup(root) {
|
|
59
|
-
writeFileSync(join(root, "CHANGELOG.md"), SAMPLE_CHANGELOG, "utf8");
|
|
60
|
-
execFileSync("git", ["init", "-q", "-b", "master", root]);
|
|
61
|
-
execFileSync("git", ["config", "user.email", "parity@test.local"], { cwd: root });
|
|
62
|
-
execFileSync("git", ["config", "user.name", "deft-parity"], { cwd: root });
|
|
63
|
-
execFileSync("git", ["add", "CHANGELOG.md"], { cwd: root });
|
|
64
|
-
execFileSync("git", ["commit", "-q", "-m", "init"], {
|
|
65
|
-
cwd: root,
|
|
66
|
-
env: {
|
|
67
|
-
...process.env,
|
|
68
|
-
GIT_AUTHOR_NAME: "deft-parity",
|
|
69
|
-
GIT_AUTHOR_EMAIL: "parity@test.local",
|
|
70
|
-
GIT_COMMITTER_NAME: "deft-parity",
|
|
71
|
-
GIT_COMMITTER_EMAIL: "parity@test.local",
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
{ name: "help", argv: ["--help"], compareStdout: true },
|
|
77
|
-
];
|
|
78
|
-
function runCapture(cmd, args, cwd, env = {}) {
|
|
79
|
-
const merged = {
|
|
80
|
-
...process.env,
|
|
81
|
-
...env,
|
|
82
|
-
DEFT_CACHE_DISABLE: "1",
|
|
83
|
-
PYTHONUTF8: "1",
|
|
84
|
-
};
|
|
85
|
-
for (const key of Object.keys(merged)) {
|
|
86
|
-
if (merged[key] === undefined)
|
|
87
|
-
delete merged[key];
|
|
88
|
-
}
|
|
89
|
-
try {
|
|
90
|
-
const result = spawnSync(cmd, args, {
|
|
91
|
-
cwd,
|
|
92
|
-
encoding: "utf8",
|
|
93
|
-
env: merged,
|
|
94
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
95
|
-
});
|
|
96
|
-
return {
|
|
97
|
-
status: result.status ?? 2,
|
|
98
|
-
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
99
|
-
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
const e = err;
|
|
104
|
-
return {
|
|
105
|
-
status: typeof e.status === "number" ? e.status : 2,
|
|
106
|
-
stdout: typeof e.stdout === "string" ? e.stdout : "",
|
|
107
|
-
stderr: typeof e.stderr === "string" ? e.stderr : "",
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function resolveDeftRoot() {
|
|
112
|
-
if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
|
|
113
|
-
return resolve(process.env.DEFT_ROOT);
|
|
114
|
-
}
|
|
115
|
-
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
116
|
-
}
|
|
117
|
-
/** Normalise volatile ISO dates in stderr while preserving semantics. */
|
|
118
|
-
export function normaliseStderr(text) {
|
|
119
|
-
return text
|
|
120
|
-
.replace(/\d{4}-\d{2}-\d{2}/g, "YYYY-MM-DD")
|
|
121
|
-
.replace(/(?:\/private)?\/var\/folders\/[^\s)]+\/deft-release-parity-[^\s)]+/g, "<TMP>")
|
|
122
|
-
.replace(/\/tmp\/deft-release-parity-[^\s)]+/g, "<TMP>");
|
|
123
|
-
}
|
|
124
|
-
export function pickOutput(result, stream) {
|
|
125
|
-
return stream === "stdout" ? result.stdout : result.stderr;
|
|
126
|
-
}
|
|
127
|
-
function runScenario(deftRoot, scenario) {
|
|
128
|
-
let cwd = deftRoot;
|
|
129
|
-
let tempRoot;
|
|
130
|
-
let projectRoot;
|
|
131
|
-
const argv = [...scenario.argv];
|
|
132
|
-
if (scenario.setup) {
|
|
133
|
-
tempRoot = mkdtempSync(join(tmpdir(), "deft-release-parity-"));
|
|
134
|
-
projectRoot = tempRoot;
|
|
135
|
-
scenario.setup(tempRoot);
|
|
136
|
-
const idx = argv.indexOf("--project-root");
|
|
137
|
-
if (idx === -1) {
|
|
138
|
-
argv.push("--project-root", tempRoot);
|
|
139
|
-
}
|
|
140
|
-
cwd = deftRoot;
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
const pyArgs = ["run", "python", join(deftRoot, "scripts", "release.py"), ...argv];
|
|
144
|
-
const tsArgs = [join(deftRoot, "packages", "cli", "dist", "release.js"), ...argv];
|
|
145
|
-
const py = runCapture("uv", pyArgs, cwd);
|
|
146
|
-
const ts = runCapture("node", tsArgs, cwd);
|
|
147
|
-
return {
|
|
148
|
-
python: { name: scenario.name, exitCode: py.status, stdout: py.stdout, stderr: py.stderr },
|
|
149
|
-
ts: { name: scenario.name, exitCode: ts.status, stdout: ts.stdout, stderr: ts.stderr },
|
|
150
|
-
projectRoot,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
finally {
|
|
154
|
-
if (tempRoot) {
|
|
155
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
export function diffParity(python, ts, stream) {
|
|
160
|
-
let pythonOutput = pickOutput(python, stream);
|
|
161
|
-
let tsOutput = pickOutput(ts, stream);
|
|
162
|
-
if (stream === "stderr") {
|
|
163
|
-
pythonOutput = normaliseStderr(pythonOutput);
|
|
164
|
-
tsOutput = normaliseStderr(tsOutput);
|
|
165
|
-
}
|
|
166
|
-
return {
|
|
167
|
-
exitMismatch: python.exitCode !== ts.exitCode,
|
|
168
|
-
outputMismatch: pythonOutput !== tsOutput,
|
|
169
|
-
pythonOutput,
|
|
170
|
-
tsOutput,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
export function runParity() {
|
|
174
|
-
const deftRoot = resolveDeftRoot();
|
|
175
|
-
const scenarios = [];
|
|
176
|
-
for (const scenario of PARITY_SCENARIOS) {
|
|
177
|
-
const ran = runScenario(deftRoot, scenario);
|
|
178
|
-
const stream = scenario.compareStdout ? "stdout" : "stderr";
|
|
179
|
-
scenarios.push({
|
|
180
|
-
name: scenario.name,
|
|
181
|
-
pythonExit: ran.python.exitCode,
|
|
182
|
-
tsExit: ran.ts.exitCode,
|
|
183
|
-
stream,
|
|
184
|
-
...diffParity(ran.python, ran.ts, stream),
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
const ok = scenarios.every((s) => !s.exitMismatch && !s.outputMismatch);
|
|
188
|
-
return { ok, scenarios };
|
|
189
|
-
}
|
|
190
|
-
export function renderReport(result) {
|
|
191
|
-
if (result.ok) {
|
|
192
|
-
return `release parity: CLEAN -- Python and TS agree on ${result.scenarios.length} scenario(s).`;
|
|
193
|
-
}
|
|
194
|
-
const lines = ["release parity: DIVERGENCE"];
|
|
195
|
-
for (const s of result.scenarios) {
|
|
196
|
-
if (s.exitMismatch || s.outputMismatch) {
|
|
197
|
-
lines.push(` scenario: ${s.name}`);
|
|
198
|
-
if (s.exitMismatch) {
|
|
199
|
-
lines.push(` exit mismatch: python=${s.pythonExit} ts=${s.tsExit}`);
|
|
200
|
-
}
|
|
201
|
-
if (s.outputMismatch) {
|
|
202
|
-
lines.push(` stream: ${s.stream}`);
|
|
203
|
-
lines.push(` python (${s.pythonOutput.length} bytes)`);
|
|
204
|
-
lines.push(` ts (${s.tsOutput.length} bytes)`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return lines.join("\n");
|
|
209
|
-
}
|
|
210
|
-
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
211
|
-
try {
|
|
212
|
-
const result = runParity();
|
|
213
|
-
if (result.ok) {
|
|
214
|
-
process.stdout.write(`${renderReport(result)}\n`);
|
|
215
|
-
process.exit(0);
|
|
216
|
-
}
|
|
217
|
-
process.stderr.write(`${renderReport(result)}\n`);
|
|
218
|
-
process.exit(1);
|
|
219
|
-
}
|
|
220
|
-
catch (err) {
|
|
221
|
-
const msg = String(err).replace(/\r?\n/g, " ");
|
|
222
|
-
process.stderr.write(`release parity: harness error -- ${msg}\n`);
|
|
223
|
-
process.exit(2);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
//# sourceMappingURL=release-parity.js.map
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
export interface ScenarioResult {
|
|
3
|
-
readonly name: string;
|
|
4
|
-
readonly exitCode: number;
|
|
5
|
-
readonly stdout: string;
|
|
6
|
-
readonly stderr: string;
|
|
7
|
-
}
|
|
8
|
-
export interface ParityScenario {
|
|
9
|
-
readonly name: string;
|
|
10
|
-
readonly argv: readonly string[];
|
|
11
|
-
readonly compareStdout?: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface ParityResult {
|
|
14
|
-
readonly ok: boolean;
|
|
15
|
-
readonly scenarios: Array<{
|
|
16
|
-
readonly name: string;
|
|
17
|
-
readonly exitMismatch: boolean;
|
|
18
|
-
readonly pythonExit: number;
|
|
19
|
-
readonly tsExit: number;
|
|
20
|
-
readonly outputMismatch: boolean;
|
|
21
|
-
readonly pythonOutput: string;
|
|
22
|
-
readonly tsOutput: string;
|
|
23
|
-
readonly stream: "stdout" | "stderr";
|
|
24
|
-
}>;
|
|
25
|
-
}
|
|
26
|
-
export declare const PARITY_SCENARIOS: readonly ParityScenario[];
|
|
27
|
-
export declare function pickOutput(result: ScenarioResult, stream: "stdout" | "stderr"): string;
|
|
28
|
-
export declare function diffParity(python: ScenarioResult, ts: ScenarioResult, stream: "stdout" | "stderr"): {
|
|
29
|
-
exitMismatch: boolean;
|
|
30
|
-
outputMismatch: boolean;
|
|
31
|
-
pythonOutput: string;
|
|
32
|
-
tsOutput: string;
|
|
33
|
-
};
|
|
34
|
-
export declare function runParity(): ParityResult;
|
|
35
|
-
export declare function renderReport(result: ParityResult): string;
|
|
36
|
-
//# sourceMappingURL=release-publish-parity.d.ts.map
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Golden-output parity harness (#1729): runs BOTH the Python oracle
|
|
4
|
-
* (`scripts/release_publish.py`) and the ported TS release:publish CLI
|
|
5
|
-
* with identical argv, then diffs exit codes and normalised stderr/stdout.
|
|
6
|
-
* Exit 0 only on byte-identical results (cache off).
|
|
7
|
-
*
|
|
8
|
-
* Exit codes: 0 parity / 1 divergence / 2 harness setup error.
|
|
9
|
-
*/
|
|
10
|
-
import { spawnSync } from "node:child_process";
|
|
11
|
-
import { dirname, join, resolve } from "node:path";
|
|
12
|
-
import { fileURLToPath } from "node:url";
|
|
13
|
-
export const PARITY_SCENARIOS = [
|
|
14
|
-
{ name: "invalid-version", argv: ["not-a-version"] },
|
|
15
|
-
{ name: "missing-version", argv: [] },
|
|
16
|
-
{
|
|
17
|
-
name: "dry-run",
|
|
18
|
-
argv: ["0.21.0", "--dry-run", "--repo", "deftai/directive"],
|
|
19
|
-
},
|
|
20
|
-
{ name: "help", argv: ["--help"], compareStdout: true },
|
|
21
|
-
];
|
|
22
|
-
function runCapture(cmd, args, cwd, env = {}) {
|
|
23
|
-
const merged = {
|
|
24
|
-
...process.env,
|
|
25
|
-
...env,
|
|
26
|
-
DEFT_CACHE_DISABLE: "1",
|
|
27
|
-
PYTHONUTF8: "1",
|
|
28
|
-
};
|
|
29
|
-
for (const key of Object.keys(merged)) {
|
|
30
|
-
if (merged[key] === undefined)
|
|
31
|
-
delete merged[key];
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const result = spawnSync(cmd, args, {
|
|
35
|
-
cwd,
|
|
36
|
-
encoding: "utf8",
|
|
37
|
-
env: merged,
|
|
38
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
39
|
-
});
|
|
40
|
-
return {
|
|
41
|
-
status: result.status ?? 2,
|
|
42
|
-
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
43
|
-
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
const e = err;
|
|
48
|
-
return {
|
|
49
|
-
status: typeof e.status === "number" ? e.status : 2,
|
|
50
|
-
stdout: typeof e.stdout === "string" ? e.stdout : "",
|
|
51
|
-
stderr: typeof e.stderr === "string" ? e.stderr : "",
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function resolveDeftRoot() {
|
|
56
|
-
if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
|
|
57
|
-
return resolve(process.env.DEFT_ROOT);
|
|
58
|
-
}
|
|
59
|
-
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
60
|
-
}
|
|
61
|
-
export function pickOutput(result, stream) {
|
|
62
|
-
return stream === "stdout" ? result.stdout : result.stderr;
|
|
63
|
-
}
|
|
64
|
-
function runScenario(deftRoot, scenario) {
|
|
65
|
-
const argv = [...scenario.argv];
|
|
66
|
-
const pyArgs = ["run", "python", join(deftRoot, "scripts", "release_publish.py"), ...argv];
|
|
67
|
-
const tsArgs = [join(deftRoot, "packages", "cli", "dist", "release-publish.js"), ...argv];
|
|
68
|
-
const py = runCapture("uv", pyArgs, deftRoot);
|
|
69
|
-
const ts = runCapture("node", tsArgs, deftRoot);
|
|
70
|
-
return {
|
|
71
|
-
python: { name: scenario.name, exitCode: py.status, stdout: py.stdout, stderr: py.stderr },
|
|
72
|
-
ts: { name: scenario.name, exitCode: ts.status, stdout: ts.stdout, stderr: ts.stderr },
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
export function diffParity(python, ts, stream) {
|
|
76
|
-
const pythonOutput = pickOutput(python, stream);
|
|
77
|
-
const tsOutput = pickOutput(ts, stream);
|
|
78
|
-
return {
|
|
79
|
-
exitMismatch: python.exitCode !== ts.exitCode,
|
|
80
|
-
outputMismatch: pythonOutput !== tsOutput,
|
|
81
|
-
pythonOutput,
|
|
82
|
-
tsOutput,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
export function runParity() {
|
|
86
|
-
const deftRoot = resolveDeftRoot();
|
|
87
|
-
const scenarios = [];
|
|
88
|
-
for (const scenario of PARITY_SCENARIOS) {
|
|
89
|
-
const ran = runScenario(deftRoot, scenario);
|
|
90
|
-
const stream = scenario.compareStdout ? "stdout" : "stderr";
|
|
91
|
-
scenarios.push({
|
|
92
|
-
name: scenario.name,
|
|
93
|
-
pythonExit: ran.python.exitCode,
|
|
94
|
-
tsExit: ran.ts.exitCode,
|
|
95
|
-
stream,
|
|
96
|
-
...diffParity(ran.python, ran.ts, stream),
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
const ok = scenarios.every((s) => !s.exitMismatch && !s.outputMismatch);
|
|
100
|
-
return { ok, scenarios };
|
|
101
|
-
}
|
|
102
|
-
export function renderReport(result) {
|
|
103
|
-
if (result.ok) {
|
|
104
|
-
return `release-publish parity: CLEAN -- Python and TS agree on ${result.scenarios.length} scenario(s).`;
|
|
105
|
-
}
|
|
106
|
-
const lines = ["release-publish parity: DIVERGENCE"];
|
|
107
|
-
for (const s of result.scenarios) {
|
|
108
|
-
if (s.exitMismatch || s.outputMismatch) {
|
|
109
|
-
lines.push(` scenario: ${s.name}`);
|
|
110
|
-
if (s.exitMismatch) {
|
|
111
|
-
lines.push(` exit mismatch: python=${s.pythonExit} ts=${s.tsExit}`);
|
|
112
|
-
}
|
|
113
|
-
if (s.outputMismatch) {
|
|
114
|
-
lines.push(` stream: ${s.stream}`);
|
|
115
|
-
lines.push(` python (${s.pythonOutput.length} bytes)`);
|
|
116
|
-
lines.push(` ts (${s.tsOutput.length} bytes)`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return lines.join("\n");
|
|
121
|
-
}
|
|
122
|
-
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
123
|
-
try {
|
|
124
|
-
const result = runParity();
|
|
125
|
-
if (result.ok) {
|
|
126
|
-
process.stdout.write(`${renderReport(result)}\n`);
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}
|
|
129
|
-
process.stderr.write(`${renderReport(result)}\n`);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
catch (err) {
|
|
133
|
-
const msg = String(err).replace(/\r?\n/g, " ");
|
|
134
|
-
process.stderr.write(`release-publish parity: harness error -- ${msg}\n`);
|
|
135
|
-
process.exit(2);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
//# sourceMappingURL=release-publish-parity.js.map
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
export interface ScenarioResult {
|
|
3
|
-
readonly name: string;
|
|
4
|
-
readonly exitCode: number;
|
|
5
|
-
readonly stdout: string;
|
|
6
|
-
readonly stderr: string;
|
|
7
|
-
}
|
|
8
|
-
export interface ParityScenario {
|
|
9
|
-
readonly name: string;
|
|
10
|
-
readonly argv: readonly string[];
|
|
11
|
-
readonly compareStdout?: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface ParityResult {
|
|
14
|
-
readonly ok: boolean;
|
|
15
|
-
readonly scenarios: Array<{
|
|
16
|
-
readonly name: string;
|
|
17
|
-
readonly exitMismatch: boolean;
|
|
18
|
-
readonly pythonExit: number;
|
|
19
|
-
readonly tsExit: number;
|
|
20
|
-
readonly outputMismatch: boolean;
|
|
21
|
-
readonly pythonOutput: string;
|
|
22
|
-
readonly tsOutput: string;
|
|
23
|
-
readonly stream: "stdout" | "stderr";
|
|
24
|
-
}>;
|
|
25
|
-
}
|
|
26
|
-
export declare const PARITY_SCENARIOS: readonly ParityScenario[];
|
|
27
|
-
export declare function normaliseStderr(text: string): string;
|
|
28
|
-
export declare function pickOutput(result: ScenarioResult, stream: "stdout" | "stderr"): string;
|
|
29
|
-
export declare function diffParity(python: ScenarioResult, ts: ScenarioResult, stream: "stdout" | "stderr"): {
|
|
30
|
-
exitMismatch: boolean;
|
|
31
|
-
outputMismatch: boolean;
|
|
32
|
-
pythonOutput: string;
|
|
33
|
-
tsOutput: string;
|
|
34
|
-
};
|
|
35
|
-
export declare function runParity(): ParityResult;
|
|
36
|
-
export declare function renderReport(result: ParityResult): string;
|
|
37
|
-
//# sourceMappingURL=release-rollback-parity.d.ts.map
|