@deftai/directive 0.79.3 → 0.79.4

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,18 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ coverageDir: string | null;
5
+ minHeadroomPp: number | null;
6
+ baseRef: string | null;
7
+ pathFilter: string[];
8
+ useDiffPaths: boolean;
9
+ json: boolean;
10
+ quiet: boolean;
11
+ error?: string;
12
+ }
13
+ /** Parse coverage-hotspots CLI args. */
14
+ export declare function parseArgs(argv: string[]): ParsedArgs;
15
+ /** Run coverage-hotspots and return the process exit code. */
16
+ export declare function run(argv: string[]): number;
17
+ export {};
18
+ //# sourceMappingURL=coverage-hotspots.d.ts.map
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { evaluateCoverageHotspots, formatJsonReport } from "@deftai/directive-core";
5
+ function parseNumber(raw) {
6
+ const value = Number.parseFloat(raw);
7
+ if (!Number.isFinite(value)) {
8
+ return null;
9
+ }
10
+ return value;
11
+ }
12
+ /** Parse coverage-hotspots CLI args. */
13
+ export function parseArgs(argv) {
14
+ const parsed = {
15
+ projectRoot: ".",
16
+ coverageDir: null,
17
+ minHeadroomPp: null,
18
+ baseRef: null,
19
+ pathFilter: [],
20
+ useDiffPaths: true,
21
+ json: false,
22
+ quiet: false,
23
+ };
24
+ for (let i = 0; i < argv.length; i += 1) {
25
+ const arg = argv[i];
26
+ if (arg === "--json") {
27
+ parsed.json = true;
28
+ }
29
+ else if (arg === "--quiet") {
30
+ parsed.quiet = true;
31
+ }
32
+ else if (arg === "--no-diff-filter") {
33
+ parsed.useDiffPaths = false;
34
+ }
35
+ else if (arg === "--project-root") {
36
+ const value = argv[i + 1];
37
+ if (value === undefined) {
38
+ return { ...parsed, error: "argument --project-root: expected one argument" };
39
+ }
40
+ parsed.projectRoot = value;
41
+ i += 1;
42
+ }
43
+ else if (arg?.startsWith("--project-root=")) {
44
+ parsed.projectRoot = arg.slice("--project-root=".length);
45
+ }
46
+ else if (arg === "--coverage-dir") {
47
+ const value = argv[i + 1];
48
+ if (value === undefined) {
49
+ return { ...parsed, error: "argument --coverage-dir: expected one argument" };
50
+ }
51
+ parsed.coverageDir = value;
52
+ i += 1;
53
+ }
54
+ else if (arg?.startsWith("--coverage-dir=")) {
55
+ parsed.coverageDir = arg.slice("--coverage-dir=".length);
56
+ }
57
+ else if (arg === "--min-headroom-pp") {
58
+ const value = argv[i + 1];
59
+ if (value === undefined) {
60
+ return { ...parsed, error: "argument --min-headroom-pp: expected one argument" };
61
+ }
62
+ const num = parseNumber(value);
63
+ if (num === null) {
64
+ return { ...parsed, error: "argument --min-headroom-pp: expected a number" };
65
+ }
66
+ parsed.minHeadroomPp = num;
67
+ i += 1;
68
+ }
69
+ else if (arg?.startsWith("--min-headroom-pp=")) {
70
+ const num = parseNumber(arg.slice("--min-headroom-pp=".length));
71
+ if (num === null) {
72
+ return { ...parsed, error: "argument --min-headroom-pp: expected a number" };
73
+ }
74
+ parsed.minHeadroomPp = num;
75
+ }
76
+ else if (arg === "--base-ref") {
77
+ const value = argv[i + 1];
78
+ if (value === undefined) {
79
+ return { ...parsed, error: "argument --base-ref: expected one argument" };
80
+ }
81
+ parsed.baseRef = value;
82
+ i += 1;
83
+ }
84
+ else if (arg?.startsWith("--base-ref=")) {
85
+ parsed.baseRef = arg.slice("--base-ref=".length);
86
+ }
87
+ else if (arg === "--path" || arg === "--paths") {
88
+ const value = argv[i + 1];
89
+ if (value === undefined) {
90
+ return { ...parsed, error: `argument ${arg}: expected one argument` };
91
+ }
92
+ parsed.pathFilter.push(...value
93
+ .split(",")
94
+ .map((part) => part.trim())
95
+ .filter(Boolean));
96
+ parsed.useDiffPaths = false;
97
+ i += 1;
98
+ }
99
+ else if (arg?.startsWith("--path=") || arg?.startsWith("--paths=")) {
100
+ const prefix = arg.startsWith("--path=") ? "--path=" : "--paths=";
101
+ parsed.pathFilter.push(...arg
102
+ .slice(prefix.length)
103
+ .split(",")
104
+ .map((part) => part.trim())
105
+ .filter(Boolean));
106
+ parsed.useDiffPaths = false;
107
+ }
108
+ else {
109
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
110
+ }
111
+ }
112
+ return parsed;
113
+ }
114
+ /** Run coverage-hotspots and return the process exit code. */
115
+ export function run(argv) {
116
+ const args = parseArgs(argv);
117
+ if (args.error !== undefined) {
118
+ process.stderr.write(`coverage-hotspots: ${args.error}\n`);
119
+ return 2;
120
+ }
121
+ const projectRoot = resolve(args.projectRoot);
122
+ const result = evaluateCoverageHotspots({
123
+ projectRoot,
124
+ coverageDir: args.coverageDir ?? undefined,
125
+ minHeadroomPp: args.minHeadroomPp ?? undefined,
126
+ baseRef: args.baseRef,
127
+ pathFilter: args.pathFilter.length > 0 ? args.pathFilter : null,
128
+ useDiffPaths: args.useDiffPaths,
129
+ });
130
+ if (result.exitCode === 2 || result.report === null) {
131
+ process.stderr.write(`${result.message}\n`);
132
+ return result.exitCode;
133
+ }
134
+ const payload = args.json ? formatJsonReport(result.report) : result.message;
135
+ if (result.exitCode === 0) {
136
+ if (!args.quiet) {
137
+ process.stdout.write(payload);
138
+ }
139
+ }
140
+ else {
141
+ process.stderr.write(payload);
142
+ }
143
+ return result.exitCode;
144
+ }
145
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
146
+ process.exit(run(process.argv.slice(2)));
147
+ }
148
+ //# sourceMappingURL=coverage-hotspots.js.map
@@ -10,7 +10,7 @@ export interface DispatchIo {
10
10
  writeErr: (text: string) => void;
11
11
  }
