proteum 2.5.4 → 2.5.5

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.
@@ -66,9 +66,9 @@ Use MCP for repeated reads when a client is available:
66
66
  proteum mcp
67
67
  ```
68
68
 
69
- The machine router discovers live `proteum dev` sessions and offline Proteum app roots under a cwd. `proteum dev` ensures one managed machine MCP daemon is running; terminal `proteum mcp` starts or reuses that daemon and prints a compact central MCP banner with the HTTP client URL, while MCP clients can use stdio. Agents should call MCP `workflow_start` with `cwd` or a known `projectId`, use `project_resolve { cwd }` when routing is ambiguous or offline, and pass the returned live `projectId` to every follow-up app-bound MCP tool. Offline candidates include port-inspected next actions, so agents should follow those instead of guessing the manifest default port. The router forwards to the selected dev-hosted `/__proteum/mcp` endpoint and strips routing fields before the app sees the call.
69
+ The machine router discovers live `proteum dev` sessions and offline Proteum app roots under a cwd. `proteum dev` ensures one managed machine MCP daemon is running; terminal `proteum mcp` starts or reuses that daemon and prints a compact central MCP banner with the HTTP client URL, while MCP clients can use stdio. Agents should call MCP `workflow_start` with `cwd` or a known `projectId`, use `project_resolve { cwd }` when routing is ambiguous or offline, resolve any returned `data.readiness.state="blocked"` fresh-copy setup actions, and pass the returned live `projectId` to every follow-up app-bound MCP tool. Offline candidates include readiness and port-inspected next actions, so agents should follow those instead of guessing the manifest default port. The router forwards to the selected dev-hosted `/__proteum/mcp` endpoint and strips routing fields before the app sees the call.
70
70
 
71
- If machine MCP routing returns offline candidates, choose the intended app root and follow that candidate's next action from the app root, not from the monorepo wrapper. In `/.codex/worktrees/`, if `workflow_start` returns a worktree bootstrap block, run `npx proteum worktree init --source <source-app-root>` or the returned `--refresh` command before any runtime read. If machine MCP routing fails, run `proteum mcp status` and `proteum runtime status` from the intended app root; if no live session exists, use the exact Start Dev next action from runtime status so occupied router/HMR ports are avoided. If the same app already responds on the configured port without live tracking, use or repair that runtime instead of starting another server. Do not `curl` normal page routes to identify which app owns a port; use runtime status or Proteum dev-only endpoints. If a live session exists but runtime/MCP is unreachable, stop the listed session file first, then start dev again. Do not run diagnose, trace, or perf reads while runtime health is unreachable. Do not start a second dev server in the same worktree, and do not start a second managed MCP daemon. Then retry MCP `workflow_start`.
71
+ If machine MCP routing returns offline candidates, choose the intended app root and follow that candidate's readiness and next actions from the app root, not from the monorepo wrapper. In `/.codex/worktrees/`, if `workflow_start` returns a worktree bootstrap block, run `npx proteum worktree init --source <source-app-root>` or the returned `--refresh` command before any runtime read. If machine MCP routing fails, run `proteum mcp status` and `proteum runtime status` from the intended app root; if no live session exists, use the exact Start Dev next action from runtime status so occupied router/HMR ports are avoided. If the same app already responds on the configured port without live tracking, use or repair that runtime instead of starting another server. Do not `curl` normal page routes to identify which app owns a port; use runtime status or Proteum dev-only endpoints. If a live session exists but runtime/MCP is unreachable, stop the listed session file first, then start dev again. Do not run diagnose, trace, or perf reads while runtime health is unreachable. Do not start a second dev server in the same worktree, and do not start a second managed MCP daemon. Then retry MCP `workflow_start`.
72
72
 
73
73
  Prefer CLI over MCP when the result must be reproducible as a shell command, part of verification, or copied into CI/debug instructions.
74
74
 
@@ -135,6 +135,6 @@ The latest Product `/domains` benchmark used routed instructions plus the compac
135
135
  The result confirms the intended routing:
136
136
 
137
137
  - use CLI for reproducible verification and final command evidence
138
- - use `workflow_start` to collapse project resolution, runtime status, instruction previews, owner summary, and first next actions into one read
138
+ - use `workflow_start` to collapse project resolution, fresh-copy readiness, runtime status, instruction previews, owner summary, and first next actions into one read
139
139
  - use machine MCP with `projectId` for repeated runtime reads against an already running app
140
140
  - use `instructions_resolve` to refresh routing instead of rereading full instruction files
@@ -114,7 +114,7 @@ Default compact command output follows this shape:
114
114
 
115
115
  Inside `/.codex/worktrees/`, `proteum dev`, `proteum refresh`, `proteum runtime status`, `proteum verify`, and MCP `workflow_start` require a fresh `.proteum/worktree-bootstrap.json`. If the marker is missing, run `npx proteum worktree init --source <source-app-root>`. If hashes, app `.env`, workspace-root `.env` for monorepos with root tooling, `.proteum/manifest.json`, `node_modules`, or the Proteum version are stale, run the returned `npx proteum worktree init --source <source-app-root> --refresh` command. `PROTEUM_ALLOW_UNBOOTSTRAPPED_WORKTREE=1` bypasses the block but remains visible in runtime status, doctor diagnostics, and MCP output.
116
116
 
117
- During `proteum dev`, `/__proteum/mcp` exposes compact `workflow_start`, `runtime_status`, `orient`, `instructions_resolve`, `route_candidates`, `explain_summary`, `doctor`, `diagnose`, `trace_*`, `perf_*`, and `logs_tail` tools without spawning CLI commands for each repeated read. `proteum dev` also ensures one managed machine `proteum mcp` daemon is running. Through the machine router, call `workflow_start` with `cwd` or a known `projectId`; if routing is ambiguous or returns offline app candidates, use `project_resolve { cwd }`, follow the selected app root's port-inspected next action when needed, then pass the selected live `projectId` to follow-up app-bound tools.
117
+ During `proteum dev`, `/__proteum/mcp` exposes compact `workflow_start`, `runtime_status`, `orient`, `instructions_resolve`, `route_candidates`, `explain_summary`, `doctor`, `diagnose`, `trace_*`, `perf_*`, and `logs_tail` tools without spawning CLI commands for each repeated read. `proteum dev` also ensures one managed machine `proteum mcp` daemon is running. Through the machine router, call `workflow_start` with `cwd` or a known `projectId`; if routing is ambiguous or returns offline app candidates, use `project_resolve { cwd }`, follow the selected app root's fresh-copy readiness and port-inspected next actions when needed, then pass the selected live `projectId` to follow-up app-bound tools. `workflow_start` returns `data.readiness` with read-only setup checks for `.env`, dependencies, generated manifest state, connected producers, Prisma/client readiness, redacted database URL shape, and local database TCP reachability.
118
118
 
119
119
  MCP tool/resource output follows compact single-line `proteum-mcp-v1` JSON:
120
120
 
@@ -251,7 +251,7 @@ Treat these as framework contract failures first. The fix usually belongs at the
251
251
 
252
252
  For AI coding agents or automation:
253
253
 
254
- 1. When MCP is available, call `workflow_start` with `cwd` or a known `projectId`; if routing is ambiguous or returns offline app candidates, call `project_resolve { cwd }`, select the intended app root, start dev from that app root when needed, then retry with the selected stable live `projectId`.
254
+ 1. When MCP is available, call `workflow_start` with `cwd` or a known `projectId`; if routing is ambiguous or returns offline app candidates, call `project_resolve { cwd }`, select the intended app root, resolve any returned `data.readiness.state="blocked"` setup actions, start dev from that app root when needed, then retry with the selected stable live `projectId`.
255
255
  2. Use the returned `projectId` for MCP `runtime_status`, `orient`, `instructions_resolve`, `route_candidates`, `explain_summary`, `doctor`, `diagnose`, `trace_show`, `perf_request`, and `logs_tail` read-only runtime, owner, route, instruction, trace, perf, and log reads.
256
256
  3. Do not run CLI equivalents after a successful MCP result for the same read, and do not run broad source searches for ownership MCP already returned. Use CLI for fallback, `dev`, `build`, `check`, `verify`, migrations, E2E, and final terminal evidence.
257
257
  4. Use selected instruction previews for read-only discovery and diagnostics; read full files only before edits or git writes, when returned `fullRead`/`fullReadPolicy` requires it, or when the preview is insufficient.
package/docs/mcp.md CHANGED
@@ -28,7 +28,7 @@ The router is read-only. It does not start or stop dev servers, mutate files, re
28
28
  Use this flow:
29
29
 
30
30
  1. Call MCP `workflow_start` with `cwd` or a known `projectId`.
31
- 2. If the result is ambiguous or returns offline app candidates, call `project_resolve { cwd }`, pick the intended app root, start exactly one `proteum dev` server from that app root when needed, then retry `workflow_start`.
31
+ 2. If the result is ambiguous or returns offline app candidates, call `project_resolve { cwd }`, pick the intended app root, resolve any returned `data.readiness.state="blocked"` setup actions, start exactly one `proteum dev` server from that app root when needed, then retry `workflow_start`.
32
32
  3. Pass the returned live `projectId` to every follow-up app-bound MCP call.
33
33
  4. After an MCP read succeeds, do not run the equivalent CLI command or broad source search for the same state; keep CLI for fallback, validation, and final terminal evidence.
34
34
 
@@ -47,7 +47,7 @@ Example tool calls:
47
47
  {"tool":"db_query","arguments":{"projectId":"prj_0123abcd4567","sql":"SELECT id, email FROM User LIMIT 5","limit":5}}
48
48
  ```
