@deftai/directive 0.56.2 → 0.58.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/agents-refresh.d.ts +11 -0
- package/dist/agents-refresh.js +82 -0
- package/dist/cli-router/route-argv.js +6 -0
- package/dist/codebase-parity.d.ts +1 -0
- package/dist/codebase-parity.js +11 -2
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +2 -0
- package/dist/doc-cli-parity.d.ts +29 -0
- package/dist/doc-cli-parity.js +159 -0
- package/dist/lifecycle-packs-parity.js +2 -2
- package/dist/release-parity.js +4 -1
- package/dist/render-parity.d.ts +1 -0
- package/dist/render-parity.js +4 -2
- package/dist/session-parity.js +6 -4
- package/dist/swarm-parity.js +1 -0
- package/dist/triage-actions-parity.js +1 -0
- package/dist/triage-aux-a-parity.js +7 -2
- package/dist/triage-queue-parity.js +3 -1
- package/dist/vbrief-reconcile-parity.d.ts +1 -0
- package/dist/vbrief-reconcile-parity.js +12 -3
- package/package.json +3 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export interface AgentsRefreshArgs {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
check: boolean;
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseAgentsRefreshArgs(argv: readonly string[]): AgentsRefreshArgs;
|
|
9
|
+
export declare function runAgentsRefresh(argv: readonly string[]): number;
|
|
10
|
+
export declare function run(argv: readonly string[]): number;
|
|
11
|
+
//# sourceMappingURL=agents-refresh.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* agents:refresh — rewrite AGENTS.md managed section from the canonical template (#768 / #1996).
|
|
4
|
+
*/
|
|
5
|
+
import { writeFileSync } from "node:fs";
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { agentsRefreshPlan } from "@deftai/directive-core/platform";
|
|
9
|
+
export function parseAgentsRefreshArgs(argv) {
|
|
10
|
+
let projectRoot = process.cwd();
|
|
11
|
+
let check = false;
|
|
12
|
+
let dryRun = false;
|
|
13
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
14
|
+
const arg = argv[i] ?? "";
|
|
15
|
+
if (arg === "--check") {
|
|
16
|
+
check = true;
|
|
17
|
+
}
|
|
18
|
+
else if (arg === "--dry-run") {
|
|
19
|
+
dryRun = true;
|
|
20
|
+
}
|
|
21
|
+
else if (arg === "--project-root") {
|
|
22
|
+
const next = argv[i + 1];
|
|
23
|
+
if (next === undefined) {
|
|
24
|
+
return { projectRoot, check, dryRun, error: "missing --project-root value" };
|
|
25
|
+
}
|
|
26
|
+
projectRoot = next;
|
|
27
|
+
i += 1;
|
|
28
|
+
}
|
|
29
|
+
else if (arg.startsWith("--project-root=")) {
|
|
30
|
+
projectRoot = arg.slice("--project-root=".length);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return { projectRoot, check, dryRun, error: `unrecognized argument: ${arg}` };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { projectRoot: resolve(projectRoot), check, dryRun };
|
|
37
|
+
}
|
|
38
|
+
export function runAgentsRefresh(argv) {
|
|
39
|
+
const args = parseAgentsRefreshArgs(argv);
|
|
40
|
+
if (args.error !== undefined) {
|
|
41
|
+
process.stderr.write(`agents:refresh: ${args.error}\n`);
|
|
42
|
+
return 2;
|
|
43
|
+
}
|
|
44
|
+
const plan = agentsRefreshPlan(args.projectRoot);
|
|
45
|
+
const state = String(plan.state ?? "unknown");
|
|
46
|
+
if (args.check) {
|
|
47
|
+
if (state === "current")
|
|
48
|
+
return 0;
|
|
49
|
+
process.stderr.write(`agents:refresh --check: AGENTS.md state is ${state}\n`);
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
if (state === "current") {
|
|
53
|
+
process.stdout.write("AGENTS.md managed section is current — no changes.\n");
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
if (state === "template-missing" || state === "template-malformed" || state === "unreadable") {
|
|
57
|
+
process.stderr.write(`agents:refresh failed: ${state}\n`);
|
|
58
|
+
return 2;
|
|
59
|
+
}
|
|
60
|
+
const newContent = plan.new_content;
|
|
61
|
+
if (typeof newContent !== "string") {
|
|
62
|
+
process.stderr.write("agents:refresh failed: plan produced no new_content\n");
|
|
63
|
+
return 2;
|
|
64
|
+
}
|
|
65
|
+
const path = String(plan.path ?? resolve(args.projectRoot, "AGENTS.md"));
|
|
66
|
+
if (args.dryRun) {
|
|
67
|
+
process.stdout.write(`[dry-run] would write ${path} (state=${state})\n`);
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
writeFileSync(path, newContent, "utf8");
|
|
71
|
+
process.stdout.write(`AGENTS.md updated (state=${state}).\n`);
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
export function run(argv) {
|
|
75
|
+
return runAgentsRefresh(argv);
|
|
76
|
+
}
|
|
77
|
+
/* v8 ignore start -- entry guard */
|
|
78
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
79
|
+
process.exit(run(process.argv.slice(2)));
|
|
80
|
+
}
|
|
81
|
+
/* v8 ignore stop */
|
|
82
|
+
//# sourceMappingURL=agents-refresh.js.map
|
|
@@ -126,6 +126,12 @@ function routeNamespaceVerb(ns, verb, rest) {
|
|
|
126
126
|
if (resolveCanonicalVerb(colonKey) !== null) {
|
|
127
127
|
return { kind: "dispatch", argv: [colonKey, ...rest] };
|
|
128
128
|
}
|
|
129
|
+
if (ns === "framework" && verb === "doctor") {
|
|
130
|
+
return { kind: "dispatch", argv: ["doctor", ...rest] };
|
|
131
|
+
}
|
|
132
|
+
if (ns === "agents" && verb === "refresh") {
|
|
133
|
+
return { kind: "dispatch", argv: ["agents-refresh", ...rest] };
|
|
134
|
+
}
|
|
129
135
|
if (ns === "scope") {
|
|
130
136
|
if (SCOPE_LIFECYCLE_VERBS.has(verb)) {
|
|
131
137
|
return { kind: "dispatch", argv: ["scope-lifecycle", verb, ...rest] };
|
|
@@ -24,6 +24,7 @@ export interface ParityResult {
|
|
|
24
24
|
readonly diffs: ParityDiff[];
|
|
25
25
|
}
|
|
26
26
|
export declare const PARITY_CASES: readonly ParityCase[];
|
|
27
|
+
export declare function normalizeOutput(text: string): string;
|
|
27
28
|
export declare function diffCase(python: CommandCapture, ts: CommandCapture, caseName: string): ParityDiff;
|
|
28
29
|
export declare function runParity(): ParityResult;
|
|
29
30
|
export declare function renderReport(result: ParityResult): string;
|
package/dist/codebase-parity.js
CHANGED
|
@@ -229,12 +229,21 @@ export const PARITY_CASES = [
|
|
|
229
229
|
setup: writeCapacityProject,
|
|
230
230
|
},
|
|
231
231
|
];
|
|
232
|
+
export function normalizeOutput(text) {
|
|
233
|
+
return text
|
|
234
|
+
.replace(/(?:\/private)?\/var\/folders\/[^\s"')]+\/deft-codebase-parity-[^\s"')]+/g, "<TMP>")
|
|
235
|
+
.replace(/\/tmp\/deft-codebase-parity-[^\s"')]+/g, "<TMP>");
|
|
236
|
+
}
|
|
232
237
|
export function diffCase(python, ts, caseName) {
|
|
238
|
+
const pythonStdout = normalizeOutput(python.stdout);
|
|
239
|
+
const pythonStderr = normalizeOutput(python.stderr);
|
|
240
|
+
const tsStdout = normalizeOutput(ts.stdout);
|
|
241
|
+
const tsStderr = normalizeOutput(ts.stderr);
|
|
233
242
|
return {
|
|
234
243
|
caseName,
|
|
235
244
|
exitMismatch: python.exitCode !== ts.exitCode,
|
|
236
|
-
stdoutMismatch:
|
|
237
|
-
stderrMismatch:
|
|
245
|
+
stdoutMismatch: pythonStdout !== tsStdout,
|
|
246
|
+
stderrMismatch: pythonStderr !== tsStderr,
|
|
238
247
|
pythonExit: python.exitCode,
|
|
239
248
|
tsExit: ts.exitCode,
|
|
240
249
|
};
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface DispatchIo {
|
|
|
8
8
|
writeErr: (text: string) => void;
|
|
9
9
|
}
|
|
10
10
|
/** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
|
|
11
|
-
export declare const CLI_MODULE_VERBS: readonly ["cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "parity", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "verify-branch", "verify-encoding", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-stubs", "rule-ownership-lint", "verify-story-ready", "verify-tools", "verify-wip-cap"];
|
|
11
|
+
export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "parity", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "verify-branch", "verify-encoding", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-stubs", "rule-ownership-lint", "verify-story-ready", "verify-tools", "verify-wip-cap"];
|
|
12
12
|
/** Core-only CLI entrypoints without a packages/cli wrapper. */
|
|
13
13
|
export declare const CORE_MODULE_VERBS: readonly ["scm", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "project-render", "roadmap-render", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor"];
|
|
14
14
|
/** Task-style aliases (framework_commands / Taskfile names). */
|
package/dist/dispatch.js
CHANGED
|
@@ -17,6 +17,7 @@ const HANDLER_KEYS = [
|
|
|
17
17
|
];
|
|
18
18
|
/** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
|
|
19
19
|
export const CLI_MODULE_VERBS = [
|
|
20
|
+
"agents-refresh",
|
|
20
21
|
"cache",
|
|
21
22
|
"check",
|
|
22
23
|
"capacity-backfill",
|
|
@@ -158,6 +159,7 @@ export const VERB_ALIASES = {
|
|
|
158
159
|
"triage:scope": "triage-scope",
|
|
159
160
|
"triage:accept": "triage-actions",
|
|
160
161
|
"triage:status": "triage-actions",
|
|
162
|
+
"agents:refresh": "agents-refresh",
|
|
161
163
|
"session:start": "framework-commands",
|
|
162
164
|
"toolchain:check": "toolchain-check",
|
|
163
165
|
"ts:check-lane": "ts-check-lane",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doc ↔ CLI parity gate (#1996).
|
|
3
|
+
*
|
|
4
|
+
* Extracts npm-canonical CLI invocations from UPGRADING.md and the AGENTS.md
|
|
5
|
+
* managed-section template, then asserts each resolves through the top-level
|
|
6
|
+
* router to a registered dispatcher verb (or an explicitly allowlisted legacy
|
|
7
|
+
* back-compat surface documented post-#1912).
|
|
8
|
+
*/
|
|
9
|
+
/** Documented legacy surfaces that remain in prose but are not npm-router verbs. */
|
|
10
|
+
export declare const LEGACY_DOC_VERB_KEYS: Set<string>;
|
|
11
|
+
export interface DocCliReference {
|
|
12
|
+
readonly source: string;
|
|
13
|
+
readonly raw: string;
|
|
14
|
+
readonly normalized: string;
|
|
15
|
+
}
|
|
16
|
+
export interface DocCliParityFailure {
|
|
17
|
+
readonly source: string;
|
|
18
|
+
readonly raw: string;
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
}
|
|
21
|
+
/** Pull CLI command references from UPGRADING.md + agents-entry managed section. */
|
|
22
|
+
export declare function extractDocCliReferences(repoRoot?: string): DocCliReference[];
|
|
23
|
+
/** Strip flags/placeholders; return null when the literal is not a CLI verb invocation. */
|
|
24
|
+
export declare function normalizeDocCommand(raw: string): string | null;
|
|
25
|
+
/** Validate one normalized doc command against the router + registeredVerbs(). */
|
|
26
|
+
export declare function validateDocCliCommand(normalized: string): string | null;
|
|
27
|
+
/** Run the parity gate; returns failure rows (empty == pass). */
|
|
28
|
+
export declare function collectDocCliParityFailures(repoRoot?: string): DocCliParityFailure[];
|
|
29
|
+
//# sourceMappingURL=doc-cli-parity.d.ts.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doc ↔ CLI parity gate (#1996).
|
|
3
|
+
*
|
|
4
|
+
* Extracts npm-canonical CLI invocations from UPGRADING.md and the AGENTS.md
|
|
5
|
+
* managed-section template, then asserts each resolves through the top-level
|
|
6
|
+
* router to a registered dispatcher verb (or an explicitly allowlisted legacy
|
|
7
|
+
* back-compat surface documented post-#1912).
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { join, resolve } from "node:path";
|
|
11
|
+
import { hasCommand } from "@deftai/directive-core/render";
|
|
12
|
+
import { routeArgv } from "./cli-router/route-argv.js";
|
|
13
|
+
import { registeredVerbs, resolveCanonicalVerb, VERB_ALIASES } from "./dispatch.js";
|
|
14
|
+
/** Documented legacy surfaces that remain in prose but are not npm-router verbs. */
|
|
15
|
+
export const LEGACY_DOC_VERB_KEYS = new Set(["setup", "upgrade", "relocate"]);
|
|
16
|
+
const CLI_PREFIX_RE = /^(?:directive|deft|npx @deftai\/directive)\s+/;
|
|
17
|
+
const BACKTICK_COMMAND_RE = /`((?:directive|deft|npx @deftai\/directive)\s+[^`]+)`/g;
|
|
18
|
+
const TOP_LEVEL_UX = new Set(["init", "update", "migrate"]);
|
|
19
|
+
function repoRootFromModule() {
|
|
20
|
+
return resolve(import.meta.dirname, "..", "..", "..");
|
|
21
|
+
}
|
|
22
|
+
function extractManagedSection(text) {
|
|
23
|
+
const open = text.indexOf("<!-- deft:managed-section");
|
|
24
|
+
if (open < 0)
|
|
25
|
+
return text;
|
|
26
|
+
const close = text.indexOf("<!-- /deft:managed-section -->", open);
|
|
27
|
+
if (close < 0)
|
|
28
|
+
return text.slice(open);
|
|
29
|
+
return text.slice(open, close);
|
|
30
|
+
}
|
|
31
|
+
/** Pull CLI command references from UPGRADING.md + agents-entry managed section. */
|
|
32
|
+
export function extractDocCliReferences(repoRoot = repoRootFromModule()) {
|
|
33
|
+
const sources = [
|
|
34
|
+
["content/UPGRADING.md", readFileSync(join(repoRoot, "content/UPGRADING.md"), "utf8")],
|
|
35
|
+
[
|
|
36
|
+
"content/templates/agents-entry.md",
|
|
37
|
+
extractManagedSection(readFileSync(join(repoRoot, "content/templates/agents-entry.md"), "utf8")),
|
|
38
|
+
],
|
|
39
|
+
];
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const [source, text] of sources) {
|
|
43
|
+
for (const match of text.matchAll(BACKTICK_COMMAND_RE)) {
|
|
44
|
+
const raw = match[1]?.trim() ?? "";
|
|
45
|
+
if (!CLI_PREFIX_RE.test(raw))
|
|
46
|
+
continue;
|
|
47
|
+
const normalized = normalizeDocCommand(raw);
|
|
48
|
+
if (normalized === null)
|
|
49
|
+
continue;
|
|
50
|
+
const key = `${source}\0${normalized}`;
|
|
51
|
+
if (seen.has(key))
|
|
52
|
+
continue;
|
|
53
|
+
seen.add(key);
|
|
54
|
+
out.push({ source, raw, normalized });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out.sort((a, b) => a.source.localeCompare(b.source) || a.normalized.localeCompare(b.normalized));
|
|
58
|
+
}
|
|
59
|
+
function stripAnglePlaceholders(text) {
|
|
60
|
+
let out = text;
|
|
61
|
+
let start = out.indexOf("<");
|
|
62
|
+
while (start >= 0) {
|
|
63
|
+
const end = out.indexOf(">", start + 1);
|
|
64
|
+
if (end < 0)
|
|
65
|
+
break;
|
|
66
|
+
out = `${out.slice(0, start)}${out.slice(end + 1)}`;
|
|
67
|
+
start = out.indexOf("<");
|
|
68
|
+
}
|
|
69
|
+
return out.trim();
|
|
70
|
+
}
|
|
71
|
+
/** Strip flags/placeholders; return null when the literal is not a CLI verb invocation. */
|
|
72
|
+
export function normalizeDocCommand(raw) {
|
|
73
|
+
let rest = raw.replace(CLI_PREFIX_RE, "").trim();
|
|
74
|
+
if (rest.length === 0)
|
|
75
|
+
return null;
|
|
76
|
+
const dd = rest.indexOf(" --");
|
|
77
|
+
if (dd >= 0)
|
|
78
|
+
rest = rest.slice(0, dd).trim();
|
|
79
|
+
rest = rest.replace(/\s+\[[^\]]*\]/g, "").trim();
|
|
80
|
+
rest = rest.replace(/\s+--[^\s]+(\s+[^\s]+)?/g, "").trim();
|
|
81
|
+
rest = stripAnglePlaceholders(rest);
|
|
82
|
+
if (rest.includes("/") || rest.includes(".md") || rest.includes("*"))
|
|
83
|
+
return null;
|
|
84
|
+
if (/^deft-install\b/.test(rest))
|
|
85
|
+
return null;
|
|
86
|
+
if (/^deft-directive\b/.test(rest))
|
|
87
|
+
return null;
|
|
88
|
+
if (/^deftai\b/.test(rest))
|
|
89
|
+
return null;
|
|
90
|
+
const first = rest.split(/\s+/)[0] ?? "";
|
|
91
|
+
if (!/^[\w:-]+$/.test(first))
|
|
92
|
+
return null;
|
|
93
|
+
if (first.includes(":")) {
|
|
94
|
+
return first;
|
|
95
|
+
}
|
|
96
|
+
return first;
|
|
97
|
+
}
|
|
98
|
+
function tokenizeDocVerb(normalized) {
|
|
99
|
+
if (normalized.includes(":")) {
|
|
100
|
+
const colon = normalized.indexOf(":");
|
|
101
|
+
return [normalized.slice(0, colon), normalized.slice(colon + 1)];
|
|
102
|
+
}
|
|
103
|
+
return [normalized];
|
|
104
|
+
}
|
|
105
|
+
function colonKeyFromNormalized(normalized) {
|
|
106
|
+
if (normalized.includes(":"))
|
|
107
|
+
return normalized;
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function isRegisteredHandler(flatVerb) {
|
|
111
|
+
const verbs = new Set(registeredVerbs());
|
|
112
|
+
if (verbs.has(flatVerb))
|
|
113
|
+
return true;
|
|
114
|
+
const canon = resolveCanonicalVerb(flatVerb);
|
|
115
|
+
return canon !== null && verbs.has(canon);
|
|
116
|
+
}
|
|
117
|
+
/** Validate one normalized doc command against the router + registeredVerbs(). */
|
|
118
|
+
export function validateDocCliCommand(normalized) {
|
|
119
|
+
const colonKey = colonKeyFromNormalized(normalized);
|
|
120
|
+
if (colonKey !== null) {
|
|
121
|
+
if (LEGACY_DOC_VERB_KEYS.has(colonKey)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
if (colonKey in VERB_ALIASES || hasCommand(colonKey)) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (LEGACY_DOC_VERB_KEYS.has(normalized)) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const tokens = tokenizeDocVerb(normalized);
|
|
132
|
+
const routed = routeArgv(tokens);
|
|
133
|
+
if (routed.kind === "stub") {
|
|
134
|
+
return routed.stubMessage ?? "routes to stub handler";
|
|
135
|
+
}
|
|
136
|
+
const head = routed.argv[0];
|
|
137
|
+
if (head === undefined || head.length === 0) {
|
|
138
|
+
return "router produced empty argv";
|
|
139
|
+
}
|
|
140
|
+
if (TOP_LEVEL_UX.has(head)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
if (isRegisteredHandler(head)) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return `unregistered handler '${head}' (tokens=${JSON.stringify(tokens)}, routed=${JSON.stringify(routed.argv.slice(0, 3))})`;
|
|
147
|
+
}
|
|
148
|
+
/** Run the parity gate; returns failure rows (empty == pass). */
|
|
149
|
+
export function collectDocCliParityFailures(repoRoot = repoRootFromModule()) {
|
|
150
|
+
const failures = [];
|
|
151
|
+
for (const ref of extractDocCliReferences(repoRoot)) {
|
|
152
|
+
const reason = validateDocCliCommand(ref.normalized);
|
|
153
|
+
if (reason !== null) {
|
|
154
|
+
failures.push({ source: ref.source, raw: ref.raw, reason });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return failures;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=doc-cli-parity.js.map
|
|
@@ -174,7 +174,7 @@ export const PARITY_CASES = [
|
|
|
174
174
|
const script = `import sys
|
|
175
175
|
from pathlib import Path
|
|
176
176
|
root = Path(${JSON.stringify(deftRoot)})
|
|
177
|
-
repo = Path(${JSON.stringify(repo)})
|
|
177
|
+
repo = Path(${JSON.stringify(repo)}).resolve()
|
|
178
178
|
sys.path.insert(0, str(root / "scripts"))
|
|
179
179
|
import packs_slice
|
|
180
180
|
packs_slice.REPO_ROOT = repo
|
|
@@ -199,7 +199,7 @@ raise SystemExit(0)`;
|
|
|
199
199
|
const script = `import sys
|
|
200
200
|
from pathlib import Path
|
|
201
201
|
root = Path(${JSON.stringify(deftRoot)})
|
|
202
|
-
repo = Path(${JSON.stringify(repo)})
|
|
202
|
+
repo = Path(${JSON.stringify(repo)}).resolve()
|
|
203
203
|
sys.path.insert(0, str(root / "scripts"))
|
|
204
204
|
import packs_slice
|
|
205
205
|
packs_slice.REPO_ROOT = repo
|
package/dist/release-parity.js
CHANGED
|
@@ -116,7 +116,10 @@ function resolveDeftRoot() {
|
|
|
116
116
|
}
|
|
117
117
|
/** Normalise volatile ISO dates in stderr while preserving semantics. */
|
|
118
118
|
export function normaliseStderr(text) {
|
|
119
|
-
return 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>");
|
|
120
123
|
}
|
|
121
124
|
export function pickOutput(result, stream) {
|
|
122
125
|
return stream === "stdout" ? result.stdout : result.stderr;
|
package/dist/render-parity.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export interface ParityResult {
|
|
|
29
29
|
readonly diffs: ParityDiff[];
|
|
30
30
|
}
|
|
31
31
|
export declare const PARITY_CASES: readonly ParityCase[];
|
|
32
|
+
export declare function normalizeMessage(text: string): string;
|
|
32
33
|
export declare function diffCase(python: CommandCapture, ts: CommandCapture, gate: string, caseName: string): ParityDiff;
|
|
33
34
|
export declare function runParity(): ParityResult;
|
|
34
35
|
export declare function renderReport(result: ParityResult): string;
|
package/dist/render-parity.js
CHANGED
|
@@ -296,8 +296,10 @@ function normalizeProjectBytes(bytes) {
|
|
|
296
296
|
text = text.replace(/"created": "[^"]+"/g, '"created": "<TS>"');
|
|
297
297
|
return Buffer.from(text, "utf8");
|
|
298
298
|
}
|
|
299
|
-
function normalizeMessage(text) {
|
|
300
|
-
return text
|
|
299
|
+
export function normalizeMessage(text) {
|
|
300
|
+
return text
|
|
301
|
+
.replace(/(?:\/private)?\/var\/folders\/[^\s"')]+\/deft-render-parity-(py|ts)-[^/\s"')]+/g, "<TMP>")
|
|
302
|
+
.replace(/\/tmp\/deft-render-parity-(py|ts)-[^/\s"')]+/g, "<TMP>");
|
|
301
303
|
}
|
|
302
304
|
export function diffCase(python, ts, gate, caseName) {
|
|
303
305
|
let bytesMismatch = false;
|
package/dist/session-parity.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* shared fixtures (cache-off) and diffs JSON stdout + exit codes.
|
|
6
6
|
*/
|
|
7
7
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
8
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { dirname, join, resolve } from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
@@ -53,10 +53,11 @@ function fakeGitRunner(head, worktree) {
|
|
|
53
53
|
}
|
|
54
54
|
function writeFreshState(fixture, startedAt, gated = {}) {
|
|
55
55
|
const now = new Date(startedAt);
|
|
56
|
+
const worktree = realpathSync(fixture.root);
|
|
56
57
|
writeRitualState(fixture.root, newRitualStatePayload({
|
|
57
58
|
sessionId: "parity-session",
|
|
58
59
|
gitHead: fixture.head,
|
|
59
|
-
worktreePath:
|
|
60
|
+
worktreePath: worktree,
|
|
60
61
|
startedAt: now,
|
|
61
62
|
quickSteps: {
|
|
62
63
|
alignment: ritualStep({ ok: true, ts: now }),
|
|
@@ -107,7 +108,7 @@ function runTsVerify(fixture, scenario) {
|
|
|
107
108
|
tier: scenario.tier,
|
|
108
109
|
now: new Date(scenario.nowIso),
|
|
109
110
|
bypass: scenario.bypass,
|
|
110
|
-
runGit: fakeGitRunner(fixture.head,
|
|
111
|
+
runGit: fakeGitRunner(fixture.head, realpathSync(fixture.root)),
|
|
111
112
|
runner: scenario.runner,
|
|
112
113
|
});
|
|
113
114
|
return {
|
|
@@ -161,10 +162,11 @@ export const PARITY_CASES = [
|
|
|
161
162
|
setup() {
|
|
162
163
|
const fixture = initGitRepo();
|
|
163
164
|
const now = new Date(FIXED_NOW);
|
|
165
|
+
const worktree = realpathSync(fixture.root);
|
|
164
166
|
writeRitualState(fixture.root, newRitualStatePayload({
|
|
165
167
|
sessionId: "parity-session",
|
|
166
168
|
gitHead: fixture.head,
|
|
167
|
-
worktreePath:
|
|
169
|
+
worktreePath: worktree,
|
|
168
170
|
startedAt: now,
|
|
169
171
|
quickSteps: {
|
|
170
172
|
alignment: ritualStep({ ok: true, ts: now }),
|
package/dist/swarm-parity.js
CHANGED
|
@@ -44,6 +44,7 @@ export function normalizeOutput(text) {
|
|
|
44
44
|
return text
|
|
45
45
|
.replace(/--project-root [^\s]+/g, "--project-root <ROOT>")
|
|
46
46
|
.replace(/--repo-root [^\s]+/g, "--repo-root <ROOT>")
|
|
47
|
+
.replace(/(?:\/private)?\/var\/folders\/[^\s"')]+\/swarm-[^\s"')]+/g, "<TMP>")
|
|
47
48
|
.replace(/\/tmp\/[^\s]+/g, "<TMP>")
|
|
48
49
|
.replace(/\/home\/[^\s]+/g, "<PATH>")
|
|
49
50
|
.trim()
|
|
@@ -15,6 +15,7 @@ import { cachePut } from "@deftai/directive-core/dist/cache/operations.js";
|
|
|
15
15
|
/** Strip volatile UUIDs and timestamps before compare. */
|
|
16
16
|
export function normalizeOutput(text) {
|
|
17
17
|
return text
|
|
18
|
+
.replace(/(?:\/private)?\/(?:tmp|var\/folders\/[^\s"']+\/T)\/deft-triage-actions-parity-[^/\s"']+/g, "<FIXTURE>")
|
|
18
19
|
.replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g, "<UUID>")
|
|
19
20
|
.replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/g, "<TS>")
|
|
20
21
|
.replace(/Using CPython[^\n]*\n/g, "")
|
|
@@ -16,7 +16,12 @@ export function normalizeOutput(text) {
|
|
|
16
16
|
return text
|
|
17
17
|
.replace(/project_root=[^\s)"]+/g, "project_root=<ROOT>")
|
|
18
18
|
.replace(/"project_root": "[^"]+"/g, '"project_root": "<ROOT>"')
|
|
19
|
-
.replace(/\/tmp\/[^\s"']+/g, "<TMP>")
|
|
19
|
+
.replace(/\/tmp\/[^\s"']+/g, "<TMP>")
|
|
20
|
+
.replace(/(?:\/private)?\/var\/folders\/[^\s"']+/g, "<TMP>")
|
|
21
|
+
.replace(/^WARN [^\n]*\n/gm, "")
|
|
22
|
+
.replace(/Using CPython[^\n]*\n/g, "")
|
|
23
|
+
.replace(/Creating virtual environment[^\n]*\n/g, "")
|
|
24
|
+
.replace(/Installed \d+ packages[^\n]*\n/g, "");
|
|
20
25
|
}
|
|
21
26
|
function runCapture(cmd, args, cwd) {
|
|
22
27
|
const result = spawnSync(cmd, args, {
|
|
@@ -39,7 +44,7 @@ function resolveDeftRoot() {
|
|
|
39
44
|
}
|
|
40
45
|
export { resolveDeftRoot };
|
|
41
46
|
function runPython(deftRoot, script, repo, argv) {
|
|
42
|
-
const cap = runCapture("
|
|
47
|
+
const cap = runCapture("uv", ["run", "python", join(deftRoot, "scripts", script), ...argv, "--project-root", repo], deftRoot);
|
|
43
48
|
return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
|
|
44
49
|
}
|
|
45
50
|
function runTs(deftRoot, cli, repo, argv) {
|
|
@@ -14,7 +14,9 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
const DEFAULT_REPO = "owner/repo";
|
|
15
15
|
/** Strip volatile absolute paths before compare. */
|
|
16
16
|
export function normalizeOutput(text) {
|
|
17
|
-
return text
|
|
17
|
+
return text
|
|
18
|
+
.replace(/^WARN [^\n]*\n/gm, "")
|
|
19
|
+
.replace(/project_root=[^\s)]+/g, "project_root=<ROOT>");
|
|
18
20
|
}
|
|
19
21
|
function runCapture(cmd, args, cwd, env = {}) {
|
|
20
22
|
const merged = { ...process.env, ...env };
|
|
@@ -17,6 +17,7 @@ export interface ParityResult {
|
|
|
17
17
|
readonly tsOutput: string;
|
|
18
18
|
}>;
|
|
19
19
|
}
|
|
20
|
+
export declare function normalizeOutput(text: string): string;
|
|
20
21
|
export declare function runParity(): ParityResult;
|
|
21
22
|
export declare function renderReport(result: ParityResult): string;
|
|
22
23
|
//# sourceMappingURL=vbrief-reconcile-parity.d.ts.map
|
|
@@ -241,6 +241,11 @@ function resolveDeftRoot() {
|
|
|
241
241
|
return resolve(process.env.DEFT_ROOT);
|
|
242
242
|
return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
243
243
|
}
|
|
244
|
+
export function normalizeOutput(text) {
|
|
245
|
+
return text
|
|
246
|
+
.replace(/(?:\/private)?\/var\/folders\/[^\s"')]+\/deft-vbrief-reconcile-[^\s"')]+/g, "<TMP>")
|
|
247
|
+
.replace(/\/tmp\/deft-vbrief-reconcile-[^\s"')]+/g, "<TMP>");
|
|
248
|
+
}
|
|
244
249
|
function installPythonDriver() {
|
|
245
250
|
const dir = mkdtempSync(join(tmpdir(), "deft-vbrief-reconcile-driver-"));
|
|
246
251
|
const driverPath = join(dir, "vbrief_reconcile_parity_driver.py");
|
|
@@ -543,14 +548,18 @@ export function runParity() {
|
|
|
543
548
|
else {
|
|
544
549
|
ran = runLabelsUmbrellasParity(deftRoot, name, env);
|
|
545
550
|
}
|
|
551
|
+
const pythonStdout = normalizeOutput(ran.python.stdout);
|
|
552
|
+
const pythonStderr = normalizeOutput(ran.python.stderr);
|
|
553
|
+
const tsStdout = normalizeOutput(ran.ts.stdout);
|
|
554
|
+
const tsStderr = normalizeOutput(ran.ts.stderr);
|
|
546
555
|
scenarios.push({
|
|
547
556
|
name,
|
|
548
557
|
pythonExit: ran.python.exitCode,
|
|
549
558
|
tsExit: ran.ts.exitCode,
|
|
550
559
|
exitMismatch: ran.python.exitCode !== ran.ts.exitCode,
|
|
551
|
-
outputMismatch:
|
|
552
|
-
pythonOutput:
|
|
553
|
-
tsOutput:
|
|
560
|
+
outputMismatch: pythonStdout !== tsStdout || pythonStderr !== tsStderr,
|
|
561
|
+
pythonOutput: pythonStdout || pythonStderr,
|
|
562
|
+
tsOutput: tsStdout || tsStderr,
|
|
554
563
|
});
|
|
555
564
|
}
|
|
556
565
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Directive CLI — npm install path for the Deft Directive framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"provenance": true
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@deftai/directive-core": "^0.
|
|
46
|
-
"@deftai/directive-content": "^0.
|
|
45
|
+
"@deftai/directive-core": "^0.58.0",
|
|
46
|
+
"@deftai/directive-content": "^0.58.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsc -b"
|