@harness-engineering/cli 1.7.0 → 1.8.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 (130) hide show
  1. package/dist/agents/personas/documentation-maintainer.yaml +3 -1
  2. package/dist/agents/personas/performance-guardian.yaml +23 -0
  3. package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
  4. package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
  5. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
  6. package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
  7. package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +48 -1
  8. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
  9. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +7 -0
  10. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +9 -1
  11. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +76 -4
  12. package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
  13. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
  14. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
  15. package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
  16. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
  17. package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
  18. package/dist/agents/skills/claude-code/harness-docs-pipeline/SKILL.md +460 -0
  19. package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
  20. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
  21. package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
  22. package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
  23. package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
  24. package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
  25. package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
  26. package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
  27. package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
  28. package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
  29. package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +35 -6
  30. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +17 -1
  31. package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
  32. package/dist/agents/skills/claude-code/harness-perf/SKILL.md +37 -8
  33. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
  34. package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
  35. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +57 -3
  36. package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
  37. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +16 -0
  38. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +562 -0
  39. package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
  40. package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
  41. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
  42. package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
  43. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
  44. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
  45. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
  46. package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
  47. package/dist/agents/skills/claude-code/harness-verify/SKILL.md +11 -0
  48. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
  49. package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
  50. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +7 -0
  51. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -1
  52. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
  53. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
  54. package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
  55. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
  56. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
  57. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
  58. package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
  59. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
  60. package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
  61. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
  62. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
  63. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
  64. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +35 -6
  65. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
  66. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
  67. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  68. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
  69. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +16 -0
  70. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +562 -0
  71. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
  72. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
  73. package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
  74. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
  75. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
  76. package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
  77. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
  78. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
  79. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
  80. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
  81. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
  82. package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
  83. package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
  84. package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
  85. package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
  86. package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
  87. package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
  88. package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
  89. package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
  90. package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
  91. package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
  92. package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
  93. package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
  94. package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
  95. package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
  96. package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
  97. package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
  98. package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
  99. package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
  100. package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
  101. package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
  102. package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
  103. package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
  104. package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
  105. package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
  106. package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
  107. package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
  108. package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
  109. package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
  110. package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
  111. package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
  112. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
  113. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
  114. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
  115. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
  116. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
  117. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
  118. package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
  119. package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
  120. package/dist/bin/harness.js +64 -4
  121. package/dist/{chunk-4WUGOJQ7.js → chunk-3JWCBVUZ.js} +1 -1
  122. package/dist/{chunk-FFIX3QVG.js → chunk-LNI4T7R6.js} +131 -41
  123. package/dist/{chunk-GA6GN5J2.js → chunk-SJECMKSS.js} +2244 -34
  124. package/dist/{dist-N4D4QWFV.js → dist-BDO5GFEM.js} +1 -1
  125. package/dist/{dist-C4J67MPP.js → dist-NT3GXHQZ.js} +95 -1
  126. package/dist/index.d.ts +187 -7
  127. package/dist/index.js +7 -3
  128. package/dist/validate-cross-check-2OPGCGGU.js +7 -0
  129. package/package.json +7 -7
  130. package/dist/validate-cross-check-WGXQ7K62.js +0 -7
@@ -1,20 +1,80 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- createProgram
4
- } from "../chunk-FFIX3QVG.js";
5
- import "../chunk-4WUGOJQ7.js";
6
- import "../chunk-GA6GN5J2.js";
3
+ createProgram,
4
+ findConfigFile,
5
+ loadConfig
6
+ } from "../chunk-LNI4T7R6.js";
7
+ import "../chunk-3JWCBVUZ.js";
8
+ import {
9
+ VERSION,
10
+ getUpdateNotification,
11
+ isUpdateCheckEnabled,
12
+ readCheckState,
13
+ shouldRunCheck,
14
+ spawnBackgroundCheck
15
+ } from "../chunk-SJECMKSS.js";
7
16
  import {
8
17
  handleError
9
18
  } from "../chunk-ACMDUQJG.js";
10
19
 