49
49
 
50
- `workflow_start` is the only app-bound bootstrap tool that may resolve from `cwd` when `projectId` is not known. It may return offline app candidates when no matching dev server is running yet. Other app-bound tools require a live `projectId`; if they omit it, the router returns a compact error that tells the agent to call `projects_list` or `project_resolve`. There is no single-project fallback, because wrong-project reads are worse than an explicit routing retry.
50
+ `workflow_start` is the only app-bound bootstrap tool that may resolve from `cwd` when `projectId` is not known. It may return offline app candidates when no matching dev server is running yet. Its machine-router response includes `data.readiness`, a read-only fresh-copy preflight covering app/root `.env` files, dependency install root and package manager, generated Proteum manifest state, local connected producer apps, Prisma schema/client readiness, redacted database URL shape, and local TCP database reachability when the host is local. The preflight adds exact setup commands where safe, such as copying `.env.example`, installing dependencies, running `npx proteum refresh`, generating Prisma Client, checking Prisma migration status, preflighting connected producer apps, and starting `proteum dev` on a checked port. Other app-bound tools require a live `projectId`; if they omit it, the router returns a compact error that tells the agent to call `projects_list` or `project_resolve`. There is no single-project fallback, because wrong-project reads are worse than an explicit routing retry.
51
51
 
