proteum 2.3.0 → 2.4.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.
Files changed (56) hide show
  1. package/AGENTS.md +8 -3
  2. package/README.md +20 -15
  3. package/agents/project/AGENTS.md +16 -10
  4. package/agents/project/DOCUMENTATION.md +1326 -0
  5. package/agents/project/app-root/AGENTS.md +2 -2
  6. package/agents/project/diagnostics.md +10 -9
  7. package/agents/project/optimizations.md +1 -1
  8. package/agents/project/root/AGENTS.md +15 -8
  9. package/agents/project/server/services/AGENTS.md +1 -0
  10. package/agents/project/tests/AGENTS.md +1 -0
  11. package/cli/commands/db.ts +160 -0
  12. package/cli/commands/dev.ts +148 -25
  13. package/cli/commands/diagnose.ts +2 -0
  14. package/cli/commands/explain.ts +38 -9
  15. package/cli/commands/mcp.ts +126 -9
  16. package/cli/commands/orient.ts +44 -17
  17. package/cli/commands/runtime.ts +100 -17
  18. package/cli/mcp/router.ts +1028 -0
  19. package/cli/presentation/commands.ts +56 -25
  20. package/cli/presentation/help.ts +1 -1
  21. package/cli/runtime/commands.ts +163 -21
  22. package/cli/runtime/devSessions.ts +328 -2
  23. package/cli/runtime/mcpDaemon.ts +288 -0
  24. package/cli/runtime/ports.ts +151 -0
  25. package/cli/utils/agents.ts +94 -17
  26. package/cli/utils/appRoots.ts +232 -0
  27. package/common/dev/database.ts +226 -0
  28. package/common/dev/diagnostics.ts +1 -1
  29. package/common/dev/inspection.ts +8 -1
  30. package/common/dev/mcpPayloads.ts +456 -17
  31. package/common/dev/mcpServer.ts +51 -0
  32. package/docs/agent-routing.md +32 -21
  33. package/docs/dev-commands.md +1 -1
  34. package/docs/dev-sessions.md +3 -1
  35. package/docs/diagnostics.md +21 -20
  36. package/docs/mcp.md +114 -50
  37. package/docs/migrate-from-2.1.3.md +3 -5
  38. package/docs/request-tracing.md +3 -3
  39. package/package.json +10 -3
  40. package/server/app/devDiagnostics.ts +92 -0
  41. package/server/app/devMcp.ts +55 -0
  42. package/server/services/prisma/mariadb.ts +7 -3
  43. package/server/services/router/http/index.ts +25 -0
  44. package/server/services/router/request/ip.test.cjs +0 -1
  45. package/tests/agents-utils.test.cjs +58 -3
  46. package/tests/cli-mcp-command.test.cjs +327 -0
  47. package/tests/codex-mcp-usage.test.cjs +307 -0
  48. package/tests/dev-sessions.test.cjs +113 -0
  49. package/tests/dev-transpile-watch.test.cjs +0 -1
  50. package/tests/eslint-rules.test.cjs +0 -1
  51. package/tests/inspection.test.cjs +0 -1
  52. package/tests/mcp.test.cjs +769 -2
  53. package/tests/router-cache-config.test.cjs +0 -1
  54. package/vitest.config.mjs +9 -0
  55. package/cli/mcp/provider.ts +0 -365
  56. package/cli/mcp/stdio.ts +0 -16