20
+ // src/bin/update-check-hooks.ts
21
+ var DEFAULT_INTERVAL_MS = 864e5;
22
+ var cachedConfigInterval = null;
23
+ function readConfigInterval() {
24
+ if (cachedConfigInterval !== null) return cachedConfigInterval;
25
+ try {
26
+ const findResult = findConfigFile();
27
+ if (!findResult.ok) {
28
+ cachedConfigInterval = void 0;
29
+ return void 0;
30
+ }
31
+ const configResult = loadConfig(findResult.value);
32
+ if (!configResult.ok) {
33
+ cachedConfigInterval = void 0;
34
+ return void 0;
35
+ }
36
+ const val = configResult.value.updateCheckInterval;
37
+ cachedConfigInterval = val;
38
+ return val;
39
+ } catch {
40
+ cachedConfigInterval = void 0;
41
+ return void 0;
42
+ }
43
+ }
44
+ function runUpdateCheckAtStartup() {
45
+ try {
46
+ const configInterval = readConfigInterval();
47
+ if (!isUpdateCheckEnabled(configInterval)) return;
48
+ const state = readCheckState();
49
+ const interval = configInterval ?? DEFAULT_INTERVAL_MS;
50
+ if (!shouldRunCheck(state, interval)) return;
51
+ spawnBackgroundCheck(VERSION);
52
+ } catch {
53
+ }
54
+ }
55
+ function printUpdateNotification() {
56
+ try {
57
+ const configInterval = readConfigInterval();
58
+ if (!isUpdateCheckEnabled(configInterval)) return;
59
+ const message = getUpdateNotification(VERSION);
60
+ if (message) {
61
+ process.stderr.write(`
62
+ ${message}
63
+ `);
64
+ }
65
+ } catch {
66
+ }
67
+ }
68
+
11
69
  // src/bin/harness.ts
12
70
  async function main() {
71
+ runUpdateCheckAtStartup();
13
72
  const program = createProgram();
14
73
  try {
15
74
  await program.parseAsync(process.argv);
16
75
  } catch (error) {
17
76
  handleError(error);
18
77
  }
78
+ printUpdateNotification();
19
79
  }
20
80
  void main();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Ok
3
- } from "./chunk-GA6GN5J2.js";
3
+ } from "./chunk-SJECMKSS.js";
4
4
 
5
5
  // src/commands/validate-cross-check.ts
6
6
  import * as fs from "fs";