52
52
  When the selected app root is inside `/.codex/worktrees/`, `workflow_start` first checks `.proteum/worktree-bootstrap.json`. If the marker is missing or stale, it returns `ok: false` with a single next action such as `npx proteum worktree init --source <source-app-root>` or the same command with `--refresh`. The router does not forward to the app MCP endpoint until bootstrap is complete, unless `PROTEUM_ALLOW_UNBOOTSTRAPPED_WORKTREE=1` is set; bypasses remain visible in MCP, `runtime status`, and `doctor`.
53
53
 
@@ -79,9 +79,10 @@ If machine MCP routing fails:
79
79
  1. Run `proteum mcp status`.
80
80
  2. Run `proteum runtime status` from the intended app root. If you are in a monorepo wrapper, use the returned app candidates and exact next action instead of starting dev from the wrapper.
81
81
  3. If the app root is inside `/.codex/worktrees/` and runtime status or workflow start reports missing/stale bootstrap, run `proteum worktree init --source <source-app-root>` or the returned `--refresh` command first.
82
- 4. If no live app session exists, use the exact Start Dev next action returned by runtime status. It checks the configured router/HMR ports and suggests an alternate free port when the manifest default is occupied.
83
- 5. If a live session exists but runtime/MCP is unreachable, stop the listed session file with `proteum dev stop --session-file <path>`, then start dev again.
84
- 6. Retry MCP `workflow_start` and use the returned `projectId`.
82
+ 4. If `workflow_start` returns `data.readiness.state="blocked"`, run or resolve the readiness setup actions before starting dev.
83
+ 5. If no live app session exists, use the exact Start Dev next action returned by runtime status or `workflow_start`. It checks the configured router/HMR ports and suggests an alternate free port when the manifest default is occupied.
84
+ 6. If a live session exists but runtime/MCP is unreachable, stop the listed session file with `proteum dev stop --session-file <path>`, then start dev again.
85
+ 7. Retry MCP `workflow_start` and use the returned `projectId`.
85
86
 
