@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.
Files changed (261) hide show
  1. package/dist/bin.d.ts +3 -0
  2. package/dist/bin.js +5 -0
  3. package/dist/branch-parity.d.ts +47 -0
  4. package/dist/branch-parity.js +263 -0
  5. package/dist/cache-parity.d.ts +36 -0
  6. package/dist/cache-parity.js +165 -0
  7. package/dist/cache.d.ts +4 -0
  8. package/dist/cache.js +10 -0
  9. package/dist/capacity-backfill.d.ts +3 -0
  10. package/dist/capacity-backfill.js +9 -0
  11. package/dist/capacity-show.d.ts +3 -0
  12. package/dist/capacity-show.js +9 -0
  13. package/dist/check.d.ts +10 -0
  14. package/dist/check.js +60 -0
  15. package/dist/cli-router/index.d.ts +8 -0
  16. package/dist/cli-router/index.js +37 -0
  17. package/dist/cli-router/route-argv.d.ts +32 -0
  18. package/dist/cli-router/route-argv.js +226 -0
  19. package/dist/codebase-default-extractor.d.ts +3 -0
  20. package/dist/codebase-default-extractor.js +9 -0
  21. package/dist/codebase-map-fresh.d.ts +3 -0
  22. package/dist/codebase-map-fresh.js +9 -0
  23. package/dist/codebase-map.d.ts +3 -0
  24. package/dist/codebase-map.js +9 -0
  25. package/dist/codebase-parity.d.ts +30 -0
  26. package/dist/codebase-parity.js +294 -0
  27. package/dist/codebase-projection-registry.d.ts +3 -0
  28. package/dist/codebase-projection-registry.js +9 -0
  29. package/dist/codebase-provider.d.ts +3 -0
  30. package/dist/codebase-provider.js +9 -0
  31. package/dist/content-validate-cli/validate-links.d.ts +11 -0
  32. package/dist/content-validate-cli/validate-links.js +37 -0
  33. package/dist/content-validate-cli/validate-strategy-output.d.ts +13 -0
  34. package/dist/content-validate-cli/validate-strategy-output.js +56 -0
  35. package/dist/content-validate-cli/verify-capacity.d.ts +12 -0
  36. package/dist/content-validate-cli/verify-capacity.js +54 -0
  37. package/dist/dispatch.d.ts +26 -0
  38. package/dist/dispatch.js +569 -0
  39. package/dist/doctor-parity.d.ts +38 -0
  40. package/dist/doctor-parity.js +151 -0
  41. package/dist/doctor.d.ts +3 -0
  42. package/dist/doctor.js +10 -0
  43. package/dist/gates-cli/_helpers.d.ts +18 -0
  44. package/dist/gates-cli/_helpers.js +71 -0
  45. package/dist/index.d.ts +11 -0
  46. package/dist/index.js +15 -0
  47. package/dist/init-cli/constants.d.ts +5 -0
  48. package/dist/init-cli/constants.js +5 -0
  49. package/dist/init-cli/init.d.ts +3 -0
  50. package/dist/init-cli/init.js +11 -0
  51. package/dist/init-cli/resolve-binary.d.ts +34 -0
  52. package/dist/init-cli/resolve-binary.js +78 -0
  53. package/dist/init-cli/run-deft-install.d.ts +23 -0
  54. package/dist/init-cli/run-deft-install.js +71 -0
  55. package/dist/init-cli/update.d.ts +3 -0
  56. package/dist/init-cli/update.js +11 -0
  57. package/dist/install-cli/coverage-map.d.ts +14 -0
  58. package/dist/install-cli/coverage-map.js +111 -0
  59. package/dist/intake-parity.d.ts +30 -0
  60. package/dist/intake-parity.js +203 -0
  61. package/dist/lifecycle-cli/coverage-map.d.ts +16 -0
  62. package/dist/lifecycle-cli/coverage-map.js +254 -0
  63. package/dist/lifecycle-cli/helpers.d.ts +8 -0
  64. package/dist/lifecycle-cli/helpers.js +20 -0
  65. package/dist/lifecycle-packs-parity.d.ts +30 -0
  66. package/dist/lifecycle-packs-parity.js +377 -0
  67. package/dist/orchestration-cli/coverage-map.d.ts +21 -0
  68. package/dist/orchestration-cli/coverage-map.js +225 -0
  69. package/dist/orchestration-cli/helpers.d.ts +11 -0
  70. package/dist/orchestration-cli/helpers.js +35 -0
  71. package/dist/orchestration-parity.d.ts +38 -0
  72. package/dist/orchestration-parity.js +364 -0
  73. package/dist/parity.d.ts +36 -0
  74. package/dist/parity.js +176 -0
  75. package/dist/platform-parity.d.ts +26 -0
  76. package/dist/platform-parity.js +309 -0
  77. package/dist/policy-parity.d.ts +35 -0
  78. package/dist/policy-parity.js +214 -0
  79. package/dist/policy.d.ts +27 -0
  80. package/dist/policy.js +316 -0
  81. package/dist/pr-closing-keywords-parity.d.ts +45 -0
  82. package/dist/pr-closing-keywords-parity.js +259 -0
  83. package/dist/pr-closing-keywords.d.ts +3 -0
  84. package/dist/pr-closing-keywords.js +10 -0
  85. package/dist/pr-merge-readiness-parity.d.ts +44 -0
  86. package/dist/pr-merge-readiness-parity.js +296 -0
  87. package/dist/pr-merge-readiness.d.ts +3 -0
  88. package/dist/pr-merge-readiness.js +10 -0
  89. package/dist/pr-monitor-parity.d.ts +44 -0
  90. package/dist/pr-monitor-parity.js +283 -0
  91. package/dist/pr-monitor.d.ts +3 -0
  92. package/dist/pr-monitor.js +10 -0
  93. package/dist/pr-protected-issues-parity.d.ts +41 -0
  94. package/dist/pr-protected-issues-parity.js +220 -0
  95. package/dist/pr-protected-issues.d.ts +3 -0
  96. package/dist/pr-protected-issues.js +10 -0
  97. package/dist/pr-wait-mergeable-parity.d.ts +45 -0
  98. package/dist/pr-wait-mergeable-parity.js +340 -0
  99. package/dist/pr-wait-mergeable.d.ts +3 -0
  100. package/dist/pr-wait-mergeable.js +10 -0
  101. package/dist/preflight-cache.d.ts +16 -0
  102. package/dist/preflight-cache.js +106 -0
  103. package/dist/preflight-gh.d.ts +12 -0
  104. package/dist/preflight-gh.js +188 -0
  105. package/dist/probe-session.d.ts +3 -0
  106. package/dist/probe-session.js +10 -0
  107. package/dist/release-e2e-parity.d.ts +31 -0
  108. package/dist/release-e2e-parity.js +114 -0
  109. package/dist/release-e2e.d.ts +3 -0
  110. package/dist/release-e2e.js +10 -0
  111. package/dist/release-parity.d.ts +40 -0
  112. package/dist/release-parity.js +223 -0
  113. package/dist/release-publish-parity.d.ts +36 -0
  114. package/dist/release-publish-parity.js +138 -0
  115. package/dist/release-publish.d.ts +3 -0
  116. package/dist/release-publish.js +10 -0
  117. package/dist/release-rollback-parity.d.ts +37 -0
  118. package/dist/release-rollback-parity.js +161 -0
  119. package/dist/release-rollback.d.ts +3 -0
  120. package/dist/release-rollback.js +10 -0
  121. package/dist/release.d.ts +3 -0
  122. package/dist/release.js +10 -0
  123. package/dist/render-cli/deft-ts-runner.d.ts +20 -0
  124. package/dist/render-cli/deft-ts-runner.js +35 -0
  125. package/dist/render-cli/prd-render-cli.d.ts +2 -0
  126. package/dist/render-cli/prd-render-cli.js +7 -0
  127. package/dist/render-cli/project-render-cli.d.ts +2 -0
  128. package/dist/render-cli/project-render-cli.js +6 -0
  129. package/dist/render-cli/spec-render-cli.d.ts +2 -0
  130. package/dist/render-cli/spec-render-cli.js +6 -0
  131. package/dist/render-cli/spec-validate-cli.d.ts +2 -0
  132. package/dist/render-cli/spec-validate-cli.js +6 -0
  133. package/dist/render-parity.d.ts +35 -0
  134. package/dist/render-parity.js +383 -0
  135. package/dist/scm-parity.d.ts +39 -0
  136. package/dist/scm-parity.js +181 -0
  137. package/dist/scope-lifecycle-parity.d.ts +35 -0
  138. package/dist/scope-lifecycle-parity.js +177 -0
  139. package/dist/scope-lifecycle.d.ts +4 -0
  140. package/dist/scope-lifecycle.js +29 -0
  141. package/dist/session-parity.d.ts +39 -0
  142. package/dist/session-parity.js +260 -0
  143. package/dist/slice-parity.d.ts +36 -0
  144. package/dist/slice-parity.js +304 -0
  145. package/dist/slice.d.ts +4 -0
  146. package/dist/slice.js +29 -0
  147. package/dist/story-ready-parity.d.ts +49 -0
  148. package/dist/story-ready-parity.js +254 -0
  149. package/dist/subagent-monitor.d.ts +3 -0
  150. package/dist/subagent-monitor.js +10 -0
  151. package/dist/swarm-parity.d.ts +28 -0
  152. package/dist/swarm-parity.js +326 -0
  153. package/dist/toolchain-check.d.ts +3 -0
  154. package/dist/toolchain-check.js +14 -0
  155. package/dist/triage-actions-parity.d.ts +33 -0
  156. package/dist/triage-actions-parity.js +201 -0
  157. package/dist/triage-actions.d.ts +17 -0
  158. package/dist/triage-actions.js +144 -0
  159. package/dist/triage-aux-a-parity.d.ts +35 -0
  160. package/dist/triage-aux-a-parity.js +172 -0
  161. package/dist/triage-aux-b-parity.d.ts +32 -0
  162. package/dist/triage-aux-b-parity.js +308 -0
  163. package/dist/triage-bootstrap-parity.d.ts +44 -0
  164. package/dist/triage-bootstrap-parity.js +226 -0
  165. package/dist/triage-bootstrap.d.ts +24 -0
  166. package/dist/triage-bootstrap.js +172 -0
  167. package/dist/triage-bulk.d.ts +17 -0
  168. package/dist/triage-bulk.js +154 -0
  169. package/dist/triage-classify-parity.d.ts +40 -0
  170. package/dist/triage-classify-parity.js +227 -0
  171. package/dist/triage-classify.d.ts +13 -0
  172. package/dist/triage-classify.js +76 -0
  173. package/dist/triage-help.d.ts +3 -0
  174. package/dist/triage-help.js +10 -0
  175. package/dist/triage-queue-parity.d.ts +59 -0
  176. package/dist/triage-queue-parity.js +363 -0
  177. package/dist/triage-queue.d.ts +17 -0
  178. package/dist/triage-queue.js +174 -0
  179. package/dist/triage-reconcile.d.ts +11 -0
  180. package/dist/triage-reconcile.js +76 -0
  181. package/dist/triage-refresh.d.ts +7 -0
  182. package/dist/triage-refresh.js +37 -0
  183. package/dist/triage-scope-drift.d.ts +12 -0
  184. package/dist/triage-scope-drift.js +117 -0
  185. package/dist/triage-scope-parity.d.ts +34 -0
  186. package/dist/triage-scope-parity.js +218 -0
  187. package/dist/triage-scope.d.ts +4 -0
  188. package/dist/triage-scope.js +29 -0
  189. package/dist/triage-smoketest.d.ts +3 -0
  190. package/dist/triage-smoketest.js +43 -0
  191. package/dist/triage-subscribe.d.ts +15 -0
  192. package/dist/triage-subscribe.js +157 -0
  193. package/dist/triage-summary-parity.d.ts +50 -0
  194. package/dist/triage-summary-parity.js +306 -0
  195. package/dist/triage-summary.d.ts +14 -0
  196. package/dist/triage-summary.js +77 -0
  197. package/dist/triage-welcome.d.ts +12 -0
  198. package/dist/triage-welcome.js +78 -0
  199. package/dist/ts-check-lane.d.ts +9 -0
  200. package/dist/ts-check-lane.js +49 -0
  201. package/dist/validate-content-parity.d.ts +33 -0
  202. package/dist/validate-content-parity.js +356 -0
  203. package/dist/vbrief-activate-parity.d.ts +39 -0
  204. package/dist/vbrief-activate-parity.js +216 -0
  205. package/dist/vbrief-activate.d.ts +3 -0
  206. package/dist/vbrief-activate.js +7 -0
  207. package/dist/vbrief-build-parity.d.ts +28 -0
  208. package/dist/vbrief-build-parity.js +399 -0
  209. package/dist/vbrief-build.d.ts +3 -0
  210. package/dist/vbrief-build.js +8 -0
  211. package/dist/vbrief-preflight-parity.d.ts +34 -0
  212. package/dist/vbrief-preflight-parity.js +163 -0
  213. package/dist/vbrief-preflight.d.ts +12 -0
  214. package/dist/vbrief-preflight.js +58 -0
  215. package/dist/vbrief-reconcile-parity.d.ts +22 -0
  216. package/dist/vbrief-reconcile-parity.js +600 -0
  217. package/dist/vbrief-reconcile.d.ts +3 -0
  218. package/dist/vbrief-reconcile.js +7 -0
  219. package/dist/vbrief-validate-parity.d.ts +27 -0
  220. package/dist/vbrief-validate-parity.js +122 -0
  221. package/dist/vbrief-validate.d.ts +3 -0
  222. package/dist/vbrief-validate.js +8 -0
  223. package/dist/vbrief-validation-parity.d.ts +28 -0
  224. package/dist/vbrief-validation-parity.js +645 -0
  225. package/dist/vbrief-validation.d.ts +3 -0
  226. package/dist/vbrief-validation.js +8 -0
  227. package/dist/verify-branch.d.ts +14 -0
  228. package/dist/verify-branch.js +81 -0
  229. package/dist/verify-encoding.d.ts +15 -0
  230. package/dist/verify-encoding.js +86 -0
  231. package/dist/verify-env-parity.d.ts +28 -0
  232. package/dist/verify-env-parity.js +272 -0
  233. package/dist/verify-hooks-installed.d.ts +10 -0
  234. package/dist/verify-hooks-installed.js +48 -0
  235. package/dist/verify-investigation.d.ts +3 -0
  236. package/dist/verify-investigation.js +10 -0
  237. package/dist/verify-judgment-gates.d.ts +3 -0
  238. package/dist/verify-judgment-gates.js +10 -0
  239. package/dist/verify-no-task-runtime.d.ts +3 -0
  240. package/dist/verify-no-task-runtime.js +16 -0
  241. package/dist/verify-session-ritual.d.ts +13 -0
  242. package/dist/verify-session-ritual.js +78 -0
  243. package/dist/verify-source-cli/rule-ownership-lint.d.ts +12 -0
  244. package/dist/verify-source-cli/rule-ownership-lint.js +61 -0
  245. package/dist/verify-source-cli/verify-content-manifest.d.ts +12 -0
  246. package/dist/verify-source-cli/verify-content-manifest.js +61 -0
  247. package/dist/verify-source-cli/verify-scm-boundary.d.ts +13 -0
  248. package/dist/verify-source-cli/verify-scm-boundary.js +66 -0
  249. package/dist/verify-source-cli/verify-stubs.d.ts +11 -0
  250. package/dist/verify-source-cli/verify-stubs.js +27 -0
  251. package/dist/verify-source-parity.d.ts +26 -0
  252. package/dist/verify-source-parity.js +178 -0
  253. package/dist/verify-story-ready.d.ts +16 -0
  254. package/dist/verify-story-ready.js +138 -0
  255. package/dist/verify-tools.d.ts +13 -0
  256. package/dist/verify-tools.js +67 -0
  257. package/dist/verify-wip-cap.d.ts +13 -0
  258. package/dist/verify-wip-cap.js +62 -0
  259. package/dist/wip-cap-parity.d.ts +39 -0
  260. package/dist/wip-cap-parity.js +209 -0
  261. package/package.json +50 -0
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ import { statSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
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);
8
+ }
9
+ /** Parse triage-bootstrap CLI args, mirroring the Python argparse surface. */
10
+ export function parseArgs(argv) {
11
+ const parsed = {
12
+ projectRoot: process.env.DEFT_PROJECT_ROOT ?? ".",
13
+ repo: process.env.DEFT_TRIAGE_REPO ?? null,
14
+ labels: [],
15
+ fetchTimeoutS: Number.NaN,
16
+ quiet: false,
17
+ emitJson: false,
18
+ };
19
+ for (let i = 0; i < argv.length; i += 1) {
20
+ const arg = argv[i];
21
+ if (arg === "--quiet") {
22
+ parsed.quiet = true;
23
+ }
24
+ else if (arg === "--json") {
25
+ parsed.emitJson = true;
26
+ }
27
+ else if (arg === "--project-root") {
28
+ const value = argv[i + 1];
29
+ if (value === undefined) {
30
+ return { ...parsed, error: "argument --project-root: expected one argument" };
31
+ }
32
+ parsed.projectRoot = value;
33
+ i += 1;
34
+ }
35
+ else if (arg?.startsWith("--project-root=")) {
36
+ parsed.projectRoot = arg.slice("--project-root=".length);
37
+ }
38
+ else if (arg === "--repo") {
39
+ const value = argv[i + 1];
40
+ if (value === undefined) {
41
+ return { ...parsed, error: "argument --repo: expected one argument" };
42
+ }
43
+ parsed.repo = value;
44
+ i += 1;
45
+ }
46
+ else if (arg?.startsWith("--repo=")) {
47
+ parsed.repo = arg.slice("--repo=".length);
48
+ }
49
+ else if (arg === "--limit") {
50
+ const value = argv[i + 1];
51
+ if (value === undefined) {
52
+ return { ...parsed, error: "argument --limit: expected one argument" };
53
+ }
54
+ parsed.limit = Number.parseInt(value, 10);
55
+ i += 1;
56
+ }
57
+ else if (arg === "--state") {
58
+ const value = argv[i + 1];
59
+ if (value === undefined) {
60
+ return { ...parsed, error: "argument --state: expected one argument" };
61
+ }
62
+ if (value !== "open" && value !== "closed" && value !== "all") {
63
+ return {
64
+ ...parsed,
65
+ error: `invalid choice: '${value}' (choose from 'open', 'closed', 'all')`,
66
+ };
67
+ }
68
+ parsed.state = value;
69
+ i += 1;
70
+ }
71
+ else if (arg === "--label") {
72
+ const value = argv[i + 1];
73
+ if (value === undefined) {
74
+ return { ...parsed, error: "argument --label: expected one argument" };
75
+ }
76
+ parsed.labels.push(value);
77
+ i += 1;
78
+ }
79
+ else if (arg === "--author") {
80
+ const value = argv[i + 1];
81
+ if (value === undefined) {
82
+ return { ...parsed, error: "argument --author: expected one argument" };
83
+ }
84
+ parsed.author = value;
85
+ i += 1;
86
+ }
87
+ else if (arg === "--batch-size") {
88
+ const value = argv[i + 1];
89
+ if (value === undefined) {
90
+ return { ...parsed, error: "argument --batch-size: expected one argument" };
91
+ }
92
+ parsed.batchSize = Number.parseInt(value, 10);
93
+ i += 1;
94
+ }
95
+ else if (arg === "--delay-ms") {
96
+ const value = argv[i + 1];
97
+ if (value === undefined) {
98
+ return { ...parsed, error: "argument --delay-ms: expected one argument" };
99
+ }
100
+ parsed.delayMs = Number.parseInt(value, 10);
101
+ i += 1;
102
+ }
103
+ else if (arg === "--fetch-timeout-s") {
104
+ const value = argv[i + 1];
105
+ if (value === undefined) {
106
+ return { ...parsed, error: "argument --fetch-timeout-s: expected one argument" };
107
+ }
108
+ parsed.fetchTimeoutS = Number.parseFloat(value);
109
+ i += 1;
110
+ }
111
+ else {
112
+ return { ...parsed, error: `unrecognized arguments: ${arg}` };
113
+ }
114
+ }
115
+ return parsed;
116
+ }
117
+ /** Run triage:bootstrap with an injected core module (test seam). */
118
+ export async function runWithModule(mod, argv) {
119
+ const args = parseArgs(argv);
120
+ if (args.error !== undefined) {
121
+ process.stderr.write(`triage_bootstrap: ${args.error}\n`);
122
+ return 2;
123
+ }
124
+ const fetchTimeoutS = Number.isNaN(args.fetchTimeoutS)
125
+ ? mod.defaultFetchTimeoutFromEnv()
126
+ : args.fetchTimeoutS;
127
+ const projectRoot = resolve(args.projectRoot);
128
+ let isDir = false;
129
+ try {
130
+ isDir = statSync(projectRoot).isDirectory();
131
+ }
132
+ catch {
133
+ isDir = false;
134
+ }
135
+ if (!isDir) {
136
+ process.stderr.write(`❌ triage:bootstrap: --project-root ${projectRoot} does not exist or is not a directory.\n`);
137
+ return 2;
138
+ }
139
+ const labels = mod.normaliseLabelFilter(args.labels);
140
+ const result = await mod.runBootstrap(projectRoot, args.repo, {
141
+ batchSize: args.batchSize,
142
+ delayMs: args.delayMs,
143
+ state: args.state,
144
+ limit: args.limit,
145
+ labels,
146
+ author: args.author,
147
+ fetchTimeoutS,
148
+ progress: args.quiet ? null : mod.PROGRESS_DEFAULT,
149
+ });
150
+ if (args.emitJson) {
151
+ process.stdout.write(`${mod.formatJson(result)}\n`);
152
+ }
153
+ else {
154
+ process.stdout.write(`${mod.formatSummary(result)}\n`);
155
+ }
156
+ return result.exitCode;
157
+ }
158
+ /** Run triage:bootstrap and return the process exit code. */
159
+ export async function run(argv) {
160
+ return runWithModule(await loadBootstrapModule(), argv);
161
+ }
162
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
163
+ run(process.argv.slice(2))
164
+ .then((code) => {
165
+ process.exit(code);
166
+ })
167
+ .catch((err) => {
168
+ process.stderr.write(`triage_bootstrap: ${String(err)}\n`);
169
+ process.exit(2);
170
+ });
171
+ }
172
+ //# sourceMappingURL=triage-bootstrap.js.map
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ action: string;
4
+ repo: string;
5
+ label: string | null;
6
+ author: string | null;
7
+ ageDays: number | null;
8
+ cluster: string | null;
9
+ reason: string | null;
10
+ reAction: boolean;
11
+ showHelp: boolean;
12
+ error?: string;
13
+ }
14
+ export declare function parseArgs(argv: string[]): ParsedArgs;
15
+ export declare function run(argv: string[]): number;
16
+ export {};
17
+ //# sourceMappingURL=triage-bulk.d.ts.map
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import { join, resolve } from "node:path";
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";
6
+ export function parseArgs(argv) {
7
+ const parsed = {
8
+ action: "",
9
+ repo: "",
10
+ label: null,
11
+ author: null,
12
+ ageDays: null,
13
+ cluster: null,
14
+ reason: null,
15
+ reAction: false,
16
+ showHelp: false,
17
+ };
18
+ const positional = [];
19
+ for (let i = 0; i < argv.length; i += 1) {
20
+ const arg = argv[i];
21
+ if (arg === undefined)
22
+ continue;
23
+ if (arg === "--help" || arg === "-h") {
24
+ parsed.showHelp = true;
25
+ }
26
+ else if (arg === "--re-action") {
27
+ parsed.reAction = true;
28
+ }
29
+ else if (arg === "--repo") {
30
+ const value = argv[i + 1];
31
+ if (value === undefined) {
32
+ return { ...parsed, error: "argument --repo: expected one argument" };
33
+ }
34
+ parsed.repo = value;
35
+ i += 1;
36
+ }
37
+ else if (arg.startsWith("--repo=")) {
38
+ parsed.repo = arg.slice("--repo=".length);
39
+ }
40
+ else if (arg === "--label") {
41
+ const value = argv[i + 1];
42
+ if (value === undefined) {
43
+ return { ...parsed, error: "argument --label: expected one argument" };
44
+ }
45
+ parsed.label = value;
46
+ i += 1;
47
+ }
48
+ else if (arg.startsWith("--label=")) {
49
+ parsed.label = arg.slice("--label=".length);
50
+ }
51
+ else if (arg === "--author") {
52
+ const value = argv[i + 1];
53
+ if (value === undefined) {
54
+ return { ...parsed, error: "argument --author: expected one argument" };
55
+ }
56
+ parsed.author = value;
57
+ i += 1;
58
+ }
59
+ else if (arg.startsWith("--author=")) {
60
+ parsed.author = arg.slice("--author=".length);
61
+ }
62
+ else if (arg === "--age-days") {
63
+ const value = argv[i + 1];
64
+ if (value === undefined) {
65
+ return { ...parsed, error: "argument --age-days: expected one argument" };
66
+ }
67
+ parsed.ageDays = Number.parseInt(value, 10);
68
+ i += 1;
69
+ }
70
+ else if (arg.startsWith("--age-days=")) {
71
+ parsed.ageDays = Number.parseInt(arg.slice("--age-days=".length), 10);
72
+ }
73
+ else if (arg === "--cluster") {
74
+ const value = argv[i + 1];
75
+ if (value === undefined) {
76
+ return { ...parsed, error: "argument --cluster: expected one argument" };
77
+ }
78
+ parsed.cluster = value;
79
+ i += 1;
80
+ }
81
+ else if (arg.startsWith("--cluster=")) {
82
+ parsed.cluster = arg.slice("--cluster=".length);
83
+ }
84
+ else if (arg === "--reason") {
85
+ const value = argv[i + 1];
86
+ if (value === undefined) {
87
+ return { ...parsed, error: "argument --reason: expected one argument" };
88
+ }
89
+ parsed.reason = value;
90
+ i += 1;
91
+ }
92
+ else if (arg.startsWith("--reason=")) {
93
+ parsed.reason = arg.slice("--reason=".length);
94
+ }
95
+ else if (arg.startsWith("-")) {
96
+ return { ...parsed, error: `unrecognized arguments: ${arg}` };
97
+ }
98
+ else {
99
+ positional.push(arg);
100
+ }
101
+ }
102
+ if (positional.length > 0 && positional[0] !== undefined) {
103
+ parsed.action = positional[0];
104
+ }
105
+ return parsed;
106
+ }
107
+ export function run(argv) {
108
+ const helpRc = interceptHelp("triage_bulk", argv);
109
+ if (helpRc !== null) {
110
+ return helpRc;
111
+ }
112
+ const args = parseArgs(argv);
113
+ if (args.showHelp && args.action === "") {
114
+ return 0;
115
+ }
116
+ if (args.error !== undefined) {
117
+ process.stderr.write(`${args.error}\n`);
118
+ return 2;
119
+ }
120
+ if (!["accept", "reject", "defer", "needs-ac"].includes(args.action)) {
121
+ process.stderr.write("triage_bulk: action required (accept|reject|defer|needs-ac)\n");
122
+ return 2;
123
+ }
124
+ if (args.repo === "") {
125
+ process.stderr.write("triage_bulk: --repo is required\n");
126
+ return 2;
127
+ }
128
+ const projectRoot = process.cwd();
129
+ const frameworkRoot = resolve(process.env.DEFT_ROOT ?? projectRoot);
130
+ try {
131
+ bulkActionWithDefaults(args.action, args.repo, {
132
+ label: args.label,
133
+ author: args.author,
134
+ ageDays: args.ageDays,
135
+ cluster: args.cluster,
136
+ reason: args.reason,
137
+ reAction: args.reAction,
138
+ deftRoot: projectRoot,
139
+ scriptsDir: join(frameworkRoot, "scripts"),
140
+ });
141
+ }
142
+ catch (exc) {
143
+ if (exc instanceof CacheEmptyError) {
144
+ process.stderr.write(`${exc.message}\n`);
145
+ return 2;
146
+ }
147
+ throw exc;
148
+ }
149
+ return 0;
150
+ }
151
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
152
+ process.exit(run(process.argv.slice(2)));
153
+ }
154
+ //# sourceMappingURL=triage-bulk.js.map
@@ -0,0 +1,40 @@
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 FixtureOptions {
8
+ readonly plan?: Record<string, unknown>;
9
+ readonly omitProjectDefinition?: boolean;
10
+ readonly rawProjectDefinition?: Record<string, unknown>;
11
+ }
12
+ export interface ParityCase {
13
+ readonly name: string;
14
+ readonly argv: readonly string[];
15
+ readonly fixture?: FixtureOptions;
16
+ readonly useRepoRoot?: boolean;
17
+ }
18
+ export interface ParityDiff {
19
+ readonly caseName: string;
20
+ readonly exitMismatch: boolean;
21
+ readonly stdoutMismatch: boolean;
22
+ readonly stderrMismatch: boolean;
23
+ readonly pythonExit: number;
24
+ readonly tsExit: number;
25
+ }
26
+ export interface ParityResult {
27
+ readonly ok: boolean;
28
+ readonly diffs: ParityDiff[];
29
+ }
30
+ /** Strip volatile absolute paths before compare. */
31
+ export declare function normalizeOutput(text: string): string;
32
+ /** Build a throwaway project root with optional PROJECT-DEFINITION. */
33
+ export declare function buildFixtureRepo(options?: FixtureOptions): string;
34
+ /** Diff one parity case between Python oracle and TS CLI. */
35
+ export declare function diffCase(python: CommandCapture, ts: CommandCapture, caseName: string): ParityDiff;
36
+ export declare const PARITY_CASES: readonly ParityCase[];
37
+ /** Run all parity cases; returns aggregate result. */
38
+ export declare function runParity(): ParityResult;
39
+ export declare function renderReport(result: ParityResult): string;
40
+ //# sourceMappingURL=triage-classify-parity.d.ts.map
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Golden-output parity harness (#1725): runs BOTH the Python oracle
4
+ * (`scripts/triage_classify.py`) and the ported TS triage-classify CLI with
5
+ * identical argv, then diffs exit codes and normalised stdout/stderr.
6
+ *
7
+ * Exit codes: 0 parity / 1 divergence / 2 harness setup error.
8
+ */
9
+ import { spawnSync } 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 absolute paths before compare. */
15
+ export function normalizeOutput(text) {
16
+ return (text
17
+ .replace(/project_root=[^\s)]+/g, "project_root=<ROOT>")
18
+ // Match the parity temp root regardless of platform tmpdir prefix
19
+ // (/tmp on Linux, /var/folders/... on macOS, etc.).
20
+ .replace(/\S*deft-triage-classify-parity-[^\s/]+/g, "<TMPROOT>"));
21
+ }
22
+ function runCapture(cmd, args, cwd, env = {}) {
23
+ const merged = { ...process.env, ...env };
24
+ for (const key of Object.keys(merged)) {
25
+ if (merged[key] === undefined)
26
+ delete merged[key];
27
+ }
28
+ const result = spawnSync(cmd, args, {
29
+ cwd,
30
+ encoding: "utf8",
31
+ env: merged,
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ });
34
+ return {
35
+ status: result.status ?? 2,
36
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
37
+ stderr: typeof result.stderr === "string" ? result.stderr : "",
38
+ };
39
+ }
40
+ function writeProjectDefinition(root, plan) {
41
+ const dir = join(root, "vbrief");
42
+ mkdirSync(dir, { recursive: true });
43
+ writeFileSync(join(dir, "PROJECT-DEFINITION.vbrief.json"), `${JSON.stringify({
44
+ vBRIEFInfo: { version: "0.6" },
45
+ plan: { title: "T", status: "running", items: [], ...plan },
46
+ }, null, 2)}\n`, { encoding: "utf8" });
47
+ }
48
+ /** Build a throwaway project root with optional PROJECT-DEFINITION. */
49
+ export function buildFixtureRepo(options = {}) {
50
+ const root = mkdtempSync(join(tmpdir(), "deft-triage-classify-parity-"));
51
+ mkdirSync(join(root, "vbrief"), { recursive: true });
52
+ if (options.rawProjectDefinition !== undefined) {
53
+ writeFileSync(join(root, "vbrief", "PROJECT-DEFINITION.vbrief.json"), `${JSON.stringify(options.rawProjectDefinition, null, 2)}\n`, { encoding: "utf8" });
54
+ }
55
+ else if (!options.omitProjectDefinition && options.plan !== undefined) {
56
+ writeProjectDefinition(root, options.plan);
57
+ }
58
+ else if (!options.omitProjectDefinition) {
59
+ writeProjectDefinition(root, {});
60
+ }
61
+ return root;
62
+ }
63
+ function resolveDeftRoot() {
64
+ if (process.env.DEFT_ROOT !== undefined && process.env.DEFT_ROOT.length > 0) {
65
+ return resolve(process.env.DEFT_ROOT);
66
+ }
67
+ return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
68
+ }
69
+ function runPythonClassify(deftRoot, repo, argv) {
70
+ const cap = runCapture("uv", [
71
+ "run",
72
+ "python",
73
+ join(deftRoot, "scripts", "triage_classify.py"),
74
+ ...argv,
75
+ "--project-root",
76
+ repo,
77
+ ], deftRoot);
78
+ return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
79
+ }
80
+ function runTsClassify(deftRoot, repo, argv) {
81
+ const cap = runCapture("node", [
82
+ join(deftRoot, "packages", "cli", "dist", "triage-classify.js"),
83
+ ...argv,
84
+ "--project-root",
85
+ repo,
86
+ ], deftRoot);
87
+ return { exitCode: cap.status, stdout: cap.stdout, stderr: cap.stderr };
88
+ }
89
+ /** Diff one parity case between Python oracle and TS CLI. */
90
+ export function diffCase(python, ts, caseName) {
91
+ const pyOut = normalizeOutput(python.stdout);
92
+ const tsOut = normalizeOutput(ts.stdout);
93
+ const pyErr = normalizeOutput(python.stderr);
94
+ const tsErr = normalizeOutput(ts.stderr);
95
+ return {
96
+ caseName,
97
+ exitMismatch: python.exitCode !== ts.exitCode,
98
+ stdoutMismatch: pyOut !== tsOut,
99
+ stderrMismatch: pyErr !== tsErr,
100
+ pythonExit: python.exitCode,
101
+ tsExit: ts.exitCode,
102
+ };
103
+ }
104
+ export const PARITY_CASES = [
105
+ {
106
+ name: "list-default-repo-root",
107
+ argv: ["--list"],
108
+ useRepoRoot: true,
109
+ },
110
+ {
111
+ name: "list-no-project-definition",
112
+ argv: ["--list"],
113
+ fixture: { omitProjectDefinition: true },
114
+ },
115
+ {
116
+ name: "validate-no-project-definition",
117
+ argv: ["--validate"],
118
+ fixture: { omitProjectDefinition: true },
119
+ },
120
+ {
121
+ name: "validate-valid-consumer-rules",
122
+ argv: ["--validate"],
123
+ fixture: {
124
+ plan: {
125
+ policy: {
126
+ triageAutoClassify: [
127
+ {
128
+ match: { labels: { "any-of": ["bug"] } },
129
+ action: "escalate",
130
+ reason: "p0 bug",
131
+ },
132
+ ],
133
+ triageHoldMarkers: ["BLOCKED", "WONTFIX"],
134
+ },
135
+ },
136
+ },
137
+ },
138
+ {
139
+ name: "validate-invalid-empty-match",
140
+ argv: ["--validate"],
141
+ fixture: {
142
+ plan: {
143
+ policy: {
144
+ triageAutoClassify: [{ match: {}, action: "defer", reason: "??" }],
145
+ },
146
+ },
147
+ },
148
+ },
149
+ {
150
+ name: "validate-invalid-hold-markers",
151
+ argv: ["--validate"],
152
+ fixture: {
153
+ plan: {
154
+ policy: {
155
+ triageHoldMarkers: "",
156
+ },
157
+ },
158
+ },
159
+ },
160
+ {
161
+ name: "validate-malformed-plan",
162
+ argv: ["--validate"],
163
+ fixture: {
164
+ rawProjectDefinition: {
165
+ vBRIEFInfo: { version: "0.6" },
166
+ plan: null,
167
+ },
168
+ },
169
+ },
170
+ ];
171
+ /** Run all parity cases; returns aggregate result. */
172
+ export function runParity() {
173
+ const deftRoot = resolveDeftRoot();
174
+ const diffs = [];
175
+ for (const testCase of PARITY_CASES) {
176
+ const pyRepo = testCase.useRepoRoot === true ? deftRoot : buildFixtureRepo(testCase.fixture ?? {});
177
+ const tsRepo = testCase.useRepoRoot === true ? deftRoot : buildFixtureRepo(testCase.fixture ?? {});
178
+ const ownsFixture = testCase.useRepoRoot !== true;
179
+ try {
180
+ const python = runPythonClassify(deftRoot, pyRepo, testCase.argv);
181
+ const ts = runTsClassify(deftRoot, tsRepo, testCase.argv);
182
+ diffs.push(diffCase(python, ts, testCase.name));
183
+ }
184
+ finally {
185
+ if (ownsFixture) {
186
+ rmSync(pyRepo, { recursive: true, force: true });
187
+ rmSync(tsRepo, { recursive: true, force: true });
188
+ }
189
+ }
190
+ }
191
+ const ok = diffs.every((d) => !d.exitMismatch && !d.stdoutMismatch && !d.stderrMismatch);
192
+ return { ok, diffs };
193
+ }
194
+ export function renderReport(result) {
195
+ if (result.ok) {
196
+ return `triage:classify parity: CLEAN -- Python and TS agree on ${PARITY_CASES.length} cases.`;
197
+ }
198
+ const lines = ["triage:classify parity: DIVERGENCE"];
199
+ for (const d of result.diffs) {
200
+ if (d.exitMismatch || d.stdoutMismatch || d.stderrMismatch) {
201
+ lines.push(` case: ${d.caseName}`);
202
+ if (d.exitMismatch)
203
+ lines.push(` exit: python=${d.pythonExit} ts=${d.tsExit}`);
204
+ if (d.stdoutMismatch)
205
+ lines.push(" stdout mismatch");
206
+ if (d.stderrMismatch)
207
+ lines.push(" stderr mismatch");
208
+ }
209
+ }
210
+ return lines.join("\n");
211
+ }
212
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
213
+ try {
214
+ const result = runParity();
215
+ if (result.ok) {
216
+ process.stdout.write(`${renderReport(result)}\n`);
217
+ process.exit(0);
218
+ }
219
+ process.stderr.write(`${renderReport(result)}\n`);
220
+ process.exit(1);
221
+ }
222
+ catch (err) {
223
+ process.stderr.write(`triage:classify parity: harness error -- ${String(err)}\n`);
224
+ process.exit(2);
225
+ }
226
+ }
227
+ //# sourceMappingURL=triage-classify-parity.js.map
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ doList: boolean;
5
+ doValidate: boolean;
6
+ error?: string;
7
+ }
8
+ /** Parse triage-classify CLI args, mirroring the Python argparse surface. */
9
+ export declare function parseArgs(argv: string[]): ParsedArgs;
10
+ /** Run the CLI and return the process exit code. */
11
+ export declare function run(argv: string[]): number;
12
+ export {};
13
+ //# sourceMappingURL=triage-classify.d.ts.map