@wairon/cli 5.1.1-dev.62 → 5.1.1-dev.63

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/index.js CHANGED
@@ -65,7 +65,7 @@ var init_defaults = __esm({
65
65
  copilot: ".github/prompts",
66
66
  codex: ".codex/agents"
67
67
  };
68
- WAIRON_VERSION = "5.1.1-dev.62";
68
+ WAIRON_VERSION = "5.1.1-dev.63";
69
69
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
70
70
  SUPPORTED_ALIASES = ["wai"];
71
71
  SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
@@ -27947,21 +27947,33 @@ var init_context = __esm({
27947
27947
  });
27948
27948
 
27949
27949
  // src/core/status.ts
27950
- function getStatusReport(options = {}) {
27950
+ function fillDecor(decor) {
27951
+ return {
27952
+ structure: decor?.structure ?? asWritten,
27953
+ emphasis: decor?.emphasis ?? asWritten,
27954
+ layer: decor?.layer ?? ((_kind, text2) => text2),
27955
+ score: decor?.score ?? ((_pct, text2) => text2),
27956
+ draft: decor?.draft ?? asWritten,
27957
+ present: decor?.present ?? asWritten,
27958
+ missing: decor?.missing ?? asWritten
27959
+ };
27960
+ }
27961
+ function getStatusReport(options = {}, decor) {
27962
+ const mark = fillDecor(decor);
27951
27963
  scanAllSpecs({ recursive: options.recursive ?? true });
27952
27964
  const system = loadSystemSpec();
27953
27965
  const loaderErrors = getLoaderIssues();
27954
27966
  if (loaderErrors.length > 0) {
27955
27967
  let errText2 = "Failed to parse specification files:\n";
27956
27968
  for (const issue2 of loaderErrors) {
27957
- const prefix = issue2.specId ? `[${issue2.specId}] ` : "";
27969
+ const prefix = issue2.specId ? mark.structure(`[${issue2.specId}] `) : "";
27958
27970
  errText2 += `${prefix}[${issue2.code}] ${issue2.message}
27959
27971
  `;
27960
27972
  }
27961
- return errText2;
27973
+ return { text: errText2, failed: true };
27962
27974
  }
27963
27975
  if (!system) {
27964
- return "L0 System specification (system.yaml) is missing.";
27976
+ return { text: "L0 System specification (system.yaml) is missing.", failed: true };
27965
27977
  }
27966
27978
  let subsystems = loadSubsystemSpecs();
27967
27979
  let components = loadComponentSpecs();
@@ -28015,7 +28027,7 @@ function getStatusReport(options = {}) {
28015
28027
  };
28016
28028
  const totalSubsystemsScore = subsystems.reduce((acc, s) => acc + getSubsystemScore(s.id), 0);
28017
28029
  const systemScore = subsystems.length > 0 ? Math.round(totalSubsystemsScore / subsystems.length) : 0;
28018
- output += `\u25CF System: ${system.name} (${systemScore}% Complete)
28030
+ output += `${mark.layer("system", "\u25CF System:")} ${mark.emphasis(system.name)} ${mark.score(systemScore, `(${systemScore}% Complete)`)}
28019
28031
  `;
28020
28032
  for (let i = 0; i < subsystems.length; i++) {
28021
28033
  const sub = subsystems[i];
@@ -28023,8 +28035,8 @@ function getStatusReport(options = {}) {
28023
28035
  const subPrefix = isLastSub ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
28024
28036
  const subIndent = isLastSub ? " " : "\u2502 ";
28025
28037
  const subScore = getSubsystemScore(sub.id);
28026
- const subStatusStr = sub.status !== "complete" ? ` [${sub.status}]` : "";
28027
- output += `${subPrefix}[Subsystem] ${sub.id}${subStatusStr} (${subScore}%)
28038
+ const subStatusStr = sub.status !== "complete" ? mark.draft(` [${sub.status}]`) : "";
28039
+ output += `${mark.structure(subPrefix)}${mark.layer("subsystem", `[Subsystem] ${sub.id}`)}${subStatusStr} ${mark.score(subScore, `(${subScore}%)`)}
28028
28040
  `;
28029
28041
  const subComps = components.filter((c) => c.subsystem === sub.id);
28030
28042
  for (let j = 0; j < subComps.length; j++) {
@@ -28033,32 +28045,32 @@ function getStatusReport(options = {}) {
28033
28045
  const compPrefix = isLastComp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
28034
28046
  const compIndent = isLastComp ? " " : "\u2502 ";
28035
28047
  const compScore = componentScores.get(comp.id) ?? 0;
28036
- const compStatusStr = comp.status !== "complete" ? ` [${comp.status}]` : "";
28037
- output += `${subIndent}${compPrefix}[Component: ${comp.componentType}] ${comp.id}${compStatusStr} (${compScore}%)
28048
+ const compStatusStr = comp.status !== "complete" ? mark.draft(` [${comp.status}]`) : "";
28049
+ output += `${mark.structure(subIndent + compPrefix)}${mark.layer("component", `[Component: ${comp.componentType}] ${comp.id}`)}${compStatusStr} ${mark.score(compScore, `(${compScore}%)`)}
28038
28050
  `;
28039
28051
  const intf = interfaces.find((inf) => inf.component === comp.id);
28040
28052
  const impl = implementations.find((im) => intf && im.contract === intf.id);
28041
28053
  const intfPrefix = intf && impl ? "\u251C\u2500\u2500 " : "\u2514\u2500\u2500 ";
28042
28054
  if (intf) {
28043
- const intfStatusStr = intf.status !== "complete" ? ` [${intf.status}]` : "";
28044
- output += `${subIndent}${compIndent}${intfPrefix}Interface: ${intf.id}${intfStatusStr} (${intf.methods.length} methods)
28055
+ const intfStatusStr = intf.status !== "complete" ? mark.draft(` [${intf.status}]`) : "";
28056
+ output += `${mark.structure(subIndent + compIndent + intfPrefix)}${mark.layer("interface", `Interface: ${intf.id}`)}${intfStatusStr} (${intf.methods.length} methods)
28045
28057
  `;
28046
28058
  } else {
28047
- output += `${subIndent}${compIndent}${intfPrefix}Interface: Missing (-30%)
28059
+ output += `${mark.structure(subIndent + compIndent + intfPrefix)}${mark.missing("Interface: Missing (-30%)")}
28048
28060
  `;
28049
28061
  }
28050
28062
  if (impl) {
28051
- const implStatusStr = impl.status !== "complete" ? ` [${impl.status}]` : "";
28063
+ const implStatusStr = impl.status !== "complete" ? mark.draft(` [${impl.status}]`) : "";
28052
28064
  const methodsWithOwnPath = impl.methods.filter((m) => m.sourcePath);
28053
28065
  let pathStr;
28054
28066
  if (impl.sourcePath) {
28055
- pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? ` -> ${impl.sourcePath}` : ` -> ${impl.sourcePath} (File Missing!)`;
28067
+ pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? mark.present(` -> ${impl.sourcePath}`) : mark.missing(` -> ${impl.sourcePath} (File Missing!)`);
28056
28068
  } else if (methodsWithOwnPath.length > 0) {
28057
28069
  pathStr = "";
28058
28070
  } else {
28059
- pathStr = " (No source path)";
28071
+ pathStr = mark.structure(" (No source path)");
28060
28072
  }
28061
- output += `${subIndent}${compIndent}\u2514\u2500\u2500 Implementation: ${impl.id}${implStatusStr}${pathStr}
28073
+ output += `${mark.structure(subIndent + compIndent + "\u2514\u2500\u2500 ")}${mark.layer("implementation", `Implementation: ${impl.id}`)}${implStatusStr}${pathStr}
28062
28074
  `;
28063
28075
  const methodIndent = `${subIndent}${compIndent} `;
28064
28076
  for (let k = 0; k < methodsWithOwnPath.length; k++) {
@@ -28066,24 +28078,26 @@ function getStatusReport(options = {}) {
28066
28078
  const isLastMethod = k === methodsWithOwnPath.length - 1;
28067
28079
  const methodPrefix = isLastMethod ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
28068
28080
  const methodPath = method2.sourcePath;
28069
- const fileMissing = !pathExists(fromProjectRoot(methodPath));
28070
- output += `${methodIndent}${methodPrefix}method ${method2.name} -> ${methodPath}${fileMissing ? " (File Missing!)" : ""}
28081
+ const methodLine = pathExists(fromProjectRoot(methodPath)) ? mark.present(`method ${method2.name} -> ${methodPath}`) : mark.missing(`method ${method2.name} -> ${methodPath} (File Missing!)`);
28082
+ output += `${mark.structure(methodIndent + methodPrefix)}${methodLine}
28071
28083
  `;
28072
28084
  }
28073
28085
  } else {
28074
- output += `${subIndent}${compIndent}\u2514\u2500\u2500 Implementation: Missing (-30%)
28086
+ output += `${mark.structure(subIndent + compIndent + "\u2514\u2500\u2500 ")}${mark.missing("Implementation: Missing (-30%)")}
28075
28087
  `;
28076
28088
  }
28077
28089
  }
28078
28090
  }
28079
- return output;
28091
+ return { text: output, failed: false };
28080
28092
  }
28093
+ var asWritten;
28081
28094
  var init_status = __esm({
28082
28095
  "src/core/status.ts"() {
28083
28096
  "use strict";
28084
28097
  init_specs2();
28085
28098
  init_specs();
28086
28099
  init_fs();
28100
+ asWritten = (text2) => text2;
28087
28101
  }
28088
28102
  });
28089
28103
 
@@ -30003,7 +30017,7 @@ function createMcpServer(options = {}) {
30003
30017
  });
30004
30018
  const family = statusFamilyContext();
30005
30019
  const verdict = approvalVerdict();
30006
- return text(`${family}${report2}${verdict.text}`);
30020
+ return text(`${family}${report2.text}${verdict.text}`);
30007
30021
  } catch (e) {
30008
30022
  return errText(String(e));
30009
30023
  }
@@ -31010,6 +31024,12 @@ function hasContext2() {
31010
31024
  function derivedDocPaths2() {
31011
31025
  return derivedDocPaths();
31012
31026
  }
31027
+ function getStatusReport2(options, decor) {
31028
+ return getStatusReport(options, decor);
31029
+ }
31030
+ function approvalVerdict2() {
31031
+ return approvalVerdict();
31032
+ }
31013
31033
  async function runSubsystemAdd(id, options = {}) {
31014
31034
  logger.header("wairon subsystem add");
31015
31035
  if (!projectConfigExists2()) {
@@ -32460,137 +32480,49 @@ var isNewer = isNewerVersion;
32460
32480
  var import_chalk9 = __toESM(require("chalk"));
32461
32481
  init_logger();
32462
32482
  init_paths();
32463
- init_fs();
32464
- init_specs2();
32465
- init_core();
32466
- init_specs();
32483
+ var LAYER_COLOUR = {
32484
+ system: (text2) => import_chalk9.default.bold.blue(text2),
32485
+ subsystem: (text2) => import_chalk9.default.bold.cyan(text2),
32486
+ component: (text2) => import_chalk9.default.magenta(text2),
32487
+ interface: (text2) => import_chalk9.default.blue(text2),
32488
+ implementation: (text2) => import_chalk9.default.green(text2)
32489
+ };
32490
+ function scoreColour(pct) {
32491
+ if (pct === 100) return (text2) => import_chalk9.default.green(text2);
32492
+ if (pct >= 50) return (text2) => import_chalk9.default.yellow(text2);
32493
+ return (text2) => import_chalk9.default.red(text2);
32494
+ }
32495
+ var TERMINAL_DECOR = {
32496
+ structure: (text2) => import_chalk9.default.gray(text2),
32497
+ emphasis: (text2) => import_chalk9.default.bold(text2),
32498
+ layer: (kind, text2) => (LAYER_COLOUR[kind] ?? ((plain) => plain))(text2),
32499
+ score: (pct, text2) => scoreColour(pct)(text2),
32500
+ draft: (text2) => import_chalk9.default.yellow(text2),
32501
+ present: (text2) => import_chalk9.default.green(text2),
32502
+ missing: (text2) => import_chalk9.default.red(text2)
32503
+ };
32504
+ var NO_SYSTEM_SPEC = "L0 System specification (system.yaml) is missing.";
32505
+ var INIT_HINT = " Run `wairon init` first.";
32506
+ function refuseUnreadableTree(explanation) {
32507
+ const lines = withoutTrailingNewline(explanation).split("\n");
32508
+ const last = lines.length - 1;
32509
+ if (lines[last] === NO_SYSTEM_SPEC) lines[last] += INIT_HINT;
32510
+ for (const line2 of lines) logger.error(line2);
32511
+ process.exit(1);
32512
+ }
32513
+ function withoutTrailingNewline(text2) {
32514
+ return text2.endsWith("\n") ? text2.slice(0, -1) : text2;
32515
+ }
32467
32516
  async function runStatus(options = {}) {
32468
32517
  assertProjectInitialized();
32469
- scanAllSpecs({ recursive: options.recursive ?? true });
32470
- const system = loadSystemSpec();
32471
- const loaderErrors = getLoaderIssues();
32472
- if (loaderErrors.length > 0) {
32473
- logger.error("Failed to parse specification files:");
32474
- for (const issue2 of loaderErrors) {
32475
- const prefix = issue2.specId ? import_chalk9.default.gray(`[${issue2.specId}] `) : "";
32476
- logger.error(`${prefix}[${issue2.code}] ${issue2.message}`);
32477
- }
32478
- process.exit(1);
32479
- }
32480
- let subsystems = loadSubsystemSpecs();
32481
- let components = loadComponentSpecs();
32482
- let interfaces = loadInterfaceSpecs();
32483
- let implementations = loadImplementationSpecs();
32484
- if (options.subsystem) {
32485
- subsystems = subsystems.filter((s) => s.id === options.subsystem || s.id.startsWith(`${options.subsystem}::`));
32486
- components = components.filter((c) => c.subsystem === options.subsystem || c.subsystem.startsWith(`${options.subsystem}::`));
32487
- interfaces = interfaces.filter((i) => {
32488
- const c = components.find((comp) => comp.id === i.component);
32489
- return c !== void 0;
32490
- });
32491
- implementations = implementations.filter((im) => {
32492
- const inf = interfaces.find((i) => i.id === im.contract);
32493
- return inf !== void 0;
32494
- });
32495
- }
32496
- if (!system) {
32497
- logger.error("L0 System specification (system.yaml) is missing. Run `wairon init` first.");
32498
- process.exit(1);
32518
+ const report2 = getStatusReport2(options, TERMINAL_DECOR);
32519
+ if (report2.failed) {
32520
+ refuseUnreadableTree(report2.text);
32499
32521
  }
32500
32522
  logger.header("Architecture Status Dashboard");
32501
32523
  logger.blank();
32502
- const componentScores = /* @__PURE__ */ new Map();
32503
- for (const comp of components) {
32504
- let score = 20;
32505
- const intf = interfaces.find((i) => i.component === comp.id);
32506
- if (intf) {
32507
- score += 30;
32508
- }
32509
- const impl = implementations.find((im) => intf && im.contract === intf.id);
32510
- if (impl) {
32511
- score += 30;
32512
- const sourceFiles = implementationSourceFiles(impl);
32513
- if (sourceFiles.length > 0 && sourceFiles.every((f) => pathExists(fromProjectRoot(f)))) {
32514
- score += 20;
32515
- }
32516
- }
32517
- const isDraft = comp.status === "draft" || comp.status === "design" || intf && (intf.status === "draft" || intf.status === "design") || impl && (impl.status === "draft" || impl.status === "design");
32518
- if (isDraft) {
32519
- score = Math.min(score, 50);
32520
- }
32521
- componentScores.set(comp.id, score);
32522
- }
32523
- const getSubsystemScore = (subId) => {
32524
- const sub = subsystems.find((s) => s.id === subId);
32525
- if (!sub) return 0;
32526
- const subComps = components.filter((c) => c.subsystem === subId);
32527
- if (subComps.length === 0) return 0;
32528
- const totalScore = subComps.reduce((acc, c) => acc + (componentScores.get(c.id) ?? 0), 0);
32529
- let avg = Math.round(totalScore / subComps.length);
32530
- if (sub.status === "draft" || sub.status === "design") {
32531
- avg = Math.min(avg, 50);
32532
- }
32533
- return avg;
32534
- };
32535
- const totalSubsystemsScore = subsystems.reduce((acc, s) => acc + getSubsystemScore(s.id), 0);
32536
- const systemScore = subsystems.length > 0 ? Math.round(totalSubsystemsScore / subsystems.length) : 0;
32537
- const systemColor = systemScore === 100 ? import_chalk9.default.green : systemScore >= 50 ? import_chalk9.default.yellow : import_chalk9.default.red;
32538
- console.log(`${import_chalk9.default.bold.blue("\u25CF System:")} ${import_chalk9.default.bold(system.name)} ${systemColor(`(${systemScore}% Complete)`)}`);
32539
- for (let i = 0; i < subsystems.length; i++) {
32540
- const sub = subsystems[i];
32541
- const isLastSub = i === subsystems.length - 1;
32542
- const subPrefix = isLastSub ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
32543
- const subIndent = isLastSub ? " " : "\u2502 ";
32544
- const subScore = getSubsystemScore(sub.id);
32545
- const subStatusStr = sub.status !== "complete" ? import_chalk9.default.yellow(` [${sub.status}]`) : "";
32546
- const subScoreColor = subScore === 100 ? import_chalk9.default.green : subScore >= 50 ? import_chalk9.default.yellow : import_chalk9.default.red;
32547
- console.log(`${import_chalk9.default.gray(subPrefix)}${import_chalk9.default.bold.cyan(`[Subsystem] ${sub.id}`)}${subStatusStr} ${subScoreColor(`(${subScore}%)`)}`);
32548
- const subComps = components.filter((c) => c.subsystem === sub.id);
32549
- for (let j = 0; j < subComps.length; j++) {
32550
- const comp = subComps[j];
32551
- const isLastComp = j === subComps.length - 1;
32552
- const compPrefix = isLastComp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
32553
- const compIndent = isLastComp ? " " : "\u2502 ";
32554
- const compScore = componentScores.get(comp.id) ?? 0;
32555
- const compStatusStr = comp.status !== "complete" ? import_chalk9.default.yellow(` [${comp.status}]`) : "";
32556
- const compScoreColor = compScore === 100 ? import_chalk9.default.green : compScore >= 50 ? import_chalk9.default.yellow : import_chalk9.default.red;
32557
- console.log(`${import_chalk9.default.gray(subIndent + compPrefix)}${import_chalk9.default.magenta(`[Component: ${comp.componentType}] ${comp.id}`)}${compStatusStr} ${compScoreColor(`(${compScore}%)`)}`);
32558
- const intf = interfaces.find((inf) => inf.component === comp.id);
32559
- const impl = implementations.find((im) => intf && im.contract === intf.id);
32560
- const intfPrefix = intf && impl ? "\u251C\u2500\u2500 " : "\u2514\u2500\u2500 ";
32561
- if (intf) {
32562
- const intfStatusStr = intf.status !== "complete" ? import_chalk9.default.yellow(` [${intf.status}]`) : "";
32563
- console.log(`${import_chalk9.default.gray(subIndent + compIndent + intfPrefix)}${import_chalk9.default.blue(`Interface: ${intf.id}`)}${intfStatusStr} (${intf.methods.length} methods)`);
32564
- } else {
32565
- console.log(`${import_chalk9.default.gray(subIndent + compIndent + intfPrefix)}${import_chalk9.default.red("Interface: Missing (-30%)")}`);
32566
- }
32567
- if (impl) {
32568
- const implStatusStr = impl.status !== "complete" ? import_chalk9.default.yellow(` [${impl.status}]`) : "";
32569
- const methodsWithOwnPath = impl.methods.filter((m) => m.sourcePath);
32570
- let pathStr;
32571
- if (impl.sourcePath) {
32572
- pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? import_chalk9.default.green(` -> ${impl.sourcePath}`) : import_chalk9.default.red(` -> ${impl.sourcePath} (File Missing!)`);
32573
- } else if (methodsWithOwnPath.length > 0) {
32574
- pathStr = "";
32575
- } else {
32576
- pathStr = import_chalk9.default.gray(" (No source path)");
32577
- }
32578
- console.log(`${import_chalk9.default.gray(subIndent + compIndent + "\u2514\u2500\u2500 ")}${import_chalk9.default.green(`Implementation: ${impl.id}`)}${implStatusStr}${pathStr}`);
32579
- const methodIndent = subIndent + compIndent + " ";
32580
- for (let k = 0; k < methodsWithOwnPath.length; k++) {
32581
- const method2 = methodsWithOwnPath[k];
32582
- const isLastMethod = k === methodsWithOwnPath.length - 1;
32583
- const methodPrefix = isLastMethod ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
32584
- const methodPath = method2.sourcePath;
32585
- const methodLine = pathExists(fromProjectRoot(methodPath)) ? import_chalk9.default.green(`method ${method2.name} -> ${methodPath}`) : import_chalk9.default.red(`method ${method2.name} -> ${methodPath} (File Missing!)`);
32586
- console.log(`${import_chalk9.default.gray(methodIndent + methodPrefix)}${methodLine}`);
32587
- }
32588
- } else {
32589
- console.log(`${import_chalk9.default.gray(subIndent + compIndent + "\u2514\u2500\u2500 ")}${import_chalk9.default.red("Implementation: Missing (-30%)")}`);
32590
- }
32591
- }
32592
- }
32593
- const lock = approvalVerdict();
32524
+ console.log(withoutTrailingNewline(report2.text));
32525
+ const lock = approvalVerdict2();
32594
32526
  if (lock.text.trim()) {
32595
32527
  logger.blank();
32596
32528
  if (lock.drifted) logger.warn(lock.text.trim());