musubix2 0.5.0 → 0.5.2

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.
package/dist/cli.js CHANGED
@@ -11780,8 +11780,8 @@ __export(init_command_handler_exports, {
11780
11780
  InitCommandHandler: () => InitCommandHandler,
11781
11781
  createInitCommandHandler: () => createInitCommandHandler
11782
11782
  });
11783
- import { readdirSync } from "node:fs";
11784
- import { basename } from "node:path";
11783
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, existsSync as existsSync10 } from "node:fs";
11784
+ import { basename, join as join5 } from "node:path";
11785
11785
  function createInitCommandHandler() {
11786
11786
  const locator = new PackageRootLocator();
11787
11787
  const catalog = new PackageAssetCatalog(locator);
@@ -11800,7 +11800,7 @@ function createInitCommandHandler() {
11800
11800
  const dryRunReporter = new DryRunReporter();
11801
11801
  return new InitCommandHandler(detector, confirmation, planner, copilotSetup, claudeSetup, merger, writer, updateService, dryRunReporter);
11802
11802
  }
11803
- var InitCommandHandler;
11803
+ var STARTER_REQUIREMENTS, InitCommandHandler;
11804
11804
  var init_init_command_handler = __esm({
11805
11805
  "dist/interface/cli/init-command-handler.js"() {
11806
11806
  "use strict";
@@ -11819,6 +11819,20 @@ var init_init_command_handler = __esm({
11819
11819
  init_workspace_writer();
11820
11820
  init_confirmation_resolver();
11821
11821
  init_dry_run_reporter();
11822
+ STARTER_REQUIREMENTS = `# \u8981\u4EF6\u5B9A\u7FA9\u66F8
11823
+
11824
+ > \`musubix requirements analyze storage/specs/requirements.md\` \u3067\u89E3\u6790\u3067\u304D\u307E\u3059\u3002
11825
+ > \u8981\u4EF6\u306F\u898B\u51FA\u3057\u5F62\u5F0F\u30FBID \u306F \`REQ-<3\u6587\u5B57\u30C9\u30E1\u30A4\u30F3>-<3\u6841\u9023\u756A>\` \u3067\u8A18\u8FF0\u3057\u3066\u304F\u3060\u3055\u3044\u3002
11826
+
11827
+ ## REQ-SMP-001: \u30B5\u30F3\u30D7\u30EB\u8981\u4EF6
11828
+ **\u7A2E\u5225**: UBIQUITOUS
11829
+ **\u512A\u5148\u5EA6**: P1
11830
+ **\u8981\u4EF6**:
11831
+ THE \u30B7\u30B9\u30C6\u30E0 SHALL \u30E6\u30FC\u30B6\u30FC\u306B\u30B5\u30F3\u30D7\u30EB\u6A5F\u80FD\u3092\u63D0\u4F9B\u3059\u308B\u3002
11832
+
11833
+ **\u53D7\u5165\u57FA\u6E96**:
11834
+ - [ ] \u30B5\u30F3\u30D7\u30EB\u6A5F\u80FD\u304C\u52D5\u4F5C\u3059\u308B
11835
+ `;
11822
11836
  InitCommandHandler = class {
11823
11837
  detector;
11824
11838
  confirmation;
@@ -11886,22 +11900,49 @@ var init_init_command_handler = __esm({
11886
11900
  await this.writer.execute(copilotOps, false);
11887
11901
  }
11888
11902
  const summary = await this.writer.execute([], true);
11903
+ const scaffolded = options.dryRun ? [] : this.scaffoldSddWorkspace(options.projectPath);
11889
11904
  return {
11890
11905
  detectedPlatforms: selection,
11891
- created: summary.created,
11906
+ created: [...summary.created, ...scaffolded],
11892
11907
  updated: summary.updated,
11893
11908
  skipped: summary.skipped,
11894
11909
  warnings,
11895
11910
  durationMs: Date.now() - start
11896
11911
  };
11897
11912
  }
11898
- buildProjectContext(projectPath) {
11899
- const name = basename(projectPath);
11900
- let rootStructure = [];
11913
+ /**
11914
+ * Create the SDD directory skeleton and a parseable starter requirements
11915
+ * document. Idempotent and non-destructive — existing files are left as-is.
11916
+ * Returns the relative paths of files/dirs actually created.
11917
+ */
11918
+ scaffoldSddWorkspace(projectPath) {
11919
+ const created = [];
11901
11920
  try {
11902
- rootStructure = readdirSync(projectPath, { withFileTypes: true }).slice(0, 20).map((d) => d.isDirectory() ? `${d.name}/` : d.name);
11921
+ for (const dir of ["steering", "storage/specs"]) {
11922
+ const abs = join5(projectPath, dir);
11923
+ if (!existsSync10(abs)) {
11924
+ mkdirSync2(abs, { recursive: true });
11925
+ created.push(`${dir}/`);
11926
+ }
11927
+ }
11928
+ const reqPath = join5(projectPath, "storage/specs/requirements.md");
11929
+ if (!existsSync10(reqPath)) {
11930
+ writeFileSync2(reqPath, STARTER_REQUIREMENTS, "utf-8");
11931
+ created.push("storage/specs/requirements.md");
11932
+ }
11903
11933
  } catch {
11904
11934
  }
11935
+ return created;
11936
+ }
11937
+ buildProjectContext(projectPath) {
11938
+ const name = basename(projectPath);
11939
+ const rootStructure = [
11940
+ "steering/ # \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30E1\u30E2\u30EA\uFF08\u6C7A\u5B9A\u524D\u306B\u53C2\u7167\uFF09",
11941
+ "storage/specs/ # requirements / design / tasks \u4ED5\u69D8",
11942
+ ".claude/skills/ # SDD Agent Skills",
11943
+ "src/ # \u5B9F\u88C5\u30B3\u30FC\u30C9",
11944
+ "tests/ # \u30C6\u30B9\u30C8\u30B3\u30FC\u30C9"
11945
+ ];
11905
11946
  return {
11906
11947
  projectName: name,
11907
11948
  packageManager: "npm",
@@ -12903,7 +12944,7 @@ __export(dist_exports16, {
12903
12944
  import { execFile } from "node:child_process";
12904
12945
  import { writeFile as writeFile3, unlink } from "node:fs/promises";
12905
12946
  import { tmpdir as tmpdir2 } from "node:os";
12906
- import { join as join5 } from "node:path";
12947
+ import { join as join6 } from "node:path";
12907
12948
  import { promisify } from "node:util";
12908
12949
  import { randomBytes } from "node:crypto";
12909
12950
  function sanitizeName(raw) {
@@ -13106,7 +13147,7 @@ var init_dist16 = __esm({
13106
13147
  }
13107
13148
  async realSolve(smtScript) {
13108
13149
  const start = Date.now();
13109
- const tmpFile = join5(tmpdir2(), `musubix2-z3-${randomBytes(8).toString("hex")}.smt2`);
13150
+ const tmpFile = join6(tmpdir2(), `musubix2-z3-${randomBytes(8).toString("hex")}.smt2`);
13110
13151
  try {
13111
13152
  await writeFile3(tmpFile, smtScript, "utf-8");
13112
13153
  const { stdout, stderr } = await execFileAsync(this.z3Path, ["-smt2", tmpFile], {
@@ -13330,7 +13371,7 @@ __export(dist_exports17, {
13330
13371
  import { execFile as execFile2 } from "node:child_process";
13331
13372
  import { writeFile as writeFile4, unlink as unlink2 } from "node:fs/promises";
13332
13373
  import { tmpdir as tmpdir3 } from "node:os";
13333
- import { join as join6 } from "node:path";
13374
+ import { join as join7 } from "node:path";
13334
13375
  import { promisify as promisify2 } from "node:util";
13335
13376
  import { randomBytes as randomBytes2 } from "node:crypto";
13336
13377
  function createLeanIntegration() {
@@ -13454,7 +13495,7 @@ var init_dist17 = __esm({
13454
13495
  time: Date.now() - start
13455
13496
  };
13456
13497
  }
13457
- const tmpFile = join6(tmpdir3(), `musubix2-lean-${randomBytes2(8).toString("hex")}.lean`);
13498
+ const tmpFile = join7(tmpdir3(), `musubix2-lean-${randomBytes2(8).toString("hex")}.lean`);
13458
13499
  try {
13459
13500
  await writeFile4(tmpFile, leanCode, "utf-8");
13460
13501
  const timeout = timeoutMs ?? this.defaultTimeoutMs;
@@ -15215,7 +15256,8 @@ init_dist5();
15215
15256
  init_dist6();
15216
15257
  init_dist();
15217
15258
  init_dist();
15218
- import { readFileSync as readFileSync6, existsSync as existsSync10 } from "node:fs";
15259
+ import { readFileSync as readFileSync6, existsSync as existsSync11, statSync, readdirSync } from "node:fs";
15260
+ import { join as joinPath } from "node:path";
15219
15261
  function parseArgs(argv) {
15220
15262
  const command = argv[0] ?? "";
15221
15263
  let subcommand;
@@ -15275,7 +15317,7 @@ var COMMAND_HELP = {
15275
15317
  description: "\u8A2D\u8A08\u751F\u6210"
15276
15318
  },
15277
15319
  codegen: {
15278
- usage: "musubix codegen [options]",
15320
+ usage: "musubix codegen [generate] <name> [--type class|interface|function|...]",
15279
15321
  description: "\u30B3\u30FC\u30C9\u751F\u6210"
15280
15322
  },
15281
15323
  tasks: {
@@ -15311,8 +15353,8 @@ var COMMAND_HELP = {
15311
15353
  description: "\u30B3\u30FC\u30C9\u30B0\u30E9\u30D5\u5206\u6790"
15312
15354
  },
15313
15355
  security: {
15314
- usage: "musubix security <path>",
15315
- description: "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30B9\u30AD\u30E3\u30F3"
15356
+ usage: "musubix security <path> [--fail-on critical|high|medium|low|info]",
15357
+ description: "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30B9\u30AD\u30E3\u30F3\uFF08\u30D5\u30A1\u30A4\u30EB/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5BFE\u5FDC\uFF09"
15316
15358
  },
15317
15359
  skills: {
15318
15360
  usage: "musubix skills <list|validate|create> [args]",
@@ -15407,7 +15449,7 @@ var CLIDispatcher = class {
15407
15449
  if (!command) {
15408
15450
  throw new Error(`Unknown command: ${commandName}. Available: ${[...this.commands.keys()].join(", ")}`);
15409
15451
  }
15410
- await command.action(args);
15452
+ return await command.action(args);
15411
15453
  }
15412
15454
  getHelp() {
15413
15455
  const lines = [
@@ -15445,12 +15487,12 @@ var CLIDispatcher = class {
15445
15487
  return ExitCode.SUCCESS;
15446
15488
  }
15447
15489
  try {
15448
- await this.dispatch(parsed.command, {
15490
+ const result = await this.dispatch(parsed.command, {
15449
15491
  subcommand: parsed.subcommand,
15450
15492
  args: parsed.args,
15451
15493
  ...parsed.flags
15452
15494
  });
15453
- return ExitCode.SUCCESS;
15495
+ return result ?? ExitCode.SUCCESS;
15454
15496
  } catch (err) {
15455
15497
  const message = err instanceof Error ? err.message : String(err);
15456
15498
  console.error(message);
@@ -15552,21 +15594,21 @@ async function handleInit(targetPath = ".", name, force) {
15552
15594
  console.log(` ${f}`);
15553
15595
  }
15554
15596
  try {
15555
- const { cpSync, existsSync: existsSync11, mkdirSync: mkdirSync2 } = await import("node:fs");
15597
+ const { cpSync, existsSync: existsSync12, mkdirSync: mkdirSync3 } = await import("node:fs");
15556
15598
  const { resolve: resolve9, dirname: dirname4 } = await import("node:path");
15557
15599
  const { fileURLToPath: fileURLToPath2 } = await import("node:url");
15558
15600
  const thisDir = typeof __dirname !== "undefined" ? __dirname : dirname4(fileURLToPath2(import.meta.url));
15559
15601
  const pkgGithub = resolve9(thisDir, "..", ".github");
15560
15602
  const destGithub = resolve9(targetPath, ".github");
15561
- if (existsSync11(pkgGithub)) {
15562
- mkdirSync2(destGithub, { recursive: true });
15603
+ if (existsSync12(pkgGithub)) {
15604
+ mkdirSync3(destGithub, { recursive: true });
15563
15605
  const skillsSrc = resolve9(pkgGithub, "skills");
15564
- if (existsSync11(skillsSrc)) {
15606
+ if (existsSync12(skillsSrc)) {
15565
15607
  cpSync(skillsSrc, resolve9(destGithub, "skills"), { recursive: true });
15566
15608
  console.log(" .github/skills/ (SDD skills)");
15567
15609
  }
15568
15610
  const instrSrc = resolve9(pkgGithub, "copilot-instructions.md");
15569
- if (existsSync11(instrSrc)) {
15611
+ if (existsSync12(instrSrc)) {
15570
15612
  cpSync(instrSrc, resolve9(destGithub, "copilot-instructions.md"));
15571
15613
  console.log(" .github/copilot-instructions.md");
15572
15614
  }
@@ -15581,6 +15623,7 @@ async function handleTrace(sub, args) {
15581
15623
  const generator = createMatrixGenerator();
15582
15624
  const report = generator.generate([], [], []);
15583
15625
  console.log(generator.toMarkdown(report));
15626
+ console.log("\n\u2139 No traceability data loaded \u2014 matrix is empty (completeness is N/A).");
15584
15627
  return ExitCode.SUCCESS;
15585
15628
  }
15586
15629
  case "validate": {
@@ -15612,6 +15655,11 @@ async function handleTrace(sub, args) {
15612
15655
  async function handleTraceVerify() {
15613
15656
  const validator = createTraceabilityValidator();
15614
15657
  const report = validator.validateCoverage([], [], [], []);
15658
+ if (report.totalRequirements === 0) {
15659
+ console.log("No traceability data loaded \u2014 nothing to verify.");
15660
+ console.log("\u2139 Coverage cannot be computed with 0 requirements (reported as N/A).");
15661
+ return ExitCode.SUCCESS;
15662
+ }
15615
15663
  console.log(`Coverage: ${report.coveragePercent}%`);
15616
15664
  console.log(`Requirements: ${report.coveredRequirements}/${report.totalRequirements}`);
15617
15665
  if (report.gaps.length > 0) {
@@ -15711,6 +15759,31 @@ var EXT_TO_LANG = {
15711
15759
  hs: "haskell",
15712
15760
  lua: "lua"
15713
15761
  };
15762
+ var WALK_IGNORE = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "coverage", ".next", "build"]);
15763
+ function collectFiles(target, extFilter) {
15764
+ const stat = statSync(target);
15765
+ if (stat.isFile())
15766
+ return [target];
15767
+ const out = [];
15768
+ const walk = (dir) => {
15769
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
15770
+ if (entry.name.startsWith(".") && entry.name !== ".")
15771
+ continue;
15772
+ if (WALK_IGNORE.has(entry.name))
15773
+ continue;
15774
+ const full = joinPath(dir, entry.name);
15775
+ if (entry.isDirectory()) {
15776
+ walk(full);
15777
+ } else if (entry.isFile()) {
15778
+ const ext = entry.name.split(".").pop() ?? "";
15779
+ if (!extFilter || extFilter(ext))
15780
+ out.push(full);
15781
+ }
15782
+ }
15783
+ };
15784
+ walk(target);
15785
+ return out;
15786
+ }
15714
15787
  async function handleCodegraph(sub, args) {
15715
15788
  switch (sub) {
15716
15789
  case "index": {
@@ -15720,29 +15793,40 @@ async function handleCodegraph(sub, args) {
15720
15793
  return ExitCode.GENERAL_ERROR;
15721
15794
  }
15722
15795
  try {
15723
- const parser = createASTParser();
15724
- const content = readFileSync6(targetPath, "utf-8");
15725
- const ext = targetPath.split(".").pop() ?? "";
15726
- const lang = EXT_TO_LANG[ext];
15727
- if (!lang) {
15728
- console.error(`\u274C Unsupported file extension: .${ext}`);
15796
+ if (!existsSync11(targetPath)) {
15797
+ console.error(`\u274C Path not found: ${targetPath}`);
15729
15798
  return ExitCode.GENERAL_ERROR;
15730
15799
  }
15731
- const nodes = parser.parse(content, lang);
15800
+ const parser = createASTParser();
15732
15801
  const engine = createGraphEngine();
15733
- for (const node of nodes) {
15734
- engine.addNode({
15735
- id: `${targetPath}:${node.name}`,
15736
- name: node.name,
15737
- kind: node.kind,
15738
- filePath: targetPath,
15739
- language: lang,
15740
- startLine: 0,
15741
- endLine: 0
15742
- });
15802
+ const files = collectFiles(targetPath, (ext) => ext in EXT_TO_LANG);
15803
+ if (files.length === 0) {
15804
+ console.error(`\u274C No indexable source files found under: ${targetPath}`);
15805
+ return ExitCode.GENERAL_ERROR;
15806
+ }
15807
+ let indexedFiles = 0;
15808
+ for (const file of files) {
15809
+ const ext = file.split(".").pop() ?? "";
15810
+ const lang = EXT_TO_LANG[ext];
15811
+ if (!lang)
15812
+ continue;
15813
+ const content = readFileSync6(file, "utf-8");
15814
+ const nodes = parser.parse(content, lang);
15815
+ for (const node of nodes) {
15816
+ engine.addNode({
15817
+ id: `${file}:${node.name}`,
15818
+ name: node.name,
15819
+ kind: node.kind,
15820
+ filePath: file,
15821
+ language: lang,
15822
+ startLine: 0,
15823
+ endLine: 0
15824
+ });
15825
+ }
15826
+ indexedFiles++;
15743
15827
  }
15744
15828
  const stats = engine.getStats();
15745
- console.log(`\u2705 Indexed ${targetPath}: ${stats.nodeCount} nodes, ${stats.edgeCount} edges`);
15829
+ console.log(`\u2705 Indexed ${targetPath}: ${indexedFiles} file(s), ${stats.nodeCount} nodes, ${stats.edgeCount} edges`);
15746
15830
  } catch (err) {
15747
15831
  const msg = err instanceof Error ? err.message : String(err);
15748
15832
  console.error(`\u274C ${msg}`);
@@ -15784,40 +15868,54 @@ async function handleCodegraph(sub, args) {
15784
15868
  return ExitCode.SUCCESS;
15785
15869
  }
15786
15870
  }
15787
- async function handleSecurity(filePath) {
15871
+ var SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
15872
+ async function handleSecurity(filePath, failOn) {
15788
15873
  try {
15789
- if (!existsSync10(filePath)) {
15790
- console.error(`\u274C File not found: ${filePath}`);
15874
+ if (!existsSync11(filePath)) {
15875
+ console.error(`\u274C Path not found: ${filePath}`);
15791
15876
  return ExitCode.GENERAL_ERROR;
15792
15877
  }
15793
- const code = readFileSync6(filePath, "utf-8");
15794
15878
  const secrets = createSecretDetector();
15795
15879
  const taint = new TaintAnalyzer();
15796
15880
  const deps = new DependencyScanner();
15797
- const findings = [
15798
- ...secrets.scan(code, filePath),
15799
- ...taint.analyze(code, filePath),
15800
- ...deps.scan(code, filePath)
15801
- ];
15881
+ const files = collectFiles(filePath, (ext) => ext in EXT_TO_LANG);
15882
+ const findings = [];
15883
+ for (const file of files) {
15884
+ const code = readFileSync6(file, "utf-8");
15885
+ findings.push(...secrets.scan(code, file), ...taint.analyze(code, file), ...deps.scan(code, file));
15886
+ }
15802
15887
  const bySeverity = /* @__PURE__ */ new Map();
15803
15888
  for (const f of findings) {
15804
15889
  const list = bySeverity.get(f.severity) ?? [];
15805
15890
  list.push(f);
15806
15891
  bySeverity.set(f.severity, list);
15807
15892
  }
15808
- console.log(`Security scan: ${filePath}`);
15893
+ console.log(`Security scan: ${filePath} (${files.length} file(s))`);
15809
15894
  console.log(`Total findings: ${findings.length}`);
15810
- const severityOrder = ["critical", "high", "medium", "low", "info"];
15811
- for (const sev of severityOrder) {
15895
+ for (const sev of SEVERITY_ORDER) {
15812
15896
  const items = bySeverity.get(sev);
15813
15897
  if (items && items.length > 0) {
15814
15898
  console.log(`
15815
15899
  ${sev.toUpperCase()} (${items.length}):`);
15816
15900
  for (const f of items) {
15817
- console.log(` - ${f.description}`);
15901
+ console.log(` - ${f.description} (${f.location.file}:${f.location.line})`);
15818
15902
  }
15819
15903
  }
15820
15904
  }
15905
+ if (failOn) {
15906
+ const threshold = failOn.toLowerCase();
15907
+ if (!SEVERITY_ORDER.includes(threshold)) {
15908
+ console.error(`\u274C Invalid --fail-on severity: ${failOn} (use critical|high|medium|low|info)`);
15909
+ return ExitCode.VALIDATION_ERROR;
15910
+ }
15911
+ const maxIdx = SEVERITY_ORDER.indexOf(threshold);
15912
+ const gating = findings.filter((f) => SEVERITY_ORDER.indexOf(f.severity) <= maxIdx);
15913
+ if (gating.length > 0) {
15914
+ console.error(`
15915
+ \u274C ${gating.length} finding(s) at or above "${threshold}" \u2014 failing.`);
15916
+ return ExitCode.VALIDATION_ERROR;
15917
+ }
15918
+ }
15821
15919
  return ExitCode.SUCCESS;
15822
15920
  } catch (err) {
15823
15921
  const msg = err instanceof Error ? err.message : String(err);
@@ -15904,6 +16002,17 @@ async function handleReqValidate(filePath) {
15904
16002
  }
15905
16003
  if (requirements.length === 0) {
15906
16004
  console.log("No requirements found in file");
16005
+ if (/REQ-/i.test(content)) {
16006
+ const headingLike = /^#{1,4}\s+REQ-[A-Z]{3}-\d{3}:/m.test(content);
16007
+ console.error('\u26A0 Found "REQ-" text but no parseable requirements. Requirements must be Markdown headings shaped like:');
16008
+ console.error(" ## REQ-XXX-000: <title> (XXX = 3-letter domain code)");
16009
+ console.error(" **\u8981\u4EF6**:");
16010
+ console.error(" THE \u30B7\u30B9\u30C6\u30E0 SHALL ...");
16011
+ if (!headingLike) {
16012
+ console.error('\u2139 Hint: list items (e.g. "- REQ-001: ...") and IDs without a 3-letter domain code are not recognized.');
16013
+ }
16014
+ return ExitCode.VALIDATION_ERROR;
16015
+ }
15907
16016
  }
15908
16017
  return hasIssues ? ExitCode.VALIDATION_ERROR : ExitCode.SUCCESS;
15909
16018
  } catch (err) {
@@ -16494,7 +16603,7 @@ async function handleExplain(input) {
16494
16603
  const recorder = new ReasoningChainRecorder2();
16495
16604
  const generator = new ExplanationGenerator2();
16496
16605
  let code;
16497
- if (existsSync10(input)) {
16606
+ if (existsSync11(input)) {
16498
16607
  code = readFileSync6(input, "utf-8");
16499
16608
  } else {
16500
16609
  code = input;
@@ -16622,6 +16731,29 @@ async function handleWatch(pattern) {
16622
16731
  });
16623
16732
  return ExitCode.SUCCESS;
16624
16733
  }
16734
+ function resolveTarget(args, verbs) {
16735
+ const positional = args["args"] ?? [];
16736
+ const sub = args["subcommand"];
16737
+ const explicitFile = args["file"];
16738
+ if (explicitFile)
16739
+ return explicitFile;
16740
+ if (sub && verbs.includes(sub.toLowerCase())) {
16741
+ return positional[0];
16742
+ }
16743
+ return sub ?? positional[0];
16744
+ }
16745
+ async function reqAction(args) {
16746
+ if (args["help"] === true || args["h"] === true) {
16747
+ console.log(showHelp("requirements"));
16748
+ return;
16749
+ }
16750
+ const filePath = resolveTarget(args, ["analyze", "validate"]);
16751
+ if (!filePath) {
16752
+ console.error("\u274C Usage: musubix requirements [analyze|validate] <file>");
16753
+ return ExitCode.VALIDATION_ERROR;
16754
+ }
16755
+ return await handleReqValidate(filePath);
16756
+ }
16625
16757
  function getDefaultCommands() {
16626
16758
  return [
16627
16759
  {
@@ -16671,7 +16803,7 @@ function getDefaultCommands() {
16671
16803
  return;
16672
16804
  }
16673
16805
  const targetPath = args["subcommand"] ?? args["args"]?.[0] ?? ".";
16674
- await handleInit(targetPath, args["name"], args["force"] === true);
16806
+ return await handleInit(targetPath, args["name"], args["force"] === true);
16675
16807
  }
16676
16808
  },
16677
16809
  {
@@ -16689,37 +16821,32 @@ function getDefaultCommands() {
16689
16821
  case "validate":
16690
16822
  if (!filePath) {
16691
16823
  console.error("\u274C Usage: musubix tasks validate <file>");
16692
- return;
16824
+ return ExitCode.VALIDATION_ERROR;
16693
16825
  }
16694
- await handleTasksValidate(filePath);
16826
+ return await handleTasksValidate(filePath);
16695
16827
  break;
16696
16828
  case "list":
16697
- await handleTasksList(filePath);
16829
+ return await handleTasksList(filePath);
16698
16830
  break;
16699
16831
  case "stats":
16700
- await handleTasksStats(filePath);
16832
+ return await handleTasksStats(filePath);
16701
16833
  break;
16702
16834
  default:
16703
16835
  console.log(showHelp("tasks"));
16836
+ return;
16704
16837
  }
16705
16838
  }
16706
16839
  },
16707
16840
  {
16708
16841
  name: "req",
16709
16842
  description: "Analyze requirements (EARS validation)",
16710
- action: async (args) => {
16711
- if (args["help"] === true || args["h"] === true) {
16712
- console.log(showHelp("requirements"));
16713
- return;
16714
- }
16715
- const positionalArgs = args["args"] ?? [];
16716
- const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16717
- if (!filePath) {
16718
- console.error("\u274C Usage: musubix req <file>");
16719
- return;
16720
- }
16721
- await handleReqValidate(filePath);
16722
- }
16843
+ action: reqAction
16844
+ },
16845
+ {
16846
+ // Alias matching the documented `musubix requirements <analyze|validate> <file>` form.
16847
+ name: "requirements",
16848
+ description: "Analyze/validate requirements (EARS validation)",
16849
+ action: reqAction
16723
16850
  },
16724
16851
  {
16725
16852
  name: "req:wizard",
@@ -16729,7 +16856,7 @@ function getDefaultCommands() {
16729
16856
  console.log(showHelp("requirements"));
16730
16857
  return;
16731
16858
  }
16732
- await handleReqWizard();
16859
+ return await handleReqWizard();
16733
16860
  }
16734
16861
  },
16735
16862
  {
@@ -16740,7 +16867,7 @@ function getDefaultCommands() {
16740
16867
  console.log(showHelp("requirements"));
16741
16868
  return;
16742
16869
  }
16743
- await handleReqInterview(args);
16870
+ return await handleReqInterview(args);
16744
16871
  }
16745
16872
  },
16746
16873
  {
@@ -16751,13 +16878,20 @@ function getDefaultCommands() {
16751
16878
  console.log(showHelp("design"));
16752
16879
  return;
16753
16880
  }
16754
- const positionalArgs = args["args"] ?? [];
16755
- const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16881
+ if (args["subcommand"]?.toLowerCase() === "verify") {
16882
+ const vf = resolveTarget(args, ["verify"]);
16883
+ if (!vf) {
16884
+ console.error("\u274C Usage: musubix design verify <design-file>");
16885
+ return ExitCode.VALIDATION_ERROR;
16886
+ }
16887
+ return await handleDesignVerify(vf);
16888
+ }
16889
+ const filePath = resolveTarget(args, ["generate"]);
16756
16890
  if (!filePath) {
16757
- console.error("\u274C Usage: musubix design <requirements-file>");
16758
- return;
16891
+ console.error("\u274C Usage: musubix design [generate] <requirements-file>");
16892
+ return ExitCode.VALIDATION_ERROR;
16759
16893
  }
16760
- await handleDesignGenerate(filePath);
16894
+ return await handleDesignGenerate(filePath);
16761
16895
  }
16762
16896
  },
16763
16897
  {
@@ -16772,10 +16906,10 @@ function getDefaultCommands() {
16772
16906
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16773
16907
  if (!filePath) {
16774
16908
  console.error("\u274C Usage: musubix design:c4 <file> [--level context|container|component]");
16775
- return;
16909
+ return ExitCode.VALIDATION_ERROR;
16776
16910
  }
16777
16911
  const level = args["level"] ?? "context";
16778
- await handleDesignC4(filePath, level);
16912
+ return await handleDesignC4(filePath, level);
16779
16913
  }
16780
16914
  },
16781
16915
  {
@@ -16790,9 +16924,9 @@ function getDefaultCommands() {
16790
16924
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16791
16925
  if (!filePath) {
16792
16926
  console.error("\u274C Usage: musubix design:verify <design-file>");
16793
- return;
16927
+ return ExitCode.VALIDATION_ERROR;
16794
16928
  }
16795
- await handleDesignVerify(filePath);
16929
+ return await handleDesignVerify(filePath);
16796
16930
  }
16797
16931
  },
16798
16932
  {
@@ -16803,14 +16937,13 @@ function getDefaultCommands() {
16803
16937
  console.log(showHelp("codegen"));
16804
16938
  return;
16805
16939
  }
16806
- const positionalArgs = args["args"] ?? [];
16807
- const name = args["subcommand"] ?? positionalArgs[0];
16940
+ const name = resolveTarget(args, ["generate"]);
16808
16941
  if (!name) {
16809
- console.error("\u274C Usage: musubix codegen <name> [--type class|interface|function|...]");
16810
- return;
16942
+ console.error("\u274C Usage: musubix codegen [generate] <name> [--type class|interface|function|...]");
16943
+ return ExitCode.VALIDATION_ERROR;
16811
16944
  }
16812
16945
  const type = args["type"] ?? "class";
16813
- await handleCodegen(name, type);
16946
+ return await handleCodegen(name, type);
16814
16947
  }
16815
16948
  },
16816
16949
  {
@@ -16825,9 +16958,9 @@ function getDefaultCommands() {
16825
16958
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16826
16959
  if (!filePath) {
16827
16960
  console.error("\u274C Usage: musubix test:gen <source-file>");
16828
- return;
16961
+ return ExitCode.VALIDATION_ERROR;
16829
16962
  }
16830
- await handleTestGen(filePath);
16963
+ return await handleTestGen(filePath);
16831
16964
  }
16832
16965
  },
16833
16966
  {
@@ -16840,7 +16973,7 @@ function getDefaultCommands() {
16840
16973
  }
16841
16974
  const sub = args["subcommand"];
16842
16975
  const positionalArgs = args["args"] ?? [];
16843
- await handleTrace(sub, positionalArgs);
16976
+ return await handleTrace(sub, positionalArgs);
16844
16977
  }
16845
16978
  },
16846
16979
  {
@@ -16851,7 +16984,7 @@ function getDefaultCommands() {
16851
16984
  console.log(showHelp("trace:verify"));
16852
16985
  return;
16853
16986
  }
16854
- await handleTraceVerify();
16987
+ return await handleTraceVerify();
16855
16988
  }
16856
16989
  },
16857
16990
  {
@@ -16864,7 +16997,7 @@ function getDefaultCommands() {
16864
16997
  }
16865
16998
  const sub = args["subcommand"];
16866
16999
  const positionalArgs = args["args"] ?? [];
16867
- await handlePolicy(sub, positionalArgs);
17000
+ return await handlePolicy(sub, positionalArgs);
16868
17001
  }
16869
17002
  },
16870
17003
  {
@@ -16876,7 +17009,7 @@ function getDefaultCommands() {
16876
17009
  return;
16877
17010
  }
16878
17011
  const sub = args["subcommand"];
16879
- await handleOntology(sub);
17012
+ return await handleOntology(sub);
16880
17013
  }
16881
17014
  },
16882
17015
  {
@@ -16889,7 +17022,7 @@ function getDefaultCommands() {
16889
17022
  }
16890
17023
  const sub = args["subcommand"];
16891
17024
  const positionalArgs = args["args"] ?? [];
16892
- await handleCodegraph(sub, positionalArgs);
17025
+ return await handleCodegraph(sub, positionalArgs);
16893
17026
  }
16894
17027
  },
16895
17028
  {
@@ -16903,10 +17036,10 @@ function getDefaultCommands() {
16903
17036
  const positionalArgs = args["args"] ?? [];
16904
17037
  const filePath = args["subcommand"] ?? positionalArgs[0];
16905
17038
  if (!filePath) {
16906
- console.error("\u274C Usage: musubix security <path>");
16907
- return;
17039
+ console.error("\u274C Usage: musubix security <path> [--fail-on critical|high|medium|low|info]");
17040
+ return ExitCode.VALIDATION_ERROR;
16908
17041
  }
16909
- await handleSecurity(filePath);
17042
+ return await handleSecurity(filePath, args["fail-on"]);
16910
17043
  }
16911
17044
  },
16912
17045
  {
@@ -16919,7 +17052,7 @@ function getDefaultCommands() {
16919
17052
  }
16920
17053
  const sub = args["subcommand"];
16921
17054
  const positionalArgs = args["args"] ?? [];
16922
- await handleWorkflow(sub, positionalArgs);
17055
+ return await handleWorkflow(sub, positionalArgs);
16923
17056
  }
16924
17057
  },
16925
17058
  {
@@ -16930,7 +17063,7 @@ function getDefaultCommands() {
16930
17063
  console.log(showHelp("status"));
16931
17064
  return;
16932
17065
  }
16933
- await handleStatus();
17066
+ return await handleStatus();
16934
17067
  }
16935
17068
  },
16936
17069
  {
@@ -16943,7 +17076,7 @@ function getDefaultCommands() {
16943
17076
  }
16944
17077
  const sub = args["subcommand"];
16945
17078
  const positionalArgs = args["args"] ?? [];
16946
- await handleSkills(sub, positionalArgs);
17079
+ return await handleSkills(sub, positionalArgs);
16947
17080
  }
16948
17081
  },
16949
17082
  {
@@ -16956,7 +17089,7 @@ function getDefaultCommands() {
16956
17089
  }
16957
17090
  const sub = args["subcommand"];
16958
17091
  const positionalArgs = args["args"] ?? [];
16959
- await handleKnowledge(sub, positionalArgs, args);
17092
+ return await handleKnowledge(sub, positionalArgs, args);
16960
17093
  }
16961
17094
  },
16962
17095
  {
@@ -16969,7 +17102,7 @@ function getDefaultCommands() {
16969
17102
  }
16970
17103
  const sub = args["subcommand"];
16971
17104
  const positionalArgs = args["args"] ?? [];
16972
- await handleDecision(sub, positionalArgs, args);
17105
+ return await handleDecision(sub, positionalArgs, args);
16973
17106
  }
16974
17107
  },
16975
17108
  {
@@ -16982,7 +17115,7 @@ function getDefaultCommands() {
16982
17115
  }
16983
17116
  const sub = args["subcommand"];
16984
17117
  const positionalArgs = args["args"] ?? [];
16985
- await handleDeepResearch(sub, positionalArgs);
17118
+ return await handleDeepResearch(sub, positionalArgs);
16986
17119
  }
16987
17120
  },
16988
17121
  {
@@ -16993,7 +17126,7 @@ function getDefaultCommands() {
16993
17126
  console.log(showHelp("repl"));
16994
17127
  return;
16995
17128
  }
16996
- await handleRepl();
17129
+ return await handleRepl();
16997
17130
  }
16998
17131
  },
16999
17132
  {
@@ -17006,7 +17139,7 @@ function getDefaultCommands() {
17006
17139
  }
17007
17140
  const sub = args["subcommand"];
17008
17141
  const positionalArgs = args["args"] ?? [];
17009
- await handleScaffold(sub, positionalArgs);
17142
+ return await handleScaffold(sub, positionalArgs);
17010
17143
  }
17011
17144
  },
17012
17145
  {
@@ -17019,7 +17152,7 @@ function getDefaultCommands() {
17019
17152
  }
17020
17153
  const positionalArgs = args["args"] ?? [];
17021
17154
  const input = args["subcommand"] ?? positionalArgs[0];
17022
- await handleExplain(input);
17155
+ return await handleExplain(input);
17023
17156
  }
17024
17157
  },
17025
17158
  {
@@ -17032,7 +17165,7 @@ function getDefaultCommands() {
17032
17165
  }
17033
17166
  const sub = args["subcommand"];
17034
17167
  const positionalArgs = args["args"] ?? [];
17035
- await handleLearn(sub, positionalArgs);
17168
+ return await handleLearn(sub, positionalArgs);
17036
17169
  }
17037
17170
  },
17038
17171
  {
@@ -17045,7 +17178,7 @@ function getDefaultCommands() {
17045
17178
  }
17046
17179
  const sub = args["subcommand"];
17047
17180
  const positionalArgs = args["args"] ?? [];
17048
- await handleSynthesis(sub, positionalArgs);
17181
+ return await handleSynthesis(sub, positionalArgs);
17049
17182
  }
17050
17183
  },
17051
17184
  {
@@ -17058,7 +17191,7 @@ function getDefaultCommands() {
17058
17191
  }
17059
17192
  const positionalArgs = args["args"] ?? [];
17060
17193
  const pattern = args["subcommand"] ?? positionalArgs[0];
17061
- await handleWatch(pattern);
17194
+ return await handleWatch(pattern);
17062
17195
  }
17063
17196
  },
17064
17197
  // P3-07: MCP server launcher
@@ -17095,6 +17228,7 @@ function createCLIDispatcher() {
17095
17228
  }
17096
17229
  export {
17097
17230
  CLIDispatcher,
17231
+ collectFiles,
17098
17232
  createCLIDispatcher,
17099
17233
  getDefaultCommands,
17100
17234
  handleCodegen,
@@ -17129,5 +17263,6 @@ export {
17129
17263
  handleWorkflow,
17130
17264
  parseArgs,
17131
17265
  parseTaskFile,
17266
+ resolveTarget,
17132
17267
  showHelp
17133
17268
  };