@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,309 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Golden-output parity harness (#1787 s3): runs BOTH the frozen Python oracle
|
|
4
|
+
* modules and the ported TS @deftai/directive-core/platform helpers over shared fixtures,
|
|
5
|
+
* cache-off, and diffs JSON payloads + exit codes.
|
|
6
|
+
*
|
|
7
|
+
* Exit codes: 0 parity / 1 divergence / 2 harness setup error.
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } from "node:child_process";
|
|
10
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, 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
|
+
import { agentsRefreshPlan, detectIpTerms, disambiguateSlug, normalizeSlug, probeRuntimeCapabilities, reportToDict, resolveChangelog, resolveVersion, toPep440, } from "@deftai/directive-core/platform";
|
|
15
|
+
const FIXED_ISO = "2026-06-19T12:00:00Z";
|
|
16
|
+
const FIXED_SESSION = "abcdef012345";
|
|
17
|
+
const FIXED_SHA = "deadbeefcafe";
|
|
18
|
+
const SLUG_FIXTURES = [
|
|
19
|
+
"Hello World",
|
|
20
|
+
"Add widget (v2)!",
|
|
21
|
+
"café latte",
|
|
22
|
+
"El Niño Año",
|
|
23
|
+
"日本語",
|
|
24
|
+
"[x] Fix login bug",
|
|
25
|
+
"con",
|
|
26
|
+
"foo bar---baz",
|
|
27
|
+
];
|
|
28
|
+
const PEP440_FIXTURES = ["v0.22.0", "v0.20.0-rc.3", "v0.20.0-beta.2", "0.20.0-alpha.1"];
|
|
29
|
+
function resolveDeftRoot() {
|
|
30
|
+
if (process.env.DEFT_ROOT)
|
|
31
|
+
return resolve(process.env.DEFT_ROOT);
|
|
32
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
33
|
+
}
|
|
34
|
+
function runPythonJson(deftRoot, code) {
|
|
35
|
+
const scriptsDir = join(deftRoot, "scripts").replace(/\\/g, "/");
|
|
36
|
+
const wrapped = [
|
|
37
|
+
"import json,sys",
|
|
38
|
+
`sys.path.insert(0, ${JSON.stringify(scriptsDir)})`,
|
|
39
|
+
code,
|
|
40
|
+
].join("\n");
|
|
41
|
+
const stdout = execFileSync("uv", ["run", "python", "-c", wrapped], {
|
|
42
|
+
cwd: deftRoot,
|
|
43
|
+
encoding: "utf8",
|
|
44
|
+
env: { ...process.env, DEFT_CACHE_DISABLE: "1", PYTHONUTF8: "1" },
|
|
45
|
+
});
|
|
46
|
+
return JSON.parse(stdout.trim());
|
|
47
|
+
}
|
|
48
|
+
function stableJson(value) {
|
|
49
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
50
|
+
}
|
|
51
|
+
/** Strip volatile filesystem paths from capability reports before compare. */
|
|
52
|
+
export function normalizeCapabilityReport(value) {
|
|
53
|
+
if (value === null || typeof value !== "object")
|
|
54
|
+
return value;
|
|
55
|
+
const record = value;
|
|
56
|
+
const out = { ...record };
|
|
57
|
+
if (record.ownership && typeof record.ownership === "object") {
|
|
58
|
+
out.ownership = { ...record.ownership, path: "<REPO>" };
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
/** Normalise volatile agents-refresh plan fields for comparison. */
|
|
63
|
+
export function normalizeAgentsPlan(plan) {
|
|
64
|
+
const out = { ...plan };
|
|
65
|
+
for (const key of ["sha", "refreshed", "session", "attributed_rendered", "new_content"]) {
|
|
66
|
+
if (key in out)
|
|
67
|
+
out[key] = "<NORMALIZED>";
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
const CHANGELOG_HEADER = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n";
|
|
72
|
+
function buildConflictChangelog() {
|
|
73
|
+
return (`${CHANGELOG_HEADER}## [Unreleased]\n\n` +
|
|
74
|
+
"### Added\n\n" +
|
|
75
|
+
"<<<<<<< HEAD\n" +
|
|
76
|
+
"- **feat: head entry** -- landed (#100)\n" +
|
|
77
|
+
"=======\n" +
|
|
78
|
+
"- **feat: branch entry** -- new (#200)\n" +
|
|
79
|
+
">>>>>>> branch-sha\n\n" +
|
|
80
|
+
"## [0.1.0] - 2026-01-01\n");
|
|
81
|
+
}
|
|
82
|
+
function readTemplate(deftRoot) {
|
|
83
|
+
// #1875: the AGENTS.md template moved under content/ in the source repo
|
|
84
|
+
// (content/templates/agents-entry.md). Prefer that location and fall back to
|
|
85
|
+
// the flattened layout (templates/agents-entry.md) so the harness resolves in
|
|
86
|
+
// both a source checkout and a flattened consumer deposit.
|
|
87
|
+
const contentCandidate = join(deftRoot, "content", "templates", "agents-entry.md");
|
|
88
|
+
const flatCandidate = join(deftRoot, "templates", "agents-entry.md");
|
|
89
|
+
return readFileSync(existsSync(contentCandidate) ? contentCandidate : flatCandidate, "utf8");
|
|
90
|
+
}
|
|
91
|
+
export const PARITY_CASES = [
|
|
92
|
+
{
|
|
93
|
+
name: "slug-normalize-unicode",
|
|
94
|
+
runPython: (deftRoot) => runPythonJson(deftRoot, [
|
|
95
|
+
"from slug_normalize import normalize_slug, disambiguate_slug",
|
|
96
|
+
`fixtures = ${JSON.stringify(SLUG_FIXTURES)}`,
|
|
97
|
+
"out = {'slugs': [normalize_slug(t) for t in fixtures], 'collision': disambiguate_slug('hello-world', {'hello-world'})}",
|
|
98
|
+
"print(json.dumps(out))",
|
|
99
|
+
].join("\n")),
|
|
100
|
+
runTs: () => ({
|
|
101
|
+
slugs: SLUG_FIXTURES.map((t) => normalizeSlug(t)),
|
|
102
|
+
collision: disambiguateSlug("hello-world", new Set(["hello-world"])),
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: "version-resolve-manifest",
|
|
107
|
+
setup: (repo) => {
|
|
108
|
+
writeFileSync(join(repo, "VERSION"), "tag: v9.8.7\nref: v9.8.7\n", "utf8");
|
|
109
|
+
},
|
|
110
|
+
runPython: (deftRoot, repo) => runPythonJson(deftRoot, [
|
|
111
|
+
"import json",
|
|
112
|
+
"from pathlib import Path",
|
|
113
|
+
"import resolve_version as rv",
|
|
114
|
+
`base = Path(${JSON.stringify(repo)})`,
|
|
115
|
+
"print(json.dumps({'version': rv._from_manifest(base), 'pep440': [rv.to_pep440(v) for v in " +
|
|
116
|
+
JSON.stringify(PEP440_FIXTURES) +
|
|
117
|
+
"]}))",
|
|
118
|
+
].join("\n")),
|
|
119
|
+
runTs: (_deftRoot, repo) => ({
|
|
120
|
+
version: resolveVersion({
|
|
121
|
+
frameworkRoot: repo,
|
|
122
|
+
fromEnv: () => null,
|
|
123
|
+
fromManifest: (base) => {
|
|
124
|
+
const text = readFileSync(join(base, "VERSION"), "utf8");
|
|
125
|
+
for (const line of text.split("\n")) {
|
|
126
|
+
const trimmed = line.trim();
|
|
127
|
+
if (trimmed.startsWith("tag:") || trimmed.startsWith("ref:")) {
|
|
128
|
+
let value = trimmed.slice(trimmed.indexOf(":") + 1).trim();
|
|
129
|
+
if (value.startsWith("v"))
|
|
130
|
+
value = value.slice(1);
|
|
131
|
+
return value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
},
|
|
136
|
+
fromDeftVersion: () => null,
|
|
137
|
+
fromGit: () => null,
|
|
138
|
+
}),
|
|
139
|
+
pep440: PEP440_FIXTURES.map((v) => toPep440(v)),
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "changelog-union-merge",
|
|
144
|
+
runPython: (deftRoot) => runPythonJson(deftRoot, [
|
|
145
|
+
"import resolve_changelog_unreleased as r",
|
|
146
|
+
`content = ${JSON.stringify(buildConflictChangelog())}`,
|
|
147
|
+
"new_content, msg = r.resolve_changelog(content)",
|
|
148
|
+
"print(json.dumps({'message': msg, 'has_100': '(#100)' in new_content, 'has_200': '(#200)' in new_content, 'markers': '<<<<<<<' in new_content}))",
|
|
149
|
+
].join("\n")),
|
|
150
|
+
runTs: () => {
|
|
151
|
+
const { content, message } = resolveChangelog(buildConflictChangelog());
|
|
152
|
+
return {
|
|
153
|
+
message,
|
|
154
|
+
has_100: content?.includes("(#100)") ?? false,
|
|
155
|
+
has_200: content?.includes("(#200)") ?? false,
|
|
156
|
+
markers: content?.includes("<<<<<<<") ?? false,
|
|
157
|
+
};
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "agents-refresh-managed-section",
|
|
162
|
+
setup: (repo) => {
|
|
163
|
+
const deftRoot = resolveDeftRoot();
|
|
164
|
+
const template = readTemplate(deftRoot);
|
|
165
|
+
writeFileSync(join(repo, "AGENTS.md"), `# Notes\n\n<!-- deft:managed-section v3 sha=old refreshed=2020-01-01T00:00:00Z session=oldsession12 -->\nlegacy body\n<!-- /deft:managed-section -->\n`, "utf8");
|
|
166
|
+
mkdirSync(join(repo, "templates"), { recursive: true });
|
|
167
|
+
writeFileSync(join(repo, "templates", "agents-entry.md"), template, "utf8");
|
|
168
|
+
},
|
|
169
|
+
runPython: (deftRoot, repo) => {
|
|
170
|
+
const template = readTemplate(deftRoot);
|
|
171
|
+
return runPythonJson(deftRoot, [
|
|
172
|
+
"import json",
|
|
173
|
+
"from pathlib import Path",
|
|
174
|
+
"import _agents_md as am",
|
|
175
|
+
`root = Path(${JSON.stringify(repo)})`,
|
|
176
|
+
`template = ${JSON.stringify(template)}`,
|
|
177
|
+
"plan = am._agents_refresh_plan(",
|
|
178
|
+
" root,",
|
|
179
|
+
" read_template=lambda: template,",
|
|
180
|
+
` resolve_sha=lambda: ${JSON.stringify(FIXED_SHA)},`,
|
|
181
|
+
` now_iso=lambda: ${JSON.stringify(FIXED_ISO)},`,
|
|
182
|
+
` new_session=lambda: ${JSON.stringify(FIXED_SESSION)},`,
|
|
183
|
+
")",
|
|
184
|
+
"print(json.dumps({'state': plan['state'], 'rendered_len': len(plan.get('rendered') or ''), 'has_v3': 'v3 sha=' in (plan.get('new_content') or '')}))",
|
|
185
|
+
].join("\n"));
|
|
186
|
+
},
|
|
187
|
+
runTs: (deftRoot, repo) => {
|
|
188
|
+
const template = readTemplate(deftRoot);
|
|
189
|
+
const plan = agentsRefreshPlan(repo, {
|
|
190
|
+
frameworkRoot: repo,
|
|
191
|
+
readTemplate: () => template,
|
|
192
|
+
resolveSha: () => FIXED_SHA,
|
|
193
|
+
nowIso: () => FIXED_ISO,
|
|
194
|
+
newSession: () => FIXED_SESSION,
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
state: plan.state,
|
|
198
|
+
rendered_len: (plan.rendered ?? "").length,
|
|
199
|
+
has_v3: String(plan.new_content ?? "").includes("v3 sha="),
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: "platform-capabilities-sandbox",
|
|
205
|
+
setup: (repo) => {
|
|
206
|
+
writeFileSync(join(repo, "uid_map"), "0 1000 1\n1 100001 1\n", "utf8");
|
|
207
|
+
},
|
|
208
|
+
runPython: (deftRoot, repo) => runPythonJson(deftRoot, [
|
|
209
|
+
"import json",
|
|
210
|
+
"from pathlib import Path",
|
|
211
|
+
"import platform_capabilities as pc",
|
|
212
|
+
`env = {'CURSOR_ORIG_UID': '1000', 'CURSOR_SANDBOX': '1'}`,
|
|
213
|
+
`report = pc.probe_runtime_capabilities(environ=env, uid_map_path=Path(${JSON.stringify(join(repo, "uid_map"))}), cwd=Path(${JSON.stringify(repo)}), effective_uid_override=0)`,
|
|
214
|
+
"payload = report.to_dict()",
|
|
215
|
+
"if payload.get('ownership'): payload['ownership'] = {**payload['ownership'], 'path': '<REPO>'}",
|
|
216
|
+
"print(json.dumps(payload))",
|
|
217
|
+
].join("\n")),
|
|
218
|
+
runTs: (_deftRoot, repo) => normalizeCapabilityReport(reportToDict(probeRuntimeCapabilities({
|
|
219
|
+
environ: { CURSOR_ORIG_UID: "1000", CURSOR_SANDBOX: "1" },
|
|
220
|
+
uidMapPath: join(repo, "uid_map"),
|
|
221
|
+
cwd: repo,
|
|
222
|
+
effectiveUidOverride: 0,
|
|
223
|
+
}))),
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: "ip-risk-detect",
|
|
227
|
+
runPython: (deftRoot) => runPythonJson(deftRoot, [
|
|
228
|
+
"import json",
|
|
229
|
+
"import ip_risk",
|
|
230
|
+
"text = 'A Magic: The Gathering deck-builder with NFL stats'",
|
|
231
|
+
"hits = ip_risk.detect_ip_terms(text)",
|
|
232
|
+
"print(json.dumps([{'term': h.term, 'category': h.category} for h in hits]))",
|
|
233
|
+
].join("\n")),
|
|
234
|
+
runTs: () => detectIpTerms("A Magic: The Gathering deck-builder with NFL stats").map((h) => ({
|
|
235
|
+
term: h.term,
|
|
236
|
+
category: h.category,
|
|
237
|
+
})),
|
|
238
|
+
},
|
|
239
|
+
];
|
|
240
|
+
export function diffCase(name, python, ts) {
|
|
241
|
+
const pythonJson = stableJson(python);
|
|
242
|
+
const tsJson = stableJson(ts);
|
|
243
|
+
return {
|
|
244
|
+
caseName: name,
|
|
245
|
+
mismatch: pythonJson !== tsJson,
|
|
246
|
+
pythonJson,
|
|
247
|
+
tsJson,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
export function runParity() {
|
|
251
|
+
const deftRoot = resolveDeftRoot();
|
|
252
|
+
const diffs = [];
|
|
253
|
+
for (const testCase of PARITY_CASES) {
|
|
254
|
+
const pyRepo = mkdtempSync(join(tmpdir(), "deft-platform-parity-py-"));
|
|
255
|
+
const tsRepo = mkdtempSync(join(tmpdir(), "deft-platform-parity-ts-"));
|
|
256
|
+
try {
|
|
257
|
+
testCase.setup?.(pyRepo);
|
|
258
|
+
testCase.setup?.(tsRepo);
|
|
259
|
+
const python = testCase.runPython(deftRoot, pyRepo);
|
|
260
|
+
const ts = testCase.runTs(deftRoot, tsRepo);
|
|
261
|
+
diffs.push(diffCase(testCase.name, python, ts));
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
rmSync(pyRepo, { recursive: true, force: true });
|
|
265
|
+
rmSync(tsRepo, { recursive: true, force: true });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return { ok: diffs.every((d) => !d.mismatch), diffs };
|
|
269
|
+
}
|
|
270
|
+
export function renderReport(result) {
|
|
271
|
+
if (result.ok) {
|
|
272
|
+
return `platform parity: CLEAN -- Python and TS agree on ${PARITY_CASES.length} case(s).`;
|
|
273
|
+
}
|
|
274
|
+
const lines = ["platform parity: DIVERGENCE"];
|
|
275
|
+
for (const d of result.diffs) {
|
|
276
|
+
if (d.mismatch) {
|
|
277
|
+
lines.push(` case: ${d.caseName}`);
|
|
278
|
+
lines.push(" --- python");
|
|
279
|
+
lines.push(d.pythonJson
|
|
280
|
+
.split("\n")
|
|
281
|
+
.slice(0, 12)
|
|
282
|
+
.map((l) => ` ${l}`)
|
|
283
|
+
.join("\n"));
|
|
284
|
+
lines.push(" --- ts");
|
|
285
|
+
lines.push(d.tsJson
|
|
286
|
+
.split("\n")
|
|
287
|
+
.slice(0, 12)
|
|
288
|
+
.map((l) => ` ${l}`)
|
|
289
|
+
.join("\n"));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return lines.join("\n");
|
|
293
|
+
}
|
|
294
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
295
|
+
try {
|
|
296
|
+
const result = runParity();
|
|
297
|
+
if (result.ok) {
|
|
298
|
+
process.stdout.write(`${renderReport(result)}\n`);
|
|
299
|
+
process.exit(0);
|
|
300
|
+
}
|
|
301
|
+
process.stderr.write(`${renderReport(result)}\n`);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
process.stderr.write(`platform parity: harness error -- ${String(err)}\n`);
|
|
306
|
+
process.exit(2);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=platform-parity.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
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 ParityCase {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly argv: string[];
|
|
10
|
+
readonly env?: Record<string, string | undefined>;
|
|
11
|
+
readonly fixture?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
export interface ParityDiff {
|
|
14
|
+
readonly caseName: string;
|
|
15
|
+
readonly exitMismatch: boolean;
|
|
16
|
+
readonly stdoutMismatch: boolean;
|
|
17
|
+
readonly stderrMismatch: boolean;
|
|
18
|
+
readonly pythonExit: number;
|
|
19
|
+
readonly tsExit: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ParityResult {
|
|
22
|
+
readonly ok: boolean;
|
|
23
|
+
readonly diffs: ParityDiff[];
|
|
24
|
+
}
|
|
25
|
+
/** Strip volatile ISO timestamps from audit / JSON envelopes before compare. */
|
|
26
|
+
export declare function normalizeOutput(text: string): string;
|
|
27
|
+
/** Build a throwaway project root with optional PROJECT-DEFINITION plan payload. */
|
|
28
|
+
export declare function buildFixtureRepo(plan?: Record<string, unknown>): string;
|
|
29
|
+
/** Diff one parity case between Python oracle and TS CLI. */
|
|
30
|
+
export declare function diffCase(python: CommandCapture, ts: CommandCapture, caseName: string): ParityDiff;
|
|
31
|
+
export declare const PARITY_CASES: readonly ParityCase[];
|
|
32
|
+
/** Run all parity cases; returns aggregate result. */
|
|
33
|
+
export declare function runParity(): ParityResult;
|
|
34
|
+
export declare function renderReport(result: ParityResult): string;
|
|
35
|
+
//# sourceMappingURL=policy-parity.d.ts.map
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Golden-output parity harness (#1722): builds throwaway fixture repos, runs
|
|
4
|
+
* BOTH the Python oracle (scripts/policy.py + shims) and the TS policy CLI,
|
|
5
|
+
* and diffs resolution output + disclosure_line + exit codes.
|
|
6
|
+
*
|
|
7
|
+
* Exit codes: 0 parity / 1 divergence / 2 harness setup error.
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } 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
|
+
/** Strip volatile ISO timestamps from audit / JSON envelopes before compare. */
|
|
15
|
+
export function normalizeOutput(text) {
|
|
16
|
+
return text
|
|
17
|
+
.replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/g, "<TS>")
|
|
18
|
+
.replace(/PROJECT-DEFINITION not found at [^\s)]+/g, "PROJECT-DEFINITION not found at <ROOT>")
|
|
19
|
+
.replace(/fail-closed: PROJECT-DEFINITION not found at [^)]+/g, "fail-closed: PROJECT-DEFINITION not found at <ROOT>");
|
|
20
|
+
}
|
|
21
|
+
function runCapture(cmd, args, cwd, env = {}) {
|
|
22
|
+
const merged = { ...process.env, ...env };
|
|
23
|
+
for (const key of Object.keys(merged)) {
|
|
24
|
+
if (merged[key] === undefined)
|
|
25
|
+
delete merged[key];
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const stdout = execFileSync(cmd, args, {
|
|
29
|
+
cwd,
|
|
30
|
+
encoding: "utf8",
|
|
31
|
+
env: merged,
|
|
32
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
33
|
+
});
|
|
34
|
+
return { status: 0, stdout, stderr: "" };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const e = err;
|
|
38
|
+
return {
|
|
39
|
+
status: typeof e.status === "number" ? e.status : 2,
|
|
40
|
+
stdout: typeof e.stdout === "string" ? e.stdout : "",
|
|
41
|
+
stderr: typeof e.stderr === "string" ? e.stderr : "",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function writeFixture(root, plan) {
|
|
46
|
+
const dir = join(root, "vbrief");
|
|
47
|
+
mkdirSync(dir, { recursive: true });
|
|
48
|
+
writeFileSync(join(dir, "PROJECT-DEFINITION.vbrief.json"), `${JSON.stringify({
|
|
49
|
+
vBRIEFInfo: { version: "0.6" },
|
|
50
|
+
plan: { title: "T", status: "running", items: [], ...plan },
|
|
51
|
+
}, null, 2)}\n`, { encoding: "utf8" });
|
|
52
|
+
}
|
|
53
|
+
/** Build a throwaway project root with optional PROJECT-DEFINITION plan payload. */
|
|
54
|
+
export function buildFixtureRepo(plan) {
|
|
55
|
+
const root = mkdtempSync(join(tmpdir(), "deft-policy-parity-"));
|
|
56
|
+
mkdirSync(join(root, "vbrief"), { recursive: true });
|
|
57
|
+
if (plan !== undefined) {
|
|
58
|
+
writeFixture(root, plan);
|
|
59
|
+
}
|
|
60
|
+
return root;
|
|
61
|
+
}
|
|
62
|
+
function resolveDeftRoot() {
|
|
63
|
+
if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
|
|
64
|
+
return resolve(process.env.DEFT_ROOT);
|
|
65
|
+
}
|
|
66
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
67
|
+
}
|
|
68
|
+
function runPythonPolicy(deftRoot, repo, argv, env) {
|
|
69
|
+
const sub = argv[0];
|
|
70
|
+
if (sub === undefined) {
|
|
71
|
+
throw new Error("missing policy subcommand");
|
|
72
|
+
}
|
|
73
|
+
const rest = argv.slice(1);
|
|
74
|
+
const withRoot = [...rest, "--project-root", repo];
|
|
75
|
+
if (sub === "show") {
|
|
76
|
+
const cap = runCapture("uv", ["run", "python", join(deftRoot, "scripts", "_policy_show_cli.py"), ...withRoot], deftRoot, env);
|
|
77
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
78
|
+
}
|
|
79
|
+
if (sub === "resolve") {
|
|
80
|
+
const cap = runCapture("uv", ["run", "python", join(deftRoot, "scripts", "policy.py"), "show", ...withRoot], deftRoot, env);
|
|
81
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
82
|
+
}
|
|
83
|
+
const cap = runCapture("uv", ["run", "python", join(deftRoot, "scripts", "policy_set.py"), sub, ...withRoot], deftRoot, env);
|
|
84
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
85
|
+
}
|
|
86
|
+
function runTsPolicy(deftRoot, repo, argv, env) {
|
|
87
|
+
const cap = runCapture("node", [join(deftRoot, "packages", "cli", "dist", "policy.js"), ...argv, "--project-root", repo], deftRoot, env);
|
|
88
|
+
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
89
|
+
}
|
|
90
|
+
/** Diff one parity case between Python oracle and TS CLI. */
|
|
91
|
+
export function diffCase(python, ts, caseName) {
|
|
92
|
+
const pyOut = normalizeOutput(python.stdout);
|
|
93
|
+
const tsOut = normalizeOutput(ts.stdout);
|
|
94
|
+
const pyErr = normalizeOutput(python.stderr);
|
|
95
|
+
const tsErr = normalizeOutput(ts.stderr);
|
|
96
|
+
return {
|
|
97
|
+
caseName,
|
|
98
|
+
exitMismatch: python.exitCode !== ts.exitCode,
|
|
99
|
+
stdoutMismatch: pyOut !== tsOut,
|
|
100
|
+
stderrMismatch: pyErr !== tsErr,
|
|
101
|
+
pythonExit: python.exitCode,
|
|
102
|
+
tsExit: ts.exitCode,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export const PARITY_CASES = [
|
|
106
|
+
{
|
|
107
|
+
name: "resolve-default-missing-pd",
|
|
108
|
+
argv: ["resolve"],
|
|
109
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "resolve-typed-false",
|
|
113
|
+
argv: ["resolve"],
|
|
114
|
+
fixture: { policy: { allowDirectCommitsToMaster: false } },
|
|
115
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "resolve-typed-true",
|
|
119
|
+
argv: ["resolve"],
|
|
120
|
+
fixture: { policy: { allowDirectCommitsToMaster: true } },
|
|
121
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "resolve-legacy-narrative",
|
|
125
|
+
argv: ["resolve"],
|
|
126
|
+
fixture: { narratives: { "Allow direct commits to master": "true" } },
|
|
127
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "resolve-env-bypass",
|
|
131
|
+
argv: ["resolve"],
|
|
132
|
+
fixture: { policy: { allowDirectCommitsToMaster: false } },
|
|
133
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "1" },
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "show-text-defaults",
|
|
137
|
+
argv: ["show"],
|
|
138
|
+
fixture: {},
|
|
139
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "show-field-wipCap",
|
|
143
|
+
argv: ["show", "--field", "plan.policy.wipCap"],
|
|
144
|
+
fixture: { policy: { wipCap: 7 } },
|
|
145
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "allow-direct-commits-refuse",
|
|
149
|
+
argv: ["allow-direct-commits"],
|
|
150
|
+
fixture: {},
|
|
151
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "enforce-branches",
|
|
155
|
+
argv: ["enforce-branches", "--actor", "parity-test"],
|
|
156
|
+
fixture: { policy: { allowDirectCommitsToMaster: true } },
|
|
157
|
+
env: { DEFT_ALLOW_DEFAULT_BRANCH_COMMIT: "" },
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
/** Run all parity cases; returns aggregate result. */
|
|
161
|
+
export function runParity() {
|
|
162
|
+
const deftRoot = resolveDeftRoot();
|
|
163
|
+
const diffs = [];
|
|
164
|
+
for (const testCase of PARITY_CASES) {
|
|
165
|
+
const pyRepo = buildFixtureRepo(testCase.fixture);
|
|
166
|
+
const tsRepo = buildFixtureRepo(testCase.fixture);
|
|
167
|
+
try {
|
|
168
|
+
const env = testCase.env ?? {};
|
|
169
|
+
const python = runPythonPolicy(deftRoot, pyRepo, testCase.argv, env);
|
|
170
|
+
const ts = runTsPolicy(deftRoot, tsRepo, testCase.argv, env);
|
|
171
|
+
diffs.push(diffCase(python, ts, testCase.name));
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
rmSync(pyRepo, { recursive: true, force: true });
|
|
175
|
+
rmSync(tsRepo, { recursive: true, force: true });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const ok = diffs.every((d) => !d.exitMismatch && !d.stdoutMismatch && !d.stderrMismatch);
|
|
179
|
+
return { ok, diffs };
|
|
180
|
+
}
|
|
181
|
+
export function renderReport(result) {
|
|
182
|
+
if (result.ok) {
|
|
183
|
+
return `policy parity: CLEAN -- Python and TS agree on ${PARITY_CASES.length} cases.`;
|
|
184
|
+
}
|
|
185
|
+
const lines = ["policy parity: DIVERGENCE"];
|
|
186
|
+
for (const d of result.diffs) {
|
|
187
|
+
if (d.exitMismatch || d.stdoutMismatch || d.stderrMismatch) {
|
|
188
|
+
lines.push(` case: ${d.caseName}`);
|
|
189
|
+
if (d.exitMismatch)
|
|
190
|
+
lines.push(` exit: python=${d.pythonExit} ts=${d.tsExit}`);
|
|
191
|
+
if (d.stdoutMismatch)
|
|
192
|
+
lines.push(" stdout mismatch");
|
|
193
|
+
if (d.stderrMismatch)
|
|
194
|
+
lines.push(" stderr mismatch");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return lines.join("\n");
|
|
198
|
+
}
|
|
199
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
200
|
+
try {
|
|
201
|
+
const result = runParity();
|
|
202
|
+
if (result.ok) {
|
|
203
|
+
process.stdout.write(`${renderReport(result)}\n`);
|
|
204
|
+
process.exit(0);
|
|
205
|
+
}
|
|
206
|
+
process.stderr.write(`${renderReport(result)}\n`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
process.stderr.write(`policy parity: harness error -- ${String(err)}\n`);
|
|
211
|
+
process.exit(2);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=policy-parity.js.map
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
interface ShowArgs {
|
|
3
|
+
format: "text" | "json";
|
|
4
|
+
changedOnly: boolean;
|
|
5
|
+
field: string | null;
|
|
6
|
+
projectRoot: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
interface SetArgs {
|
|
10
|
+
cmd: "show" | "enforce-branches" | "allow-direct-commits" | "resolve";
|
|
11
|
+
confirm: boolean;
|
|
12
|
+
actor: string;
|
|
13
|
+
note: string;
|
|
14
|
+
projectRoot: string;
|
|
15
|
+
format: "text" | "json";
|
|
16
|
+
changedOnly: boolean;
|
|
17
|
+
field: string | null;
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Parse policy:show flags (mirrors _policy_show_cli.py). */
|
|
21
|
+
export declare function parseShowArgs(argv: string[]): ShowArgs;
|
|
22
|
+
/** Parse argv for the policy CLI (show + set subcommands). */
|
|
23
|
+
export declare function parseArgs(argv: string[]): SetArgs;
|
|
24
|
+
/** Run the policy CLI; returns process exit code. */
|
|
25
|
+
export declare function run(argv: string[]): number;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=policy.d.ts.map
|