@harness-engineering/cli 1.2.0 → 1.3.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 (52) hide show
  1. package/dist/bin/harness.js +1 -1
  2. package/dist/{chunk-IXT3KLVN.js → chunk-APYEWOCR.js} +355 -19
  3. package/dist/index.js +1 -1
  4. package/package.json +6 -4
  5. package/dist/agents/commands/claude-code/harness/add-component.md +0 -34
  6. package/dist/agents/commands/claude-code/harness/align-documentation.md +0 -33
  7. package/dist/agents/commands/claude-code/harness/architecture-advisor.md +0 -41
  8. package/dist/agents/commands/claude-code/harness/brainstorming.md +0 -42
  9. package/dist/agents/commands/claude-code/harness/check-mechanical-constraints.md +0 -32
  10. package/dist/agents/commands/claude-code/harness/cleanup-dead-code.md +0 -33
  11. package/dist/agents/commands/claude-code/harness/code-review.md +0 -33
  12. package/dist/agents/commands/claude-code/harness/debugging.md +0 -43
  13. package/dist/agents/commands/claude-code/harness/detect-doc-drift.md +0 -32
  14. package/dist/agents/commands/claude-code/harness/diagnostics.md +0 -43
  15. package/dist/agents/commands/claude-code/harness/enforce-architecture.md +0 -32
  16. package/dist/agents/commands/claude-code/harness/execution.md +0 -43
  17. package/dist/agents/commands/claude-code/harness/git-workflow.md +0 -32
  18. package/dist/agents/commands/claude-code/harness/initialize-project.md +0 -33
  19. package/dist/agents/commands/claude-code/harness/onboarding.md +0 -32
  20. package/dist/agents/commands/claude-code/harness/parallel-agents.md +0 -35
  21. package/dist/agents/commands/claude-code/harness/planning.md +0 -41
  22. package/dist/agents/commands/claude-code/harness/pre-commit-review.md +0 -38
  23. package/dist/agents/commands/claude-code/harness/refactoring.md +0 -35
  24. package/dist/agents/commands/claude-code/harness/skill-authoring.md +0 -35
  25. package/dist/agents/commands/claude-code/harness/state-management.md +0 -35
  26. package/dist/agents/commands/claude-code/harness/tdd.md +0 -42
  27. package/dist/agents/commands/claude-code/harness/validate-context-engineering.md +0 -32
  28. package/dist/agents/commands/claude-code/harness/verification.md +0 -38
  29. package/dist/agents/commands/gemini-cli/harness/add-component.toml +0 -240
  30. package/dist/agents/commands/gemini-cli/harness/align-documentation.toml +0 -238
  31. package/dist/agents/commands/gemini-cli/harness/architecture-advisor.toml +0 -469
  32. package/dist/agents/commands/gemini-cli/harness/brainstorming.toml +0 -326
  33. package/dist/agents/commands/gemini-cli/harness/check-mechanical-constraints.toml +0 -249
  34. package/dist/agents/commands/gemini-cli/harness/cleanup-dead-code.toml +0 -258
  35. package/dist/agents/commands/gemini-cli/harness/code-review.toml +0 -461
  36. package/dist/agents/commands/gemini-cli/harness/debugging.toml +0 -436
  37. package/dist/agents/commands/gemini-cli/harness/detect-doc-drift.toml +0 -215
  38. package/dist/agents/commands/gemini-cli/harness/diagnostics.toml +0 -401
  39. package/dist/agents/commands/gemini-cli/harness/enforce-architecture.toml +0 -222
  40. package/dist/agents/commands/gemini-cli/harness/execution.toml +0 -381
  41. package/dist/agents/commands/gemini-cli/harness/git-workflow.toml +0 -325
  42. package/dist/agents/commands/gemini-cli/harness/initialize-project.toml +0 -257
  43. package/dist/agents/commands/gemini-cli/harness/onboarding.toml +0 -316
  44. package/dist/agents/commands/gemini-cli/harness/parallel-agents.toml +0 -221
  45. package/dist/agents/commands/gemini-cli/harness/planning.toml +0 -405
  46. package/dist/agents/commands/gemini-cli/harness/pre-commit-review.toml +0 -294
  47. package/dist/agents/commands/gemini-cli/harness/refactoring.toml +0 -209
  48. package/dist/agents/commands/gemini-cli/harness/skill-authoring.toml +0 -350
  49. package/dist/agents/commands/gemini-cli/harness/state-management.toml +0 -354
  50. package/dist/agents/commands/gemini-cli/harness/tdd.toml +0 -247
  51. package/dist/agents/commands/gemini-cli/harness/validate-context-engineering.toml +0 -186
  52. package/dist/agents/commands/gemini-cli/harness/verification.toml +0 -334
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createProgram
4
- } from "../chunk-IXT3KLVN.js";
4
+ } from "../chunk-APYEWOCR.js";
5
5
  import "../chunk-3U5VZYR7.js";