86
87
  Offline `project_resolve` and `workflow_start` candidates also inspect configured router/HMR ports before returning `nextAction`. If the configured port already serves the same app but no live machine project is registered, the next action is runtime tracking repair, not starting a second dev server.
87
88
 
@@ -122,7 +123,7 @@ App-bound tools require `projectId` when called through `proteum mcp`:
122
123
 
123
124
  | Tool | Purpose |
124
125
  | --- | --- |
125
- | `workflow_start` | One-call bootstrap with resolved project, runtime, selected instruction previews, owner summary, doctor summaries, duplicate-avoidance rules, and next actions |
126
+ | `workflow_start` | One-call bootstrap with resolved project, fresh-copy readiness, runtime, selected instruction previews, owner summary, doctor summaries, duplicate-avoidance rules, and next actions |
126
127
  | `runtime_status` | Manifest summary, selected runtime, tracked sessions, health, and MCP URL |
127
128
  | `orient` | Owner, instruction routing, connected boundaries, and next actions |
128
129
  | `instructions_resolve` | Selected instruction files for a query, with short previews and full-read policy |
@@ -33,7 +33,7 @@ proteum perf memory --since 1h --group-by controller
33
33
 
34
34
  Default trace output is compact `proteum-agent-v1` JSON with counts, failed calls, error events, hot calls, and hot SQL. Use `--events` or `--full` only when raw event details, payload summaries, or SQL text are needed.
35
35
 
36
- When an MCP client is available, call `workflow_start` with `cwd` or a known `projectId`, then use the returned live `projectId` with MCP `trace_latest`, `trace_show`, `perf_top`, and `perf_request` for repeated reads against the same running app. If `workflow_start` returns offline app candidates or unreachable runtime health, start or repair exactly one `proteum dev` server from the intended app root before trace or perf reads. Keep the CLI commands for reproducible terminal evidence and final verification logs.
36
+ When an MCP client is available, call `workflow_start` with `cwd` or a known `projectId`, then use the returned live `projectId` with MCP `trace_latest`, `trace_show`, `perf_top`, and `perf_request` for repeated reads against the same running app. If `workflow_start` returns offline app candidates, `data.readiness.state="blocked"`, or unreachable runtime health, resolve the readiness setup actions and start or repair exactly one `proteum dev` server from the intended app root before trace or perf reads. Keep the CLI commands for reproducible terminal evidence and final verification logs.
37
37
 
38
38
  Before reproducing a bug or starting a new test pass:
39
39
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proteum",
3
3
  "description": "LLM-first Opinionated Typescript Framework for web applications.",
4
- "version": "2.5.4",
4
+ "version": "2.5.5",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/proteum.git",
7
7
  "license": "MIT",
