maxsimcli 4.4.0 → 4.5.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 (53) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/assets/CHANGELOG.md +19 -0
  3. package/dist/assets/dashboard/server.js +248 -240
  4. package/dist/assets/templates/agents/AGENTS.md +1 -0
  5. package/dist/assets/templates/agents/maxsim-drift-checker.md +522 -0
  6. package/dist/assets/templates/commands/maxsim/check-drift.md +56 -0
  7. package/dist/assets/templates/commands/maxsim/discuss.md +70 -0
  8. package/dist/assets/templates/commands/maxsim/realign.md +39 -0
  9. package/dist/assets/templates/workflows/check-drift.md +248 -0
  10. package/dist/assets/templates/workflows/discuss.md +343 -0
  11. package/dist/assets/templates/workflows/progress.md +8 -0
  12. package/dist/assets/templates/workflows/realign.md +288 -0
  13. package/dist/assets/templates/workflows/roadmap.md +69 -20
  14. package/dist/backend-server.cjs +52 -29
  15. package/dist/backend-server.cjs.map +1 -1
  16. package/dist/cli.cjs +261 -5
  17. package/dist/cli.cjs.map +1 -1
  18. package/dist/cli.js +20 -1
  19. package/dist/cli.js.map +1 -1
  20. package/dist/core/core.d.ts.map +1 -1
  21. package/dist/core/core.js +1 -0
  22. package/dist/core/core.js.map +1 -1
  23. package/dist/core/drift.d.ts +37 -0
  24. package/dist/core/drift.d.ts.map +1 -0
  25. package/dist/core/drift.js +213 -0
  26. package/dist/core/drift.js.map +1 -0
  27. package/dist/core/frontmatter.d.ts.map +1 -1
  28. package/dist/core/frontmatter.js +3 -0
  29. package/dist/core/frontmatter.js.map +1 -1
  30. package/dist/core/index.d.ts +3 -2
  31. package/dist/core/index.d.ts.map +1 -1
  32. package/dist/core/index.js +12 -2
  33. package/dist/core/index.js.map +1 -1
  34. package/dist/core/init.d.ts +5 -3
  35. package/dist/core/init.d.ts.map +1 -1
  36. package/dist/core/init.js +89 -0
  37. package/dist/core/init.js.map +1 -1
  38. package/dist/core/types.d.ts +50 -1
  39. package/dist/core/types.d.ts.map +1 -1
  40. package/dist/core/types.js.map +1 -1
  41. package/dist/core-RRjCSt0G.cjs.map +1 -1
  42. package/dist/{lifecycle-0M4VqOMm.cjs → lifecycle-DxCru7rk.cjs} +2 -2
  43. package/dist/{lifecycle-0M4VqOMm.cjs.map → lifecycle-DxCru7rk.cjs.map} +1 -1
  44. package/dist/mcp/phase-tools.d.ts.map +1 -1
  45. package/dist/mcp/phase-tools.js +17 -4
  46. package/dist/mcp/phase-tools.js.map +1 -1
  47. package/dist/mcp-server.cjs +20 -5
  48. package/dist/mcp-server.cjs.map +1 -1
  49. package/dist/{server-G1MIg_Oe.cjs → server-By0TN-nC.cjs} +21 -6
  50. package/dist/server-By0TN-nC.cjs.map +1 -0
  51. package/dist/skills-MYlMkYNt.cjs.map +1 -1
  52. package/package.json +1 -1
  53. package/dist/server-G1MIg_Oe.cjs.map +0 -1
package/dist/cli.cjs CHANGED
@@ -4722,6 +4722,12 @@ const MODEL_PROFILES = {
4722
4722
  balanced: "sonnet",
4723
4723
  budget: "haiku",
4724
4724
  tokenburner: "opus"
4725
+ },
4726
+ "maxsim-drift-checker": {
4727
+ quality: "sonnet",
4728
+ balanced: "sonnet",
4729
+ budget: "haiku",
4730
+ tokenburner: "opus"
4725
4731
  }
4726
4732
  };
4727
4733
  /** Thrown by output() to signal successful command completion. */
@@ -12035,6 +12041,14 @@ const FRONTMATTER_SCHEMAS = {
12035
12041
  "status",
12036
12042
  "critical_count",
12037
12043
  "warning_count"
12044
+ ] },
12045
+ drift: { required: [
12046
+ "status",
12047
+ "checked",
12048
+ "total_items",
12049
+ "critical_count",
12050
+ "warning_count",
12051
+ "info_count"
12038
12052
  ] }