6
6
  import {
7
7
  handleError
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-EFZOLZFB.js";
9
9
 
10
10
  // src/index.ts
11
- import { Command as Command29 } from "commander";
12
- import { VERSION } from "@harness-engineering/core";
11
+ import { Command as Command33 } from "commander";
12
+ import { VERSION as VERSION2 } from "@harness-engineering/core";
13
13
 
14
14
  // src/commands/validate.ts
15
15
  import { Command } from "commander";
@@ -1387,8 +1387,8 @@ async function runPersona(persona, executor) {
1387
1387
  const result = await Promise.race([
1388
1388
  executor(command),
1389
1389
  new Promise(
1390
- (resolve13) => setTimeout(
1391
- () => resolve13({ ok: false, error: new Error(TIMEOUT_ERROR_MESSAGE) }),
1390
+ (resolve14) => setTimeout(
1391
+ () => resolve14({ ok: false, error: new Error(TIMEOUT_ERROR_MESSAGE) }),
1392
1392
  remainingTime
1393
1393
  )
1394
1394
  )
@@ -2560,8 +2560,8 @@ function createResetCommand() {
2560
2560
  }
2561
2561
  if (!opts.yes) {
2562
2562
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2563
- const answer = await new Promise((resolve13) => {
2564
- rl.question("Reset project state? This cannot be undone. [y/N] ", resolve13);
2563
+ const answer = await new Promise((resolve14) => {
2564
+ rl.question("Reset project state? This cannot be undone. [y/N] ", resolve14);
2565
2565
  });
2566
2566
  rl.close();
2567
2567
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
@@ -2860,8 +2860,7 @@ function buildArgumentHint(args) {
2860
2860
 
2861
2861
  // src/slash-commands/render-claude-code.ts
2862
2862
  function renderClaudeCode(spec) {
2863
- const lines = [GENERATED_HEADER_CLAUDE];
2864
- lines.push("---");
2863
+ const lines = ["---"];
2865
2864
  lines.push(`name: ${spec.fullName}`);
2866
2865
  lines.push(`description: ${spec.description}`);
2867
2866
  const hint = buildArgumentHint(spec.args);
@@ -2876,6 +2875,8 @@ function renderClaudeCode(spec) {
2876
2875
  }
2877
2876
  lines.push("---");
2878
2877
  lines.push("");
2878
+ lines.push(GENERATED_HEADER_CLAUDE);
2879
+ lines.push("");
2879
2880
  lines.push("<context>");
2880
2881
  lines.push(spec.prompt.context);
2881
2882
  lines.push("</context>");
@@ -2898,14 +2899,14 @@ function renderClaudeCode(spec) {
2898
2899
  }
2899
2900
 
2900
2901
  // src/slash-commands/render-gemini.ts
2901
- function escapeToml(content) {
2902
- return content.replace(/"""/g, '""\\"');
2902
+ function escapeTomlLiteral(content) {
2903
+ return content.replace(/'''/g, "''\\'''");
2903
2904
  }
2904
2905
  function renderGemini(spec, skillMdContent, skillYamlContent) {
2905
2906
  const lines = [GENERATED_HEADER_GEMINI];
2906
2907
  const safeDesc = spec.description.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
2907
2908
  lines.push(`description = "${safeDesc}"`);
2908
- lines.push('prompt = """');
2909
+ lines.push("prompt = '''");
2909
2910
  lines.push("<context>");
2910
2911
  lines.push(spec.prompt.context);
2911
2912
  lines.push("</context>");
@@ -2919,14 +2920,14 @@ function renderGemini(spec, skillMdContent, skillYamlContent) {
2919
2920
  if (skillMdContent) {
2920
2921
  const mdPath = spec.prompt.executionContext.split("\n")[0]?.replace(/^@/, "") ?? "";
2921
2922
  lines.push(`--- SKILL.md (${mdPath}) ---`);
2922
- lines.push(escapeToml(skillMdContent));
2923
+ lines.push(escapeTomlLiteral(skillMdContent));
2923
2924
  lines.push("");
2924
2925
  }
2925
2926
  if (skillYamlContent) {
2926
2927
  const refs = spec.prompt.executionContext.split("\n");
2927
2928
  const yamlPath = (refs[1] ?? refs[0] ?? "").replace(/^@/, "");
2928
2929
  lines.push(`--- skill.yaml (${yamlPath}) ---`);
2929
- lines.push(escapeToml(skillYamlContent));
2930
+ lines.push(escapeTomlLiteral(skillYamlContent));
2930
2931
  }
2931
2932
  lines.push("</execution_context>");
2932
2933
  lines.push("");
@@ -2938,7 +2939,7 @@ function renderGemini(spec, skillMdContent, skillYamlContent) {
2938
2939
  lines.push("<process>");
2939
2940
  lines.push(geminiProcess);
2940
2941
  lines.push("</process>");
2941
- lines.push('"""');
2942
+ lines.push("'''");
2942
2943
  lines.push("");
2943
2944
  return lines.join("\n");
2944
2945
  }
@@ -2972,7 +2973,7 @@ function computeSyncPlan(outputDir, rendered) {
2972
2973
  for (const filename of existing) {
2973
2974
  if (rendered.has(filename)) continue;
2974
2975
  const content = fs16.readFileSync(path24.join(outputDir, filename), "utf-8");
2975
- if (content.startsWith(GENERATED_HEADER_CLAUDE) || content.startsWith(GENERATED_HEADER_GEMINI)) {
2976
+ if (content.includes(GENERATED_HEADER_CLAUDE) || content.includes(GENERATED_HEADER_GEMINI)) {
2976
2977
  removed.push(filename);
2977
2978
  }
2978
2979
  }
@@ -3013,11 +3014,11 @@ function fileExtension(platform) {
3013
3014
  }
3014
3015
  async function confirmDeletion(files) {
3015
3016
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
3016
- return new Promise((resolve13) => {
3017
+ return new Promise((resolve14) => {
3017
3018
  rl.question(`
3018
3019
  Remove ${files.length} orphaned command(s)? (y/N) `, (answer) => {
3019
3020
  rl.close();
3020
- resolve13(answer.toLowerCase() === "y");
3021
+ resolve14(answer.toLowerCase() === "y");
3021
3022
  });
3022
3023
  });
3023
3024
  }
@@ -3139,10 +3140,343 @@ ${result.platform} \u2192 ${result.outputDir}`);
3139
3140
  });
3140
3141
  }
3141
3142
 
3143
+ // src/commands/ci/index.ts
3144
+ import { Command as Command31 } from "commander";
3145
+
3146
+ // src/commands/ci/check.ts
3147
+ import { Command as Command29 } from "commander";
3148
+ import { runCIChecks } from "@harness-engineering/core";
3149
+ var VALID_CHECKS = ["validate", "deps", "docs", "entropy", "phase-gate"];
3150
+ async function runCICheck(options) {
3151
+ const configResult = resolveConfig(options.configPath);
3152
+ if (!configResult.ok) {
3153
+ return configResult;
3154
+ }
3155
+ const input = {
3156
+ projectRoot: process.cwd(),
3157
+ config: configResult.value
3158
+ };
3159
+ if (options.skip) input.skip = options.skip;
3160
+ if (options.failOn) input.failOn = options.failOn;
3161
+ const result = await runCIChecks(input);
3162
+ if (!result.ok) {
3163
+ return {
3164
+ ok: false,
3165
+ error: new CLIError(result.error.message, ExitCode.ERROR)
3166
+ };
3167
+ }
3168
+ return { ok: true, value: result.value };
3169
+ }
3170
+ function parseSkip(skip) {
3171
+ if (!skip) return [];
3172
+ return skip.split(",").map((s) => s.trim()).filter((s) => VALID_CHECKS.includes(s));
3173
+ }
3174
+ function parseFailOn(failOn) {
3175
+ if (failOn === "warning") return "warning";
3176
+ return "error";
3177
+ }
3178
+ function createCheckCommand() {
3179
+ return new Command29("check").description("Run all harness checks for CI (validate, deps, docs, entropy, phase-gate)").option("--skip <checks>", "Comma-separated checks to skip (e.g., entropy,docs)").option("--fail-on <severity>", "Fail on severity level: error (default) or warning", "error").action(async (opts, cmd) => {
3180
+ const globalOpts = cmd.optsWithGlobals();
3181
+ const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
3182
+ const skip = parseSkip(opts.skip);
3183
+ const failOn = parseFailOn(opts.failOn);
3184
+ const result = await runCICheck({
3185
+ configPath: globalOpts.config,
3186
+ skip,
3187
+ failOn
3188
+ });
3189
+ if (!result.ok) {
3190
+ if (mode === OutputMode.JSON) {
3191
+ console.log(JSON.stringify({ error: result.error.message }));
3192
+ } else {
3193
+ logger.error(result.error.message);
3194
+ }
3195
+ process.exit(ExitCode.ERROR);
3196
+ }
3197
+ const report = result.value;
3198
+ if (mode === OutputMode.JSON) {
3199
+ console.log(JSON.stringify(report, null, 2));
3200
+ } else if (mode !== OutputMode.QUIET) {
3201
+ for (const check of report.checks) {
3202
+ const logFn = check.status === "pass" ? logger.success : check.status === "fail" ? logger.error : check.status === "warn" ? logger.warn : logger.dim;
3203
+ logFn(`${check.name}: ${check.status} (${check.durationMs}ms)`);
3204
+ for (const issue of check.issues) {
3205
+ const prefix = issue.severity === "error" ? " x" : " !";
3206
+ console.log(`${prefix} ${issue.message}${issue.file ? ` (${issue.file})` : ""}`);
3207
+ }
3208
+ }
3209
+ console.log("");
3210
+ if (report.exitCode === 0) {
3211
+ logger.success(`All checks passed (${report.summary.passed}/${report.summary.total})`);
3212
+ } else {
3213
+ logger.error(
3214
+ `${report.summary.failed} failed, ${report.summary.warnings} warnings, ${report.summary.passed} passed`
3215
+ );
3216
+ }
3217
+ }
3218
+ process.exit(report.exitCode);
3219
+ });
3220
+ }
3221
+
3222
+ // src/commands/ci/init.ts
3223
+ import { Command as Command30 } from "commander";
3224
+ import * as fs18 from "fs";
3225
+ import * as path26 from "path";
3226
+ import { Ok as Ok17, Err as Err14 } from "@harness-engineering/core";
3227
+ var ALL_CHECKS = ["validate", "deps", "docs", "entropy", "phase-gate"];
3228
+ function buildSkipFlag(checks) {
3229
+ if (!checks) return "";
3230
+ const skipChecks = ALL_CHECKS.filter((c) => !checks.includes(c));
3231
+ if (skipChecks.length === 0) return "";
3232
+ return ` --skip ${skipChecks.join(",")}`;
3233
+ }
3234
+ function generateGitHubActions(skipFlag) {
3235
+ return `name: Harness Checks
3236
+
3237
+ on:
3238
+ push:
3239
+ branches: [main]
3240
+ pull_request:
3241
+ branches: [main]
3242
+
3243
+ concurrency:
3244
+ group: harness-\${{ github.ref }}
3245
+ cancel-in-progress: true
3246
+
3247
+ jobs:
3248
+ harness:
3249
+ runs-on: ubuntu-latest
3250
+ steps:
3251
+ - uses: actions/checkout@v4
3252
+ - uses: actions/setup-node@v4
3253
+ with:
3254
+ node-version: '22'
3255
+ - run: npm install -g @harness-engineering/cli
3256
+ - name: Run harness checks
3257
+ run: harness ci check --json${skipFlag}
3258
+ `;
3259
+ }
3260
+ function generateGitLabCI(skipFlag) {
3261
+ return `harness:
3262
+ stage: test
3263
+ image: node:22
3264
+ before_script:
3265
+ - npm install -g @harness-engineering/cli
3266
+ script:
3267
+ - harness ci check --json${skipFlag}
3268
+ rules:
3269
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
3270
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
3271
+ `;
3272
+ }
3273
+ function generateGenericScript(skipFlag) {
3274
+ return `#!/usr/bin/env bash
3275
+ set -euo pipefail
3276
+
3277
+ # Harness CI Check Script
3278
+ # Generated by: harness ci init --platform generic
3279
+
3280
+ if ! command -v harness &> /dev/null; then
3281
+ echo "Installing @harness-engineering/cli..."
3282
+ npm install -g @harness-engineering/cli
3283
+ fi
3284
+
3285
+ echo "Running harness checks..."
3286
+ harness ci check --json${skipFlag}
3287
+ EXIT_CODE=$?
3288
+
3289
+ if [ $EXIT_CODE -eq 0 ]; then
3290
+ echo "All harness checks passed."
3291
+ elif [ $EXIT_CODE -eq 1 ]; then
3292
+ echo "Harness checks failed. See report above."
3293
+ else
3294
+ echo "Harness internal error."
3295
+ fi
3296
+
3297
+ exit $EXIT_CODE
3298
+ `;
3299
+ }
3300
+ function generateCIConfig(options) {
3301
+ const { platform, checks } = options;
3302
+ const skipFlag = buildSkipFlag(checks);
3303
+ const generators = {
3304
+ github: { filename: ".github/workflows/harness.yml", generate: generateGitHubActions },
3305
+ gitlab: { filename: ".gitlab-ci-harness.yml", generate: generateGitLabCI },
3306
+ generic: { filename: "harness-ci.sh", generate: generateGenericScript }
3307
+ };
3308
+ const entry = generators[platform];
3309
+ if (!entry) {
3310
+ return Err14(new CLIError(`Unknown platform: ${platform}`, ExitCode.ERROR));
3311
+ }
3312
+ return Ok17({
3313
+ filename: entry.filename,
3314
+ content: entry.generate(skipFlag)
3315
+ });
3316
+ }
3317
+ function detectPlatform() {
3318
+ if (fs18.existsSync(".github")) return "github";
3319
+ if (fs18.existsSync(".gitlab-ci.yml")) return "gitlab";
3320
+ return null;
3321
+ }
3322
+ function createInitCommand2() {
3323
+ return new Command30("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
3324
+ const globalOpts = cmd.optsWithGlobals();
3325
+ const platform = opts.platform ?? detectPlatform() ?? "generic";
3326
+ const checks = opts.checks ? opts.checks.split(",").map((s) => s.trim()) : void 0;
3327
+ const opts2 = { platform };
3328
+ if (checks) opts2.checks = checks;
3329
+ const result = generateCIConfig(opts2);
3330
+ if (!result.ok) {
3331
+ logger.error(result.error.message);
3332
+ process.exit(result.error.exitCode);
3333
+ }
3334
+ const { filename, content } = result.value;
3335
+ const targetPath = path26.resolve(filename);
3336
+ const dir = path26.dirname(targetPath);
3337
+ fs18.mkdirSync(dir, { recursive: true });
3338
+ fs18.writeFileSync(targetPath, content);
3339
+ if (platform === "generic") {
3340
+ fs18.chmodSync(targetPath, "755");
3341
+ }
3342
+ if (globalOpts.json) {
3343
+ console.log(JSON.stringify({ file: filename, platform }));
3344
+ } else {
3345
+ logger.success(`Generated ${filename} for ${platform}`);
3346
+ logger.dim("Run 'harness ci check' to test locally");
3347
+ }
3348
+ });
3349
+ }
3350
+
3351
+ // src/commands/ci/index.ts
3352
+ function createCICommand() {
3353
+ const command = new Command31("ci").description("CI/CD integration commands");
3354
+ command.addCommand(createCheckCommand());
3355
+ command.addCommand(createInitCommand2());
3356
+ return command;
3357
+ }
3358
+
3359
+ // src/commands/update.ts
3360
+ import { Command as Command32 } from "commander";
3361
+ import { execSync as execSync3 } from "child_process";
3362
+ import { realpathSync } from "fs";
3363
+ import readline3 from "readline";
3364
+ import chalk4 from "chalk";
3365
+ import { VERSION } from "@harness-engineering/core";
3366
+ function detectPackageManager() {
3367
+ try {
3368
+ const argv1 = process.argv[1];
3369
+ if (!argv1) return "npm";
3370
+ const binPath = realpathSync(argv1);
3371
+ if (binPath.includes("pnpm/global/") || binPath.includes("pnpm-global/")) {
3372
+ return "pnpm";
3373
+ }
3374
+ if (binPath.includes(".yarn/")) {
3375
+ return "yarn";
3376
+ }
3377
+ } catch {
3378
+ }
3379
+ return "npm";
3380
+ }
3381
+ function getLatestVersion() {
3382
+ const output = execSync3("npm view @harness-engineering/cli dist-tags.latest", {
3383
+ encoding: "utf-8",
3384
+ timeout: 15e3
3385
+ });
3386
+ return output.trim();
3387
+ }
3388
+ function getInstalledPackages(pm) {
3389
+ try {
3390
+ const output = execSync3(`${pm} list -g --json`, {
3391
+ encoding: "utf-8",
3392
+ timeout: 15e3
3393
+ });
3394
+ const data = JSON.parse(output);
3395
+ const deps = data.dependencies ?? {};
3396
+ return Object.keys(deps).filter((name) => name.startsWith("@harness-engineering/"));
3397
+ } catch {
3398
+ return ["@harness-engineering/cli", "@harness-engineering/core"];
3399
+ }
3400
+ }
3401
+ function prompt(question) {
3402
+ const rl = readline3.createInterface({
3403
+ input: process.stdin,
3404
+ output: process.stdout
3405
+ });
3406
+ return new Promise((resolve14) => {
3407
+ rl.question(question, (answer) => {
3408
+ rl.close();
3409
+ resolve14(answer.trim().toLowerCase());
3410
+ });
3411
+ });
3412
+ }
3413
+ function createUpdateCommand() {
3414
+ return new Command32("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Install a specific version instead of latest").action(async (opts, cmd) => {
3415
+ const globalOpts = cmd.optsWithGlobals();
3416
+ const pm = detectPackageManager();
3417
+ if (globalOpts.verbose) {
3418
+ logger.info(`Detected package manager: ${pm}`);
3419
+ }
3420
+ let targetVersion;
3421
+ if (opts.version) {
3422
+ targetVersion = opts.version;
3423
+ } else {
3424
+ logger.info("Checking for updates...");
3425
+ try {
3426
+ targetVersion = getLatestVersion();
3427
+ } catch {
3428
+ logger.error("Failed to fetch latest version from npm registry");
3429
+ return process.exit(ExitCode.ERROR);
3430
+ }
3431
+ }
3432
+ if (VERSION === targetVersion) {
3433
+ logger.success(`Already up to date (v${VERSION})`);
3434
+ process.exit(ExitCode.SUCCESS);
3435
+ }
3436
+ console.log("");
3437
+ logger.info(`Current version: ${chalk4.dim(`v${VERSION}`)}`);
3438
+ logger.info(`Target version: ${chalk4.green(`v${targetVersion}`)}`);
3439
+ console.log("");
3440
+ const packages = getInstalledPackages(pm);
3441
+ if (globalOpts.verbose) {
3442
+ logger.info(`Installed packages: ${packages.join(", ")}`);
3443
+ }
3444
+ const installArgs = packages.map((pkg) => `${pkg}@${targetVersion}`).join(" ");
3445
+ const installCmd = `${pm} install -g ${installArgs}`;
3446
+ if (globalOpts.verbose) {
3447
+ logger.info(`Running: ${installCmd}`);
3448
+ }
3449
+ try {
3450
+ logger.info("Updating packages...");
3451
+ execSync3(installCmd, { stdio: "inherit", timeout: 12e4 });
3452
+ console.log("");
3453
+ logger.success(`Updated to v${targetVersion}`);
3454
+ } catch {
3455
+ console.log("");
3456
+ logger.error("Update failed. You can try manually:");
3457
+ console.log(` ${chalk4.cyan(installCmd)}`);
3458
+ process.exit(ExitCode.ERROR);
3459
+ }
3460
+ console.log("");
3461
+ const regenAnswer = await prompt("Regenerate slash commands? (y/N) ");
3462
+ if (regenAnswer === "y" || regenAnswer === "yes") {
3463
+ const scopeAnswer = await prompt("Generate for (g)lobal or (l)ocal project? (g/l) ");
3464
+ const globalFlag = scopeAnswer === "g" || scopeAnswer === "global" ? " --global" : "";
3465
+ try {
3466
+ execSync3(`harness generate-slash-commands${globalFlag}`, { stdio: "inherit" });
3467
+ } catch {
3468
+ logger.warn("Slash command generation failed. Run manually:");
3469
+ console.log(` ${chalk4.cyan(`harness generate-slash-commands${globalFlag}`)}`);
3470
+ }
3471
+ }
3472
+ process.exit(ExitCode.SUCCESS);
3473
+ });
3474
+ }
3475
+
3142
3476
  // src/index.ts
3143
3477
  function createProgram() {
3144
- const program = new Command29();
3145
- program.name("harness").description("CLI for Harness Engineering toolkit").version(VERSION).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
3478
+ const program = new Command33();
3479
+ program.name("harness").description("CLI for Harness Engineering toolkit").version(VERSION2).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
3146
3480
  program.addCommand(createValidateCommand());
3147
3481
  program.addCommand(createCheckDepsCommand());
3148
3482
  program.addCommand(createCheckDocsCommand());
@@ -3159,6 +3493,8 @@ function createProgram() {
3159
3493
  program.addCommand(createCreateSkillCommand());
3160
3494
  program.addCommand(createSetupMcpCommand());
3161
3495
  program.addCommand(createGenerateSlashCommandsCommand());
3496
+ program.addCommand(createCICommand());
3497
+ program.addCommand(createUpdateCommand());
3162
3498
  return program;
3163
3499
  }
3164
3500
 
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  resolveConfig,
16
16
  runCheckPhaseGate,
17
17
  runPersona
18
- } from "./chunk-IXT3KLVN.js";
18
+ } from "./chunk-APYEWOCR.js";
19
19
  import {
20
20
  runCrossCheck
21
21
  } from "./chunk-3U5VZYR7.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-engineering/cli",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI for Harness Engineering toolkit",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,7 +26,7 @@
26
26
  "handlebars": "^4.7.0",
27
27
  "yaml": "^2.3.0",
28
28
  "zod": "^3.22.0",
29
- "@harness-engineering/core": "0.5.0",
29
+ "@harness-engineering/core": "0.7.0",
30
30
  "@harness-engineering/linter-gen": "0.1.0"
31
31
  },
32
32
  "devDependencies": {
@@ -53,7 +53,9 @@
53
53
  "dev": "tsup src/index.ts src/bin/harness.ts --format esm --dts --watch",
54
54
  "lint": "eslint src",
55
55
  "typecheck": "tsc --noEmit",
56
- "test": "vitest",
57
- "test:coverage": "vitest run --coverage"
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "test:coverage": "vitest run --coverage",
59
+ "clean": "rm -rf dist"
58
60
  }
59
61
  }
@@ -1,34 +0,0 @@
1
- ## <!-- Generated by harness generate-slash-commands. Do not edit. -->
2
-
3
- name: harness:add-component
4
- description: Add a component to an existing harness project
5
- argument-hint: "[--path <path>]"
6
- allowed-tools:
7
-
8
- - Bash
9
- - Read
10
- - Write
11
- - Edit
12
- - Glob
13
-
14
- ---
15
-
16
- <context>
17
- Cognitive mode: constructive-architect
18
- Type: flexible
19
- </context>
20
-
21
- <objective>
22
- Add a component to an existing harness project
23
- </objective>
24
-
25
- <execution_context>
26
- @agents/skills/claude-code/add-harness-component/SKILL.md
27
- @agents/skills/claude-code/add-harness-component/skill.yaml
28
- </execution_context>
29
-
30
- <process>
31
- 1. Try: invoke mcp__harness__run_skill with skill: "add-harness-component"
32
- 2. If MCP unavailable: read SKILL.md and follow its workflow directly
33
- 3. Pass through any arguments provided by the user
34
- </process>
@@ -1,33 +0,0 @@
1
- ## <!-- Generated by harness generate-slash-commands. Do not edit. -->
2
-
3
- name: harness:align-documentation
4
- description: Auto-fix documentation drift issues
5
- argument-hint: "[--path <path>]"
6
- allowed-tools:
7
-
8
- - Bash
9
- - Read
10
- - Write
11
- - Edit
12
-
13
- ---
14
-
15
- <context>
16
- Cognitive mode: meticulous-verifier
17
- Type: flexible
18
- </context>
19
-
20
- <objective>
21
- Auto-fix documentation drift issues
22
- </objective>
23
-
24
- <execution_context>
25
- @agents/skills/claude-code/align-documentation/SKILL.md
26
- @agents/skills/claude-code/align-documentation/skill.yaml
27
- </execution_context>
28
-
29
- <process>
30
- 1. Try: invoke mcp__harness__run_skill with skill: "align-documentation"
31
- 2. If MCP unavailable: read SKILL.md and follow its workflow directly
32
- 3. Pass through any arguments provided by the user
33
- </process>
@@ -1,41 +0,0 @@
1
- ## <!-- Generated by harness generate-slash-commands. Do not edit. -->
2
-
3
- name: harness:architecture-advisor
4
- description: Interactive architecture advisor that surfaces trade-offs and helps humans choose
5
- argument-hint: "[--path <path>] [--topic <topic>]"
6
- allowed-tools:
7
-
8
- - Read
9
- - Glob
10
- - Grep
11
- - Bash
12
-
13
- ---
14
-
15
- <context>
16
- Cognitive mode: advisory-guide
17
- Type: flexible
18
- State: persistent (files: .harness/architecture/)
19
- </context>
20
-
21
- <objective>
22
- Interactive architecture advisor that surfaces trade-offs and helps humans choose
23
-
24
- Phases:
25
-
26
- - discover: Ask questions about the problem space and constraints
27
- - analyze: Research the codebase and identify relevant patterns
28
- - propose: Present 2-3 architectural options with trade-offs
29
- - document: Write an Architecture Decision Record for the chosen option
30
- </objective>
31
-
32
- <execution_context>
33
- @agents/skills/claude-code/harness-architecture-advisor/SKILL.md
34
- @agents/skills/claude-code/harness-architecture-advisor/skill.yaml
35
- </execution_context>
36
-
37
- <process>
38
- 1. Try: invoke mcp__harness__run_skill with skill: "harness-architecture-advisor"
39
- 2. If MCP unavailable: read SKILL.md and follow its workflow directly
40
- 3. Pass through any arguments provided by the user
41
- </process>
@@ -1,42 +0,0 @@
1
- ## <!-- Generated by harness generate-slash-commands. Do not edit. -->
2
-
3
- name: harness:brainstorming
4
- description: Structured ideation and exploration with harness methodology
5
- argument-hint: "[--path <path>]"
6
- allowed-tools:
7
-
8
- - Bash
9
- - Read
10
- - Write
11
- - Edit
12
- - Glob
13
- - Grep
14
-
15
- ---
16
-
17
- <context>
18
- Cognitive mode: constructive-architect
19
- Type: rigid
20
- </context>
21
-
22
- <objective>
23
- Structured ideation and exploration with harness methodology
24
-
25
- Phases:
26
-
27
- - explore: Generate ideas and possibilities
28
- - evaluate: Assess ideas against constraints
29
- - prioritize: Select and sequence top ideas
30
- - validate: Run harness checks on selected approach
31
- </objective>
32
-
33
- <execution_context>
34
- @agents/skills/claude-code/harness-brainstorming/SKILL.md
35
- @agents/skills/claude-code/harness-brainstorming/skill.yaml
36
- </execution_context>
37
-
38
- <process>
39
- 1. Try: invoke mcp__harness__run_skill with skill: "harness-brainstorming"
40
- 2. If MCP unavailable: read SKILL.md and follow its workflow directly
41
- 3. Pass through any arguments provided by the user
42
- </process>