12
12
  /** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
13
- 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", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "lifecycle-event", "session-start", "plan-sequence", "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-forward-coverage", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-contract-drift", "verify-cursor-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "review-monitor-register", "verify-tools", "verify-wip-cap", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
13
+ 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", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "coverage-hotspots", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "lifecycle-event", "session-start", "plan-sequence", "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-forward-coverage", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-contract-drift", "verify-cursor-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "review-monitor-register", "verify-tools", "verify-wip-cap", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
14
14
  /** Core-only CLI entrypoints without a packages/cli wrapper. */
15
15
  export declare const CORE_MODULE_VERBS: readonly ["scm", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "issue-sync-from-xbrief", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "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", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor", "feedback-file", "value-readback"];
16
16
  /** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
package/dist/dispatch.js CHANGED
@@ -46,6 +46,7 @@ export const CLI_MODULE_VERBS = [
46
46
  "changelog-check",
47
47
  "change-init",
48
48
  "commit-lint",
49
+ "coverage-hotspots",
49
50
  "policy",
50
51
  "pr-closing-keywords",
51
52
  "pr-merge-readiness",
@@ -199,6 +200,7 @@ export const VERB_ALIASES = {
199
200
  "hook:dispatch": "hook-dispatch",
200
201
  "verify:encoding": "verify-encoding",
201
202
  "verify:forward-coverage": "verify-forward-coverage",
203
+ "coverage:hotspots": "coverage-hotspots",
202
204
  "verify:branch": "verify-branch",
203
205
  "verify:vbrief-conformance": "vbrief-validate",
204
206
  "verify:wip-cap": "verify-wip-cap",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { type HookEvent, type HookHost } from "@deftai/directive-core/hooks";
2
+ import { type HookEvent, type HookHost, type HookPayloadContext } from "@deftai/directive-core/hooks";
3
3
  interface ParsedArgs {
4
4
  host?: HookHost;
5
5
  event?: HookEvent;
@@ -13,6 +13,11 @@ export interface HookDispatchCliSeams {
13
13
  readonly cwd?: () => string;
14
14
  }
15
15
  export declare function parseArgs(argv: readonly string[]): ParsedArgs;
16
+ export interface ParsedPayload {
17
+ readonly payload: unknown;
18
+ readonly context: HookPayloadContext;
19
+ }
20
+ export declare function parsePayload(raw: string): ParsedPayload;
16
21
  export declare function run(argv: string[], seams?: HookDispatchCliSeams): number;
17
22
  export {};
18
23
  //# sourceMappingURL=hook-dispatch.d.ts.map
@@ -2,7 +2,7 @@
2
2
  import { readFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { decideHook, isHookEvent, isHookHost, projectRootFromHookPayload, renderHostDecision, } from "@deftai/directive-core/hooks";
5
+ import { decideHook, hookPayloadTopLevelKeys, isHookEvent, isHookHost, projectRootFromHookPayload, renderHostDecision, } from "@deftai/directive-core/hooks";
6
6
  function takeValue(argv, index, flag) {
7
7
  const token = argv[index];
8
8
  const prefix = `${flag}=`;
@@ -57,16 +57,17 @@ export function parseArgs(argv) {
57
57
  return { error: "--event is required" };
58
58
  return parsed;
59
59
  }
60
- function parsePayload(raw) {
61
- if (raw.trim().length === 0)
62
- return {};
60
+ export function parsePayload(raw) {
61
+ if (raw.trim().length === 0) {
62
+ return { payload: {}, context: { stdinEmpty: true } };
63
+ }
63
64
  try {
64
- return JSON.parse(raw);
65
+ return { payload: JSON.parse(raw), context: {} };
65
66
  }
66
67
  catch {
67
68
  // tool.before is installed only on direct-write matchers, so an unreadable
68
69
  // payload becomes a missing-tool denial rather than a fail-open crash.
69
- return {};
70
+ return { payload: {}, context: { parseFailed: true } };
70
71
  }
71
72
  }
72
73
  export function run(argv, seams = {}) {
@@ -79,7 +80,7 @@ export function run(argv, seams = {}) {
79
80
  }
80
81
  const readStdin = seams.readStdin ?? (() => readFileSync(0, "utf8"));
81
82
  const cwd = (seams.cwd ?? process.cwd)();
82
- const payload = parsePayload(readStdin());
83
+ const { payload, context: payloadContext } = parsePayload(readStdin());
83
84
  const projectRoot = args.projectRoot
84
85
  ? resolve(args.projectRoot)
85
86
  : projectRootFromHookPayload(payload, cwd);
@@ -88,10 +89,18 @@ export function run(argv, seams = {}) {
88
89
  event: args.event,
89
90
  projectRoot,
90
91
  payload,
92
+ payloadContext,
91
93
  });
92
94
  const rendered = renderHostDecision(args.host, decision);
93
95
  if (rendered.length > 0)
94
96
  writeOut(`${rendered}\n`);
97
+ if (decision.code === "invalid-input" && args.host === "cursor") {
98
+ // Keys are already embedded in decision.message; stderr helps operators tailing logs.
99
+ const keys = hookPayloadTopLevelKeys(payload);
100
+ if (keys.length > 0) {
101
+ writeErr(`Directive hook diagnostic: payload top-level keys: ${keys.join(", ")}\n`);
102
+ }
103
+ }
95
104
  if (decision.code === "session-start-degraded")
96
105
  writeErr(`${decision.message}\n`);
97
106
  return 0;
@@ -19,6 +19,9 @@ export function parseArgs(argv) {
19
19
  };
20
20
  for (let i = 0; i < argv.length; i += 1) {
21
21
  const arg = argv[i];
22
+ if (arg === "--") {
23
+ continue;
24
+ }
22
25
  if (arg === "--json") {
23
26
  parsed.emitJson = true;
24
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.79.3",
3
+ "version": "0.79.4",
4
4
  "description": "Directive CLI — npm install path for the Deft Directive framework.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,8 +31,8 @@
31
31
  "provenance": true
32
32
  },
33
33
  "dependencies": {
34
- "@deftai/directive-core": "^0.79.3",
35
- "@deftai/directive-content": "^0.79.3"
34
+ "@deftai/directive-core": "^0.79.4",
35
+ "@deftai/directive-content": "^0.79.4"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -b"