@@ -99,8 +99,53 @@ const createManifest = (appRoot, overrides = {}) => ({
99
99
 
100
100
  const writeProteumAppFixture = (appRoot, manifestOverrides = {}) => {
101
101
  writeFile(path.join(appRoot, 'package.json'), '{"name":"fixture"}\n');
102
+ writeFile(path.join(appRoot, 'package-lock.json'), '{"lockfileVersion":3}\n');
103
+ writeFile(
104
+ path.join(appRoot, '.env'),
105
+ [
106
+ 'ENV_NAME=local',
107
+ 'ENV_PROFILE=dev',
108
+ `PORT=${manifestOverrides.routerPort || 3104}`,
109
+ `URL=http://localhost:${manifestOverrides.routerPort || 3104}`,
110
+ `URL_INTERNAL=http://localhost:${manifestOverrides.routerPort || 3104}`,
111
+ '',
112
+ ].join('\n'),
113
+ );
114
+ fs.mkdirSync(path.join(appRoot, 'node_modules'), { recursive: true });
115
+ writeFile(path.join(appRoot, 'identity.config.ts'), 'export default {};\n');
116
+ writeFile(path.join(appRoot, 'proteum.config.ts'), 'export default {};\n');
117
+ writeFile(path.join(appRoot, 'client', 'AGENTS.md'), '# Client\n');
118
+ writeFile(path.join(appRoot, 'client', 'pages', 'AGENTS.md'), '# Pages\n');
119
+ writeFile(path.join(appRoot, 'server', 'AGENTS.md'), '# Server\n');
120
+ writeFile(path.join(appRoot, 'server', 'routes', 'AGENTS.md'), '# Routes\n');
121
+ writeFile(path.join(appRoot, 'AGENTS.md'), '# App\n');
122
+ writeFile(path.join(appRoot, 'diagnostics.md'), '# Diagnostics\n');
123
+ writeFile(path.join(appRoot, '.proteum', 'manifest.json'), JSON.stringify(createManifest(appRoot, manifestOverrides), null, 2));
124
+ };
125
+
126
+ const writeFreshCopyFixture = (appRoot, manifestOverrides = {}) => {
127
+ writeFile(path.join(appRoot, 'package.json'), '{"name":"fresh-copy"}\n');
128
+ writeFile(path.join(appRoot, 'package-lock.json'), '{"lockfileVersion":3}\n');
129
+ writeFile(
130
+ path.join(appRoot, '.env.example'),
131
+ [
132
+ 'ENV_NAME=local',
133
+ 'ENV_PROFILE=dev',
134
+ 'PORT=3020',
135
+ 'URL=http://localhost:3020',
136
+ 'URL_INTERNAL=http://localhost:3020',
137
+ 'DATABASE_URL=mysql://user:pass@localhost:3306/app',
138
+ '',
139
+ ].join('\n'),
140
+ );
102
141
  writeFile(path.join(appRoot, 'identity.config.ts'), 'export default {};\n');
103
142
  writeFile(path.join(appRoot, 'proteum.config.ts'), 'export default {};\n');
143
+ writeFile(
144
+ path.join(appRoot, 'prisma', 'schema.prisma'),
145
+ ['generator client {', ' provider = "prisma-client-js"', ' output = "../var/prisma"', '}', '', 'datasource db {', ' provider = "mysql"', '}'].join(
146
+ '\n',
147
+ ),
148
+ );
104
149
  writeFile(path.join(appRoot, 'client', 'AGENTS.md'), '# Client\n');
105
150
  writeFile(path.join(appRoot, 'client', 'pages', 'AGENTS.md'), '# Pages\n');
106
151
  writeFile(path.join(appRoot, 'server', 'AGENTS.md'), '# Server\n');
@@ -700,7 +745,10 @@ test('machine MCP router resolves projects by cwd and bootstraps workflow withou
700
745
  assert.equal(forwardedCall.name, 'workflow_start');
701
746
  assert.deepEqual(forwardedCall.arguments, { route: '/domains', task: 'read-only runtime health pass' });
702
747
  assert.equal(workflowPayload.data.project.projectId, productMachineRecord.projectId);
703
- assert.equal(workflowPayload.nextActions[0].toolArgs.projectId, productMachineRecord.projectId);
748
+ assert.equal(
749
+ workflowPayload.nextActions.find((action) => action.tool === 'diagnose').toolArgs.projectId,
750
+ productMachineRecord.projectId,
751
+ );
704
752
 
705
753
  await client.close();
706
754
  await server.close();
@@ -785,6 +833,55 @@ test('machine MCP router resolves offline monorepo app candidates before dev is
785
833
  await server.close();
786
834
  });
787
835
 
836
+ test('machine MCP workflow_start reports fresh-copy setup blockers before dev start', async (t) => {
837
+ const previousRegistryDir = process.env.PROTEUM_MACHINE_DEV_SESSION_DIR;
838
+ const registryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'proteum-machine-fresh-copy-registry-'));
839
+ process.env.PROTEUM_MACHINE_DEV_SESSION_DIR = registryDir;
840
+ t.onTestFinished(() => {
841
+ if (previousRegistryDir === undefined) delete process.env.PROTEUM_MACHINE_DEV_SESSION_DIR;
842
+ else process.env.PROTEUM_MACHINE_DEV_SESSION_DIR = previousRegistryDir;
843
+ });
844
+
845
+ const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'proteum-machine-fresh-copy-'));
846
+ const appRoot = path.join(repoRoot, 'apps', 'product');
847
+ writeFreshCopyFixture(appRoot, {
848
+ identifier: 'FreshCopyApp',
849
+ name: 'Fresh Copy',
850
+ routerPort: 3022,
851
+ });
852
+
853
+ const server = createProteumMachineMcpServer({ version: 'test' });
854
+ const client = new Client({ name: 'machine-mcp-test', version: '1.0.0' });
855
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
856
+
857
+ await server.connect(serverTransport);
858
+ await client.connect(clientTransport);
859
+
860
+ const workflow = await client.callTool({
861
+ name: 'workflow_start',
862
+ arguments: { cwd: appRoot, task: 'prepare fresh copy' },
863
+ });
864
+ const payload = JSON.parse(workflow.content[0].text);
865
+ const actionLabels = payload.nextActions.map((action) => action.label);
866
+
867
+ assert.equal(payload.ok, true);
868
+ assert.equal(payload.data.readiness.state, 'blocked');
869
+ assert.equal(payload.data.readiness.env.app.present, false);
870
+ assert.equal(payload.data.readiness.dependencies.nodeModulesPresent, false);
871
+ assert.equal(payload.data.readiness.database.detected, true);
872
+ assert.equal(payload.data.readiness.database.generatedClientPresent, false);
873
+ assert.equal(actionLabels.includes('Copy App Env Example'), true);
874
+ assert.equal(actionLabels.includes('Install Dependencies'), true);
875
+ assert.equal(actionLabels.includes('Generate Prisma Client'), true);
876
+ assert.equal(actionLabels.includes('Start Dev'), true);
877
+ assert.match(payload.nextActions.find((action) => action.label === 'Install Dependencies').command, /npm install/);
878
+ assert.match(payload.nextActions.find((action) => action.label === 'Generate Prisma Client').command, /prisma generate/);
879
+ assert.doesNotMatch(workflow.content[0].text, /mysql:\/\/user:pass/);
880
+
881
+ await client.close();
882
+ await server.close();
883
+ });
884
+
788
885
  test('machine MCP workflow_start blocks offline unbootstrapped Codex worktrees', async (t) => {
789
886
  const previousRegistryDir = process.env.PROTEUM_MACHINE_DEV_SESSION_DIR;
790
887
  const registryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'proteum-machine-worktree-offline-'));