@@ -21,6 +21,7 @@ export const proteumCommandNames = [
21
21
  'orient',
22
22
  'diagnose',
23
23
  'perf',
24
+ 'db',
24
25
  'runtime',
25
26
  'mcp',
26
27
  'trace',
@@ -59,7 +60,7 @@ export const proteumRecommendedFlow: TRow[] = [
59
60
  export const proteumCommandGroups: Array<{ title: string; names: TProteumCommandName[] }> = [
60
61
  { title: 'Daily workflow', names: ['dev', 'refresh', 'build'] },
61
62
  { title: 'Quality gates', names: ['typecheck', 'lint', 'check', 'e2e'] },
62
- { title: 'Manifest and contracts', names: ['connect', 'doctor', 'explain', 'orient', 'diagnose', 'perf', 'runtime', 'mcp', 'trace', 'command', 'session', 'verify'] },
63
+ { title: 'Manifest and contracts', names: ['connect', 'doctor', 'explain', 'orient', 'diagnose', 'perf', 'db', 'runtime', 'mcp', 'trace', 'command', 'session', 'verify'] },
63
64
  { title: 'Project scaffolding', names: ['init', 'configure', 'create', 'migrate'] },
64
65
  ];
65
66
 
@@ -128,7 +129,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
128
129
  notes: [
129
130
  'This command is interactive. It asks whether the current Proteum app belongs to a monorepo and, if so, which ancestor path should receive the reusable root instruction files.',
130
131
  'Standalone mode writes tracked instruction files into the current Proteum app root.',
131
- 'Monorepo mode writes reusable root documents such as `AGENTS.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root, then writes only app-root and area instruction files into the current Proteum app root.',
132
+ 'Monorepo mode writes reusable root documents such as `AGENTS.md`, `DOCUMENTATION.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root, then writes only app-root and area instruction files into the current Proteum app root.',
132
133
  'Every managed instruction file contains a `# Proteum Instructions` section with the full embedded Proteum project instruction corpus.',
133
134
  'Existing content outside `# Proteum Instructions` is preserved. Directories and foreign symlinks are replaced only after confirmation.',
134
135
  ],
@@ -170,11 +171,14 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
170
171
  { description: 'Start the app on its configured router port', command: 'proteum dev' },
171
172
  {
172
173
  description: 'Start a worktree or sibling checkout without changing your shell directory',
173
- command: 'proteum dev --cwd /path/to/platform-worktree --port 3101 --replace-existing',
174
+ command: 'proteum dev --cwd /path/to/platform-worktree --port 3101',
174
175
  },
175
- { description: 'Replace the tracked dev session on another port', command: 'proteum dev --port 3101 --replace-existing' },
176
176
  {
177
177
  description: 'Start a tracked dev session with an explicit session file for an agent task',
178
+ command: 'proteum dev --port 3101 --session-file var/run/proteum/dev/agents/task.json',
179
+ },
180
+ {
181
+ description: 'Restart the exact tracked session file from the current task',
178
182
  command: 'proteum dev --port 3101 --session-file var/run/proteum/dev/agents/task.json --replace-existing',
179
183
  },
180
184
  {
@@ -193,8 +197,9 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
193
197
  notes: [
194
198
  'Use `--cwd` when the target Proteum app lives in another worktree or checkout and you do not want to `cd` first.',
195
199
  'Proteum writes a machine-readable dev session file under `var/run/proteum/dev/<port>.json` by default; override it with `--session-file` when an agent needs a stable path.',
200
+ 'Before registering a new session, Proteum removes stale same-worktree session files and fails fast if another live tracked session remains.',
196
201
  'Before the dev loop starts, Proteum ensures tracked instruction files contain the current managed `# Proteum Instructions` section.',
197
- 'Use `--replace-existing` when retries should stop the previously tracked matching session before starting a new one.',
202
+ 'Use `--replace-existing` only when retrying the exact requested session file.',
198
203
  '`proteum dev list` inspects tracked sessions for the current app root. Add `--stale` to show only orphaned or dead sessions.',
199
204
  '`proteum dev stop` targets the current session file by default. Add `--all` to stop every tracked session for the current app root.',
200
205
  '`proteum dev` clears the interactive terminal once at startup, then shows `CTRL+R` reload and `CTRL+C` shutdown hotkeys in the session banner.',
@@ -359,11 +364,15 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
359
364
  examples: [
360
365
  { description: 'Show the default compact agent summary', command: 'proteum explain' },
361
366
  {
362
- description: 'Inspect generated routes, controllers, and commands together',
367
+ description: 'Summarize generated routes, controllers, and commands together',
363
368
  command: 'proteum explain --routes --controllers --commands',
364
369
  },
365
370
  {
366
- description: 'Inspect configured connected projects and imported controllers',
371
+ description: 'Emit selected route/controller/command arrays only when needed',
372
+ command: 'proteum explain --routes --controllers --commands --full',
373
+ },
374
+ {
375
+ description: 'Summarize configured connected projects and imported controllers',
367
376
  command: 'proteum explain --connected --controllers',
368
377
  },
369
378
  { description: 'Resolve the most likely manifest owner for a path or file', command: 'proteum explain owner /api/Auth/CurrentUser' },
@@ -371,7 +380,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
371
380
  ],
372
381
  notes: [
373
382
  'Default output is compact `proteum-agent-v1` JSON because the CLI is optimized for agents.',
374
- '`--full`, `--manifest`, or explicit section flags are the escape hatch for large details.',
383
+ 'Explicit section flags summarize those sections by default; add `--full` or use `--manifest` for raw manifest arrays.',
375
384
  'Legacy positional section selection remains supported, for example `proteum explain routes services`.',
376
385
  '`proteum explain owner <query>` ranks matching routes, controllers, services, commands, layouts, and diagnostics from the manifest.',
377
386
  'Connected projects are emitted from explicit `proteum.config.ts` `connect.<Namespace>.*` values plus the resolved connected contract.',
@@ -391,7 +400,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
391
400
  { description: 'Use a running dev server when the local manifest is unavailable', command: 'proteum orient /domains --port 3101' },
392
401
  ],
393
402
  notes: [
394
- 'Default output is compact `proteum-agent-v1` JSON with `mustRead`, conditional docs, owner matches, and next commands.',
403
+ 'Default output is compact `proteum-agent-v1` JSON with `mustRead`, triggered instruction files, conditional docs, owner matches, and next commands.',
395
404
  'Use it before reading source when the query might map to generated code, connected imports, framework-owned files, or area instructions.',
396
405
  'When `--port` or `--url` is provided, Proteum can read the manifest from a running dev server instead of only from disk.',
397
406
  ],
@@ -444,6 +453,26 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
444
453
  ],
445
454
  status: 'experimental',
446
455
  },
456
+ db: {
457
+ name: 'db',
458
+ category: 'Manifest and contracts',
459
+ summary: 'Run one capped read-only database diagnostic query against a running Proteum dev server.',
460
+ usage: 'proteum db [query] <sql> [--limit <rows>] [--timeout <ms>] [--port <port>|--url <baseUrl>] [--full]',
461
+ bestFor:
462
+ 'Inspecting live MySQL or MariaDB state during diagnosis without giving agents a write-capable SQL execution surface.',
463
+ examples: [
464
+ { description: 'Run a small SELECT diagnostic', command: 'proteum db query "SELECT id, email FROM User LIMIT 5"' },
465
+ { description: 'Inspect table metadata', command: 'proteum db "SHOW TABLES"' },
466
+ { description: 'Explain a query plan', command: 'proteum db query "EXPLAIN SELECT * FROM User WHERE id = 1"' },
467
+ ],
468
+ notes: [
469
+ 'Only SELECT, SHOW, and EXPLAIN statements are allowed.',
470
+ 'The dev runtime executes the query with the app DATABASE_URL and returns rows, columns, elapsedMs, and cap metadata.',
471
+ 'Multi-statement SQL, EXPLAIN ANALYZE, locking reads, LOAD_FILE, SELECT INTO OUTFILE, sleep, and benchmark functions are rejected.',
472
+ 'Default output is compact `proteum-agent-v1` JSON with capped rows; use `--full` for the raw dev endpoint payload.',
473
+ ],
474
+ status: 'experimental',
475
+ },
447
476
  runtime: {
448
477
  name: 'runtime',
449
478
  category: 'Manifest and contracts',
@@ -457,6 +486,10 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
457
486
  ],
458
487
  notes: [
459
488
  'Default output is compact `proteum-agent-v1` JSON with the selected session, health, and next command.',
489
+ 'When no tracked session exists, the configured router and HMR ports are inspected before suggesting Start Dev.',
490
+ 'If the same app already responds on the configured port, the next action uses or repairs that runtime instead of starting a second server.',
491
+ 'The selected live session includes its dev-hosted MCP URL when available.',
492
+ 'Use this command instead of curling page routes to identify port ownership.',
460
493
  'Use `--full` to include every tracked session field.',
461
494
  ],
462
495
  status: 'experimental',
@@ -464,26 +497,24 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
464
497
  mcp: {
465
498
  name: 'mcp',
466
499
  category: 'Manifest and contracts',
467
- summary: 'Start a read-only Proteum MCP server for compact agent diagnostics and runtime data.',
468
- usage: 'proteum mcp [--cwd <path>] [--url <baseUrl>] [--session-file <path>]',
500
+ summary: 'Start or attach to the machine-scope MCP router for live Proteum dev projects.',
501
+ usage: 'proteum mcp [status|stop] [--stdio|--daemon] [--port <port>]',
469
502
  bestFor:
470
- 'Agent integrations that need repeated low-token access to Proteum manifest, instruction routing, runtime status, trace, perf, diagnose, and log summaries.',
503
+ 'Registering a single MCP server in an LLM and keeping one managed machine daemon available while dev servers run.',
471
504
  examples: [
472
- { description: 'Start the MCP server for the current app over stdio', command: 'proteum mcp' },
473
- {
474
- description: 'Point the MCP server at a running dev server',
475
- command: 'proteum mcp --url http://localhost:3101',
476
- },
477
- {
478
- description: 'Resolve runtime data from an explicit tracked session file',
479
- command: 'proteum mcp --session-file var/run/proteum/dev/agents/task.json',
480
- },
505
+ { description: 'Start or reuse the managed machine MCP daemon from a terminal', command: 'proteum mcp' },
506
+ { description: 'Force stdio MCP transport for an MCP client', command: 'proteum mcp --stdio' },
507
+ { description: 'Inspect the managed machine MCP daemon', command: 'proteum mcp status' },
481
508
  ],
482
509
  notes: [
483
- '`proteum mcp` is read-only in v1 and does not start/stop dev servers, refresh generated code, write files, or mutate traces.',
484
- 'Tool and resource payloads are compact single-line `proteum-mcp-v1` JSON for low-token agent reads.',
485
- 'Use the CLI for reproducible build/dev/check workflows; use MCP for repeated agent reads and progressive detail loading.',
486
- 'A running `proteum dev` server also exposes the same tool contract at `/__proteum/mcp` for runtime-adjacent access.',
510
+ '`proteum dev` ensures one managed machine MCP daemon is running before the app dev loop starts.',
511
+ '`proteum mcp` is a router, not an app dev server. It discovers live `proteum dev` sessions from the machine registry and can resolve offline app candidates from `cwd`.',
512
+ 'Agents should call MCP `workflow_start` with `cwd` or a known `projectId`; use `project_resolve { cwd }` when routing is ambiguous or no live dev server exists yet.',
513
+ 'When an offline app candidate is returned, start exactly one `proteum dev` from that app root before runtime diagnose, trace, or perf reads.',
514
+ 'After an MCP read succeeds, agents should not run the equivalent CLI command or broad owner search for the same runtime state.',
515
+ 'App runtime data still comes from the selected dev-hosted `/__proteum/mcp` endpoint.',
516
+ 'Only one managed machine MCP daemon may run at a time; stale daemon records are cleaned automatically.',
517
+ 'MCP remains read-only and optimized for compact `proteum-mcp-v1` payloads.',
487
518
  ],
488
519
  status: 'experimental',
489
520
  },
@@ -174,7 +174,7 @@ export const renderCommandHelp = async ({
174
174
  const notes = [...(command.notes ?? [])];
175
175
 
176
176
  if (commandName === 'init') notes.push(getInitAvailabilityNote(initAvailable));
177
- if (commandName !== 'init' && !isLikelyProteumAppRoot(workdir)) {
177
+ if (commandName !== 'init' && commandName !== 'mcp' && !isLikelyProteumAppRoot(workdir)) {
178
178
  notes.push(
179
179
  'This command expects to run inside a Proteum app root. The current directory does not contain the usual `client/` and `server/` folders.',
180
180
  );
@@ -1,8 +1,72 @@
1
1
  import { Builtins, Cli, Option } from 'clipanion';
2
+ import path from 'path';
2
3
 
3
- import type { TArgsObject } from '../context';
4
+ import cli, { type TArgsObject } from '../context';
4
5
  import { applyLegacyBooleanArgs, assertNoLegacyArgs } from './argv';
5
6
  import { buildUsage, ProteumCommand, runCommandModule } from './command';
7
+ import { createStartDevCommand, quoteShellPath, resolveProteumAppRootContext } from '../utils/appRoots';
8
+ import { printJson } from '../utils/agentOutput';
9
+
10
+ const createRunInAppCommand = ({
11
+ appRoot,
12
+ baseRoot,
13
+ command,
14
+ }: {
15
+ appRoot: string;
16
+ baseRoot: string;
17
+ command: string;
18
+ }) => {
19
+ const relativeAppRoot = path.relative(baseRoot, appRoot) || '.';
20
+ if (relativeAppRoot === '.') return command;
21
+ return `cd ${quoteShellPath(relativeAppRoot)} && ${command}`;
22
+ };
23
+
24
+ const printNonAppRootResponse = ({
25
+ commandName,
26
+ cwd,
27
+ }: {
28
+ commandName: 'dev' | 'runtime';
29
+ cwd: string;
30
+ }) => {
31
+ const context = resolveProteumAppRootContext(cwd);
32
+ const appCandidates = context.appCandidates;
33
+ const commandLabel = commandName === 'dev' ? 'Dev' : 'Runtime Status';
34
+
35
+ printJson({
36
+ ok: false,
37
+ format: 'proteum-agent-v1',
38
+ summary:
39
+ appCandidates.length > 0
40
+ ? `${cwd} is a Proteum workspace wrapper or nested directory, not an app root. Found ${appCandidates.length} app candidate${appCandidates.length === 1 ? '' : 's'}.`
41
+ : `${cwd} is not a Proteum app root.`,
42
+ data: {
43
+ cwd: context.cwd,
44
+ appCandidates,
45
+ },
46
+ nextActions: appCandidates.map((candidate) => ({
47
+ label: `${commandLabel}: ${candidate.relativeAppRoot || candidate.appRoot}`,
48
+ command:
49
+ commandName === 'dev'
50
+ ? createStartDevCommand({
51
+ appRoot: candidate.appRoot,
52
+ baseRoot: context.cwd,
53
+ port: candidate.manifest?.routerPort,
54
+ })
55
+ : createRunInAppCommand({
56
+ appRoot: candidate.appRoot,
57
+ baseRoot: context.cwd,
58
+ command: 'npx proteum runtime status',
59
+ }),
60
+ reason:
61
+ commandName === 'dev'
62
+ ? 'Start Proteum dev from the app root, not the workspace wrapper.'
63
+ : 'Inspect tracked runtime sessions from the app root, not the workspace wrapper.',
64
+ })),
65
+ });
66
+ process.exitCode = 1;
67
+ };
68
+
69
+ const isCurrentWorkdirProteumAppRoot = () => resolveProteumAppRootContext(String(cli.args.workdir || process.cwd())).isAppRoot;
6
70
 
7
71
  class InitCommand extends ProteumCommand {
8
72
  public static paths = [['init']];
@@ -154,6 +218,10 @@ class DevCommand extends ProteumCommand {
154
218
  all: this.all,
155
219
  stale: this.stale,
156
220
  });
221
+ if (!isCurrentWorkdirProteumAppRoot()) {
222
+ printNonAppRootResponse({ commandName: 'dev', cwd: String(cli.args.workdir || process.cwd()) });
223
+ return 1;
224
+ }
157
225
  await runCommandModule(() => import('../commands/dev'));
158
226
  }
159
227
  }
@@ -371,18 +439,18 @@ class ExplainCommand extends ProteumCommand {
371
439
  public full = Option.Boolean('--full', false, { description: 'Print the full selected machine-readable detail.' });
372
440
  public human = Option.Boolean('--human', false, { description: 'Print the legacy human-readable report.' });
373
441
  public manifest = Option.Boolean('--manifest', false, { description: 'Print the full generated manifest.' });
374
- public all = Option.Boolean('--all', false, { description: 'Include every explain section.' });
375
- public app = Option.Boolean('--app', false, { description: 'Include the app section.' });
376
- public conventions = Option.Boolean('--conventions', false, { description: 'Include the conventions section.' });
377
- public env = Option.Boolean('--env', false, { description: 'Include the env section.' });
378
- public connected = Option.Boolean('--connected', false, { description: 'Include the connected-projects section.' });
379
- public services = Option.Boolean('--services', false, { description: 'Include the services section.' });
380
- public controllers = Option.Boolean('--controllers', false, { description: 'Include the controllers section.' });
381
- public commands = Option.Boolean('--commands', false, { description: 'Include the commands section.' });
382
- public routes = Option.Boolean('--routes', false, { description: 'Include the routes section.' });
383
- public layouts = Option.Boolean('--layouts', false, { description: 'Include the layouts section.' });
442
+ public all = Option.Boolean('--all', false, { description: 'Summarize every explain section; add --full for raw arrays.' });
443
+ public app = Option.Boolean('--app', false, { description: 'Summarize the app section; add --full for raw detail.' });
444
+ public conventions = Option.Boolean('--conventions', false, { description: 'Summarize the conventions section; add --full for raw detail.' });
445
+ public env = Option.Boolean('--env', false, { description: 'Summarize the env section; add --full for raw detail.' });
446
+ public connected = Option.Boolean('--connected', false, { description: 'Summarize the connected-projects section; add --full for raw detail.' });
447
+ public services = Option.Boolean('--services', false, { description: 'Summarize the services section; add --full for raw detail.' });
448
+ public controllers = Option.Boolean('--controllers', false, { description: 'Summarize the controllers section; add --full for raw detail.' });
449
+ public commands = Option.Boolean('--commands', false, { description: 'Summarize the commands section; add --full for raw detail.' });
450
+ public routes = Option.Boolean('--routes', false, { description: 'Summarize the routes section; add --full for raw detail.' });
451
+ public layouts = Option.Boolean('--layouts', false, { description: 'Summarize the layouts section; add --full for raw detail.' });
384
452
  public diagnostics = Option.Boolean('--diagnostics', false, {
385
- description: 'Include the diagnostics section.',
453
+ description: 'Summarize the diagnostics section; add --full for raw detail.',
386
454
  });
387
455
  public args = Option.Rest();
388
456
 
@@ -627,12 +695,47 @@ class PerfCommand extends ProteumCommand {
627
695
  }
628
696
  }
629
697
 
698
+ class DbCommand extends ProteumCommand {
699
+ public static paths = [['db']];
700
+
701
+ public static usage = buildUsage('db');
702
+
703
+ public port = Option.String('--port', { description: 'Target an existing dev server on the given port.' });
704
+ public url = Option.String('--url', { description: 'Target an existing dev server at the given base URL.' });
705
+ public limit = Option.String('--limit', { description: 'Maximum number of result rows to return, up to 500.' });
706
+ public timeout = Option.String('--timeout', { description: 'Database query timeout in milliseconds, up to 30000.' });
707
+ public json = Option.Boolean('--json', false, { description: 'Compatibility flag; compact JSON is the default output.' });
708
+ public full = Option.Boolean('--full', false, { description: 'Print the full database query payload.' });
709
+ public args = Option.Rest();
710
+
711
+ public async execute() {
712
+ const [first = '', ...restArgs] = this.args;
713
+ const sql = first === 'query' ? restArgs.join(' ').trim() : [first, ...restArgs].join(' ').trim();
714
+
715
+ this.setCliArgs({
716
+ action: 'query',
717
+ full: this.full,
718
+ json: this.json,
719
+ limit: this.limit ?? '',
720
+ port: this.port ?? '',
721
+ sql,
722
+ timeout: this.timeout ?? '',
723
+ url: this.url ?? '',
724
+ });
725
+
726
+ await runCommandModule(() => import('../commands/db'));
727
+ }
728
+ }
729
+
630
730
  class RuntimeCommand extends ProteumCommand {
631
731
  public static paths = [['runtime']];
632
732
 
633
733
  public static usage = buildUsage('runtime');
634
734
 
635
735
  public full = Option.Boolean('--full', false, { description: 'Print full tracked-session and health detail.' });
736
+ public manifest = Option.Boolean('--manifest', false, {
737
+ description: 'Unsupported compatibility guard. Use `proteum explain --manifest` instead.',
738
+ });
636
739
  public sessionFile = Option.String('--session-file', {
637
740
  description: 'Inspect one explicit dev session file instead of the app registry.',
638
741
  });
@@ -644,9 +747,35 @@ class RuntimeCommand extends ProteumCommand {
644
747
  this.setCliArgs({
645
748
  action,
646
749
  full: this.full,
750
+ manifest: this.manifest,
647
751
  sessionFile: this.sessionFile ?? '',
648
752
  });
649
753
 
754
+ if (this.manifest) {
755
+ printJson({
756
+ ok: false,
757
+ format: 'proteum-agent-v1',
758
+ summary: '`proteum runtime status --manifest` is not supported. Use `proteum explain --manifest` from the app root.',
759
+ data: {
760
+ command: 'proteum runtime status --manifest',
761
+ },
762
+ nextActions: [
763
+ {
764
+ label: 'Explain Manifest',
765
+ command: 'npx proteum explain --manifest',
766
+ reason: 'The generated manifest belongs to the explain command, not runtime status.',
767
+ },
768
+ ],
769
+ });
770
+ process.exitCode = 1;
771
+ return 1;
772
+ }
773
+
774
+ if (!isCurrentWorkdirProteumAppRoot()) {
775
+ printNonAppRootResponse({ commandName: 'runtime', cwd: String(cli.args.workdir || process.cwd()) });
776
+ return 1;
777
+ }
778
+
650
779
  await runCommandModule(() => import('../commands/runtime'));
651
780
  }
652
781
  }
@@ -656,19 +785,30 @@ class McpCommand extends ProteumCommand {
656
785
 
657
786
  public static usage = buildUsage('mcp');
658
787
 
659
- public cwd = Option.String('--cwd', { description: 'Run the MCP server against another Proteum app root.' });
660
- public sessionFile = Option.String('--session-file', {
661
- description: 'Inspect one explicit dev session file when resolving runtime data.',
788
+ public daemon = Option.Boolean('--daemon', false, {
789
+ description: 'Run the managed machine-scope MCP daemon over local HTTP.',
662
790
  });
663
- public url = Option.String('--url', { description: 'Use a running Proteum dev server as the live runtime data source.' });
664
- public legacyArgs = Option.Rest();
791
+ public stdio = Option.Boolean('--stdio', false, {
792
+ description: 'Force stdio MCP transport for an MCP client.',
793
+ });
794
+ public port = Option.String('--port', {
795
+ description: 'Port for the managed machine MCP daemon.',
796
+ });
797
+ public json = Option.Boolean('--json', false, {
798
+ description: 'Print machine-readable daemon status output.',
799
+ });
800
+ public args = Option.Rest();
665
801
 
666
802
  public async execute() {
667
- assertNoLegacyArgs('mcp', this.legacyArgs);
803
+ const [action = 'start', ...restArgs] = this.args;
804
+
805
+ assertNoLegacyArgs('mcp', restArgs);
668
806
  this.setCliArgs({
669
- sessionFile: this.sessionFile ?? '',
670
- url: this.url ?? '',
671
- workdir: this.cwd ?? '',
807
+ action,
808
+ daemon: this.daemon,
809
+ stdio: this.stdio,
810
+ port: this.port ?? '',
811
+ json: this.json,
672
812
  });
673
813
 
674
814
  await runCommandModule(() => import('../commands/mcp'));
@@ -751,6 +891,7 @@ export const registeredCommands = {
751
891
  orient: OrientCommand,
752
892
  diagnose: DiagnoseCommand,
753
893
  perf: PerfCommand,
894
+ db: DbCommand,
754
895
  runtime: RuntimeCommand,
755
896
  mcp: McpCommand,
756
897
  trace: TraceCommand,
@@ -786,6 +927,7 @@ export const createCli = (version: string) => {
786
927
  clipanion.register(OrientCommand);
787
928
  clipanion.register(DiagnoseCommand);
788
929
  clipanion.register(PerfCommand);
930
+ clipanion.register(DbCommand);
789
931
  clipanion.register(RuntimeCommand);
790
932
  clipanion.register(McpCommand);
791
933
  clipanion.register(TraceCommand);