@deftai/directive 0.56.1 → 0.57.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.
@@ -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
package/dist/cache.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { main } from "../../core/dist/cache/main.js";
2
+ import { main } from "@deftai/directive-core/dist/cache/main.js";
3
3
  export { main };
4
4
  //# sourceMappingURL=cache.d.ts.map
package/dist/cache.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { main } from "../../core/dist/cache/main.js";
3
+ import { main } from "@deftai/directive-core/dist/cache/main.js";
4
4
  /* v8 ignore start -- entry guard; behaviour covered via main() unit tests */
5
5
  if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
6
6
  process.exit(main(process.argv.slice(2)));
@@ -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] };
@@ -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",
@@ -343,55 +345,55 @@ function loadPythonScriptHandler(scriptName) {
343
345
  async function loadCoreModuleHandler(verb, io) {
344
346
  switch (verb) {
345
347
  case "scm": {
346
- const { main } = await import("../../core/dist/scm/main.js");
348
+ const { main } = await import("@deftai/directive-core/dist/scm/main.js");
347
349
  return (argv) => main(argv);
348
350
  }
349
351
  case "github-auth-modes": {
350
- const { mainEntry } = await import("../../core/dist/intake/github-auth-modes-cli.js");
352
+ const { mainEntry } = await import("@deftai/directive-core/dist/intake/github-auth-modes-cli.js");
351
353
  return mainEntry;
352
354
  }
353
355
  case "github-body": {
354
- const { mainEntry } = await import("../../core/dist/intake/github-body-cli.js");
356
+ const { mainEntry } = await import("@deftai/directive-core/dist/intake/github-body-cli.js");
355
357
  return mainEntry;
356
358
  }
357
359
  case "issue-emit": {
358
- const { mainEntry } = await import("../../core/dist/intake/issue-emit-cli.js");
360
+ const { mainEntry } = await import("@deftai/directive-core/dist/intake/issue-emit-cli.js");
359
361
  return mainEntry;
360
362
  }
361
363
  case "issue-ingest": {
362
- const { mainEntry } = await import("../../core/dist/intake/issue-ingest-cli.js");
364
+ const { mainEntry } = await import("@deftai/directive-core/dist/intake/issue-ingest-cli.js");
363
365
  return mainEntry;
364
366
  }
365
367
  case "reconcile-issues": {
366
- const { mainEntry } = await import("../../core/dist/intake/reconcile-issues-cli.js");
368
+ const { mainEntry } = await import("@deftai/directive-core/dist/intake/reconcile-issues-cli.js");
367
369
  return mainEntry;
368
370
  }
369
371
  case "swarm-launch": {
370
- const { launchMain } = await import("../../core/dist/swarm/launch-cli.js");
372
+ const { launchMain } = await import("@deftai/directive-core/dist/swarm/launch-cli.js");
371
373
  return launchMain;
372
374
  }
373
375
  case "swarm-complete-cohort": {
374
- const { completeCohortMain } = await import("../../core/dist/swarm/complete-cohort-cli.js");
376
+ const { completeCohortMain } = await import("@deftai/directive-core/dist/swarm/complete-cohort-cli.js");
375
377
  return completeCohortMain;
376
378
  }
377
379
  case "swarm-readiness": {
378
- const { readinessMain } = await import("../../core/dist/swarm/readiness-cli.js");
380
+ const { readinessMain } = await import("@deftai/directive-core/dist/swarm/readiness-cli.js");
379
381
  return readinessMain;
380
382
  }
381
383
  case "swarm-routing-verify": {
382
- const { routingVerifyMain } = await import("../../core/dist/swarm/routing-verify-cli.js");
384
+ const { routingVerifyMain } = await import("@deftai/directive-core/dist/swarm/routing-verify-cli.js");
383
385
  return routingVerifyMain;
384
386
  }
385
387
  case "swarm-routing-set": {
386
- const { routingSetMain } = await import("../../core/dist/swarm/routing-set-cli.js");
388
+ const { routingSetMain } = await import("@deftai/directive-core/dist/swarm/routing-set-cli.js");
387
389
  return routingSetMain;
388
390
  }
389
391
  case "swarm-verify-review-clean": {
390
- const { verifyReviewCleanMain } = await import("../../core/dist/swarm/verify-review-clean-cli.js");
392
+ const { verifyReviewCleanMain } = await import("@deftai/directive-core/dist/swarm/verify-review-clean-cli.js");
391
393
  return verifyReviewCleanMain;
392
394
  }
393
395
  case "swarm-worktrees": {
394
- const { worktreesMain } = await import("../../core/dist/swarm/worktrees-cli.js");
396
+ const { worktreesMain } = await import("@deftai/directive-core/dist/swarm/worktrees-cli.js");
395
397
  return worktreesMain;
396
398
  }
397
399
  case "framework-commands": {
@@ -399,15 +401,15 @@ async function loadCoreModuleHandler(verb, io) {
399
401
  return (argv) => frameworkCommandsMain(argv);
400
402
  }
401
403
  case "pack-render": {
402
- const { main } = await import("../../core/dist/packs/pack-render.js");
404
+ const { main } = await import("@deftai/directive-core/dist/packs/pack-render.js");
403
405
  return (argv) => main([...argv]);
404
406
  }
405
407
  case "packs-slice": {
406
- const { main } = await import("../../core/dist/packs/packs-slice.js");
408
+ const { main } = await import("@deftai/directive-core/dist/packs/packs-slice.js");
407
409
  return (argv) => main([...argv]);
408
410
  }
409
411
  case "roadmap-render": {
410
- const { main } = await import("../../core/dist/render/roadmap-render.js");
412
+ const { main } = await import("@deftai/directive-core/dist/render/roadmap-render.js");
411
413
  return (argv) => main(argv);
412
414
  }
413
415
  case "spec-validate": {
@@ -459,23 +461,23 @@ async function loadCoreModuleHandler(verb, io) {
459
461
  case "policy-set":
460
462
  return loadPythonScriptHandler("policy_set.py");
461
463
  case "scope-undo": {
462
- const { undoMain } = await import("../../core/dist/scope/main.js");
464
+ const { undoMain } = await import("@deftai/directive-core/dist/scope/main.js");
463
465
  return undoMain;
464
466
  }
465
467
  case "scope-demote": {
466
- const { demoteMain } = await import("../../core/dist/scope/main.js");
468
+ const { demoteMain } = await import("@deftai/directive-core/dist/scope/main.js");
467
469
  return demoteMain;
468
470
  }
469
471
  case "scope-decompose": {
470
- const { decomposeMain } = await import("../../core/dist/scope/decompose.js");
472
+ const { decomposeMain } = await import("@deftai/directive-core/dist/scope/decompose.js");
471
473
  return decomposeMain;
472
474
  }
473
475
  case "changelog-resolve-unreleased": {
474
- const { changelogResolveUnreleasedMain } = await import("../../core/dist/platform/changelog-cli.js");
476
+ const { changelogResolveUnreleasedMain } = await import("@deftai/directive-core/dist/platform/changelog-cli.js");
475
477
  return changelogResolveUnreleasedMain;
476
478
  }
477
479
  case "architecture-preflight-sor": {
478
- const { architecturePreflightSorMain } = await import("../../core/dist/architecture/sor-preflight.js");
480
+ const { architecturePreflightSorMain } = await import("@deftai/directive-core/dist/architecture/sor-preflight.js");
479
481
  return architecturePreflightSorMain;
480
482
  }
481
483
  default:
@@ -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
package/dist/doctor.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdDoctor } from "../../core/dist/doctor/main.js";
3
+ import { cmdDoctor } from "@deftai/directive-core/dist/doctor/main.js";
4
4
  export function run(argv) {
5
5
  return cmdDoctor(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdPrCheckClosingKeywords } from "../../core/dist/pr-closing-keywords/main.js";
3
+ import { cmdPrCheckClosingKeywords } from "@deftai/directive-core/dist/pr-closing-keywords/main.js";
4
4
  export function run(argv) {
5
5
  return cmdPrCheckClosingKeywords(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdPrMergeReadiness } from "../../core/dist/pr-merge-readiness/main.js";
3
+ import { cmdPrMergeReadiness } from "@deftai/directive-core/dist/pr-merge-readiness/main.js";
4
4
  export function run(argv) {
5
5
  return cmdPrMergeReadiness(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdPrMonitor } from "../../core/dist/pr-monitor/main.js";
3
+ import { cmdPrMonitor } from "@deftai/directive-core/dist/pr-monitor/main.js";
4
4
  export function run(argv) {
5
5
  return cmdPrMonitor(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdPrProtectedIssues } from "../../core/dist/pr-protected-issues/main.js";
3
+ import { cmdPrProtectedIssues } from "@deftai/directive-core/dist/pr-protected-issues/main.js";
4
4
  export function run(argv) {
5
5
  return cmdPrProtectedIssues(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdPrWaitMergeable } from "../../core/dist/pr-wait-mergeable/main.js";
3
+ import { cmdPrWaitMergeable } from "@deftai/directive-core/dist/pr-wait-mergeable/main.js";
4
4
  export function run(argv) {
5
5
  return cmdPrWaitMergeable(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdReleaseE2e } from "../../core/dist/release-e2e/main.js";
3
+ import { cmdReleaseE2e } from "@deftai/directive-core/dist/release-e2e/main.js";
4
4
  export function run(argv) {
5
5
  return cmdReleaseE2e(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdReleasePublish } from "../../core/dist/release-publish/main.js";
3
+ import { cmdReleasePublish } from "@deftai/directive-core/dist/release-publish/main.js";
4
4
  export function run(argv) {
5
5
  return cmdReleasePublish(argv);
6
6
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdRollback } from "../../core/dist/release-rollback/main.js";
3
+ import { cmdRollback } from "@deftai/directive-core/dist/release-rollback/main.js";
4
4
  export function run(argv) {
5
5
  return cmdRollback(argv);
6
6
  }
package/dist/release.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { cmdRelease } from "../../core/dist/release/main.js";
3
+ import { cmdRelease } from "@deftai/directive-core/dist/release/main.js";
4
4
  export function run(argv) {
5
5
  return cmdRelease(argv);
6
6
  }
@@ -4,10 +4,15 @@
4
4
  * Delegates to packages/core/dist/scope/cli.js.
5
5
  */
6
6
  import { spawnSync } from "node:child_process";
7
- import { dirname, join } from "node:path";
7
+ import { createRequire } from "node:module";
8
8
  import { fileURLToPath } from "node:url";
9
+ const require = createRequire(import.meta.url);
10
+ // Resolve the core CLI by its published package name so it works both in the
11
+ // source monorepo and under a flattened npm install (#1993). The bare specifier
12
+ // resolves via @deftai/directive-core's "./dist/*.js" export map; a hand-built
13
+ // relative path would point at the non-existent "@deftai/core" once published.
9
14
  function coreCliPath() {
10
- return join(dirname(fileURLToPath(import.meta.url)), "../../core/dist/scope/cli.js");
15
+ return require.resolve("@deftai/directive-core/dist/scope/cli.js");
11
16
  }
12
17
  /** Run scope lifecycle with argv; returns process exit code. */
13
18
  export function run(argv) {
package/dist/slice.js CHANGED
@@ -4,10 +4,15 @@
4
4
  * Delegates to the core implementation at packages/core/dist/slice/cli.js.
5
5
  */
6
6
  import { spawnSync } from "node:child_process";
7
- import { dirname, join } from "node:path";
7
+ import { createRequire } from "node:module";
8
8
  import { fileURLToPath } from "node:url";
9
+ const require = createRequire(import.meta.url);
10
+ // Resolve the core CLI by its published package name so it works both in the
11
+ // source monorepo and under a flattened npm install (#1993). The bare specifier
12
+ // resolves via @deftai/directive-core's "./dist/*.js" export map; a hand-built
13
+ // relative path would point at the non-existent "@deftai/core" once published.
9
14
  function coreCliPath() {
10
- return join(dirname(fileURLToPath(import.meta.url)), "../../core/dist/slice/cli.js");
15
+ return require.resolve("@deftai/directive-core/dist/slice/cli.js");
11
16
  }
12
17
  /** Run slice verbs with argv; returns process exit code. */
13
18
  export function run(argv) {
@@ -11,7 +11,7 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
11
11
  import { tmpdir } from "node:os";
12
12
  import { dirname, join, resolve } from "node:path";
13
13
  import { fileURLToPath } from "node:url";
14
- import { cachePut } from "../../core/dist/cache/operations.js";
14
+ 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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { accept, createDefaultDeps, deferAction, formatDecision, history, markDuplicate, needsAc, reject, reset, status, TriageError, UpstreamCloseError, } from "../../core/dist/triage/actions/index.js";
4
+ import { accept, createDefaultDeps, deferAction, formatDecision, history, markDuplicate, needsAc, reject, reset, status, TriageError, UpstreamCloseError, } from "@deftai/directive-core/dist/triage/actions/index.js";
5
5
  const VALID_CMDS = new Set([
6
6
  "accept",
7
7
  "reject",
@@ -13,7 +13,7 @@ export interface ParsedArgs {
13
13
  emitJson: boolean;
14
14
  error?: string;
15
15
  }
16
- type BootstrapModule = typeof import("../../core/dist/triage/bootstrap/index.js");
16
+ type BootstrapModule = typeof import("@deftai/directive-core/dist/triage/bootstrap/index.js");
17
17
  /** Parse triage-bootstrap CLI args, mirroring the Python argparse surface. */
18
18
  export declare function parseArgs(argv: string[]): ParsedArgs;
19
19
  /** Run triage:bootstrap with an injected core module (test seam). */
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { statSync } from "node:fs";
3
- import { dirname, join, resolve } from "node:path";
4
- import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import { resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
5
  async function loadBootstrapModule() {
6
- const corePath = join(dirname(fileURLToPath(import.meta.url)), "../../core/dist/triage/bootstrap/index.js");
7
- return import(pathToFileURL(corePath).href);
6
+ // Direct dynamic import of the published package subpath -- resolves via core's
7
+ // "./dist/*.js" export map in both the monorepo and a flat npm install (#1993).
8
+ // The prior hand-built relative path broke once published (and my mechanical
9
+ // import rewrite turned it into a non-existent path under packages/cli/dist).
10
+ return import("@deftai/directive-core/dist/triage/bootstrap/index.js");
8
11
  }
9
12
  /** Parse triage-bootstrap CLI args, mirroring the Python argparse surface. */
10
13
  export function parseArgs(argv) {
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { bulkActionWithDefaults, CacheEmptyError } from "../../core/dist/triage/bulk/index.js";
5
- import { interceptHelp } from "../../core/dist/triage/help/index.js";
4
+ import { bulkActionWithDefaults, CacheEmptyError, } from "@deftai/directive-core/dist/triage/bulk/index.js";
5
+ import { interceptHelp } from "@deftai/directive-core/dist/triage/help/index.js";
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
8
8
  action: "",
@@ -2,7 +2,7 @@
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { listProject, validateProject } from "../../core/dist/triage/classify/index.js";
5
+ import { listProject, validateProject } from "@deftai/directive-core/dist/triage/classify/index.js";
6
6
  /** Parse triage-classify CLI args, mirroring the Python argparse surface. */
7
7
  export function parseArgs(argv) {
8
8
  const parsed = {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { runHelp } from "../../core/dist/triage/help/index.js";
3
+ import { runHelp } from "@deftai/directive-core/dist/triage/help/index.js";
4
4
  export function run(argv) {
5
5
  return runHelp(argv);
6
6
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { dirname, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { activeReferencedIssueNumbers, buildQueue, collectOrphanIssueNumbers, DEFAULT_QUEUE_LIMIT, loadCachedIssues, loadSliceRecords, readAuditEntries, renderQueue, resolveRankingLabels, resolveRepo, } from "../../core/dist/triage/queue/index.js";
4
+ import { activeReferencedIssueNumbers, buildQueue, collectOrphanIssueNumbers, DEFAULT_QUEUE_LIMIT, loadCachedIssues, loadSliceRecords, readAuditEntries, renderQueue, resolveRankingLabels, resolveRepo, } from "@deftai/directive-core/dist/triage/queue/index.js";
5
5
  /** Parse triage-queue CLI args for the queue subcommand. */
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
@@ -2,7 +2,7 @@
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { emitReconcileJson, reconcile, reconcileSummary, } from "../../core/dist/triage/reconcile/index.js";
5
+ import { emitReconcileJson, reconcile, reconcileSummary, } from "@deftai/directive-core/dist/triage/reconcile/index.js";
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
8
8
  projectRoot: process.env.DEFT_PROJECT_ROOT ?? ".",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { refreshActive } from "../../core/dist/triage/refresh/index.js";
4
+ import { refreshActive } from "@deftai/directive-core/dist/triage/refresh/index.js";
5
5
  export function parseArgs(argv) {
6
6
  let projectRoot = ".";
7
7
  for (let i = 0; i < argv.length; i += 1) {
@@ -2,7 +2,7 @@
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { addIgnore, computeDrift, renderDriftReport, } from "../../core/dist/triage/scope-drift/index.js";
5
+ import { addIgnore, computeDrift, renderDriftReport, } from "@deftai/directive-core/dist/triage/scope-drift/index.js";
6
6
  export function parseArgs(argv) {
7
7
  const parsed = { projectRoot: process.env.DEFT_PROJECT_ROOT ?? "." };
8
8
  for (let i = 0; i < argv.length; i += 1) {
@@ -4,10 +4,15 @@
4
4
  * Delegates to the core implementation at packages/core/dist/triage/scope/cli.js.
5
5
  */
6
6
  import { spawnSync } from "node:child_process";
7
- import { dirname, join } from "node:path";
7
+ import { createRequire } from "node:module";
8
8
  import { fileURLToPath } from "node:url";
9
+ const require = createRequire(import.meta.url);
10
+ // Resolve the core CLI by its published package name so it works both in the
11
+ // source monorepo and under a flattened npm install (#1993). The bare specifier
12
+ // resolves via @deftai/directive-core's "./dist/*.js" export map; a hand-built
13
+ // relative path would point at the non-existent "@deftai/core" once published.
9
14
  function coreCliPath() {
10
- return join(dirname(fileURLToPath(import.meta.url)), "../../core/dist/triage/scope/cli.js");
15
+ return require.resolve("@deftai/directive-core/dist/triage/scope/cli.js");
11
16
  }
12
17
  /** Run triage:scope with argv; returns process exit code. */
13
18
  export function run(argv) {
@@ -2,8 +2,8 @@
2
2
  import { existsSync, statSync } from "node:fs";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { interceptHelp } from "../../core/dist/triage/help/index.js";
6
- import { DEFAULT_FIXTURE_REL, parseSmoketestArgs, runSmoketest, } from "../../core/dist/triage/smoketest/index.js";
5
+ import { interceptHelp } from "@deftai/directive-core/dist/triage/help/index.js";
6
+ import { DEFAULT_FIXTURE_REL, parseSmoketestArgs, runSmoketest, } from "@deftai/directive-core/dist/triage/smoketest/index.js";
7
7
  function resolveDeftRoot() {
8
8
  if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
9
9
  return resolve(process.env.DEFT_ROOT);
@@ -2,8 +2,8 @@
2
2
  import { existsSync, statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { interceptHelp } from "../../core/dist/triage/help/index.js";
6
- import { RECONCILE_HINT, subscribe, unsubscribe } from "../../core/dist/triage/subscribe/index.js";
5
+ import { interceptHelp } from "@deftai/directive-core/dist/triage/help/index.js";
6
+ import { RECONCILE_HINT, subscribe, unsubscribe, } from "@deftai/directive-core/dist/triage/subscribe/index.js";
7
7
  export function parseArgs(argv) {
8
8
  const parsed = {
9
9
  op: "",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { appendHistory, computeSummary, formatSummary, pythonStyleStringify, SUMMARY_HISTORY_REL_PATH, summaryResultToRecord, utcIso, } from "../../core/dist/triage/summary/index.js";
4
+ import { appendHistory, computeSummary, formatSummary, pythonStyleStringify, SUMMARY_HISTORY_REL_PATH, summaryResultToRecord, utcIso, } from "@deftai/directive-core/dist/triage/summary/index.js";
5
5
  /** Parse triage-summary CLI args, mirroring the Python argparse surface. */
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
@@ -2,7 +2,7 @@
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { runDefaultMode } from "../../core/dist/triage/welcome/default-mode.js";
5
+ import { runDefaultMode } from "@deftai/directive-core/dist/triage/welcome/default-mode.js";
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
8
8
  projectRoot: process.env.DEFT_PROJECT_ROOT ?? ".",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.56.1",
3
+ "version": "0.57.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.56.1",
46
- "@deftai/directive-content": "^0.56.1"
45
+ "@deftai/directive-core": "^0.57.0",
46
+ "@deftai/directive-content": "^0.57.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsc -b"