@@ -13,7 +13,6 @@ import {
13
13
  buildSnapshot,
14
14
  checkDocCoverage,
15
15
  createFixes,
16
- createSelfReview,
17
16
  createStream,
18
17
  defineLayer,
19
18
  detectCircularDepsInFiles,
@@ -28,11 +27,12 @@ import {
28
27
  requestPeerReview,
29
28
  resolveStreamPath,
30
29
  runCIChecks,
30
+ runReviewPipeline,
31
31
  setActiveStream,
32
32
  validateAgentsMap,
33
33
  validateDependencies,
34
34
  validateKnowledgeMap
35
- } from "./chunk-GA6GN5J2.js";
35
+ } from "./chunk-SJECMKSS.js";
36
36
  import {
37
37
  CLIError,
38
38
  ExitCode,
@@ -103,6 +103,48 @@ var DesignConfigSchema = z.object({
103
103
  tokenPath: z.string().optional(),
104
104
  aestheticIntent: z.string().optional()
105
105
  });
106
+ var I18nCoverageConfigSchema = z.object({
107
+ minimumPercent: z.number().min(0).max(100).default(100),
108
+ requirePlurals: z.boolean().default(true),
109
+ detectUntranslated: z.boolean().default(true)
110
+ });
111
+ var I18nMcpConfigSchema = z.object({
112
+ server: z.string(),
113
+ projectId: z.string().optional()
114
+ });
115
+ var I18nConfigSchema = z.object({
116
+ enabled: z.boolean().default(false),
117
+ strictness: z.enum(["strict", "standard", "permissive"]).default("standard"),
118
+ sourceLocale: z.string().default("en"),
119
+ targetLocales: z.array(z.string()).default([]),
120
+ framework: z.enum([
121
+ "auto",
122
+ "i18next",
123
+ "react-intl",
124
+ "vue-i18n",
125
+ "flutter-intl",
126
+ "apple",
127
+ "android",
128
+ "custom"
129
+ ]).default("auto"),
130
+ format: z.string().default("json"),
131
+ messageFormat: z.enum(["icu", "i18next", "custom"]).default("icu"),
132
+ keyConvention: z.enum(["dot-notation", "snake_case", "camelCase", "custom"]).default("dot-notation"),
133
+ translationPaths: z.record(z.string(), z.string()).optional(),
134
+ platforms: z.array(z.enum(["web", "mobile", "backend"])).default([]),
135
+ industry: z.string().optional(),
136
+ coverage: I18nCoverageConfigSchema.optional(),
137
+ pseudoLocale: z.string().optional(),
138
+ mcp: I18nMcpConfigSchema.optional()
139
+ });
140
+ var ModelTierConfigSchema = z.object({
141
+ fast: z.string().optional(),
142
+ standard: z.string().optional(),
143
+ strong: z.string().optional()
144
+ });
145
+ var ReviewConfigSchema = z.object({
146
+ model_tiers: ModelTierConfigSchema.optional()
147
+ });
106
148
  var HarnessConfigSchema = z.object({
107
149
  version: z.literal(1),
108
150
  name: z.string().optional(),
@@ -122,7 +164,10 @@ var HarnessConfigSchema = z.object({
122
164
  version: z.number()
123
165
  }).optional(),
124
166
  phaseGates: PhaseGatesConfigSchema.optional(),
125
- design: DesignConfigSchema.optional()
167
+ design: DesignConfigSchema.optional(),
168
+ i18n: I18nConfigSchema.optional(),
169
+ review: ReviewConfigSchema.optional(),
170
+ updateCheckInterval: z.number().int().min(0).optional()
126
171
  });
127
172
 
128
173
  // src/config/loader.ts
@@ -314,7 +359,7 @@ function createValidateCommand() {
314
359
  process.exit(result.error.exitCode);
315
360
  }
316
361
  if (opts.crossCheck) {
317
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-WGXQ7K62.js");
362
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-2OPGCGGU.js");
318
363
  const cwd = process.cwd();
319
364
  const specsDir = path2.join(cwd, "docs", "specs");
320
365
  const plansDir = path2.join(cwd, "docs", "plans");
@@ -680,7 +725,7 @@ function createPerfCommand() {
680
725
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
681
726
  const globalOpts = cmd.optsWithGlobals();
682
727
  const cwd = process.cwd();
683
- const { BenchmarkRunner } = await import("./dist-C4J67MPP.js");
728
+ const { BenchmarkRunner } = await import("./dist-NT3GXHQZ.js");
684
729
  const runner = new BenchmarkRunner();
685
730
  const benchFiles = runner.discover(cwd, glob2);
686
731
  if (benchFiles.length === 0) {
@@ -749,7 +794,7 @@ Results (${result.results.length} benchmarks):`);
749
794
  baselines.command("update").description("Update baselines from latest benchmark run").action(async (_opts, cmd) => {
750
795
  const globalOpts = cmd.optsWithGlobals();
751
796
  const cwd = process.cwd();
752
- const { BenchmarkRunner } = await import("./dist-C4J67MPP.js");
797
+ const { BenchmarkRunner } = await import("./dist-NT3GXHQZ.js");
753
798
  const runner = new BenchmarkRunner();
754
799
  const manager = new BaselineManager(cwd);
755
800
  logger.info("Running benchmarks to update baselines...");
@@ -777,7 +822,7 @@ Results (${result.results.length} benchmarks):`);
777
822
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
778
823
  const globalOpts = cmd.optsWithGlobals();
779
824
  const cwd = process.cwd();
780
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-C4J67MPP.js");
825
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-NT3GXHQZ.js");
781
826
  const analyzer = new EntropyAnalyzer2({
782
827
  rootDir: path6.resolve(cwd),
783
828
  analyze: { complexity: true, coupling: true }
@@ -2293,34 +2338,54 @@ async function runAgentReview(options) {
2293
2338
  return Err(new CLIError(parsedDiffResult.error.message, ExitCode.ERROR));
2294
2339
  }
2295
2340
  const codeChanges = parsedDiffResult.value;
2296
- const review = await createSelfReview(codeChanges, {
2297
- rootDir: config.rootDir,
2298
- diffAnalysis: {
2299
- enabled: true,
2300
- checkTestCoverage: true
2301
- }
2302
- });
2303
- if (!review.ok) {
2304
- return Err(new CLIError(review.error.message, ExitCode.ERROR));
2341
+ let commitMessage = "";
2342
+ try {
2343
+ commitMessage = execSync2("git log --oneline -1", { encoding: "utf-8" }).trim();
2344
+ } catch {
2305
2345
  }
2346
+ const diffInfo = {
2347
+ changedFiles: codeChanges.files.map((f) => f.path),
2348
+ newFiles: codeChanges.files.filter((f) => f.status === "added").map((f) => f.path),
2349
+ deletedFiles: codeChanges.files.filter((f) => f.status === "deleted").map((f) => f.path),
2350
+ totalDiffLines: diff.split("\n").length,
2351
+ fileDiffs: new Map(codeChanges.files.map((f) => [f.path, ""]))
2352
+ };
2353
+ const pipelineResult = await runReviewPipeline({
2354
+ projectRoot: config.rootDir,
2355
+ diff: diffInfo,
2356
+ commitMessage,
2357
+ flags: {
2358
+ comment: options.comment ?? false,
2359
+ ci: options.ci ?? false,
2360
+ deep: options.deep ?? false,
2361
+ noMechanical: options.noMechanical ?? false
2362
+ },
2363
+ config
2364
+ });
2306
2365
  return Ok({
2307
- passed: review.value.passed,
2308
- checklist: review.value.items.map((item) => ({
2309
- check: item.check,
2310
- passed: item.passed,
2311
- details: item.details
2312
- }))
2366
+ passed: pipelineResult.exitCode === 0,
2367
+ checklist: pipelineResult.findings.map((f) => ({
2368
+ check: `[${f.domain}] ${f.title}`,
2369
+ passed: f.severity === "suggestion",
2370
+ details: f.rationale
2371
+ })),
2372
+ pipelineResult
2313
2373
  });
2314
2374
  }
2315
2375
  function createReviewCommand() {
2316
- return new Command12("review").description("Run self-review on current changes").action(async (_opts, cmd) => {
2376
+ return new Command12("review").description("Run unified code review pipeline on current changes").option("--comment", "Post inline comments to GitHub PR").option("--ci", "Enable eligibility gate, non-interactive output").option("--deep", "Add threat modeling pass to security agent").option("--no-mechanical", "Skip mechanical checks").action(async (opts, cmd) => {
2317
2377
  const globalOpts = cmd.optsWithGlobals();
2318
2378
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : OutputMode.TEXT;
2319
2379
  const result = await runAgentReview({
2320
2380
  configPath: globalOpts.config,
2321
2381
  json: globalOpts.json,
2322
2382
  verbose: globalOpts.verbose,
2323
- quiet: globalOpts.quiet
2383
+ quiet: globalOpts.quiet,
2384
+ comment: opts.comment,
2385
+ ci: opts.ci,
2386
+ deep: opts.deep,
2387
+ noMechanical: opts.mechanical === false
2388
+ // Commander negation: --no-mechanical sets mechanical=false
2324
2389
  });
2325
2390
  if (!result.ok) {
2326
2391
  if (mode === OutputMode.JSON) {
@@ -2330,20 +2395,32 @@ function createReviewCommand() {
2330
2395
  }
2331
2396
  process.exit(result.error.exitCode);
2332
2397
  }
2398
+ const { pipelineResult } = result.value;
2333
2399
  if (mode === OutputMode.JSON) {
2334
- console.log(JSON.stringify(result.value, null, 2));
2400
+ console.log(
2401
+ JSON.stringify(
2402
+ {
2403
+ ...result.value,
2404
+ pipelineResult: pipelineResult ? {
2405
+ assessment: pipelineResult.assessment,
2406
+ findings: pipelineResult.findings,
2407
+ exitCode: pipelineResult.exitCode
2408
+ } : void 0
2409
+ },
2410
+ null,
2411
+ 2
2412
+ )
2413
+ );
2335
2414
  } else if (mode !== OutputMode.QUIET) {
2336
- console.log(result.value.passed ? "v Self-review passed" : "x Self-review found issues");
2337
- console.log("");
2338
- for (const item of result.value.checklist) {
2339
- const icon = item.passed ? "v" : "x";
2340
- console.log(` ${icon} ${item.check}`);
2341
- if (item.details && !item.passed) {
2342
- console.log(` ${item.details}`);
2343
- }
2415
+ if (pipelineResult) {
2416
+ console.log(pipelineResult.terminalOutput);
2417
+ } else {
2418
+ console.log(result.value.passed ? "v Self-review passed" : "x Self-review found issues");
2344
2419
  }
2345
2420
  }
2346
- process.exit(result.value.passed ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
2421
+ process.exit(
2422
+ pipelineResult ? pipelineResult.exitCode : result.value.passed ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED
2423
+ );
2347
2424
  });
2348
2425
  }
2349
2426
 
@@ -4698,6 +4775,14 @@ var AGENT_DESCRIPTIONS = {
4698
4775
  verifier: "Verify implementation completeness against spec and plan at three tiers (EXISTS, SUBSTANTIVE, WIRED). Use when checking if built code matches what was planned, validating phase completion, or auditing implementation quality."
4699
4776
  };
4700
4777
  var DEFAULT_TOOLS = ["Bash", "Read", "Write", "Edit", "Glob", "Grep"];
4778
+ var GEMINI_TOOL_MAP = {
4779
+ Bash: "run_shell_command",
4780
+ Read: "read_file",
4781
+ Write: "write_file",
4782
+ Edit: "replace",
4783
+ Glob: "glob",
4784
+ Grep: "search_file_content"
4785
+ };
4701
4786
  function generateAgentDefinition(persona, skillContents) {
4702
4787
  const kebabName = toKebabCase(persona.name);
4703
4788
  const name = `harness-${kebabName}`;
@@ -4712,7 +4797,7 @@ function generateAgentDefinition(persona, skillContents) {
4712
4797
  return {
4713
4798
  name,
4714
4799
  description,
4715
- tools: DEFAULT_TOOLS,
4800
+ tools: [...DEFAULT_TOOLS],
4716
4801
  role: persona.role,
4717
4802
  skills: persona.skills,
4718
4803
  steps: persona.steps,
@@ -4770,6 +4855,9 @@ function renderClaudeCodeAgent(def) {
4770
4855
  }
4771
4856
 
4772
4857
  // src/agent-definitions/render-gemini-cli.ts
4858
+ function toGeminiToolName(tool) {
4859
+ return GEMINI_TOOL_MAP[tool] ?? tool;
4860
+ }
4773
4861
  function formatStep2(step, index) {
4774
4862
  if ("command" in step && step.command) {
4775
4863
  const cmd = step.command;
@@ -4791,7 +4879,7 @@ function renderGeminiAgent(def) {
4791
4879
  if (def.tools.length > 0) {
4792
4880
  lines.push("tools:");
4793
4881
  for (const tool of def.tools) {
4794
- lines.push(` - ${tool}`);
4882
+ lines.push(` - ${toGeminiToolName(tool)}`);
4795
4883
  }
4796
4884
  }
4797
4885
  lines.push("---");
@@ -4994,7 +5082,7 @@ function createGenerateCommand3() {
4994
5082
  import { Command as Command39 } from "commander";
4995
5083
  import * as path37 from "path";
4996
5084
  async function runScan(projectPath) {
4997
- const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-N4D4QWFV.js");
5085
+ const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-BDO5GFEM.js");
4998
5086
  const store = new GraphStore();
4999
5087
  const start = Date.now();
5000
5088
  await new CodeIngestor(store).ingest(projectPath);
@@ -5075,7 +5163,7 @@ async function runIngest(projectPath, source, opts) {
5075
5163
  SyncManager,
5076
5164
  JiraConnector,
5077
5165
  SlackConnector
5078
- } = await import("./dist-N4D4QWFV.js");
5166
+ } = await import("./dist-BDO5GFEM.js");
5079
5167
  const graphDir = path38.join(projectPath, ".harness", "graph");
5080
5168
  const store = new GraphStore();
5081
5169
  await store.load(graphDir);
@@ -5168,7 +5256,7 @@ function createIngestCommand() {
5168
5256
  import { Command as Command41 } from "commander";
5169
5257
  import * as path39 from "path";
5170
5258
  async function runQuery(projectPath, rootNodeId, opts) {
5171
- const { GraphStore, ContextQL } = await import("./dist-N4D4QWFV.js");
5259
+ const { GraphStore, ContextQL } = await import("./dist-BDO5GFEM.js");
5172
5260
  const store = new GraphStore();
5173
5261
  const graphDir = path39.join(projectPath, ".harness", "graph");
5174
5262
  const loaded = await store.load(graphDir);
@@ -5217,7 +5305,7 @@ import { Command as Command42 } from "commander";
5217
5305
  // src/commands/graph/status.ts
5218
5306
  import * as path40 from "path";
5219
5307
  async function runGraphStatus(projectPath) {
5220
- const { GraphStore } = await import("./dist-N4D4QWFV.js");
5308
+ const { GraphStore } = await import("./dist-BDO5GFEM.js");
5221
5309
  const graphDir = path40.join(projectPath, ".harness", "graph");
5222
5310
  const store = new GraphStore();
5223
5311
  const loaded = await store.load(graphDir);
@@ -5257,7 +5345,7 @@ async function runGraphStatus(projectPath) {
5257
5345
  // src/commands/graph/export.ts
5258
5346
  import * as path41 from "path";
5259
5347
  async function runGraphExport(projectPath, format) {
5260
- const { GraphStore } = await import("./dist-N4D4QWFV.js");
5348
+ const { GraphStore } = await import("./dist-BDO5GFEM.js");
5261
5349
  const graphDir = path41.join(projectPath, ".harness", "graph");
5262
5350
  const store = new GraphStore();
5263
5351
  const loaded = await store.load(graphDir);
@@ -5386,6 +5474,8 @@ export {
5386
5474
  runCheckPhaseGate,
5387
5475
  generateSlashCommands,
5388
5476
  AGENT_DESCRIPTIONS,
5477
+ DEFAULT_TOOLS,
5478
+ GEMINI_TOOL_MAP,
5389
5479
  generateAgentDefinition,
5390
5480
  renderClaudeCodeAgent,
5391
5481
  renderGeminiAgent,