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/index.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;
@@ -15219,7 +15260,8 @@ init_dist5();
15219
15260
  init_dist6();
15220
15261
  init_dist();
15221
15262
  init_dist();
15222
- import { readFileSync as readFileSync6, existsSync as existsSync10 } from "node:fs";
15263
+ import { readFileSync as readFileSync6, existsSync as existsSync11, statSync, readdirSync } from "node:fs";
15264
+ import { join as joinPath } from "node:path";
15223
15265
  function parseArgs(argv) {
15224
15266
  const command = argv[0] ?? "";
15225
15267
  let subcommand;
@@ -15279,7 +15321,7 @@ var COMMAND_HELP = {
15279
15321
  description: "\u8A2D\u8A08\u751F\u6210"
15280
15322
  },
15281
15323
  codegen: {
15282
- usage: "musubix codegen [options]",
15324
+ usage: "musubix codegen [generate] <name> [--type class|interface|function|...]",
15283
15325
  description: "\u30B3\u30FC\u30C9\u751F\u6210"
15284
15326
  },
15285
15327
  tasks: {
@@ -15315,8 +15357,8 @@ var COMMAND_HELP = {
15315
15357
  description: "\u30B3\u30FC\u30C9\u30B0\u30E9\u30D5\u5206\u6790"
15316
15358
  },
15317
15359
  security: {
15318
- usage: "musubix security <path>",
15319
- description: "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30B9\u30AD\u30E3\u30F3"
15360
+ usage: "musubix security <path> [--fail-on critical|high|medium|low|info]",
15361
+ 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"
15320
15362
  },
15321
15363
  skills: {
15322
15364
  usage: "musubix skills <list|validate|create> [args]",
@@ -15411,7 +15453,7 @@ var CLIDispatcher = class {
15411
15453
  if (!command) {
15412
15454
  throw new Error(`Unknown command: ${commandName}. Available: ${[...this.commands.keys()].join(", ")}`);
15413
15455
  }
15414
- await command.action(args);
15456
+ return await command.action(args);
15415
15457
  }
15416
15458
  getHelp() {
15417
15459
  const lines = [
@@ -15449,12 +15491,12 @@ var CLIDispatcher = class {
15449
15491
  return ExitCode.SUCCESS;
15450
15492
  }
15451
15493
  try {
15452
- await this.dispatch(parsed.command, {
15494
+ const result = await this.dispatch(parsed.command, {
15453
15495
  subcommand: parsed.subcommand,
15454
15496
  args: parsed.args,
15455
15497
  ...parsed.flags
15456
15498
  });
15457
- return ExitCode.SUCCESS;
15499
+ return result ?? ExitCode.SUCCESS;
15458
15500
  } catch (err) {
15459
15501
  const message = err instanceof Error ? err.message : String(err);
15460
15502
  console.error(message);
@@ -15556,21 +15598,21 @@ async function handleInit(targetPath = ".", name, force) {
15556
15598
  console.log(` ${f}`);
15557
15599
  }
15558
15600
  try {
15559
- const { cpSync, existsSync: existsSync11, mkdirSync: mkdirSync2 } = await import("node:fs");
15601
+ const { cpSync, existsSync: existsSync12, mkdirSync: mkdirSync3 } = await import("node:fs");
15560
15602
  const { resolve: resolve9, dirname: dirname4 } = await import("node:path");
15561
15603
  const { fileURLToPath: fileURLToPath2 } = await import("node:url");
15562
15604
  const thisDir = typeof __dirname !== "undefined" ? __dirname : dirname4(fileURLToPath2(import.meta.url));
15563
15605
  const pkgGithub = resolve9(thisDir, "..", ".github");
15564
15606
  const destGithub = resolve9(targetPath, ".github");
15565
- if (existsSync11(pkgGithub)) {
15566
- mkdirSync2(destGithub, { recursive: true });
15607
+ if (existsSync12(pkgGithub)) {
15608
+ mkdirSync3(destGithub, { recursive: true });
15567
15609
  const skillsSrc = resolve9(pkgGithub, "skills");
15568
- if (existsSync11(skillsSrc)) {
15610
+ if (existsSync12(skillsSrc)) {
15569
15611
  cpSync(skillsSrc, resolve9(destGithub, "skills"), { recursive: true });
15570
15612
  console.log(" .github/skills/ (SDD skills)");
15571
15613
  }
15572
15614
  const instrSrc = resolve9(pkgGithub, "copilot-instructions.md");
15573
- if (existsSync11(instrSrc)) {
15615
+ if (existsSync12(instrSrc)) {
15574
15616
  cpSync(instrSrc, resolve9(destGithub, "copilot-instructions.md"));
15575
15617
  console.log(" .github/copilot-instructions.md");
15576
15618
  }
@@ -15585,6 +15627,7 @@ async function handleTrace(sub, args) {
15585
15627
  const generator = createMatrixGenerator();
15586
15628
  const report = generator.generate([], [], []);
15587
15629
  console.log(generator.toMarkdown(report));
15630
+ console.log("\n\u2139 No traceability data loaded \u2014 matrix is empty (completeness is N/A).");
15588
15631
  return ExitCode.SUCCESS;
15589
15632
  }
15590
15633
  case "validate": {
@@ -15616,6 +15659,11 @@ async function handleTrace(sub, args) {
15616
15659
  async function handleTraceVerify() {
15617
15660
  const validator = createTraceabilityValidator();
15618
15661
  const report = validator.validateCoverage([], [], [], []);
15662
+ if (report.totalRequirements === 0) {
15663
+ console.log("No traceability data loaded \u2014 nothing to verify.");
15664
+ console.log("\u2139 Coverage cannot be computed with 0 requirements (reported as N/A).");
15665
+ return ExitCode.SUCCESS;
15666
+ }
15619
15667
  console.log(`Coverage: ${report.coveragePercent}%`);
15620
15668
  console.log(`Requirements: ${report.coveredRequirements}/${report.totalRequirements}`);
15621
15669
  if (report.gaps.length > 0) {
@@ -15715,6 +15763,31 @@ var EXT_TO_LANG = {
15715
15763
  hs: "haskell",
15716
15764
  lua: "lua"
15717
15765
  };
15766
+ var WALK_IGNORE = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "coverage", ".next", "build"]);
15767
+ function collectFiles(target, extFilter) {
15768
+ const stat = statSync(target);
15769
+ if (stat.isFile())
15770
+ return [target];
15771
+ const out = [];
15772
+ const walk = (dir) => {
15773
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
15774
+ if (entry.name.startsWith(".") && entry.name !== ".")
15775
+ continue;
15776
+ if (WALK_IGNORE.has(entry.name))
15777
+ continue;
15778
+ const full = joinPath(dir, entry.name);
15779
+ if (entry.isDirectory()) {
15780
+ walk(full);
15781
+ } else if (entry.isFile()) {
15782
+ const ext = entry.name.split(".").pop() ?? "";
15783
+ if (!extFilter || extFilter(ext))
15784
+ out.push(full);
15785
+ }
15786
+ }
15787
+ };
15788
+ walk(target);
15789
+ return out;
15790
+ }
15718
15791
  async function handleCodegraph(sub, args) {
15719
15792
  switch (sub) {
15720
15793
  case "index": {
@@ -15724,29 +15797,40 @@ async function handleCodegraph(sub, args) {
15724
15797
  return ExitCode.GENERAL_ERROR;
15725
15798
  }
15726
15799
  try {
15727
- const parser = createASTParser();
15728
- const content = readFileSync6(targetPath, "utf-8");
15729
- const ext = targetPath.split(".").pop() ?? "";
15730
- const lang = EXT_TO_LANG[ext];
15731
- if (!lang) {
15732
- console.error(`\u274C Unsupported file extension: .${ext}`);
15800
+ if (!existsSync11(targetPath)) {
15801
+ console.error(`\u274C Path not found: ${targetPath}`);
15733
15802
  return ExitCode.GENERAL_ERROR;
15734
15803
  }
15735
- const nodes = parser.parse(content, lang);
15804
+ const parser = createASTParser();
15736
15805
  const engine = createGraphEngine();
15737
- for (const node of nodes) {
15738
- engine.addNode({
15739
- id: `${targetPath}:${node.name}`,
15740
- name: node.name,
15741
- kind: node.kind,
15742
- filePath: targetPath,
15743
- language: lang,
15744
- startLine: 0,
15745
- endLine: 0
15746
- });
15806
+ const files = collectFiles(targetPath, (ext) => ext in EXT_TO_LANG);
15807
+ if (files.length === 0) {
15808
+ console.error(`\u274C No indexable source files found under: ${targetPath}`);
15809
+ return ExitCode.GENERAL_ERROR;
15810
+ }
15811
+ let indexedFiles = 0;
15812
+ for (const file of files) {
15813
+ const ext = file.split(".").pop() ?? "";
15814
+ const lang = EXT_TO_LANG[ext];
15815
+ if (!lang)
15816
+ continue;
15817
+ const content = readFileSync6(file, "utf-8");
15818
+ const nodes = parser.parse(content, lang);
15819
+ for (const node of nodes) {
15820
+ engine.addNode({
15821
+ id: `${file}:${node.name}`,
15822
+ name: node.name,
15823
+ kind: node.kind,
15824
+ filePath: file,
15825
+ language: lang,
15826
+ startLine: 0,
15827
+ endLine: 0
15828
+ });
15829
+ }
15830
+ indexedFiles++;
15747
15831
  }
15748
15832
  const stats = engine.getStats();
15749
- console.log(`\u2705 Indexed ${targetPath}: ${stats.nodeCount} nodes, ${stats.edgeCount} edges`);
15833
+ console.log(`\u2705 Indexed ${targetPath}: ${indexedFiles} file(s), ${stats.nodeCount} nodes, ${stats.edgeCount} edges`);
15750
15834
  } catch (err) {
15751
15835
  const msg = err instanceof Error ? err.message : String(err);
15752
15836
  console.error(`\u274C ${msg}`);
@@ -15788,40 +15872,54 @@ async function handleCodegraph(sub, args) {
15788
15872
  return ExitCode.SUCCESS;
15789
15873
  }
15790
15874
  }
15791
- async function handleSecurity(filePath) {
15875
+ var SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
15876
+ async function handleSecurity(filePath, failOn) {
15792
15877
  try {
15793
- if (!existsSync10(filePath)) {
15794
- console.error(`\u274C File not found: ${filePath}`);
15878
+ if (!existsSync11(filePath)) {
15879
+ console.error(`\u274C Path not found: ${filePath}`);
15795
15880
  return ExitCode.GENERAL_ERROR;
15796
15881
  }
15797
- const code = readFileSync6(filePath, "utf-8");
15798
15882
  const secrets = createSecretDetector();
15799
15883
  const taint = new TaintAnalyzer();
15800
15884
  const deps = new DependencyScanner();
15801
- const findings = [
15802
- ...secrets.scan(code, filePath),
15803
- ...taint.analyze(code, filePath),
15804
- ...deps.scan(code, filePath)
15805
- ];
15885
+ const files = collectFiles(filePath, (ext) => ext in EXT_TO_LANG);
15886
+ const findings = [];
15887
+ for (const file of files) {
15888
+ const code = readFileSync6(file, "utf-8");
15889
+ findings.push(...secrets.scan(code, file), ...taint.analyze(code, file), ...deps.scan(code, file));
15890
+ }
15806
15891
  const bySeverity = /* @__PURE__ */ new Map();
15807
15892
  for (const f of findings) {
15808
15893
  const list = bySeverity.get(f.severity) ?? [];
15809
15894
  list.push(f);
15810
15895
  bySeverity.set(f.severity, list);
15811
15896
  }
15812
- console.log(`Security scan: ${filePath}`);
15897
+ console.log(`Security scan: ${filePath} (${files.length} file(s))`);
15813
15898
  console.log(`Total findings: ${findings.length}`);
15814
- const severityOrder = ["critical", "high", "medium", "low", "info"];
15815
- for (const sev of severityOrder) {
15899
+ for (const sev of SEVERITY_ORDER) {
15816
15900
  const items = bySeverity.get(sev);
15817
15901
  if (items && items.length > 0) {
15818
15902
  console.log(`
15819
15903
  ${sev.toUpperCase()} (${items.length}):`);
15820
15904
  for (const f of items) {
15821
- console.log(` - ${f.description}`);
15905
+ console.log(` - ${f.description} (${f.location.file}:${f.location.line})`);
15822
15906
  }
15823
15907
  }
15824
15908
  }
15909
+ if (failOn) {
15910
+ const threshold = failOn.toLowerCase();
15911
+ if (!SEVERITY_ORDER.includes(threshold)) {
15912
+ console.error(`\u274C Invalid --fail-on severity: ${failOn} (use critical|high|medium|low|info)`);
15913
+ return ExitCode.VALIDATION_ERROR;
15914
+ }
15915
+ const maxIdx = SEVERITY_ORDER.indexOf(threshold);
15916
+ const gating = findings.filter((f) => SEVERITY_ORDER.indexOf(f.severity) <= maxIdx);
15917
+ if (gating.length > 0) {
15918
+ console.error(`
15919
+ \u274C ${gating.length} finding(s) at or above "${threshold}" \u2014 failing.`);
15920
+ return ExitCode.VALIDATION_ERROR;
15921
+ }
15922
+ }
15825
15923
  return ExitCode.SUCCESS;
15826
15924
  } catch (err) {
15827
15925
  const msg = err instanceof Error ? err.message : String(err);
@@ -15908,6 +16006,17 @@ async function handleReqValidate(filePath) {
15908
16006
  }
15909
16007
  if (requirements.length === 0) {
15910
16008
  console.log("No requirements found in file");
16009
+ if (/REQ-/i.test(content)) {
16010
+ const headingLike = /^#{1,4}\s+REQ-[A-Z]{3}-\d{3}:/m.test(content);
16011
+ console.error('\u26A0 Found "REQ-" text but no parseable requirements. Requirements must be Markdown headings shaped like:');
16012
+ console.error(" ## REQ-XXX-000: <title> (XXX = 3-letter domain code)");
16013
+ console.error(" **\u8981\u4EF6**:");
16014
+ console.error(" THE \u30B7\u30B9\u30C6\u30E0 SHALL ...");
16015
+ if (!headingLike) {
16016
+ console.error('\u2139 Hint: list items (e.g. "- REQ-001: ...") and IDs without a 3-letter domain code are not recognized.');
16017
+ }
16018
+ return ExitCode.VALIDATION_ERROR;
16019
+ }
15911
16020
  }
15912
16021
  return hasIssues ? ExitCode.VALIDATION_ERROR : ExitCode.SUCCESS;
15913
16022
  } catch (err) {
@@ -16498,7 +16607,7 @@ async function handleExplain(input) {
16498
16607
  const recorder = new ReasoningChainRecorder2();
16499
16608
  const generator = new ExplanationGenerator2();
16500
16609
  let code;
16501
- if (existsSync10(input)) {
16610
+ if (existsSync11(input)) {
16502
16611
  code = readFileSync6(input, "utf-8");
16503
16612
  } else {
16504
16613
  code = input;
@@ -16626,6 +16735,29 @@ async function handleWatch(pattern) {
16626
16735
  });
16627
16736
  return ExitCode.SUCCESS;
16628
16737
  }
16738
+ function resolveTarget(args, verbs) {
16739
+ const positional = args["args"] ?? [];
16740
+ const sub = args["subcommand"];
16741
+ const explicitFile = args["file"];
16742
+ if (explicitFile)
16743
+ return explicitFile;
16744
+ if (sub && verbs.includes(sub.toLowerCase())) {
16745
+ return positional[0];
16746
+ }
16747
+ return sub ?? positional[0];
16748
+ }
16749
+ async function reqAction(args) {
16750
+ if (args["help"] === true || args["h"] === true) {
16751
+ console.log(showHelp("requirements"));
16752
+ return;
16753
+ }
16754
+ const filePath = resolveTarget(args, ["analyze", "validate"]);
16755
+ if (!filePath) {
16756
+ console.error("\u274C Usage: musubix requirements [analyze|validate] <file>");
16757
+ return ExitCode.VALIDATION_ERROR;
16758
+ }
16759
+ return await handleReqValidate(filePath);
16760
+ }
16629
16761
  function getDefaultCommands() {
16630
16762
  return [
16631
16763
  {
@@ -16675,7 +16807,7 @@ function getDefaultCommands() {
16675
16807
  return;
16676
16808
  }
16677
16809
  const targetPath = args["subcommand"] ?? args["args"]?.[0] ?? ".";
16678
- await handleInit(targetPath, args["name"], args["force"] === true);
16810
+ return await handleInit(targetPath, args["name"], args["force"] === true);
16679
16811
  }
16680
16812
  },
16681
16813
  {
@@ -16693,37 +16825,32 @@ function getDefaultCommands() {
16693
16825
  case "validate":
16694
16826
  if (!filePath) {
16695
16827
  console.error("\u274C Usage: musubix tasks validate <file>");
16696
- return;
16828
+ return ExitCode.VALIDATION_ERROR;
16697
16829
  }
16698
- await handleTasksValidate(filePath);
16830
+ return await handleTasksValidate(filePath);
16699
16831
  break;
16700
16832
  case "list":
16701
- await handleTasksList(filePath);
16833
+ return await handleTasksList(filePath);
16702
16834
  break;
16703
16835
  case "stats":
16704
- await handleTasksStats(filePath);
16836
+ return await handleTasksStats(filePath);
16705
16837
  break;
16706
16838
  default:
16707
16839
  console.log(showHelp("tasks"));
16840
+ return;
16708
16841
  }
16709
16842
  }
16710
16843
  },
16711
16844
  {
16712
16845
  name: "req",
16713
16846
  description: "Analyze requirements (EARS validation)",
16714
- action: async (args) => {
16715
- if (args["help"] === true || args["h"] === true) {
16716
- console.log(showHelp("requirements"));
16717
- return;
16718
- }
16719
- const positionalArgs = args["args"] ?? [];
16720
- const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16721
- if (!filePath) {
16722
- console.error("\u274C Usage: musubix req <file>");
16723
- return;
16724
- }
16725
- await handleReqValidate(filePath);
16726
- }
16847
+ action: reqAction
16848
+ },
16849
+ {
16850
+ // Alias matching the documented `musubix requirements <analyze|validate> <file>` form.
16851
+ name: "requirements",
16852
+ description: "Analyze/validate requirements (EARS validation)",
16853
+ action: reqAction
16727
16854
  },
16728
16855
  {
16729
16856
  name: "req:wizard",
@@ -16733,7 +16860,7 @@ function getDefaultCommands() {
16733
16860
  console.log(showHelp("requirements"));
16734
16861
  return;
16735
16862
  }
16736
- await handleReqWizard();
16863
+ return await handleReqWizard();
16737
16864
  }
16738
16865
  },
16739
16866
  {
@@ -16744,7 +16871,7 @@ function getDefaultCommands() {
16744
16871
  console.log(showHelp("requirements"));
16745
16872
  return;
16746
16873
  }
16747
- await handleReqInterview(args);
16874
+ return await handleReqInterview(args);
16748
16875
  }
16749
16876
  },
16750
16877
  {
@@ -16755,13 +16882,20 @@ function getDefaultCommands() {
16755
16882
  console.log(showHelp("design"));
16756
16883
  return;
16757
16884
  }
16758
- const positionalArgs = args["args"] ?? [];
16759
- const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16885
+ if (args["subcommand"]?.toLowerCase() === "verify") {
16886
+ const vf = resolveTarget(args, ["verify"]);
16887
+ if (!vf) {
16888
+ console.error("\u274C Usage: musubix design verify <design-file>");
16889
+ return ExitCode.VALIDATION_ERROR;
16890
+ }
16891
+ return await handleDesignVerify(vf);
16892
+ }
16893
+ const filePath = resolveTarget(args, ["generate"]);
16760
16894
  if (!filePath) {
16761
- console.error("\u274C Usage: musubix design <requirements-file>");
16762
- return;
16895
+ console.error("\u274C Usage: musubix design [generate] <requirements-file>");
16896
+ return ExitCode.VALIDATION_ERROR;
16763
16897
  }
16764
- await handleDesignGenerate(filePath);
16898
+ return await handleDesignGenerate(filePath);
16765
16899
  }
16766
16900
  },
16767
16901
  {
@@ -16776,10 +16910,10 @@ function getDefaultCommands() {
16776
16910
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16777
16911
  if (!filePath) {
16778
16912
  console.error("\u274C Usage: musubix design:c4 <file> [--level context|container|component]");
16779
- return;
16913
+ return ExitCode.VALIDATION_ERROR;
16780
16914
  }
16781
16915
  const level = args["level"] ?? "context";
16782
- await handleDesignC4(filePath, level);
16916
+ return await handleDesignC4(filePath, level);
16783
16917
  }
16784
16918
  },
16785
16919
  {
@@ -16794,9 +16928,9 @@ function getDefaultCommands() {
16794
16928
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16795
16929
  if (!filePath) {
16796
16930
  console.error("\u274C Usage: musubix design:verify <design-file>");
16797
- return;
16931
+ return ExitCode.VALIDATION_ERROR;
16798
16932
  }
16799
- await handleDesignVerify(filePath);
16933
+ return await handleDesignVerify(filePath);
16800
16934
  }
16801
16935
  },
16802
16936
  {
@@ -16807,14 +16941,13 @@ function getDefaultCommands() {
16807
16941
  console.log(showHelp("codegen"));
16808
16942
  return;
16809
16943
  }
16810
- const positionalArgs = args["args"] ?? [];
16811
- const name = args["subcommand"] ?? positionalArgs[0];
16944
+ const name = resolveTarget(args, ["generate"]);
16812
16945
  if (!name) {
16813
- console.error("\u274C Usage: musubix codegen <name> [--type class|interface|function|...]");
16814
- return;
16946
+ console.error("\u274C Usage: musubix codegen [generate] <name> [--type class|interface|function|...]");
16947
+ return ExitCode.VALIDATION_ERROR;
16815
16948
  }
16816
16949
  const type = args["type"] ?? "class";
16817
- await handleCodegen(name, type);
16950
+ return await handleCodegen(name, type);
16818
16951
  }
16819
16952
  },
16820
16953
  {
@@ -16829,9 +16962,9 @@ function getDefaultCommands() {
16829
16962
  const filePath = args["file"] ?? args["subcommand"] ?? positionalArgs[0];
16830
16963
  if (!filePath) {
16831
16964
  console.error("\u274C Usage: musubix test:gen <source-file>");
16832
- return;
16965
+ return ExitCode.VALIDATION_ERROR;
16833
16966
  }
16834
- await handleTestGen(filePath);
16967
+ return await handleTestGen(filePath);
16835
16968
  }
16836
16969
  },
16837
16970
  {
@@ -16844,7 +16977,7 @@ function getDefaultCommands() {
16844
16977
  }
16845
16978
  const sub = args["subcommand"];
16846
16979
  const positionalArgs = args["args"] ?? [];
16847
- await handleTrace(sub, positionalArgs);
16980
+ return await handleTrace(sub, positionalArgs);
16848
16981
  }
16849
16982
  },
16850
16983
  {
@@ -16855,7 +16988,7 @@ function getDefaultCommands() {
16855
16988
  console.log(showHelp("trace:verify"));
16856
16989
  return;
16857
16990
  }
16858
- await handleTraceVerify();
16991
+ return await handleTraceVerify();
16859
16992
  }
16860
16993
  },
16861
16994
  {
@@ -16868,7 +17001,7 @@ function getDefaultCommands() {
16868
17001
  }
16869
17002
  const sub = args["subcommand"];
16870
17003
  const positionalArgs = args["args"] ?? [];
16871
- await handlePolicy(sub, positionalArgs);
17004
+ return await handlePolicy(sub, positionalArgs);
16872
17005
  }
16873
17006
  },
16874
17007
  {
@@ -16880,7 +17013,7 @@ function getDefaultCommands() {
16880
17013
  return;
16881
17014
  }
16882
17015
  const sub = args["subcommand"];
16883
- await handleOntology(sub);
17016
+ return await handleOntology(sub);
16884
17017
  }
16885
17018
  },
16886
17019
  {
@@ -16893,7 +17026,7 @@ function getDefaultCommands() {
16893
17026
  }
16894
17027
  const sub = args["subcommand"];
16895
17028
  const positionalArgs = args["args"] ?? [];
16896
- await handleCodegraph(sub, positionalArgs);
17029
+ return await handleCodegraph(sub, positionalArgs);
16897
17030
  }
16898
17031
  },
16899
17032
  {
@@ -16907,10 +17040,10 @@ function getDefaultCommands() {
16907
17040
  const positionalArgs = args["args"] ?? [];
16908
17041
  const filePath = args["subcommand"] ?? positionalArgs[0];
16909
17042
  if (!filePath) {
16910
- console.error("\u274C Usage: musubix security <path>");
16911
- return;
17043
+ console.error("\u274C Usage: musubix security <path> [--fail-on critical|high|medium|low|info]");
17044
+ return ExitCode.VALIDATION_ERROR;
16912
17045
  }
16913
- await handleSecurity(filePath);
17046
+ return await handleSecurity(filePath, args["fail-on"]);
16914
17047
  }
16915
17048
  },
16916
17049
  {
@@ -16923,7 +17056,7 @@ function getDefaultCommands() {
16923
17056
  }
16924
17057
  const sub = args["subcommand"];
16925
17058
  const positionalArgs = args["args"] ?? [];
16926
- await handleWorkflow(sub, positionalArgs);
17059
+ return await handleWorkflow(sub, positionalArgs);
16927
17060
  }
16928
17061
  },
16929
17062
  {
@@ -16934,7 +17067,7 @@ function getDefaultCommands() {
16934
17067
  console.log(showHelp("status"));
16935
17068
  return;
16936
17069
  }
16937
- await handleStatus();
17070
+ return await handleStatus();
16938
17071
  }
16939
17072
  },
16940
17073
  {
@@ -16947,7 +17080,7 @@ function getDefaultCommands() {
16947
17080
  }
16948
17081
  const sub = args["subcommand"];
16949
17082
  const positionalArgs = args["args"] ?? [];
16950
- await handleSkills(sub, positionalArgs);
17083
+ return await handleSkills(sub, positionalArgs);
16951
17084
  }
16952
17085
  },
16953
17086
  {
@@ -16960,7 +17093,7 @@ function getDefaultCommands() {
16960
17093
  }
16961
17094
  const sub = args["subcommand"];
16962
17095
  const positionalArgs = args["args"] ?? [];
16963
- await handleKnowledge(sub, positionalArgs, args);
17096
+ return await handleKnowledge(sub, positionalArgs, args);
16964
17097
  }
16965
17098
  },
16966
17099
  {
@@ -16973,7 +17106,7 @@ function getDefaultCommands() {
16973
17106
  }
16974
17107
  const sub = args["subcommand"];
16975
17108
  const positionalArgs = args["args"] ?? [];
16976
- await handleDecision(sub, positionalArgs, args);
17109
+ return await handleDecision(sub, positionalArgs, args);
16977
17110
  }
16978
17111
  },
16979
17112
  {
@@ -16986,7 +17119,7 @@ function getDefaultCommands() {
16986
17119
  }
16987
17120
  const sub = args["subcommand"];
16988
17121
  const positionalArgs = args["args"] ?? [];
16989
- await handleDeepResearch(sub, positionalArgs);
17122
+ return await handleDeepResearch(sub, positionalArgs);
16990
17123
  }
16991
17124
  },
16992
17125
  {
@@ -16997,7 +17130,7 @@ function getDefaultCommands() {
16997
17130
  console.log(showHelp("repl"));
16998
17131
  return;
16999
17132
  }
17000
- await handleRepl();
17133
+ return await handleRepl();
17001
17134
  }
17002
17135
  },
17003
17136
  {
@@ -17010,7 +17143,7 @@ function getDefaultCommands() {
17010
17143
  }
17011
17144
  const sub = args["subcommand"];
17012
17145
  const positionalArgs = args["args"] ?? [];
17013
- await handleScaffold(sub, positionalArgs);
17146
+ return await handleScaffold(sub, positionalArgs);
17014
17147
  }
17015
17148
  },
17016
17149
  {
@@ -17023,7 +17156,7 @@ function getDefaultCommands() {
17023
17156
  }
17024
17157
  const positionalArgs = args["args"] ?? [];
17025
17158
  const input = args["subcommand"] ?? positionalArgs[0];
17026
- await handleExplain(input);
17159
+ return await handleExplain(input);
17027
17160
  }
17028
17161
  },
17029
17162
  {
@@ -17036,7 +17169,7 @@ function getDefaultCommands() {
17036
17169
  }
17037
17170
  const sub = args["subcommand"];
17038
17171
  const positionalArgs = args["args"] ?? [];
17039
- await handleLearn(sub, positionalArgs);
17172
+ return await handleLearn(sub, positionalArgs);
17040
17173
  }
17041
17174
  },
17042
17175
  {
@@ -17049,7 +17182,7 @@ function getDefaultCommands() {
17049
17182
  }
17050
17183
  const sub = args["subcommand"];
17051
17184
  const positionalArgs = args["args"] ?? [];
17052
- await handleSynthesis(sub, positionalArgs);
17185
+ return await handleSynthesis(sub, positionalArgs);
17053
17186
  }
17054
17187
  },
17055
17188
  {
@@ -17062,7 +17195,7 @@ function getDefaultCommands() {
17062
17195
  }
17063
17196
  const positionalArgs = args["args"] ?? [];
17064
17197
  const pattern = args["subcommand"] ?? positionalArgs[0];
17065
- await handleWatch(pattern);
17198
+ return await handleWatch(pattern);
17066
17199
  }
17067
17200
  },
17068
17201
  // P3-07: MCP server launcher