proteum 2.5.1 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -3
- package/README.md +12 -9
- package/agents/project/AGENTS.md +10 -8
- package/agents/project/CODING_STYLE.md +1 -1
- package/agents/project/diagnostics.md +2 -2
- package/agents/project/root/AGENTS.md +10 -8
- package/agents/project/tests/AGENTS.md +1 -1
- package/cli/commands/configure.ts +5 -5
- package/cli/commands/dev.ts +3 -3
- package/cli/commands/verify.ts +117 -4
- package/cli/compiler/artifacts/controllerHelper.ts +66 -0
- package/cli/compiler/artifacts/controllers.ts +3 -0
- package/cli/compiler/artifacts/services.ts +14 -8
- package/cli/compiler/common/generatedRouteModules.ts +270 -53
- package/cli/presentation/commands.ts +14 -3
- package/cli/presentation/help.ts +1 -1
- package/cli/runtime/commands.ts +6 -0
- package/cli/scaffold/templates.ts +11 -3
- package/cli/utils/agents.ts +271 -2
- package/cli/verification/changed.ts +460 -0
- package/client/app/index.ts +1 -1
- package/client/services/router/index.tsx +1 -1
- package/common/applicationConfig.ts +177 -0
- package/common/applicationConfigLoader.ts +33 -1
- package/common/dev/contractsDoctor.ts +16 -0
- package/config.ts +5 -1
- package/docs/migration-2.5.md +54 -11
- package/eslint.js +42 -8
- package/package.json +1 -1
- package/tests/agents-utils.test.cjs +72 -0
- package/tests/cli-mcp-command.test.cjs +14 -0
- package/tests/contracts-doctor.test.cjs +98 -0
- package/tests/definition-contracts.test.cjs +129 -0
- package/tests/eslint-rules.test.cjs +100 -0
- package/tests/scaffold-templates.test.cjs +27 -2
- package/tests/verify-changed.test.cjs +200 -0
package/AGENTS.md
CHANGED
|
@@ -46,8 +46,8 @@ npx prisma migrate dev --config ./prisma.config.ts --name <migration name>
|
|
|
46
46
|
[optional body]
|
|
47
47
|
```
|
|
48
48
|
If the user replies exactly `commit`, treat it as conversation-wide and cross-project, not task-scoped. Identify every affected git repository or worktree touched since the last `commit` and, if there has been no prior `commit`, since the beginning of the whole conversation. In each affected repository or worktree, stage all conversation-related changed files with `git add` while still excluding unrelated pre-existing user changes or incidental untracked files, then create one `git commit`. Do not omit linked local dependencies, framework repos, connected projects, or producer apps when they were changed to make the delivered behavior actually work.
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
When the user asks to push, explain the currently unpushed commits in short, minimalistic bullet points in plain language, like you would do to your grandma. Start each bullet with a verb in the past.
|
|
50
|
+
When an optional commit body is useful, write it as a short, minimalistic bullet list explaining what changed in this thread in plain language, like you would do to your grandma. Start each bullet with a verb in the past. Do not print a separate prompt asking for that explanation.
|
|
51
51
|
|
|
52
52
|
## Core Changes
|
|
53
53
|
|
|
@@ -65,7 +65,7 @@ npx prisma migrate dev --config ./prisma.config.ts --name <migration name>
|
|
|
65
65
|
- Keep the developer-facing contract synchronized when framework work changes CLI commands, profiler capabilities, or the `proteum dev` banner. Update the live surfaces together in the same pass: CLI command/help definitions, profiler panels and dev-only endpoints, banner text/examples, and the most relevant agent docs that describe them, especially `AGENTS.md`, `agents/project/AGENTS.md`, `agents/project/root/AGENTS.md`, `agents/project/app-root/AGENTS.md`, `agents/project/diagnostics.md`, and any narrower `agents/project/**/AGENTS.md` file that mentions the changed workflow.
|
|
66
66
|
- Proteum MCP contract: `proteum mcp` is the machine-scope router agents register once, and `proteum dev` exposes each app runtime at `/__proteum/mcp`. `proteum dev` ensures one managed machine MCP daemon is running; do not start a second managed daemon. Agents should start with MCP `workflow_start` using `cwd` or a known `projectId`; ambiguous routing or offline app candidates use `project_resolve { cwd }`, and follow-up live app tools require the returned `projectId`. Dev-hosted app tools are already rooted to their own runtime. Keep MCP tools/resources compact, typed, capped, paginated for full trace detail, and read-only unless a future task explicitly expands the mutation contract. The database diagnostic exception is still read-only: MCP `db_query` and CLI `proteum db query` allow one capped `SELECT`, `SHOW`, or `EXPLAIN` statement only and return rows plus elapsed milliseconds. MCP payloads are compact single-line `proteum-mcp-v1` JSON, not pretty-printed human output. Do not implement MCP tools as thin CLI process wrappers when the data is available through manifest readers, tracked sessions, or dev runtime registries.
|
|
67
67
|
- Keep the same-system trace contract explicit when request instrumentation changes: `TRACE_*` controls the retained dev trace store plus the trace/perf CLI, dev-only HTTP endpoints, and bottom profiler, while `ENABLE_PROFILER` enables the reduced request-local `request.profiling` snapshot and `request.finished` hook payload without retaining finished requests globally unless dev trace is also enabled.
|
|
68
|
-
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section before the dev loop begins.
|
|
68
|
+
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section and `CLAUDE.md` symlinks point to sibling `AGENTS.md` files before the dev loop begins.
|
|
69
69
|
- Keep core changes aligned with the explicit controller/page architecture in `agents/project/root/AGENTS.md` and its standalone composition in `agents/project/AGENTS.md`.
|
|
70
70
|
- Prefer removing framework magic when the same result can be expressed with explicit contracts, generated code, or typed context.
|
|
71
71
|
- Apply the pruning rules from `agents/project/optimizations.md`, especially for webpack plugins, Babel plugins, aliases, helpers, runtime services, and npm packages that are not meaningfully used by both apps.
|
package/README.md
CHANGED
|
@@ -198,10 +198,12 @@ const createRouter = (app: MyApp): MyRouter =>
|
|
|
198
198
|
app
|
|
199
199
|
);
|
|
200
200
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
const createServices = (app: MyApp): MyAppServices => ({
|
|
202
|
+
Users: new Users(app, userConfig.usersConfig, app),
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const MyApplication = defineApplication({
|
|
206
|
+
services: createServices,
|
|
205
207
|
router: createRouter,
|
|
206
208
|
});
|
|
207
209
|
|
|
@@ -281,7 +283,7 @@ What happens here:
|
|
|
281
283
|
Proteum controllers are explicit request entrypoints.
|
|
282
284
|
|
|
283
285
|
```ts
|
|
284
|
-
import { defineAction, defineController, schema } from '@server/
|
|
286
|
+
import { defineAction, defineController, schema } from '@generated/server/controller';
|
|
285
287
|
|
|
286
288
|
export default defineController({
|
|
287
289
|
path: 'Auth',
|
|
@@ -399,9 +401,9 @@ Proteum ships with a compact CLI focused on the real app lifecycle:
|
|
|
399
401
|
| `proteum command` | Run a dev-only internal command locally or against a running dev server |
|
|
400
402
|
| `proteum session` | Mint a dev-only auth session token and Playwright-ready cookie payload |
|
|
401
403
|
| `proteum e2e` | Run Playwright with Proteum-managed `E2E_*` values instead of shell-leading env assignments |
|
|
402
|
-
| `proteum verify` | Validate
|
|
404
|
+
| `proteum verify` | Validate targeted changed-file checks, focused owner/request/browser workflows, or the full framework reference-app pass |
|
|
403
405
|
| `proteum init` | Scaffold a new Proteum app with built-in deterministic templates |
|
|
404
|
-
| `proteum configure agents` | Interactively configure tracked Proteum instruction files
|
|
406
|
+
| `proteum configure agents` | Interactively configure tracked Proteum instruction files and Claude aliases |
|
|
405
407
|
| `proteum create` | Scaffold a page, controller, command, route, or root service inside an app |
|
|
406
408
|
| `proteum worktree` | Create or initialize Codex worktrees with a machine-readable bootstrap marker |
|
|
407
409
|
|
|
@@ -411,12 +413,13 @@ Recommended daily workflow:
|
|
|
411
413
|
proteum dev
|
|
412
414
|
proteum refresh
|
|
413
415
|
proteum check
|
|
416
|
+
proteum verify changed --dry-run
|
|
414
417
|
proteum build --prod
|
|
415
418
|
proteum build --prod --analyze
|
|
416
419
|
proteum build --prod --analyze --analyze-serve --analyze-port auto
|
|
417
420
|
```
|
|
418
421
|
|
|
419
|
-
Only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the banner. `proteum dev` is the only command that clears the interactive terminal before rendering its live session UI, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys, and prints connected app names plus successful connected `/ping` checks in the server-ready banner. Every `proteum dev` start ensures tracked Proteum instruction files contain the current managed `# Proteum Instructions` section before the dev loop begins.
|
|
422
|
+
Only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the banner. `proteum dev` is the only command that clears the interactive terminal before rendering its live session UI, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys, and prints connected app names plus successful connected `/ping` checks in the server-ready banner. Every `proteum dev` start ensures tracked Proteum instruction files contain the current managed `# Proteum Instructions` section and `CLAUDE.md` symlinks point to sibling `AGENTS.md` files before the dev loop begins.
|
|
420
423
|
|
|
421
424
|
Useful inspection commands:
|
|
422
425
|
|
|
@@ -464,7 +467,7 @@ proteum create controller Founder/projects --method list
|
|
|
464
467
|
proteum create service Conversion/Plans
|
|
465
468
|
```
|
|
466
469
|
|
|
467
|
-
`proteum configure agents` writes a compact managed `# Proteum Instructions` router plus the task-specific instruction files that router points to. Standalone mode writes root documents into the app root; monorepo mode writes shared root documents such as `AGENTS.md`, `DOCUMENTATION.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root and keeps only app-local instruction files in the Proteum app root. It preserves content outside managed sections and asks before replacing directories or
|
|
470
|
+
`proteum configure agents` writes a compact managed `# Proteum Instructions` router plus the task-specific instruction files that router points to. Standalone mode writes root documents into the app root; monorepo mode writes shared root documents such as `AGENTS.md`, `DOCUMENTATION.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root and keeps only app-local instruction files in the Proteum app root. For each generated `AGENTS.md`, it creates a sibling `CLAUDE.md` symlink pointing to `AGENTS.md`. It preserves content outside managed sections and asks before replacing directories, foreign symlinks, or unrelated files. If you decline, that path is left untouched.
|
|
468
471
|
|
|
469
472
|
Every `proteum dev` start runs the same idempotent instruction check. It updates missing or stale managed sections automatically and prompts only when a blocked path would need to be replaced.
|
|
470
473
|
|
package/agents/project/AGENTS.md
CHANGED
|
@@ -74,13 +74,13 @@ Managed compact root routers must use trigger -> canonical instruction file refe
|
|
|
74
74
|
- If the current app depends on local `file:` connected projects, boot every connected producer app too, each with its own task-scoped session file and free port, and run every one of those `proteum dev` processes with elevated permissions outside the sandbox before starting or verifying the consumer app.
|
|
75
75
|
- During `npx proteum dev`, the app exposes the read-only Proteum MCP runtime endpoint at `/__proteum/mcp`; use it for repeated agent reads instead of spawning equivalent diagnostics commands. For route/page/controller ownership, prefer MCP `workflow_start`, `route_candidates { projectId, query }`, or `explain_summary { projectId, query }` over broad `npx proteum explain --routes --controllers --full` dumps.
|
|
76
76
|
- For browser validation, use the browser MCP against the running app. Keep Playwright inside `npx proteum e2e --port <port>` for targeted/full end-to-end suites. Bootstrap protected browser MCP state with `npx proteum session`; bootstrap protected E2E runs with `npx proteum e2e --session-email <email> --session-role <role>`.
|
|
77
|
-
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section before the dev loop begins.
|
|
77
|
+
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section and `CLAUDE.md` symlinks point to sibling `AGENTS.md` files before the dev loop begins.
|
|
78
78
|
|
|
79
79
|
### Before Finishing
|
|
80
80
|
|
|
81
81
|
- Before finishing, re-check touched files against root-level `CODING_STYLE.md` and any narrower area `AGENTS.md` that applied to the edit. Re-check against root-level `optimizations.md` only for touched client-side files. Re-check against root-level `diagnostics.md` only if the task involved an issue, diagnosis, runtime reproduction, or verification failure.
|
|
82
82
|
- Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
|
|
83
|
-
- Run targeted tests and checks that match the changed surface before finishing each feature or change. Continue running tests after changes, but do not run coverage by default. Reserve the non-coverage commit gate for commit workflows, and reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
83
|
+
- Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Reserve the non-coverage commit gate for commit workflows, and reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
84
84
|
- Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
|
|
85
85
|
- When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
|
|
86
86
|
`Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
|
|
@@ -161,10 +161,12 @@ const createProjectRouter = (app: ProjectApp): ProjectRouter =>
|
|
|
161
161
|
app,
|
|
162
162
|
);
|
|
163
163
|
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
const createProjectServices = (app: ProjectApp): ProjectServices => ({
|
|
165
|
+
Billing: new BillingService(app, {}, app),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const ProjectApplication = defineApplication({
|
|
169
|
+
services: createProjectServices,
|
|
168
170
|
router: createProjectRouter,
|
|
169
171
|
});
|
|
170
172
|
|
|
@@ -190,7 +192,7 @@ export default ProjectApplication;
|
|
|
190
192
|
- Prefer `proteum create controller ...` for new controller boilerplate, then adapt the generated method to real service calls.
|
|
191
193
|
|
|
192
194
|
```ts
|
|
193
|
-
import { defineAction, defineController, schema } from '@server/
|
|
195
|
+
import { defineAction, defineController, schema } from '@generated/server/controller';
|
|
194
196
|
|
|
195
197
|
export default defineController({
|
|
196
198
|
path: 'Billing',
|
|
@@ -271,7 +273,7 @@ export default defineServerRoute({
|
|
|
271
273
|
|
|
272
274
|
Verify at the correct layer:
|
|
273
275
|
|
|
274
|
-
- Default: use the cheapest trustworthy verification for the changed surface, including targeted tests for changed behavior. Do not run coverage by default during ordinary change closeout.
|
|
276
|
+
- Default: use the cheapest trustworthy verification for the changed surface, including targeted tests for changed behavior. When `proteum.verify.config.ts` exists, start with `npx proteum verify changed`. Do not run coverage by default during ordinary change closeout.
|
|
275
277
|
- Route additions: boot the app and hit the real URL.
|
|
276
278
|
- Controller changes: exercise the generated client call or generated `/api/...` endpoint.
|
|
277
279
|
- SSR changes: use the browser MCP to load the real page and inspect rendered HTML plus browser console.
|
|
@@ -8,7 +8,7 @@ This file is the source of truth for codex coding style instructions in Proteum-
|
|
|
8
8
|
- Write clean, consistent, readable code with a tab size of 4.
|
|
9
9
|
- Keep functions and methods short.
|
|
10
10
|
- Every time possible, create reusable functions and components instead of repeating.
|
|
11
|
-
- Before finishing a feature or change, review touched files against this document and run targeted lint/typecheck/tests for the changed surface. Do not run coverage by default after ordinary changes. Run the repository's non-coverage commit gate before committing, and run the full `npm run check` gate before pushing or when the user explicitly asks for it; coding-style regressions are defects, not optional cleanup.
|
|
11
|
+
- Before finishing a feature or change, review touched files against this document and run targeted lint/typecheck/tests for the changed surface. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass. Do not run coverage by default after ordinary changes. Run the repository's non-coverage commit gate before committing, and run the full `npm run check` gate before pushing or when the user explicitly asks for it; coding-style regressions are defects, not optional cleanup.
|
|
12
12
|
|
|
13
13
|
## Type safety
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ This file is the canonical source of truth for diagnostics, temporary instrument
|
|
|
18
18
|
|
|
19
19
|
- For long-lived dev reproductions, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit task/thread-scoped session file, inspect `npx proteum runtime status` first, then use its exact next action so occupied router/HMR ports and untracked same-app runtimes are handled without page-body probes. After the server is ready, print the live server URL as a clickable Markdown link.
|
|
20
20
|
- Use `--replace-existing` only when restarting the exact session file started by the current thread/task. Never replace another live session that belongs to a user, another thread, or an unknown owner.
|
|
21
|
-
- Only the bare `npx proteum build` and bare `npx proteum dev` commands print the welcome banner and active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `npx proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `npx proteum dev` clears the interactive terminal before rendering and reports connected app names plus successful connected `/ping` checks in the ready banner; keep that in mind when capturing or comparing command logs during diagnosis. Every `npx proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section before the dev loop begins.
|
|
21
|
+
- Only the bare `npx proteum build` and bare `npx proteum dev` commands print the welcome banner and active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `npx proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `npx proteum dev` clears the interactive terminal before rendering and reports connected app names plus successful connected `/ping` checks in the ready banner; keep that in mind when capturing or comparing command logs during diagnosis. Every `npx proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section and `CLAUDE.md` symlinks point to sibling `AGENTS.md` files before the dev loop begins.
|
|
22
22
|
- During `npx proteum dev`, the running app exposes the read-only Proteum MCP transport at `/__proteum/mcp`. Use it for runtime-adjacent agent reads instead of repeatedly spawning equivalent CLI diagnostics.
|
|
23
23
|
- If machine MCP routing fails, run `npx proteum mcp status` and `npx proteum runtime status` from the intended app root. If no live session exists, use the exact MCP offline or runtime-status next action 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 start a second dev server in the same worktree, and do not start a second managed MCP daemon. Do not run diagnose, trace, or perf reads while runtime health is unreachable. Then retry MCP `workflow_start` and use the returned `projectId`.
|
|
24
24
|
- For ownership or repo discovery questions, start with MCP `workflow_start`; use MCP `route_candidates { projectId, query }`, MCP `orient { projectId, query }`, and MCP `explain_summary { projectId, query }` only when the bootstrap owner summary is insufficient. Use `npx proteum orient <query>` or `npx proteum explain owner <query>` only when MCP is unavailable or terminal evidence is required.
|
|
@@ -55,7 +55,7 @@ This file is the canonical source of truth for diagnostics, temporary instrument
|
|
|
55
55
|
## Verification And Testing
|
|
56
56
|
|
|
57
57
|
- Use the cheapest trustworthy verification that matches the failing layer.
|
|
58
|
-
- After implementing a change, verify at the smallest trustworthy layer required by the changed surface first, including targeted tests when behavior changed. Do not run coverage by default, and do not default to a running app, browser MCP, or Playwright while iterating when a narrower static or request-level verification is enough.
|
|
58
|
+
- After implementing a change, verify at the smallest trustworthy layer required by the changed surface first, including targeted tests when behavior changed. When the project defines `proteum.verify.config.ts`, prefer `npx proteum verify changed` for the first post-edit verification plan. Do not run coverage by default, and do not default to a running app, browser MCP, or Playwright while iterating when a narrower static or request-level verification is enough.
|
|
59
59
|
- For compile-time or type-safety issues, start with the relevant targeted typecheck or build command. Do not run them by default for unrelated runtime, copy, docs, or local refactor changes.
|
|
60
60
|
- For request/runtime issues, verify through the real page, route, generated controller call, or command on a running app.
|
|
61
61
|
- Start the smallest trustworthy runtime surface first: MCP `workflow_start`, then MCP `route_candidates { projectId, query }`, MCP `orient { projectId, query }`, or MCP `explain_summary { projectId, query }` only when more owner detail is needed. If runtime health is unreachable, repair/start dev before any diagnose, trace, or perf read. Once runtime is reachable, use the relevant real URL, generated controller call, command, or MCP `diagnose { projectId, path }`. Use CLI equivalents only when MCP is unavailable or terminal evidence is required. Use browser MCP validation only when request-level verification is insufficient or the change is browser-visible.
|
|
@@ -59,14 +59,14 @@ Managed compact root routers must use trigger -> canonical instruction file refe
|
|
|
59
59
|
- If the current app depends on local `file:` connected projects, boot every connected producer app too, each with its own task-scoped session file and free port, and run every one of those `proteum dev` processes with elevated permissions outside the sandbox before starting or verifying the consumer app.
|
|
60
60
|
- During `npx proteum dev`, the app exposes the read-only Proteum MCP runtime endpoint at `/__proteum/mcp`; use it for repeated agent reads instead of spawning equivalent diagnostics commands. For route/page/controller ownership, prefer MCP `workflow_start`, `route_candidates { projectId, query }`, or `explain_summary { projectId, query }` over broad `npx proteum explain --routes --controllers --full` dumps.
|
|
61
61
|
- For browser validation, use the browser MCP against the running app. Keep Playwright inside `npx proteum e2e --port <port>` for targeted/full end-to-end suites. Bootstrap protected browser MCP state with `npx proteum session`; bootstrap protected E2E runs with `npx proteum e2e --session-email <email> --session-role <role>`.
|
|
62
|
-
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section before the dev loop begins.
|
|
62
|
+
- Current CLI banner contract: only the bare `proteum build` and bare `proteum dev` commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the welcome banner. Terminal `proteum mcp` may print a compact central MCP ready banner when it starts or reuses the managed daemon. Only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner. Every `proteum dev` start ensures tracked instruction files contain the current managed `# Proteum Instructions` section and `CLAUDE.md` symlinks point to sibling `AGENTS.md` files before the dev loop begins.
|
|
63
63
|
|
|
64
64
|
### Before Finishing
|
|
65
65
|
|
|
66
66
|
- Before finishing, re-check touched files against root-level `CODING_STYLE.md` and any narrower area `AGENTS.md` that applied to the edit. Re-check against root-level `optimizations.md` only for touched client-side files. Re-check against root-level `diagnostics.md` only if the task involved an issue, diagnosis, runtime reproduction, or verification failure.
|
|
67
67
|
- Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
|
|
68
68
|
- For production changes, always add or update focused unit tests and run the targeted unit or integration tests that match the changed behavior. Do not run coverage after every ordinary change by default. Reserve whole-project coverage for the repository's full `npm run check` gate during push workflows or when the user explicitly requests it; do not run coverage for commit-only workflows by default. Document any generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested as explicit exceptions.
|
|
69
|
-
- Run targeted tests and checks that match the changed surface before finishing each feature or change. Continue running tests after changes, but do not run coverage by default. Reserve the non-coverage commit gate for commit workflows, and reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
69
|
+
- Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Reserve the non-coverage commit gate for commit workflows, and reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
70
70
|
- Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
|
|
71
71
|
- When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
|
|
72
72
|
`Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
|
|
@@ -147,10 +147,12 @@ const createProjectRouter = (app: ProjectApp): ProjectRouter =>
|
|
|
147
147
|
app,
|
|
148
148
|
);
|
|
149
149
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
const createProjectServices = (app: ProjectApp): ProjectServices => ({
|
|
151
|
+
Billing: new BillingService(app, {}, app),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const ProjectApplication = defineApplication({
|
|
155
|
+
services: createProjectServices,
|
|
154
156
|
router: createProjectRouter,
|
|
155
157
|
});
|
|
156
158
|
|
|
@@ -176,7 +178,7 @@ export default ProjectApplication;
|
|
|
176
178
|
- Prefer `proteum create controller ...` for new controller boilerplate, then adapt the generated method to real service calls.
|
|
177
179
|
|
|
178
180
|
```ts
|
|
179
|
-
import { defineAction, defineController, schema } from '@server/
|
|
181
|
+
import { defineAction, defineController, schema } from '@generated/server/controller';
|
|
180
182
|
|
|
181
183
|
export default defineController({
|
|
182
184
|
path: 'Billing',
|
|
@@ -257,7 +259,7 @@ export default defineServerRoute({
|
|
|
257
259
|
|
|
258
260
|
Verify at the correct layer:
|
|
259
261
|
|
|
260
|
-
- Default: use the cheapest trustworthy verification for the changed surface, including targeted tests for changed behavior. Do not run coverage by default during ordinary change closeout.
|
|
262
|
+
- Default: use the cheapest trustworthy verification for the changed surface, including targeted tests for changed behavior. When `proteum.verify.config.ts` exists, start with `npx proteum verify changed`. Do not run coverage by default during ordinary change closeout.
|
|
261
263
|
- Route additions: boot the app and hit the real URL.
|
|
262
264
|
- Controller changes: exercise the generated client call or generated `/api/...` endpoint.
|
|
263
265
|
- SSR changes: use the browser MCP to load the real page and inspect rendered HTML plus browser console.
|
|
@@ -9,7 +9,7 @@ Diagnostics source of truth: root-level `diagnostics.md`.
|
|
|
9
9
|
|
|
10
10
|
- Understand the real user flow and the main feature branches before writing tests.
|
|
11
11
|
- Test the current controller/page runtime model, not legacy `@Route` or `api.fetch(...)` behavior.
|
|
12
|
-
- For every production change, add or update focused unit tests and run the targeted test command that matches the changed behavior. Do not run whole-project coverage after every ordinary change by default. Use the repository's non-coverage commit gate before commit, and use `npm run check` as the full gate before push or when the user explicitly asks for it, and document any generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested as explicit exceptions.
|
|
12
|
+
- For every production change, add or update focused unit tests and run the targeted test command that matches the changed behavior. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` first so changed test files, related source tests, and project-specific suites are selected consistently. Do not run whole-project coverage after every ordinary change by default. Use the repository's non-coverage commit gate before commit, and use `npm run check` as the full gate before push or when the user explicitly asks for it, and document any generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested as explicit exceptions.
|
|
13
13
|
- Verify routing, controllers, SSR, and router plugins against a running app when behavior depends on real request handling.
|
|
14
14
|
- After implementing a new feature or changing existing feature behavior, update the end-to-end coverage for that behavior and run the full Playwright suite before finishing. Prefer `npx proteum e2e --port <port>` for Playwright runs so base URLs and auth tokens are passed through Proteum-managed child env instead of shell-leading environment assignments. Use a browser MCP repro against a running app during iteration when it is the fastest trustworthy loop.
|
|
15
15
|
- Exercise real URLs, generated controller calls, or real browser flows instead of re-deriving framework internals in tests.
|
|
@@ -74,7 +74,7 @@ const promptBlockedOverwritePaths = async (blockedPaths: string[]) => {
|
|
|
74
74
|
console.info(await renderWarning('Proteum found existing paths that block managed instruction updates.'));
|
|
75
75
|
console.info(
|
|
76
76
|
[
|
|
77
|
-
'Choose whether to overwrite each path with a
|
|
77
|
+
'Choose whether to overwrite each path with a Proteum-managed instruction path:',
|
|
78
78
|
...blockedPaths.map((entry) => `- ${entry}`),
|
|
79
79
|
].join('\n'),
|
|
80
80
|
);
|
|
@@ -163,7 +163,7 @@ export const runConfigureAgentsWizard = async ({
|
|
|
163
163
|
: undefined;
|
|
164
164
|
console.info(
|
|
165
165
|
[
|
|
166
|
-
await renderTitle('PROTEUM CONFIGURE AGENTS', 'Configure tracked Proteum instruction files.'),
|
|
166
|
+
await renderTitle('PROTEUM CONFIGURE AGENTS', 'Configure tracked Proteum instruction files and Claude aliases.'),
|
|
167
167
|
renderRows([{ label: 'app', value: appRoot === process.cwd() ? '.' : appRoot }]),
|
|
168
168
|
].join('\n\n'),
|
|
169
169
|
);
|
|
@@ -201,8 +201,8 @@ export const runConfigureAgentsWizard = async ({
|
|
|
201
201
|
await renderStep(
|
|
202
202
|
'[1/1]',
|
|
203
203
|
isMonorepo
|
|
204
|
-
? `Writing monorepo-aware instruction files using ${monorepoRoot}.`
|
|
205
|
-
: 'Writing standalone instruction files.',
|
|
204
|
+
? `Writing monorepo-aware instruction files and Claude aliases using ${monorepoRoot}.`
|
|
205
|
+
: 'Writing standalone instruction files and Claude aliases.',
|
|
206
206
|
),
|
|
207
207
|
);
|
|
208
208
|
|
|
@@ -214,7 +214,7 @@ export const runConfigureAgentsWizard = async ({
|
|
|
214
214
|
});
|
|
215
215
|
const sections = renderConfigureResultSections(result);
|
|
216
216
|
|
|
217
|
-
console.info(await renderSuccess('Proteum-managed instruction files are configured.'));
|
|
217
|
+
console.info(await renderSuccess('Proteum-managed instruction files and Claude aliases are configured.'));
|
|
218
218
|
|
|
219
219
|
if (sections.length > 0) console.info(`\n${sections.join('\n\n')}`);
|
|
220
220
|
};
|
package/cli/commands/dev.ts
CHANGED
|
@@ -153,7 +153,7 @@ const promptBlockedAgentInstructionOverwrites = async (blockedPaths: string[]) =
|
|
|
153
153
|
if (cli.args.json === true || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
154
154
|
throw new UsageError(
|
|
155
155
|
[
|
|
156
|
-
'Proteum could not update managed instruction
|
|
156
|
+
'Proteum could not update managed instruction paths because existing paths are blocked:',
|
|
157
157
|
...blockedPaths.map((entry) => `- ${entry}`),
|
|
158
158
|
'Run `proteum configure agents` in an interactive terminal to choose which paths can be replaced.',
|
|
159
159
|
].join('\n'),
|
|
@@ -163,7 +163,7 @@ const promptBlockedAgentInstructionOverwrites = async (blockedPaths: string[]) =
|
|
|
163
163
|
console.info(await renderWarning('Proteum found existing paths that block managed instruction updates.'));
|
|
164
164
|
console.info(
|
|
165
165
|
[
|
|
166
|
-
'Choose whether to overwrite each blocked path with a
|
|
166
|
+
'Choose whether to overwrite each blocked path with a Proteum-managed instruction path:',
|
|
167
167
|
...blockedPaths.map((entry) => `- ${entry}`),
|
|
168
168
|
].join('\n'),
|
|
169
169
|
);
|
|
@@ -212,7 +212,7 @@ const ensureProjectAgentInstructions = async () => {
|
|
|
212
212
|
|
|
213
213
|
throw new UsageError(
|
|
214
214
|
[
|
|
215
|
-
'Proteum could not update all managed instruction
|
|
215
|
+
'Proteum could not update all managed instruction paths because these paths were left blocked:',
|
|
216
216
|
...result.blocked.map((entry) => `- ${entry}`),
|
|
217
217
|
].join('\n'),
|
|
218
218
|
);
|
package/cli/commands/verify.ts
CHANGED
|
@@ -5,7 +5,6 @@ import path from 'path';
|
|
|
5
5
|
import { UsageError } from 'clipanion';
|
|
6
6
|
|
|
7
7
|
import cli from '..';
|
|
8
|
-
import Compiler from '../compiler';
|
|
9
8
|
import Paths from '../paths';
|
|
10
9
|
import { readProteumManifest } from '../compiler/common/proteumManifest';
|
|
11
10
|
import { buildContractsDoctorResponse } from '@common/dev/contractsDoctor';
|
|
@@ -14,6 +13,13 @@ import { buildOrientationResponse, type TDiagnoseChainItem, type TDiagnoseRespon
|
|
|
14
13
|
import type { TProteumManifest, TProteumManifestDiagnostic } from '@common/dev/proteumManifest';
|
|
15
14
|
import type { TDevCommandRunResponse } from '@common/dev/commands';
|
|
16
15
|
import type { TDevSessionErrorResponse, TDevSessionStartResponse } from '@common/dev/session';
|
|
16
|
+
import {
|
|
17
|
+
renderChangedVerificationPlan,
|
|
18
|
+
runChangedVerification,
|
|
19
|
+
type TChangedVerificationCheck,
|
|
20
|
+
type TChangedVerificationExecution,
|
|
21
|
+
type TChangedVerificationSkippedCheck,
|
|
22
|
+
} from '../verification/changed';
|
|
17
23
|
|
|
18
24
|
type TVerifySeverity = 'error' | 'warning';
|
|
19
25
|
type TVerifyStepStatus = 'failed' | 'info' | 'passed';
|
|
@@ -23,7 +29,7 @@ type TVerifyFinding = {
|
|
|
23
29
|
blocking: boolean;
|
|
24
30
|
code: string;
|
|
25
31
|
message: string;
|
|
26
|
-
source: 'browser' | 'contracts' | 'doctor' | 'framework-change' | 'request' | 'command';
|
|
32
|
+
source: 'browser' | 'changed' | 'contracts' | 'doctor' | 'framework-change' | 'request' | 'command';
|
|
27
33
|
filepath?: string;
|
|
28
34
|
sourceLocation?: { line?: number; column?: number };
|
|
29
35
|
relatedFilepaths?: string[];
|
|
@@ -51,12 +57,20 @@ type TVerifyResult = {
|
|
|
51
57
|
action: string;
|
|
52
58
|
target?: string;
|
|
53
59
|
orientation?: TOrientResponse;
|
|
60
|
+
changedFiles?: string[];
|
|
61
|
+
configFilepath?: string;
|
|
62
|
+
dryRun?: boolean;
|
|
63
|
+
executions?: TChangedVerificationExecution[];
|
|
54
64
|
introducedFindings: TVerifyFinding[];
|
|
55
65
|
preExistingFindings: TVerifyFinding[];
|
|
66
|
+
selectedChecks?: TChangedVerificationCheck[];
|
|
67
|
+
skippedChecks?: TChangedVerificationSkippedCheck[];
|
|
56
68
|
verificationSteps: TVerifyStep[];
|
|
57
69
|
result: {
|
|
58
70
|
ok: boolean;
|
|
59
71
|
strictGlobal: boolean;
|
|
72
|
+
failedChecks?: number;
|
|
73
|
+
selectedChecks?: number;
|
|
60
74
|
introducedBlockingFindings: number;
|
|
61
75
|
preExistingBlockingFindings: number;
|
|
62
76
|
blockingFindings: number;
|
|
@@ -267,6 +281,7 @@ const ensureServer = async ({
|
|
|
267
281
|
};
|
|
268
282
|
|
|
269
283
|
const resolveLocalManifest = async () => {
|
|
284
|
+
const { default: Compiler } = await import('../compiler');
|
|
270
285
|
const compiler = new Compiler('dev');
|
|
271
286
|
await compiler.refreshGeneratedTypings();
|
|
272
287
|
return readProteumManifest(cli.paths.appRoot);
|
|
@@ -365,9 +380,16 @@ const classifyDiagnostics = ({
|
|
|
365
380
|
const finalizeResult = ({
|
|
366
381
|
action,
|
|
367
382
|
apps,
|
|
383
|
+
changedFiles,
|
|
384
|
+
configFilepath,
|
|
385
|
+
dryRun,
|
|
386
|
+
executions,
|
|
368
387
|
introducedFindings,
|
|
369
388
|
orientation,
|
|
370
389
|
preExistingFindings,
|
|
390
|
+
selectedChecks,
|
|
391
|
+
skippedChecks,
|
|
392
|
+
changedResult,
|
|
371
393
|
strictGlobal,
|
|
372
394
|
target,
|
|
373
395
|
verificationSteps,
|
|
@@ -375,9 +397,16 @@ const finalizeResult = ({
|
|
|
375
397
|
action: string;
|
|
376
398
|
target?: string;
|
|
377
399
|
orientation?: TOrientResponse;
|
|
400
|
+
changedFiles?: string[];
|
|
401
|
+
configFilepath?: string;
|
|
402
|
+
dryRun?: boolean;
|
|
403
|
+
executions?: TChangedVerificationExecution[];
|
|
378
404
|
apps?: TVerifyAppResult[];
|
|
379
405
|
introducedFindings: TVerifyFinding[];
|
|
380
406
|
preExistingFindings: TVerifyFinding[];
|
|
407
|
+
selectedChecks?: TChangedVerificationCheck[];
|
|
408
|
+
skippedChecks?: TChangedVerificationSkippedCheck[];
|
|
409
|
+
changedResult?: { failedChecks: number; selectedChecks: number };
|
|
381
410
|
verificationSteps: TVerifyStep[];
|
|
382
411
|
strictGlobal: boolean;
|
|
383
412
|
}): TVerifyResult => {
|
|
@@ -389,13 +418,20 @@ const finalizeResult = ({
|
|
|
389
418
|
action,
|
|
390
419
|
...(target ? { target } : {}),
|
|
391
420
|
...(orientation ? { orientation } : {}),
|
|
421
|
+
...(changedFiles ? { changedFiles } : {}),
|
|
422
|
+
...(configFilepath ? { configFilepath } : {}),
|
|
423
|
+
...(dryRun !== undefined ? { dryRun } : {}),
|
|
424
|
+
...(executions ? { executions } : {}),
|
|
392
425
|
...(apps ? { apps } : {}),
|
|
393
426
|
introducedFindings,
|
|
394
427
|
preExistingFindings,
|
|
428
|
+
...(selectedChecks ? { selectedChecks } : {}),
|
|
429
|
+
...(skippedChecks ? { skippedChecks } : {}),
|
|
395
430
|
verificationSteps,
|
|
396
431
|
result: {
|
|
397
432
|
ok,
|
|
398
433
|
strictGlobal,
|
|
434
|
+
...(changedResult ? { failedChecks: changedResult.failedChecks, selectedChecks: changedResult.selectedChecks } : {}),
|
|
399
435
|
introducedBlockingFindings,
|
|
400
436
|
preExistingBlockingFindings,
|
|
401
437
|
blockingFindings: introducedBlockingFindings + preExistingBlockingFindings,
|
|
@@ -437,6 +473,24 @@ const renderFrameworkApps = (apps: TVerifyAppResult[]) =>
|
|
|
437
473
|
])
|
|
438
474
|
.join('\n');
|
|
439
475
|
|
|
476
|
+
const renderChangedChecks = (result: TVerifyResult) => {
|
|
477
|
+
if (!result.changedFiles || !result.selectedChecks || !result.skippedChecks) return '';
|
|
478
|
+
|
|
479
|
+
return [
|
|
480
|
+
'Changed Verification',
|
|
481
|
+
`- config=${result.configFilepath || 'none'}`,
|
|
482
|
+
`- dryRun=${result.dryRun === true}`,
|
|
483
|
+
`- changedFiles=${result.changedFiles.length}`,
|
|
484
|
+
`- selectedChecks=${result.selectedChecks.length}`,
|
|
485
|
+
`- skippedChecks=${result.skippedChecks.length}`,
|
|
486
|
+
...result.selectedChecks.map(
|
|
487
|
+
(check) =>
|
|
488
|
+
`- [${check.scope}] ${check.id} cwd=${check.cwd} command=${check.command} reason=${check.reasons.join('; ')}`,
|
|
489
|
+
),
|
|
490
|
+
...result.skippedChecks.map((check) => `- [skipped] ${check.id} reason=${check.reason}`),
|
|
491
|
+
].join('\n');
|
|
492
|
+
};
|
|
493
|
+
|
|
440
494
|
const renderHuman = (result: TVerifyResult) =>
|
|
441
495
|
[
|
|
442
496
|
`Proteum verify ${result.action}${result.target ? ` ${result.target}` : ''}`,
|
|
@@ -448,6 +502,7 @@ const renderHuman = (result: TVerifyResult) =>
|
|
|
448
502
|
]
|
|
449
503
|
: []),
|
|
450
504
|
...(result.apps ? [renderFrameworkApps(result.apps)] : []),
|
|
505
|
+
...(result.changedFiles ? ['', renderChangedChecks(result)] : []),
|
|
451
506
|
'',
|
|
452
507
|
renderSteps(result.verificationSteps),
|
|
453
508
|
'',
|
|
@@ -1075,6 +1130,62 @@ const collectAppResult = async ({
|
|
|
1075
1130
|
};
|
|
1076
1131
|
};
|
|
1077
1132
|
|
|
1133
|
+
const runChangedVerify = async () => {
|
|
1134
|
+
const base = typeof cli.args.base === 'string' && cli.args.base.trim() ? cli.args.base.trim() : undefined;
|
|
1135
|
+
const changed = await runChangedVerification({
|
|
1136
|
+
base,
|
|
1137
|
+
cwd: String(cli.args.workdir || process.cwd()),
|
|
1138
|
+
dryRun: cli.args.dryRun === true,
|
|
1139
|
+
onPlan: (plan) => {
|
|
1140
|
+
if (cli.args.json !== true) console.log(renderChangedVerificationPlan(plan));
|
|
1141
|
+
},
|
|
1142
|
+
staged: cli.args.staged === true,
|
|
1143
|
+
});
|
|
1144
|
+
const introducedFindings: TVerifyFinding[] = changed.executions
|
|
1145
|
+
.filter((execution) => execution.status === 'failed')
|
|
1146
|
+
.map((execution) => ({
|
|
1147
|
+
severity: 'error',
|
|
1148
|
+
blocking: true,
|
|
1149
|
+
code: 'changed/check-failed',
|
|
1150
|
+
message: `Verification check "${execution.checkId}" failed with exit code ${execution.exitCode ?? 'unknown'}.`,
|
|
1151
|
+
source: 'changed',
|
|
1152
|
+
details: [`command=${execution.command}`, `cwd=${execution.cwd}`, `durationMs=${execution.durationMs}`],
|
|
1153
|
+
}));
|
|
1154
|
+
|
|
1155
|
+
return finalizeResult({
|
|
1156
|
+
action: 'changed',
|
|
1157
|
+
changedFiles: changed.changedFiles,
|
|
1158
|
+
configFilepath: changed.configFilepath,
|
|
1159
|
+
dryRun: changed.dryRun,
|
|
1160
|
+
executions: changed.executions,
|
|
1161
|
+
introducedFindings,
|
|
1162
|
+
preExistingFindings: [],
|
|
1163
|
+
selectedChecks: changed.selectedChecks,
|
|
1164
|
+
skippedChecks: changed.skippedChecks,
|
|
1165
|
+
changedResult: changed.result,
|
|
1166
|
+
strictGlobal: false,
|
|
1167
|
+
verificationSteps: [
|
|
1168
|
+
{
|
|
1169
|
+
label: 'Discover Changed Files',
|
|
1170
|
+
status: 'passed',
|
|
1171
|
+
details: [`files=${changed.changedFiles.length}`, `gitRoot=${changed.gitRoot}`],
|
|
1172
|
+
},
|
|
1173
|
+
{
|
|
1174
|
+
label: 'Plan Targeted Checks',
|
|
1175
|
+
status: 'passed',
|
|
1176
|
+
details: [`selected=${changed.selectedChecks.length}`, `skipped=${changed.skippedChecks.length}`],
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
label: changed.dryRun ? 'Skip Execution' : 'Run Targeted Checks',
|
|
1180
|
+
status: changed.result.ok ? 'passed' : 'failed',
|
|
1181
|
+
details: changed.dryRun
|
|
1182
|
+
? ['dryRun=true']
|
|
1183
|
+
: [`executions=${changed.executions.length}`, `failed=${changed.result.failedChecks}`],
|
|
1184
|
+
},
|
|
1185
|
+
],
|
|
1186
|
+
});
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1078
1189
|
const runFrameworkChangeVerify = async () => {
|
|
1079
1190
|
const websiteRoute = typeof cli.args.route === 'string' && cli.args.route ? cli.args.route : '/';
|
|
1080
1191
|
const apps = {
|
|
@@ -1208,7 +1319,9 @@ export const run = async () => {
|
|
|
1208
1319
|
const target = typeof cli.args.target === 'string' ? cli.args.target.trim() : '';
|
|
1209
1320
|
let result: TVerifyResult;
|
|
1210
1321
|
|
|
1211
|
-
if (action === '
|
|
1322
|
+
if (action === 'changed') {
|
|
1323
|
+
result = await runChangedVerify();
|
|
1324
|
+
} else if (action === 'framework-change') {
|
|
1212
1325
|
result = await runFrameworkChangeVerify();
|
|
1213
1326
|
} else if (action === 'owner') {
|
|
1214
1327
|
if (!target) throw new UsageError('`proteum verify owner` requires a query.');
|
|
@@ -1220,7 +1333,7 @@ export const run = async () => {
|
|
|
1220
1333
|
if (!target) throw new UsageError('`proteum verify browser` requires a path or absolute URL.');
|
|
1221
1334
|
result = await runBrowserVerify(target);
|
|
1222
1335
|
} else {
|
|
1223
|
-
throw new UsageError(`Unsupported verify action "${action}". Expected framework-change, owner, request, or browser.`);
|
|
1336
|
+
throw new UsageError(`Unsupported verify action "${action}". Expected changed, framework-change, owner, request, or browser.`);
|
|
1224
1337
|
}
|
|
1225
1338
|
|
|
1226
1339
|
if (cli.args.json === true) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const createTypedControllerHelperContent = (appIdentifier: string) => `/*----------------------------------
|
|
2
|
+
- GENERATED FILE
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// This file is generated by Proteum from server/index.ts.
|
|
6
|
+
// Do not edit it manually.
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
defineAction as defineBaseAction,
|
|
10
|
+
defineController,
|
|
11
|
+
schema,
|
|
12
|
+
} from '@server/app/controller';
|
|
13
|
+
import type {
|
|
14
|
+
TControllerActionContext,
|
|
15
|
+
TControllerActionDefinition,
|
|
16
|
+
TControllerActionInput,
|
|
17
|
+
TControllerActionResult,
|
|
18
|
+
TControllerDefinition,
|
|
19
|
+
TValidationSchema,
|
|
20
|
+
TValidationShape,
|
|
21
|
+
z,
|
|
22
|
+
} from '@server/app/controller';
|
|
23
|
+
|
|
24
|
+
export { defineController, schema };
|
|
25
|
+
export type {
|
|
26
|
+
TControllerActionDefinition,
|
|
27
|
+
TControllerActionInput,
|
|
28
|
+
TControllerActionResult,
|
|
29
|
+
TControllerDefinition,
|
|
30
|
+
TValidationSchema,
|
|
31
|
+
TValidationShape,
|
|
32
|
+
z,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type TApplication = import('@/server/index').${appIdentifier};
|
|
36
|
+
export type TControllerRequestServices = import('@/server/index').TControllerRequestServices;
|
|
37
|
+
export type TTypedControllerActionContext<TInput = undefined> = TControllerActionContext<
|
|
38
|
+
TInput,
|
|
39
|
+
TApplication,
|
|
40
|
+
TControllerRequestServices
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
export function defineAction<TSchema extends TValidationSchema, TResult>(
|
|
44
|
+
definition: {
|
|
45
|
+
input: TSchema;
|
|
46
|
+
handler: (context: TTypedControllerActionContext<z.output<TSchema>>) => TResult;
|
|
47
|
+
},
|
|
48
|
+
): TControllerActionDefinition<z.output<TSchema>, TResult, TApplication, TControllerRequestServices>;
|
|
49
|
+
export function defineAction<TShape extends TValidationShape, TResult>(
|
|
50
|
+
definition: {
|
|
51
|
+
input: TShape;
|
|
52
|
+
handler: (context: TTypedControllerActionContext<z.output<z.ZodObject<TShape>>>) => TResult;
|
|
53
|
+
},
|
|
54
|
+
): TControllerActionDefinition<z.output<z.ZodObject<TShape>>, TResult, TApplication, TControllerRequestServices>;
|
|
55
|
+
export function defineAction<TResult>(
|
|
56
|
+
definition: {
|
|
57
|
+
handler: (context: TTypedControllerActionContext<undefined>) => TResult;
|
|
58
|
+
},
|
|
59
|
+
): TControllerActionDefinition<undefined, TResult, TApplication, TControllerRequestServices>;
|
|
60
|
+
export function defineAction(definition: {
|
|
61
|
+
input?: TValidationSchema | TValidationShape;
|
|
62
|
+
handler: (context: TTypedControllerActionContext<any>) => unknown;
|
|
63
|
+
}) {
|
|
64
|
+
return defineBaseAction(definition as any);
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
@@ -5,6 +5,7 @@ import cli from '../..';
|
|
|
5
5
|
import { indexControllers, printControllerTree, type TControllerFileMeta } from '../common/controllers';
|
|
6
6
|
import { TProteumManifestController } from '../common/proteumManifest';
|
|
7
7
|
import writeIfChanged from '../writeIfChanged';
|
|
8
|
+
import { createTypedControllerHelperContent } from './controllerHelper';
|
|
8
9
|
import { resolveConnectedProjectContracts, writeConnectedProjectContract } from './connectedProjects';
|
|
9
10
|
import { normalizeAbsolutePath } from './shared';
|
|
10
11
|
|
|
@@ -319,6 +320,8 @@ export default controllers;
|
|
|
319
320
|
`,
|
|
320
321
|
);
|
|
321
322
|
|
|
323
|
+
writeIfChanged(path.join(app.paths.server.generated, 'controller.ts'), createTypedControllerHelperContent(app.identity.identifier));
|
|
324
|
+
|
|
322
325
|
return {
|
|
323
326
|
connectedProjects: connectedProjectContracts,
|
|
324
327
|
controllers: [...manifestControllers, ...connectedManifestControllers],
|