mcoda 0.1.26 → 0.1.28

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.
@@ -1 +1 @@
1
- {"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AA8BA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CA8LxE"}
1
+ {"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AA+BA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAkMxE"}
@@ -10,6 +10,7 @@ import { OpenapiCommands } from "../commands/openapi/OpenapiCommands.js";
10
10
  import { CreateTasksCommand } from "../commands/planning/CreateTasksCommand.js";
11
11
  import { RefineTasksCommand } from "../commands/planning/RefineTasksCommand.js";
12
12
  import { TaskSufficiencyAuditCommand } from "../commands/planning/TaskSufficiencyAuditCommand.js";
13
+ import { SdsPreflightCommand } from "../commands/planning/SdsPreflightCommand.js";
13
14
  import { BacklogCommands } from "../commands/backlog/BacklogCommands.js";
14
15
  import { TaskShowCommands } from "../commands/backlog/TaskShowCommands.js";
15
16
  import { OrderTasksCommand } from "../commands/backlog/OrderTasksCommand.js";
@@ -82,7 +83,7 @@ export class McodaEntrypoint {
82
83
  return;
83
84
  }
84
85
  if (!command) {
85
- throw new Error("Usage: mcoda <agent|gateway-agent|test-agent|agent-run|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|task-sufficiency-audit|order-tasks|tasks|add-tests|work-on-tasks|gateway-trio|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|project-guidance|pdr|sds> [...args]\n" +
86
+ throw new Error("Usage: mcoda <agent|gateway-agent|test-agent|agent-run|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|task-sufficiency-audit|sds-preflight|order-tasks|tasks|add-tests|work-on-tasks|gateway-trio|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|project-guidance|pdr|sds> [...args]\n" +
86
87
  "Routing: use `mcoda routing defaults` to view/update workspace/global defaults, `mcoda routing preview|explain` to inspect agent selection/provenance (override → workspace_default → global_default).\n" +
87
88
  "Aliases: `tasks order-by-deps` forwards to `order-tasks` (dependency-aware ordering), `task`/`task-detail` show a single task.\n" +
88
89
  "Job commands (mcoda job --help for details): list|status|watch|logs|inspect|resume|cancel|tokens\n" +
@@ -152,6 +153,10 @@ export class McodaEntrypoint {
152
153
  await TaskSufficiencyAuditCommand.run(rest);
153
154
  return;
154
155
  }
156
+ if (command === "sds-preflight") {
157
+ await SdsPreflightCommand.run(rest);
158
+ return;
159
+ }
155
160
  if (command === "qa-tasks") {
156
161
  if (rest.includes("--help") || rest.includes("-h")) {
157
162
  // eslint-disable-next-line no-console
@@ -1 +1 @@
1
- {"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AA2TA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuThD"}
1
+ {"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AA6TA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAqVhD"}
@@ -38,11 +38,13 @@ const readSecret = async (promptText) => new Promise((resolve) => {
38
38
  });
39
39
  });
40
40
  const USAGE = `
41
- Usage: mcoda agent <list|details|add|update|delete|remove|auth|auth-status|set-default|use|ratings> ...
41
+ Usage: mcoda agent <list|details|limits|add|update|delete|remove|auth|auth-status|set-default|use|ratings> ...
42
42
 
43
43
  Subcommands:
44
44
  list List agents (supports --json)
45
45
  details <NAME> Show agent details (supports --json)
46
+ limits Show tracked usage-limit windows/reset times
47
+ --agent <NAME> Filter by agent slug/id
46
48
  add <NAME> Create a global agent
47
49
  --adapter <TYPE> Adapter slug (openai-api|zhipu-api|codex-cli|claude-cli|gemini-cli|local-model|qa-cli|ollama-remote)
48
50
  --model <MODEL> Default model name
@@ -313,9 +315,11 @@ export class AgentsCommands {
313
315
  ? "set-default"
314
316
  : rawSubcommand === "remove"
315
317
  ? "delete"
316
- : rawSubcommand === "detail" || rawSubcommand === "show"
317
- ? "details"
318
- : rawSubcommand;
318
+ : rawSubcommand === "usage-limits" || rawSubcommand === "usage-limit" || rawSubcommand === "limit"
319
+ ? "limits"
320
+ : rawSubcommand === "detail" || rawSubcommand === "show"
321
+ ? "details"
322
+ : rawSubcommand;
319
323
  if (!subcommand || argv.includes("--help") || argv.includes("-h")) {
320
324
  // eslint-disable-next-line no-console
321
325
  console.log(USAGE);
@@ -441,6 +445,36 @@ export class AgentsCommands {
441
445
  }
442
446
  break;
443
447
  }
448
+ case "limits": {
449
+ const agentName = parsed.flags.agent ? String(parsed.flags.agent) : parsed.positionals[0];
450
+ const limits = await api.listAgentUsageLimits(agentName);
451
+ if (parsed.flags.json) {
452
+ // eslint-disable-next-line no-console
453
+ console.log(JSON.stringify(limits, null, 2));
454
+ }
455
+ else if (limits.length === 0) {
456
+ // eslint-disable-next-line no-console
457
+ console.log(agentName ? `No usage-limit records found for ${agentName}.` : "No usage-limit records found.");
458
+ }
459
+ else {
460
+ const headers = ["AGENT", "SCOPE", "KEY", "WINDOW", "STATUS", "RESET", "EXACT", "OBSERVED", "SOURCE"];
461
+ const maxWidths = [24, 8, 18, 10, 10, 16, 5, 16, 28];
462
+ const rows = limits.map((entry) => [
463
+ entry.agentSlug ?? entry.agentId,
464
+ entry.limitScope,
465
+ entry.limitKey,
466
+ entry.windowType,
467
+ entry.status,
468
+ formatDate(entry.effectiveResetAt ?? entry.resetAt),
469
+ entry.resetAtExact ? "yes" : "no",
470
+ formatDate(entry.observedAt),
471
+ entry.resetAtSource ?? entry.source ?? "-",
472
+ ]);
473
+ // eslint-disable-next-line no-console
474
+ console.log(formatBoxTable(headers, rows, maxWidths));
475
+ }
476
+ break;
477
+ }
444
478
  case "add": {
445
479
  const name = parsed.positionals[0];
446
480
  if (!name)
@@ -13,6 +13,8 @@ interface ParsedArgs {
13
13
  qaEntryUrl?: string;
14
14
  qaStartCommand?: string;
15
15
  qaRequires?: string[];
16
+ sdsPreflightCommit: boolean;
17
+ sdsPreflightCommitMessage?: string;
16
18
  inputs: string[];
17
19
  }
18
20
  type ProjectKeyCandidate = {
@@ -1 +1 @@
1
- {"version":3,"file":"CreateTasksCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/planning/CreateTasksCommand.ts"],"names":[],"mappings":"AAKA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,KAAK,mBAAmB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA2D5D,eAAO,MAAM,yBAAyB,GAAI,SAAS;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC,KAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAmD3C,CAAC;AAUF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,EAAE,KAAG,UAsIrD,CAAC;AAEF,qBAAa,kBAAkB;WAChB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAmEhD"}
1
+ {"version":3,"file":"CreateTasksCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/planning/CreateTasksCommand.ts"],"names":[],"mappings":"AAKA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,KAAK,mBAAmB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA2D5D,eAAO,MAAM,yBAAyB,GAAI,SAAS;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC,KAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAmD3C,CAAC;AAUF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,EAAE,KAAG,UA6JrD,CAAC;AAEF,qBAAa,kBAAkB;WAChB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAqEhD"}
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
  import { promises as fs } from "node:fs";
3
3
  import { CreateTasksService, WorkspaceResolver } from "@mcoda/core";
4
4
  import { PathHelper } from "@mcoda/shared";
5
- const usage = `mcoda create-tasks [INPUT...] [--workspace-root <path>] [--project-key <key>] [--agent <name>] [--agent-stream [true|false]] [--rate-agents] [--force] [--max-epics N] [--max-stories-per-epic N] [--max-tasks-per-story N] [--qa-profile <csv>] [--qa-entry-url <url>] [--qa-start-command <cmd>] [--qa-requires <csv>] [--quiet]`;
5
+ const usage = `mcoda create-tasks [INPUT...] [--workspace-root <path>] [--project-key <key>] [--agent <name>] [--agent-stream [true|false]] [--rate-agents] [--force] [--max-epics N] [--max-stories-per-epic N] [--max-tasks-per-story N] [--qa-profile <csv>] [--qa-entry-url <url>] [--qa-start-command <cmd>] [--qa-requires <csv>] [--sds-preflight-commit [true|false]] [--sds-preflight-commit-message <text>] [--quiet]`;
6
6
  const readWorkspaceConfig = async (mcodaDir) => {
7
7
  const configPath = path.join(mcodaDir, "config.json");
8
8
  try {
@@ -123,6 +123,8 @@ export const parseCreateTasksArgs = (argv) => {
123
123
  let qaEntryUrl;
124
124
  let qaStartCommand;
125
125
  let qaRequires;
126
+ let sdsPreflightCommit = false;
127
+ let sdsPreflightCommitMessage;
126
128
  for (let i = 0; i < argv.length; i += 1) {
127
129
  const arg = argv[i];
128
130
  if (arg.startsWith("--")) {
@@ -131,6 +133,11 @@ export const parseCreateTasksArgs = (argv) => {
131
133
  rateAgents = parseBooleanFlag(raw, true);
132
134
  continue;
133
135
  }
136
+ if (arg.startsWith("--sds-preflight-commit=")) {
137
+ const [, raw] = arg.split("=", 2);
138
+ sdsPreflightCommit = parseBooleanFlag(raw, true);
139
+ continue;
140
+ }
134
141
  switch (arg) {
135
142
  case "--workspace-root":
136
143
  workspaceRoot = argv[i + 1] ? path.resolve(argv[i + 1]) : undefined;
@@ -205,6 +212,21 @@ export const parseCreateTasksArgs = (argv) => {
205
212
  : undefined;
206
213
  i += 1;
207
214
  break;
215
+ case "--sds-preflight-commit": {
216
+ const next = argv[i + 1];
217
+ if (next && !next.startsWith("--")) {
218
+ sdsPreflightCommit = parseBooleanFlag(next, true);
219
+ i += 1;
220
+ }
221
+ else {
222
+ sdsPreflightCommit = true;
223
+ }
224
+ break;
225
+ }
226
+ case "--sds-preflight-commit-message":
227
+ sdsPreflightCommitMessage = argv[i + 1];
228
+ i += 1;
229
+ break;
208
230
  case "--quiet":
209
231
  quiet = true;
210
232
  break;
@@ -240,6 +262,8 @@ export const parseCreateTasksArgs = (argv) => {
240
262
  qaEntryUrl,
241
263
  qaStartCommand,
242
264
  qaRequires,
265
+ sdsPreflightCommit,
266
+ sdsPreflightCommitMessage,
243
267
  inputs,
244
268
  };
245
269
  };
@@ -288,6 +312,8 @@ export class CreateTasksCommand {
288
312
  qaEntryUrl: parsed.qaEntryUrl,
289
313
  qaStartCommand: parsed.qaStartCommand,
290
314
  qaRequires: parsed.qaRequires,
315
+ sdsPreflightCommit: parsed.sdsPreflightCommit,
316
+ sdsPreflightCommitMessage: parsed.sdsPreflightCommitMessage,
291
317
  });
292
318
  const dbPath = PathHelper.getWorkspaceDbPath(workspace.workspaceRoot);
293
319
  if (!parsed.quiet) {
@@ -0,0 +1,16 @@
1
+ interface ParsedSdsPreflightArgs {
2
+ workspaceRoot?: string;
3
+ projectKey?: string;
4
+ sdsPaths: string[];
5
+ apply: boolean;
6
+ commitAppliedChanges: boolean;
7
+ commitMessage?: string;
8
+ json: boolean;
9
+ quiet: boolean;
10
+ }
11
+ export declare const parseSdsPreflightArgs: (argv: string[]) => ParsedSdsPreflightArgs;
12
+ export declare class SdsPreflightCommand {
13
+ static run(argv: string[]): Promise<void>;
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=SdsPreflightCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SdsPreflightCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/planning/SdsPreflightCommand.ts"],"names":[],"mappings":"AAGA,UAAU,sBAAsB;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,oBAAoB,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAUD,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,EAAE,KAAG,sBAmEtD,CAAC;AAEF,qBAAa,mBAAmB;WACjB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAsFhD"}
@@ -0,0 +1,153 @@
1
+ import path from "node:path";
2
+ import { SdsPreflightService, WorkspaceResolver } from "@mcoda/core";
3
+ const usage = "mcoda sds-preflight [--workspace-root <path>] [--project <PROJECT_KEY>] [--sds <path> ...] [--apply] [--commit] [--commit-message <text>] [--json] [--quiet]";
4
+ const normalizeProjectKey = (workspaceRoot) => {
5
+ const derived = path.basename(workspaceRoot).replace(/[^a-z0-9]+/gi, "").toLowerCase();
6
+ return derived || "proj";
7
+ };
8
+ export const parseSdsPreflightArgs = (argv) => {
9
+ let workspaceRoot;
10
+ let projectKey;
11
+ const sdsPaths = [];
12
+ let apply = false;
13
+ let commitAppliedChanges = false;
14
+ let commitMessage;
15
+ let json = false;
16
+ let quiet = false;
17
+ for (let i = 0; i < argv.length; i += 1) {
18
+ const arg = argv[i];
19
+ switch (arg) {
20
+ case "--workspace-root":
21
+ case "--workspace":
22
+ workspaceRoot = argv[i + 1] ? path.resolve(argv[i + 1]) : undefined;
23
+ i += 1;
24
+ break;
25
+ case "--project":
26
+ case "--project-key":
27
+ projectKey = argv[i + 1];
28
+ i += 1;
29
+ break;
30
+ case "--sds":
31
+ if (argv[i + 1]) {
32
+ sdsPaths.push(path.resolve(argv[i + 1]));
33
+ i += 1;
34
+ }
35
+ break;
36
+ case "--apply":
37
+ apply = true;
38
+ break;
39
+ case "--commit":
40
+ commitAppliedChanges = true;
41
+ apply = true;
42
+ break;
43
+ case "--commit-message":
44
+ commitMessage = argv[i + 1];
45
+ i += 1;
46
+ break;
47
+ case "--json":
48
+ json = true;
49
+ break;
50
+ case "--quiet":
51
+ quiet = true;
52
+ break;
53
+ case "--help":
54
+ case "-h":
55
+ // eslint-disable-next-line no-console
56
+ console.log(usage);
57
+ process.exit(0);
58
+ break;
59
+ default:
60
+ break;
61
+ }
62
+ }
63
+ return {
64
+ workspaceRoot,
65
+ projectKey,
66
+ sdsPaths: Array.from(new Set(sdsPaths)),
67
+ apply,
68
+ commitAppliedChanges,
69
+ commitMessage,
70
+ json,
71
+ quiet,
72
+ };
73
+ };
74
+ export class SdsPreflightCommand {
75
+ static async run(argv) {
76
+ const parsed = parseSdsPreflightArgs(argv);
77
+ const workspace = await WorkspaceResolver.resolveWorkspace({
78
+ cwd: process.cwd(),
79
+ explicitWorkspace: parsed.workspaceRoot,
80
+ });
81
+ const configuredKey = typeof workspace.config?.projectKey === "string" && workspace.config.projectKey.trim().length > 0
82
+ ? workspace.config.projectKey
83
+ : undefined;
84
+ const projectKey = parsed.projectKey?.trim() || configuredKey || normalizeProjectKey(workspace.workspaceRoot);
85
+ const service = await SdsPreflightService.create(workspace);
86
+ try {
87
+ const result = await service.runPreflight({
88
+ workspace,
89
+ projectKey,
90
+ inputPaths: [],
91
+ sdsPaths: parsed.sdsPaths,
92
+ writeArtifacts: true,
93
+ applyToSds: parsed.apply,
94
+ commitAppliedChanges: parsed.commitAppliedChanges,
95
+ commitMessage: parsed.commitMessage,
96
+ });
97
+ if (parsed.json) {
98
+ // eslint-disable-next-line no-console
99
+ console.log(JSON.stringify({
100
+ projectKey: result.projectKey,
101
+ generatedAt: result.generatedAt,
102
+ readyForPlanning: result.readyForPlanning,
103
+ qualityStatus: result.qualityStatus,
104
+ sourceSdsPaths: result.sourceSdsPaths,
105
+ reportPath: result.reportPath,
106
+ openQuestionsPath: result.openQuestionsPath,
107
+ gapAddendumPath: result.gapAddendumPath,
108
+ generatedDocPaths: result.generatedDocPaths,
109
+ questionCount: result.questionCount,
110
+ requiredQuestionCount: result.requiredQuestionCount,
111
+ issueCount: result.issueCount,
112
+ blockingIssueCount: result.blockingIssueCount,
113
+ appliedToSds: result.appliedToSds,
114
+ appliedSdsPaths: result.appliedSdsPaths,
115
+ commitHash: result.commitHash,
116
+ warnings: result.warnings,
117
+ }, null, 2));
118
+ return;
119
+ }
120
+ if (!parsed.quiet) {
121
+ const lines = [
122
+ `sds-preflight project=${result.projectKey}`,
123
+ `Ready for planning: ${result.readyForPlanning ? "yes" : "no"}`,
124
+ `Quality status: ${result.qualityStatus}`,
125
+ `SDS sources: ${result.sourceSdsPaths.length}`,
126
+ `Open questions answered: ${result.questionCount} (required=${result.requiredQuestionCount})`,
127
+ `Issues: ${result.issueCount} (blocking=${result.blockingIssueCount})`,
128
+ `SDS apply mode: ${result.appliedToSds ? "on" : "off"}`,
129
+ `SDS files updated: ${result.appliedSdsPaths.length}`,
130
+ `Commit: ${result.commitHash ?? "n/a"}`,
131
+ `Report: ${result.reportPath}`,
132
+ `Q&A doc: ${result.openQuestionsPath}`,
133
+ `Gap addendum: ${result.gapAddendumPath}`,
134
+ ];
135
+ // eslint-disable-next-line no-console
136
+ console.log(lines.join("\n"));
137
+ }
138
+ if (result.warnings.length > 0) {
139
+ // eslint-disable-next-line no-console
140
+ console.warn(result.warnings.map((warning) => `! ${warning}`).join("\n"));
141
+ }
142
+ }
143
+ catch (error) {
144
+ const message = error instanceof Error ? error.message : String(error);
145
+ // eslint-disable-next-line no-console
146
+ console.error(`sds-preflight failed: ${message}`);
147
+ process.exitCode = 1;
148
+ }
149
+ finally {
150
+ await service.close();
151
+ }
152
+ }
153
+ }
@@ -7,7 +7,7 @@ const listWorkspaceProjects = async (workspaceRoot) => {
7
7
  try {
8
8
  const rows = await repo
9
9
  .getDb()
10
- .all(`SELECT key, created_at FROM projects ORDER BY created_at ASC, key ASC`);
10
+ .all(`SELECT key, created_at FROM projects ORDER BY datetime(created_at) DESC, key ASC`);
11
11
  return rows
12
12
  .map((row) => ({ key: String(row.key), createdAt: row.created_at ?? null }))
13
13
  .filter((row) => row.key.trim().length > 0);
@@ -24,25 +24,25 @@ export const pickTaskSufficiencyProjectKey = (options) => {
24
24
  const requestedKey = options.requestedKey?.trim() || undefined;
25
25
  const configuredKey = options.configuredKey?.trim() || undefined;
26
26
  const existing = options.existing ?? [];
27
- const firstExisting = existing[0]?.key;
27
+ const latestExisting = existing[0]?.key;
28
28
  if (requestedKey) {
29
29
  if (configuredKey && configuredKey !== requestedKey) {
30
30
  warnings.push(`Using explicitly requested project key "${requestedKey}"; overriding configured project key "${configuredKey}".`);
31
31
  }
32
- if (firstExisting && requestedKey !== firstExisting) {
33
- warnings.push(`Using explicitly requested project key "${requestedKey}"; first workspace project is "${firstExisting}".`);
32
+ if (latestExisting && requestedKey !== latestExisting) {
33
+ warnings.push(`Using explicitly requested project key "${requestedKey}"; latest workspace project is "${latestExisting}".`);
34
34
  }
35
35
  return { projectKey: requestedKey, warnings };
36
36
  }
37
37
  if (configuredKey) {
38
- if (firstExisting && configuredKey !== firstExisting) {
39
- warnings.push(`Using configured project key "${configuredKey}" instead of first workspace project "${firstExisting}".`);
38
+ if (latestExisting && configuredKey !== latestExisting) {
39
+ warnings.push(`Using configured project key "${configuredKey}" instead of latest workspace project "${latestExisting}".`);
40
40
  }
41
41
  return { projectKey: configuredKey, warnings };
42
42
  }
43
- if (firstExisting) {
44
- warnings.push(`No --project provided; defaulting to first workspace project "${firstExisting}".`);
45
- return { projectKey: firstExisting, warnings };
43
+ if (latestExisting) {
44
+ warnings.push(`No --project provided; defaulting to latest workspace project "${latestExisting}".`);
45
+ return { projectKey: latestExisting, warnings };
46
46
  }
47
47
  return { projectKey: undefined, warnings };
48
48
  };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./commands/estimate/EstimateCommands.js";
11
11
  export * from "./commands/telemetry/TelemetryCommands.js";
12
12
  export * from "./commands/planning/RefineTasksCommand.js";
13
13
  export * from "./commands/planning/TaskSufficiencyAuditCommand.js";
14
+ export * from "./commands/planning/SdsPreflightCommand.js";
14
15
  export * from "./commands/work/WorkOnTasksCommand.js";
15
16
  export * from "./commands/work/GatewayTrioCommand.js";
16
17
  export * from "./commands/review/CodeReviewCommand.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,gDAAgD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,gDAAgD,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ export * from "./commands/estimate/EstimateCommands.js";
11
11
  export * from "./commands/telemetry/TelemetryCommands.js";
12
12
  export * from "./commands/planning/RefineTasksCommand.js";
13
13
  export * from "./commands/planning/TaskSufficiencyAuditCommand.js";
14
+ export * from "./commands/planning/SdsPreflightCommand.js";
14
15
  export * from "./commands/work/WorkOnTasksCommand.js";
15
16
  export * from "./commands/work/GatewayTrioCommand.js";
16
17
  export * from "./commands/review/CodeReviewCommand.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcoda",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Local-first CLI for planning, documentation, and execution workflows with agent assistance.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -45,12 +45,12 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "yaml": "^2.4.2",
48
- "@mcoda/core": "0.1.26",
49
- "@mcoda/shared": "0.1.26"
48
+ "@mcoda/core": "0.1.28",
49
+ "@mcoda/shared": "0.1.28"
50
50
  },
51
51
  "devDependencies": {
52
- "@mcoda/db": "0.1.26",
53
- "@mcoda/integrations": "0.1.26"
52
+ "@mcoda/db": "0.1.28",
53
+ "@mcoda/integrations": "0.1.28"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "tsc -p tsconfig.json",