12039
12053
  };
12040
12054
  function cmdFrontmatterGet(cwd, filePath, field) {
@@ -14564,6 +14578,164 @@ function cmdValidateHealth(cwd, options) {
14564
14578
  });
14565
14579
  }
14566
14580
 
14581
+ //#endregion
14582
+ //#region src/core/drift.ts
14583
+ /**
14584
+ * Drift — Drift report CRUD, requirement extraction, and spec extraction
14585
+ *
14586
+ * Provides CLI tool commands for the drift-checker agent and realign workflow.
14587
+ */
14588
+ const DRIFT_REPORT_NAME = "DRIFT-REPORT.md";
14589
+ /**
14590
+ * Read the drift report from .planning/DRIFT-REPORT.md.
14591
+ * Returns parsed frontmatter and body content, or structured error if not found.
14592
+ */
14593
+ function cmdDriftReadReport(cwd) {
14594
+ const content = safeReadFile(planningPath(cwd, DRIFT_REPORT_NAME));
14595
+ if (!content) return cmdOk({
14596
+ found: false,
14597
+ path: `.planning/${DRIFT_REPORT_NAME}`,
14598
+ error: "Drift report not found"
14599
+ });
14600
+ const frontmatter = extractFrontmatter(content);
14601
+ const bodyMatch = content.match(/^---\n[\s\S]+?\n---\n?([\s\S]*)$/);
14602
+ const body = bodyMatch ? bodyMatch[1].trim() : content;
14603
+ return cmdOk({
14604
+ found: true,
14605
+ path: `.planning/${DRIFT_REPORT_NAME}`,
14606
+ frontmatter,
14607
+ body
14608
+ });
14609
+ }
14610
+ /**
14611
+ * Write content to .planning/DRIFT-REPORT.md.
14612
+ * Supports direct content or reading from a file (tmpfile pattern for large reports).
14613
+ */
14614
+ function cmdDriftWriteReport(cwd, content, contentFile) {
14615
+ let reportContent;
14616
+ if (contentFile) {
14617
+ const fileContent = safeReadFile(node_path.default.isAbsolute(contentFile) ? contentFile : node_path.default.join(cwd, contentFile));
14618
+ if (!fileContent) return cmdErr(`Content file not found: ${contentFile}`);
14619
+ reportContent = fileContent;
14620
+ } else if (content) reportContent = content;
14621
+ else return cmdErr("Either --content or --content-file is required");
14622
+ const reportPath = planningPath(cwd, DRIFT_REPORT_NAME);
14623
+ const planningDir = planningPath(cwd);
14624
+ if (!node_fs.default.existsSync(planningDir)) return cmdErr(".planning/ directory does not exist");
14625
+ try {
14626
+ node_fs.default.writeFileSync(reportPath, reportContent, "utf-8");
14627
+ return cmdOk({
14628
+ written: true,
14629
+ path: `.planning/${DRIFT_REPORT_NAME}`
14630
+ });
14631
+ } catch (e) {
14632
+ debugLog("drift-write-report-failed", e);
14633
+ return cmdErr(`Failed to write drift report: ${e instanceof Error ? e.message : String(e)}`);
14634
+ }
14635
+ }
14636
+ /**
14637
+ * Extract all requirements from .planning/REQUIREMENTS.md.
14638
+ * Parses requirement lines matching `- [ ] **ID**: description` or `- [x] **ID**: description`.
14639
+ */
14640
+ function cmdDriftExtractRequirements(cwd) {
14641
+ const content = safeReadFile(planningPath(cwd, "REQUIREMENTS.md"));
14642
+ if (!content) return cmdOk({
14643
+ found: false,
14644
+ path: ".planning/REQUIREMENTS.md",
14645
+ requirements: []
14646
+ });
14647
+ const requirements = [];
14648
+ const lines = content.split("\n");
14649
+ for (let i = 0; i < lines.length; i++) {
14650
+ const match = lines[i].match(/^-\s+\[([ xX])\]\s+\*\*([^*]+)\*\*[:\s]+(.+)/);
14651
+ if (match) requirements.push({
14652
+ id: match[2].trim(),
14653
+ description: match[3].trim(),
14654
+ complete: match[1].toLowerCase() === "x",
14655
+ line_number: i + 1
14656
+ });
14657
+ }
14658
+ return cmdOk({
14659
+ found: true,
14660
+ path: ".planning/REQUIREMENTS.md",
14661
+ count: requirements.length,
14662
+ requirements
14663
+ });
14664
+ }
14665
+ /**
14666
+ * Extract no-go rules from .planning/NO-GOS.md.
14667
+ * Returns array of no-go items with section context, or empty if file missing.
14668
+ */
14669
+ function cmdDriftExtractNoGos(cwd) {
14670
+ const content = safeReadFile(planningPath(cwd, "NO-GOS.md"));
14671
+ if (!content) return cmdOk({
14672
+ found: false,
14673
+ path: ".planning/NO-GOS.md",
14674
+ nogos: []
14675
+ });
14676
+ const nogos = [];
14677
+ const lines = content.split("\n");
14678
+ let currentSection = "General";
14679
+ for (let i = 0; i < lines.length; i++) {
14680
+ const line = lines[i];
14681
+ const headingMatch = line.match(/^#{2,3}\s+(.+)/);
14682
+ if (headingMatch) {
14683
+ currentSection = headingMatch[1].trim();
14684
+ continue;
14685
+ }
14686
+ const bulletMatch = line.match(/^\s*[-*]\s+(.+)/);
14687
+ if (bulletMatch) {
14688
+ const ruleText = bulletMatch[1].trim();
14689
+ if (ruleText.length > 5) nogos.push({
14690
+ rule: ruleText,
14691
+ section: currentSection,
14692
+ line_number: i + 1
14693
+ });
14694
+ }
14695
+ }
14696
+ return cmdOk({
14697
+ found: true,
14698
+ path: ".planning/NO-GOS.md",
14699
+ count: nogos.length,
14700
+ nogos
14701
+ });
14702
+ }
14703
+ /**
14704
+ * Read .planning/CONVENTIONS.md and return its full content.
14705
+ * Returns the raw content for agent analysis, or null if missing.
14706
+ */
14707
+ function cmdDriftExtractConventions(cwd) {
14708
+ const content = safeReadFile(planningPath(cwd, "CONVENTIONS.md"));
14709
+ if (!content) return cmdOk({
14710
+ found: false,
14711
+ path: ".planning/CONVENTIONS.md",
14712
+ content: null
14713
+ });
14714
+ return cmdOk({
14715
+ found: true,
14716
+ path: ".planning/CONVENTIONS.md",
14717
+ content
14718
+ });
14719
+ }
14720
+ /**
14721
+ * Read existing DRIFT-REPORT.md frontmatter for diff tracking.
14722
+ * Returns previous_hash and checked date, or null if no report exists.
14723
+ */
14724
+ function cmdDriftPreviousHash(cwd) {
14725
+ const content = safeReadFile(planningPath(cwd, DRIFT_REPORT_NAME));
14726
+ if (!content) return cmdOk({
14727
+ found: false,
14728
+ hash: null,
14729
+ checked_date: null
14730
+ });
14731
+ const frontmatter = extractFrontmatter(content);
14732
+ return cmdOk({
14733
+ found: true,
14734
+ hash: frontmatter.previous_hash ?? null,
14735
+ checked_date: frontmatter.checked ?? null
14736
+ });
14737
+ }
14738
+
14567
14739
  //#endregion
14568
14740
  //#region src/core/phase.ts
14569
14741
  /**
@@ -16837,6 +17009,74 @@ function cmdInitDebugger(cwd, phase) {
16837
17009
  if (pathExistsInternal(cwd, ".planning/CONVENTIONS.md")) result.conventions_path = ".planning/CONVENTIONS.md";
16838
17010
  return cmdOk(result);
16839
17011
  }
17012
+ function cmdInitCheckDrift(cwd) {
17013
+ const config = loadConfig(cwd);
17014
+ const driftModel = resolveModelInternal(cwd, "maxsim-drift-checker");
17015
+ const hasPlanning = pathExistsInternal(cwd, ".planning");
17016
+ const hasRequirements = pathExistsInternal(cwd, ".planning/REQUIREMENTS.md");
17017
+ const hasRoadmap = pathExistsInternal(cwd, ".planning/ROADMAP.md");
17018
+ const hasNogos = pathExistsInternal(cwd, ".planning/NO-GOS.md");
17019
+ const hasConventions = pathExistsInternal(cwd, ".planning/CONVENTIONS.md");
17020
+ const hasPreviousReport = pathExistsInternal(cwd, ".planning/DRIFT-REPORT.md");
17021
+ const specFiles = [];
17022
+ if (hasRequirements) specFiles.push(".planning/REQUIREMENTS.md");
17023
+ if (hasRoadmap) specFiles.push(".planning/ROADMAP.md");
17024
+ if (pathExistsInternal(cwd, ".planning/STATE.md")) specFiles.push(".planning/STATE.md");
17025
+ if (hasNogos) specFiles.push(".planning/NO-GOS.md");
17026
+ if (hasConventions) specFiles.push(".planning/CONVENTIONS.md");
17027
+ let phaseDirs = [];
17028
+ try {
17029
+ phaseDirs = listSubDirs(phasesPath(cwd), true).map((d) => `.planning/phases/${d}`);
17030
+ } catch {}
17031
+ let archivedMilestoneDirs = [];
17032
+ try {
17033
+ archivedMilestoneDirs = getArchivedPhaseDirs(cwd).map((a) => a.basePath);
17034
+ archivedMilestoneDirs = [...new Set(archivedMilestoneDirs)];
17035
+ } catch {}
17036
+ const codebaseDocs = listCodebaseDocs(cwd);
17037
+ return cmdOk({
17038
+ drift_model: driftModel,
17039
+ commit_docs: config.commit_docs,
17040
+ has_planning: hasPlanning,
17041
+ has_requirements: hasRequirements,
17042
+ has_roadmap: hasRoadmap,
17043
+ has_nogos: hasNogos,
17044
+ has_conventions: hasConventions,
17045
+ has_previous_report: hasPreviousReport,
17046
+ previous_report_path: hasPreviousReport ? ".planning/DRIFT-REPORT.md" : null,
17047
+ spec_files: specFiles,
17048
+ phase_dirs: phaseDirs,
17049
+ archived_milestone_dirs: archivedMilestoneDirs,
17050
+ state_path: ".planning/STATE.md",
17051
+ requirements_path: ".planning/REQUIREMENTS.md",
17052
+ roadmap_path: ".planning/ROADMAP.md",
17053
+ nogos_path: hasNogos ? ".planning/NO-GOS.md" : null,
17054
+ conventions_path: hasConventions ? ".planning/CONVENTIONS.md" : null,
17055
+ codebase_docs: codebaseDocs
17056
+ });
17057
+ }
17058
+ function cmdInitRealign(cwd, direction) {
17059
+ const config = loadConfig(cwd);
17060
+ const hasReport = pathExistsInternal(cwd, ".planning/DRIFT-REPORT.md");
17061
+ const hasPlanning = pathExistsInternal(cwd, ".planning");
17062
+ let phaseDirs = [];
17063
+ try {
17064
+ phaseDirs = listSubDirs(phasesPath(cwd), true).map((d) => `.planning/phases/${d}`);
17065
+ } catch {}
17066
+ const codebaseDocs = listCodebaseDocs(cwd);
17067
+ return cmdOk({
17068
+ commit_docs: config.commit_docs,
17069
+ direction: direction ?? null,
17070
+ has_report: hasReport,
17071
+ report_path: ".planning/DRIFT-REPORT.md",
17072
+ has_planning: hasPlanning,
17073
+ state_path: ".planning/STATE.md",
17074
+ roadmap_path: ".planning/ROADMAP.md",
17075
+ requirements_path: ".planning/REQUIREMENTS.md",
17076
+ phase_dirs: phaseDirs,
17077
+ codebase_docs: codebaseDocs
17078
+ });
17079
+ }
16840
17080
 
16841
17081
  //#endregion
16842
17082
  //#region src/cli.ts
@@ -17026,6 +17266,19 @@ const handleValidate = (args, cwd, raw) => {
17026
17266
  if (handler) return handler();
17027
17267
  error("Unknown validate subcommand. Available: consistency, health");
17028
17268
  };
17269
+ const handleDrift = (args, cwd, raw) => {
17270
+ const sub = args[1];
17271
+ const handler = sub ? {
17272
+ "read-report": () => cmdDriftReadReport(cwd),
17273
+ "extract-requirements": () => cmdDriftExtractRequirements(cwd),
17274
+ "extract-nogos": () => cmdDriftExtractNoGos(cwd),
17275
+ "extract-conventions": () => cmdDriftExtractConventions(cwd),
17276
+ "write-report": () => cmdDriftWriteReport(cwd, getFlag(args, "--content"), getFlag(args, "--content-file")),
17277
+ "previous-hash": () => cmdDriftPreviousHash(cwd)
17278
+ }[sub] : void 0;
17279
+ if (handler) return handleResult(handler(), raw);
17280
+ error("Unknown drift subcommand. Available: read-report, extract-requirements, extract-nogos, extract-conventions, write-report, previous-hash");
17281
+ };
17029
17282
  const handleInit = (args, cwd, raw) => {
17030
17283
  const workflow = args[1];
17031
17284
  const handler = workflow ? {
@@ -17046,10 +17299,12 @@ const handleInit = (args, cwd, raw) => {
17046
17299
  "planner": () => cmdInitPlanner(cwd, args[2]),
17047
17300
  "researcher": () => cmdInitResearcher(cwd, args[2]),
17048
17301
  "verifier": () => cmdInitVerifier(cwd, args[2]),
17049
- "debugger": () => cmdInitDebugger(cwd, args[2])
17302
+ "debugger": () => cmdInitDebugger(cwd, args[2]),
17303
+ "check-drift": () => cmdInitCheckDrift(cwd),
17304
+ "realign": () => cmdInitRealign(cwd, args[2])
17050
17305
  }[workflow] : void 0;
17051
17306
  if (handler) return handleResult(handler(), raw);
17052
- error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, phase-op, todos, milestone-op, map-codebase, init-existing, progress, executor, planner, researcher, verifier, debugger`);
17307
+ error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, phase-op, todos, milestone-op, map-codebase, init-existing, progress, executor, planner, researcher, verifier, debugger, check-drift, realign`);
17053
17308
  };
17054
17309
  const COMMANDS = {
17055
17310
  "state": handleState,
@@ -17084,6 +17339,7 @@ const COMMANDS = {
17084
17339
  "phase": handlePhase,
17085
17340
  "milestone": handleMilestone,
17086
17341
  "validate": handleValidate,
17342
+ "drift": handleDrift,
17087
17343
  "progress": (args, cwd, raw) => handleResult(cmdProgressRender(cwd, args[1] || "json", raw), raw),
17088
17344
  "todo": (args, cwd, raw) => {
17089
17345
  if (args[1] === "complete") handleResult(cmdTodoComplete(cwd, args[2], raw), raw);
@@ -17131,7 +17387,7 @@ const COMMANDS = {
17131
17387
  (0, node_child_process.spawn)(process.execPath, [serverPath], { stdio: "inherit" }).on("exit", (code) => process.exit(code ?? 0));
17132
17388
  },
17133
17389
  "backend-start": async (args, cwd, raw) => {
17134
- const { startBackend } = await Promise.resolve().then(() => require("./lifecycle-0M4VqOMm.cjs"));
17390
+ const { startBackend } = await Promise.resolve().then(() => require("./lifecycle-DxCru7rk.cjs"));
17135
17391
  const portFlag = args.find((a) => a.startsWith("--port="))?.split("=")[1];
17136
17392
  const background = !args.includes("--foreground");
17137
17393
  output(await startBackend(cwd, {
@@ -17140,11 +17396,11 @@ const COMMANDS = {
17140
17396
  }), raw);
17141
17397
  },
17142
17398
  "backend-stop": async (_args, cwd, raw) => {
17143
- const { stopBackend } = await Promise.resolve().then(() => require("./lifecycle-0M4VqOMm.cjs"));
17399
+ const { stopBackend } = await Promise.resolve().then(() => require("./lifecycle-DxCru7rk.cjs"));
17144
17400
  output({ stopped: await stopBackend(cwd) }, raw);
17145
17401
  },
17146
17402
  "backend-status": async (_args, cwd, raw) => {
17147
- const { getBackendStatus } = await Promise.resolve().then(() => require("./lifecycle-0M4VqOMm.cjs"));
17403
+ const { getBackendStatus } = await Promise.resolve().then(() => require("./lifecycle-DxCru7rk.cjs"));
17148
17404
  output(await getBackendStatus(cwd) || { running: false }, raw);
17149
17405
  }
17150
17406
  };