proteum 2.4.4 → 2.5.1

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 (79) hide show
  1. package/README.md +81 -52
  2. package/agents/project/AGENTS.md +112 -31
  3. package/agents/project/CODING_STYLE.md +2 -2
  4. package/agents/project/app-root/AGENTS.md +1 -3
  5. package/agents/project/client/AGENTS.md +5 -1
  6. package/agents/project/client/pages/AGENTS.md +21 -9
  7. package/agents/project/diagnostics.md +2 -2
  8. package/agents/project/optimizations.md +1 -1
  9. package/agents/project/root/AGENTS.md +105 -22
  10. package/agents/project/server/routes/AGENTS.md +30 -1
  11. package/agents/project/server/services/AGENTS.md +4 -0
  12. package/agents/project/tests/AGENTS.md +1 -1
  13. package/cli/commands/doctor.ts +54 -3
  14. package/cli/commands/runtime.ts +6 -0
  15. package/cli/commands/worktree.ts +116 -0
  16. package/cli/compiler/artifacts/controllers.ts +16 -15
  17. package/cli/compiler/artifacts/discovery.ts +129 -17
  18. package/cli/compiler/artifacts/routing.ts +0 -5
  19. package/cli/compiler/artifacts/services.ts +253 -76
  20. package/cli/compiler/common/controllers.ts +159 -57
  21. package/cli/compiler/common/generatedRouteModules.ts +457 -363
  22. package/cli/mcp/router.ts +47 -3
  23. package/cli/presentation/commands.ts +25 -15
  24. package/cli/runtime/commands.ts +39 -12
  25. package/cli/runtime/worktreeBootstrap.ts +608 -0
  26. package/cli/scaffold/index.ts +28 -18
  27. package/cli/scaffold/templates.ts +44 -33
  28. package/cli/utils/agents.ts +14 -1
  29. package/client/app/index.ts +22 -5
  30. package/client/services/router/index.tsx +23 -3
  31. package/client/services/router/request/api.ts +16 -6
  32. package/common/dev/contractsDoctor.ts +1 -1
  33. package/common/dev/mcpPayloads.ts +8 -1
  34. package/common/env/proteumEnv.ts +14 -2
  35. package/common/router/contracts.ts +1 -1
  36. package/common/router/definitions.ts +177 -0
  37. package/common/router/index.ts +23 -12
  38. package/common/router/pageData.ts +5 -5
  39. package/common/router/register.ts +2 -2
  40. package/common/router/request/api.ts +12 -2
  41. package/docs/agent-routing.md +5 -2
  42. package/docs/diagnostics.md +2 -0
  43. package/docs/mcp.md +6 -3
  44. package/docs/migration-2.5.md +226 -0
  45. package/eslint.js +89 -42
  46. package/package.json +1 -1
  47. package/server/app/commands.ts +5 -1
  48. package/server/app/container/console/index.ts +1 -1
  49. package/server/app/controller/index.ts +98 -40
  50. package/server/app/index.ts +120 -3
  51. package/server/app/service/index.ts +5 -1
  52. package/server/index.ts +6 -2
  53. package/server/services/router/index.ts +50 -41
  54. package/server/services/router/response/index.ts +2 -2
  55. package/tests/agents-utils.test.cjs +14 -1
  56. package/tests/cli-mcp-command.test.cjs +84 -0
  57. package/tests/client-app-error-handling.test.cjs +100 -0
  58. package/tests/definition-contracts.test.cjs +453 -0
  59. package/tests/dev-transpile-watch.test.cjs +37 -31
  60. package/tests/eslint-rules.test.cjs +185 -8
  61. package/tests/mcp.test.cjs +90 -0
  62. package/tests/scaffold-templates.test.cjs +18 -0
  63. package/tests/server-app-report-error.test.cjs +135 -0
  64. package/tests/worktree-bootstrap.test.cjs +206 -0
  65. package/types/aliases.d.ts +0 -5
  66. package/types/controller-input.test.ts +23 -17
  67. package/types/controller-request-context.test.ts +10 -11
  68. package/cli/commands/migrate.ts +0 -51
  69. package/cli/migrate/pageContract.ts +0 -516
  70. package/docs/migrate-from-2.1.3.md +0 -396
  71. package/scripts/cleanup-generated-controllers.ts +0 -62
  72. package/scripts/fix-reference-app-typing.ts +0 -490
  73. package/scripts/format-router-registrations.ts +0 -119
  74. package/scripts/migrate-explicit-controllers-and-request.ts +0 -423
  75. package/scripts/refactor-client-app-imports.ts +0 -244
  76. package/scripts/refactor-client-pages.ts +0 -587
  77. package/scripts/refactor-server-controllers.ts +0 -471
  78. package/scripts/refactor-server-runtime-aliases.ts +0 -360
  79. package/scripts/restore-client-app-import-files.ts +0 -41
package/README.md CHANGED
@@ -4,8 +4,6 @@ Proteum is an LLM-first SSR / SEO / TypeScript framework for full-stack web appl
4
4
 
5
5
  It is built for teams that want explicit server contracts, server-first rendering, deterministic generated artifacts, and a codebase that an AI agent can inspect without reverse-engineering hidden runtime magic.
6
6
 
7
- Migration guide for older apps: [docs/migrate-from-2.1.3.md](docs/migrate-from-2.1.3.md)
8
-
9
7
  ## Sponsor
10
8
 
11
9
  Proteum is sponsored by [Unique Domains](https://unique.domains/?utm_source=github&utm_medium=referral&utm_campaign=repo_proteum&utm_content=top_sponsor).
@@ -33,8 +31,8 @@ Proteum combines:
33
31
  ## Core Principles
34
32
 
35
33
  - **Server-first by default.** Put data loading in the page data function and keep client code focused on UI.
36
- - **Explicit request entrypoints.** Controllers are classes. Request access is explicit through `this.request`.
37
- - **Local validation.** Validate handler input inside the handler with `this.input(schema)`.
34
+ - **Explicit request entrypoints.** Routes and controllers are exported definition objects.
35
+ - **Local validation.** Declare controller input on `defineAction({ input, handler })`; handlers receive parsed `input`.
38
36
  - **Deterministic generation.** Proteum owns `.proteum/` and regenerates it from source.
39
37
  - **Explainability matters.** `proteum explain`, `proteum doctor`, `proteum diagnose`, `proteum perf`, and `proteum trace` expose the framework view of your app and its live requests, and the profiler renders the same diagnostics and perf surfaces for humans in dev.
40
38
  - **SEO is not an afterthought.** Identity, routes, layouts, and SSR data are part of the app contract.
@@ -76,9 +74,9 @@ Important files:
76
74
  - `proteum.config.ts`: typed Proteum compiler and connection settings such as `transpile` and `connect` via `Application.setup({ ... })`
77
75
  - `process.env` / optional `.env`: `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen variables referenced by `proteum.config.ts`, and `TRACE_*` environment variables loaded by the app
78
76
  - `server/config/*.ts`: plain typed config exports consumed by the explicit app bootstrap
79
- - `server/index.ts`: default-exported `Application` subclass that instantiates root services and router plugins
80
- - `client/pages/**`: SSR page entrypoints registered through `Router.page(path, options, data, render)`
81
- - `server/controllers/**`: request handlers that extend `Controller`
77
+ - `server/index.ts`: default-exported `defineApplication({ services, router, models, commands })` application graph
78
+ - `client/pages/**`: SSR page entrypoints that default-export `definePageRoute({ path, options, data, render })`
79
+ - `server/controllers/**`: generated API definitions that default-export `defineController({ path, actions })`
82
80
  - `commands/**`: dev-only internal commands that extend `Commands`
83
81
  - `server/services/**`: business logic that extends `Service`
84
82
  - `.proteum/**`: framework-owned generated contracts and manifests
@@ -142,7 +140,7 @@ Use this for linked or workspace-local TypeScript packages that ship source file
142
140
 
143
141
  ## Example: Server Bootstrap
144
142
 
145
- Proteum app services are declared explicitly through typed config exports plus a concrete `Application` subclass.
143
+ Proteum app services and router plugins are declared explicitly through typed config exports plus a default-exported `defineApplication(...)` definition object.
146
144
 
147
145
  ```ts
148
146
  // server/config/user.ts
@@ -169,25 +167,45 @@ export const routerBaseConfig = {
169
167
 
170
168
  ```ts
171
169
  // server/index.ts
172
- import { Application } from '@server/app';
170
+ import { defineApplication, type Application } from '@server/app';
173
171
  import Router from '@server/services/router';
174
172
  import SchemaRouter from '@server/services/schema/router';
175
173
  import Users from '@/server/services/Users';
176
174
  import * as userConfig from '@/server/config/user';
177
175
 
178
- export default class MyApp extends Application {
179
- public Users = new Users(this, userConfig.usersConfig, this);
180
- public Router = new Router(
181
- this,
176
+ type MyAppServices = {
177
+ Users: Users;
178
+ };
179
+
180
+ type MyRouterPlugins = {
181
+ schema: SchemaRouter;
182
+ };
183
+
184
+ export type MyRouter = Router<MyApp, MyRouterPlugins>;
185
+ export interface MyApp extends Application, MyAppServices {
186
+ Router: MyRouter;
187
+ }
188
+
189
+ const createRouter = (app: MyApp): MyRouter =>
190
+ new Router<MyApp, MyRouterPlugins>(
191
+ app,
182
192
  {
183
193
  ...userConfig.routerBaseConfig,
184
194
  plugins: {
185
- schema: new SchemaRouter({}, this),
195
+ schema: new SchemaRouter({}, app),
186
196
  },
187
197
  },
188
- this
198
+ app
189
199
  );
190
- }
200
+
201
+ const MyApplication = defineApplication<MyAppServices, MyRouter>({
202
+ services: (app) => ({
203
+ Users: new Users(app, userConfig.usersConfig, app),
204
+ }),
205
+ router: createRouter,
206
+ });
207
+
208
+ export default MyApplication;
191
209
  ```
192
210
 
193
211
  Proteum reads `server/index.ts` as the source of truth for installed root services and router plugins, and reads `server/config/*.ts` `Services.config(...)` exports for typed config such as service priority overrides.
@@ -233,60 +251,59 @@ Default public asset validators depend on the environment: dev disables `ETag` a
233
251
  Proteum pages are explicit SSR entrypoints.
234
252
 
235
253
  ```tsx
236
- import Router from '@/client/router';
254
+ import { definePageRoute } from '@common/router/definitions';
237
255
 
238
- Router.page(
239
- '/',
240
- {
256
+ export default definePageRoute({
257
+ path: '/',
258
+ options: {
241
259
  auth: false,
242
260
  layout: false,
243
261
  },
244
- ({ Plans, Stats }) => ({
262
+ data: ({ Plans, Stats }) => ({
245
263
  plans: Plans.getPlans(),
246
264
  stats: Stats.general(),
247
265
  }),
248
- ({ plans, stats }) => {
266
+ render: ({ plans, stats }) => {
249
267
  return <LandingPage plans={plans} stats={stats} />;
250
- }
251
- );
268
+ },
269
+ });
252
270
  ```
253
271
 
254
272
  What happens here:
255
273
 
256
- - the first argument is the route path
257
- - the second argument is the explicit route-options object
258
- - the third argument is the page data function or `null`
274
+ - `path`, `options`, and error `code` metadata are static and compiler-readable
259
275
  - route behavior such as `auth`, `layout`, `static`, or `redirectLogged` lives in the options object
260
- - every key returned from the data function becomes page data
261
- - the renderer receives the resolved data and the generated controller/service context
276
+ - every key returned from `data` becomes page data
277
+ - runtime app/client references are allowed only inside `data` and `render`
262
278
 
263
279
  ## Example: Controller
264
280
 
265
281
  Proteum controllers are explicit request entrypoints.
266
282
 
267
283
  ```ts
268
- import Controller, { schema } from '@server/app/controller';
284
+ import { defineAction, defineController, schema } from '@server/app/controller';
269
285
 
270
- export default class AuthController extends Controller<MyApp> {
271
- public async loginWithPassword() {
272
- const { Auth } = this.services;
273
- const data = this.input(
274
- schema.object({
286
+ export default defineController({
287
+ path: 'Auth',
288
+ actions: {
289
+ loginWithPassword: defineAction({
290
+ input: schema.object({
275
291
  email: schema.string().email(),
276
292
  password: schema.string().min(8),
277
- })
278
- );
279
-
280
- return Auth.loginWithPassword(data, this.request);
281
- }
282
- }
293
+ }),
294
+ handler: ({ input, services, request }) => {
295
+ return services.Auth.loginWithPassword(input, request);
296
+ },
297
+ }),
298
+ },
299
+ });
283
300
  ```
284
301
 
285
302
  Controller rules:
286
303
 
287
- - read request-scoped values from `this.request`
288
- - validate once with `this.input(schema)`
289
- - call business logic through `this.services`, `this.models`, or `this.app`
304
+ - read request-scoped values from action context
305
+ - declare validation once with `defineAction({ input, handler })`
306
+ - call business logic through `services`, `models`, or `app`
290
307
  - return explicit values instead of relying on ambient globals
291
308
 
292
309
  ## Example: Command
@@ -386,6 +403,7 @@ Proteum ships with a compact CLI focused on the real app lifecycle:
386
403
  | `proteum init` | Scaffold a new Proteum app with built-in deterministic templates |
387
404
  | `proteum configure agents` | Interactively configure tracked Proteum instruction files for standalone or monorepo apps |
388
405
  | `proteum create` | Scaffold a page, controller, command, route, or root service inside an app |
406
+ | `proteum worktree` | Create or initialize Codex worktrees with a machine-readable bootstrap marker |
389
407
 
390
408
  Recommended daily workflow:
391
409
 
@@ -439,6 +457,8 @@ Useful scaffolding commands:
439
457
  proteum init my-app --name "My App"
440
458
  proteum init my-app --name "My App" --dry-run --json
441
459
  proteum configure agents
460
+ proteum worktree init --source /path/to/main-app
461
+ proteum worktree create /path/to/.codex/worktrees/feature --source /path/to/main-app --branch feature/name
442
462
  proteum create page marketing/faq --route /faq
443
463
  proteum create controller Founder/projects --method list
444
464
  proteum create service Conversion/Plans
@@ -448,6 +468,8 @@ proteum create service Conversion/Plans
448
468
 
449
469
  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.
450
470
 
471
+ `proteum worktree init` writes `.proteum/worktree-bootstrap.json` for app roots under `/.codex/worktrees/`. The marker records `.env` copy status, refresh and dependency results, runtime status, key file hashes, and the active Proteum version. `proteum dev`, `proteum refresh`, `proteum runtime status`, `proteum verify`, and MCP `workflow_start` block inside Codex worktrees until the marker is fresh. Run `npx proteum worktree init --source <source-app-root>` for a new worktree, or add `--refresh` when stale state is reported. `PROTEUM_ALLOW_UNBOOTSTRAPPED_WORKTREE=1` bypasses the block but remains visible in runtime status, doctor, and MCP output.
472
+
451
473
  `proteum connect`, `proteum explain`, `proteum doctor`, and `proteum diagnose` share the same generated manifest and contract state. `proteum perf` uses the same dev request-trace store as the profiler `Perf` tab. `proteum runtime status` also inspects the configured router/HMR ports and returns an exact Start Dev action, so agents do not need to `curl` page routes to identify port owners. `proteum dev` exposes the app-root MCP contract at `/__proteum/mcp` and ensures one managed machine MCP daemon is running; `proteum mcp` is the machine-scope router agents register once. Agents should start with MCP `workflow_start`, use offline candidates to choose the correct app root when no dev server is live, then route repeated reads by the returned live `projectId`. For the full diagnostics and tracing model, see [docs/diagnostics.md](docs/diagnostics.md), [docs/mcp.md](docs/mcp.md), and [docs/request-tracing.md](docs/request-tracing.md).
452
474
 
453
475
  ## Dev Commands
@@ -573,13 +595,14 @@ If you are an LLM or automation agent, start here:
573
595
 
574
596
  1. Use `proteum mcp` as the one registered MCP server; `proteum dev` ensures the managed machine daemon is running.
575
597
  2. Call MCP `workflow_start` with `cwd` or a known `projectId`; if it is ambiguous or returns offline app candidates, use `project_resolve { cwd }`, choose the intended app root, follow its port-inspected next action when needed, then retry `workflow_start`.
576
- 3. Use the returned live `projectId` with MCP `runtime_status`, `orient`, `instructions_resolve`, `route_candidates`, `explain_summary`, `diagnose`, `trace_show`, `perf_request`, and `logs_tail` before CLI equivalents for repeated read-only app state.
577
- 4. Treat returned instruction previews as the allowed scope for read-only discovery and diagnostics. Read full file contents only before edits or git writes, when `fullRead`/`fullReadPolicy` requires it, or when compact previews are insufficient.
578
- 5. Use compact CLI commands for fallback, `dev`, `build`, `check`, `verify`, migrations, E2E, and final reproducible terminal evidence.
579
- 6. Use `proteum diagnose`, `proteum perf`, and compact `proteum trace` for reproducible command evidence when MCP is unavailable or the terminal output itself is needed.
580
- 7. 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 MCP offline or runtime-status next action. If the same app already responds on the configured port without live tracking, use or repair that runtime instead of starting another server. If a live session exists but runtime/MCP is unreachable, stop the listed session file first, then start dev again and retry `workflow_start`. Do not run diagnose, trace, or perf reads while runtime health is unreachable, and do not `curl` normal page routes to identify port ownership.
581
- 8. Inspect `server/index.ts`, controllers, services, or pages only after the routing/diagnostic surfaces identify the relevant owner. Do not run broad owner searches after MCP already returned the route/page/controller owner.
582
- 9. If the task touches a protected route or controller in dev and login UX is not the feature under test, use `proteum e2e --session-email <email> --session-role <role>` for Playwright suites or `proteum session <email> --role <role>` before direct HTTP calls.
598
+ 3. If the app root is inside `/.codex/worktrees/` and `workflow_start` or a guarded CLI command reports missing/stale bootstrap, run the returned `npx proteum worktree init --source <source-app-root>` command before runtime reads.
599
+ 4. Use the returned live `projectId` with MCP `runtime_status`, `orient`, `instructions_resolve`, `route_candidates`, `explain_summary`, `diagnose`, `trace_show`, `perf_request`, and `logs_tail` before CLI equivalents for repeated read-only app state.
600
+ 5. Treat returned instruction previews as the allowed scope for read-only discovery and diagnostics. Read full file contents only before edits or git writes, when `fullRead`/`fullReadPolicy` requires it, or when compact previews are insufficient.
601
+ 6. Use compact CLI commands for fallback, `dev`, `build`, `check`, `verify`, migrations, E2E, and final reproducible terminal evidence.
602
+ 7. Use `proteum diagnose`, `proteum perf`, and compact `proteum trace` for reproducible command evidence when MCP is unavailable or the terminal output itself is needed.
603
+ 8. 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 MCP offline or runtime-status next action. If the same app already responds on the configured port without live tracking, use or repair that runtime instead of starting another server. If a live session exists but runtime/MCP is unreachable, stop the listed session file first, then start dev again and retry `workflow_start`. Do not run diagnose, trace, or perf reads while runtime health is unreachable, and do not `curl` normal page routes to identify port ownership.
604
+ 9. Inspect `server/index.ts`, controllers, services, or pages only after the routing/diagnostic surfaces identify the relevant owner. Do not run broad owner searches after MCP already returned the route/page/controller owner.
605
+ 10. If the task touches a protected route or controller in dev and login UX is not the feature under test, use `proteum e2e --session-email <email> --session-role <role>` for Playwright suites or `proteum session <email> --role <role>` before direct HTTP calls.
583
606
 
584
607
  For implementation rules in a real Proteum app, treat the routed local `AGENTS.md` files plus `proteum orient`, compact CLI diagnostics, and MCP repeated-read surfaces as the task contract. This README is the framework overview, not the project-local instruction layer.
585
608
 
@@ -648,6 +671,12 @@ npx proteum check
648
671
  npx proteum build --prod
649
672
  ```
650
673
 
674
+ ## Migrating To 2.5
675
+
676
+ Proteum 2.5 removes the old contextual route/controller magic. Apps migrate by replacing ambient `@app` imports, top-level `Router.*(...)` route calls, controller classes, and `Application` subclasses with explicit definition objects and typed runtime callback parameters.
677
+
678
+ Use [the 2.5 migration guide](docs/migration-2.5.md) for the full checklist.
679
+
651
680
  ## Repository Structure
652
681
 
653
682
  This repository is organized around the same explicit framework surface it exposes:
@@ -656,7 +685,7 @@ This repository is organized around the same explicit framework surface it expos
656
685
  - `client/`: client runtime, page registration, islands, and router behavior
657
686
  - `server/`: controller base classes, services, runtime, and SSR server behavior
658
687
  - `common/`: shared router contracts, models, request/response types, and utilities
659
- - `doc/`: focused design notes and internal documentation
688
+ - `docs/`: focused design notes and internal documentation
660
689
  - `agents/`: agent-specific conventions and scaffolding used in Proteum-based projects
661
690
 
662
691
  ## Status
@@ -16,16 +16,14 @@ Managed compact root routers must use trigger -> canonical instruction file refe
16
16
  ## Fast Triggers
17
17
 
18
18
  - If `cwd` is inside `/.codex/worktrees/`, run Worktree Preflight before implementation:
19
- - Copy `.env` from the main worktree when missing.
20
- - Run `npx proteum refresh`.
21
- - Run `npm i` when dependencies are missing or stale.
19
+ - Run `npx proteum worktree init --source <source-app-root>` when the bootstrap marker is missing.
20
+ - Run `npx proteum worktree init --source <source-app-root> --refresh` when Proteum reports stale bootstrap state.
21
+ - Use `--skip-deps --reason "..."` only when dependency installation is intentionally skipped.
22
22
  - Run `npx proteum runtime status`.
23
23
  - For runtime-visible work, start or reuse one tracked `npx proteum dev` session using the Task Lifecycle launch workflow.
24
24
  - If you are working in a newly created Proteum worktree, before following the rest of these instructions:
25
- - Copy `.env` from the main worktree.
26
- - Run `npx proteum refresh`.
25
+ - Run `npx proteum worktree init --source <source-app-root>`.
27
26
  - Read and acknowledge the applicable `AGENTS.md` files.
28
- - Run `npm i`.
29
27
  - Run the dev server with the task-safe elevated-permissions launch workflow from `Task Lifecycle`, keep it running so user can see the results by himself, and print the live server URL as a clickable Markdown link.
30
28
  - If the user pastes raw errors without asking for a fix, do not implement changes yet. First run the task-safe local reproduction path: identify the likely app, route, command, or request from the error, boot or reuse the relevant dev server with the elevated-permissions workflow in `Task Lifecycle`, reproduce the failing surface locally, and inspect server output, browser console output, diagnostics, traces, or the smallest relevant command result. If the error does not identify enough context to reproduce, say what is missing and use the available local evidence before guessing. Then list likely causes and, for each one, give probability, why, and how to fix it. After this, every time you implement a fix:
31
29
  - test, re-run analysis and give a comparison table of before and after
@@ -36,6 +34,7 @@ Managed compact root routers must use trigger -> canonical instruction file refe
36
34
  - When a Proteum MCP client is available, first call MCP `workflow_start` with `cwd` or a known `projectId`. If it is ambiguous or returns offline app candidates, call `project_resolve { cwd }`, select the intended app root, start exactly one dev server from that app root when needed, then retry `workflow_start`. Pass the returned live `projectId` to every follow-up app-bound MCP tool. `npx proteum dev` ensures one managed machine MCP daemon is running; do not start a second managed daemon. Prefer MCP `runtime_status`, `orient`, `instructions_resolve`, `explain_summary`, `route_candidates`, `doctor`, `diagnose`, `trace_show`, `perf_request`, `logs_tail`, and `db_query` for read-only runtime/status/orientation/owner/route/trace/perf/log/database reads. Do not run CLI equivalents after a successful MCP result for the same read. Do not run broad source searches for route/page/controller ownership after MCP returns the owner. Use CLI commands when you need reproducible terminal validation, dev/build/check workflows, fallback repair, or output to share with a human.
37
35
  - MCP payloads are compact single-line `proteum-mcp-v1` JSON with capped and paginated detail. Do not expand MCP output for human readability.
38
36
  - For every non-trivial coding task, load and follow root-level `DOCUMENTATION.md` before coding.
37
+ - For bug fixes, regressions, incidents, broken public routes, auth/OAuth failures, integration failures, or production behavior fixes, load and follow root-level `DOCUMENTATION.md` before coding so the relevant fix note, regression-test docs, ADR, or explicit skip reason is handled in the same change.
39
38
  - If the user reports an issue, or the agent encounters one during exploration, implementation, verification, or runtime reproduction, load and follow root-level `diagnostics.md`.
40
39
  - If the task touches client-side files, especially `client/**` and page files, load and apply root-level `optimizations.md` only after implementation for post-implementation checking and optimization. Skip it at task start and skip it for server-only, test-only, doc-only, and non-client refactor tasks unless the user explicitly asks for optimization work.
41
40
  - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, use root-level `DOCUMENTATION.md` to choose the smallest relevant `./docs/` pack before editing. If a dev server is already running, print the live dev server URL as a clickable Markdown link.
@@ -54,7 +53,7 @@ Managed compact root routers must use trigger -> canonical instruction file refe
54
53
 
55
54
  [optional body]
56
55
  ```
57
- Then treat `commit` as conversation-wide and cross-project, not task-scoped. Identify every affected git repository or worktree touched during that span, stage all conversation-related changed files in each affected repository or worktree with `git add` while still avoiding unrelated pre-existing user changes or incidental untracked files, and create one `git commit` per affected repository or worktree. Do not omit linked local dependencies, framework repos, connected projects, or producer apps when they were changed to make the delivered behavior actually work. Do not stop at only suggesting the message.
56
+ Then treat `commit` as conversation-wide and cross-project, not task-scoped. Before staging or committing, run the repository's non-coverage commit gate when it defines one, such as `npm run check:commit`; otherwise run targeted lint, typecheck, and test commands. Report any blocker instead of committing through a failed commit gate. Identify every affected git repository or worktree touched during that span, stage all conversation-related changed files in each affected repository or worktree with `git add` while still avoiding unrelated pre-existing user changes or incidental untracked files, and create one `git commit` per affected repository or worktree. Do not omit linked local dependencies, framework repos, connected projects, or producer apps when they were changed to make the delivered behavior actually work. Do not stop at only suggesting the message.
58
57
  After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
59
58
  `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.`
60
59
 
@@ -80,20 +79,21 @@ Managed compact root routers must use trigger -> canonical instruction file refe
80
79
  ### Before Finishing
81
80
 
82
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.
83
- - Run the full project `npx proteum check` before finishing each feature or change. Targeted lint, typecheck, diagnose, request, browser, or E2E runs are still useful while iterating, but they do not replace the final full check. After implementing a new feature or changing existing feature behavior, always update the end-to-end coverage for that behavior and run the full Playwright test suite before finishing. For docs-only, wording-only, type-only, test-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.
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.
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.`
87
87
 
88
88
  ## Core Contracts
89
89
 
90
- - Client pages live in `client/pages/**` and register routes with top-level `Router.page(...)` or `Router.error(...)`.
91
- - Page URLs come from the explicit `Router.page('/path', ...)` call, not from the file path.
92
- - Callable app APIs live only in `server/controllers/**/*.ts` files that extend `Controller`.
90
+ - Client pages live in `client/pages/**` and default-export `definePageRoute(...)` or `defineErrorRoute(...)`.
91
+ - Page URLs come from the explicit route definition `path`, not from the file path.
92
+ - Callable app APIs live only in `server/controllers/**/*.ts` files that default-export `defineController(...)`.
93
93
  - Dev-only internal execution lives only in `commands/**/*.ts` files that extend `Commands`.
94
94
  - Manual HTTP endpoints live only in `server/routes/**`.
95
- - Controllers call `this.input(schema)` inside the method body, at most once per method.
96
- - Request-scoped state lives only on `this.request` and manual-route/router context objects.
95
+ - Controllers declare input on `defineAction({ input, handler })`; handlers receive parsed `input` in context.
96
+ - Request-scoped state lives only on action handler context and manual-route handler context objects.
97
97
  - Keep one class or one React/Preact component per file.
98
98
  - Prefer a deep tree grouped by business concern instead of long file names.
99
99
  - Use the default `*.ts` or `*.tsx` file unless an `*.ssr.ts` or `*.ssr.tsx` variant is truly required.
@@ -106,14 +106,15 @@ Managed compact root routers must use trigger -> canonical instruction file refe
106
106
  - Do not import runtime values from `@models`.
107
107
  - Do not use `@request` runtime globals.
108
108
  - Do not use `@app` on the client.
109
+ - Do not import `@app` in route, page, or controller files. Runtime app/services/router access belongs in typed callback parameters.
109
110
  - Prefer type inference rooted in the explicit application graph in `server/index.ts`.
110
111
 
111
112
  ## Surface Contracts
112
113
 
113
114
  ### App Bootstrap And Services
114
115
 
115
- - `server/index.ts` default-exports the app `Application` subclass and is the canonical type root.
116
- - Root services are public class fields instantiated with `new ServiceClass(this, config, this)`.
116
+ - `server/index.ts` default-exports `defineApplication({ services, router, models, commands })` and is the canonical type root.
117
+ - Root services are declared in the explicit `services` graph and instantiated with `new ServiceClass(app, config, app)`.
117
118
  - Typed root-service config lives in `server/config/*.ts` via `Services.config(ServiceClass, { ... })`.
118
119
  - Router plugins are instantiated explicitly inside the `Router` config `plugins` object.
119
120
  - Router plugins can subscribe to `request` and `request.finished`; `request.profiling` exists before `request` runs and carries the finalized request/API/SQL snapshot by `request.finished`.
@@ -125,6 +126,51 @@ Managed compact root routers must use trigger -> canonical instruction file refe
125
126
  - Companion client-callable entrypoints live in `server/controllers/**`.
126
127
  - `proteum create service ...` scaffolds the service file, a typed config export under `server/config/*.ts`, and the root registration in `server/index.ts`; review and adapt the generated names before committing.
127
128
 
129
+ Example app root shape; replace names with the project app type and service names:
130
+
131
+ ```ts
132
+ import { defineApplication, type Application } from '@server/app';
133
+ import Router from '@server/services/router';
134
+ import SchemaRouter from '@server/services/schema/router';
135
+ import BillingService from '@/server/services/Billing';
136
+
137
+ import * as appConfig from '@/server/config/app';
138
+
139
+ type ProjectServices = {
140
+ Billing: BillingService;
141
+ };
142
+
143
+ type ProjectRouterPlugins = {
144
+ schema: SchemaRouter;
145
+ };
146
+
147
+ export type ProjectRouter = Router<ProjectApp, ProjectRouterPlugins>;
148
+ export interface ProjectApp extends Application, ProjectServices {
149
+ Router: ProjectRouter;
150
+ }
151
+
152
+ const createProjectRouter = (app: ProjectApp): ProjectRouter =>
153
+ new Router<ProjectApp, ProjectRouterPlugins>(
154
+ app,
155
+ {
156
+ ...appConfig.routerBaseConfig,
157
+ plugins: {
158
+ schema: new SchemaRouter({}, app),
159
+ },
160
+ },
161
+ app,
162
+ );
163
+
164
+ const ProjectApplication = defineApplication<ProjectServices, ProjectRouter>({
165
+ services: (app) => ({
166
+ Billing: new BillingService(app, {}, app),
167
+ }),
168
+ router: createProjectRouter,
169
+ });
170
+
171
+ export default ProjectApplication;
172
+ ```
173
+
128
174
  ### Connected Projects
129
175
 
130
176
  - Declare connected namespaces in `proteum.config.ts` with explicit values such as `connect: { Product: { source: PRODUCT_CONNECTED_SOURCE, urlInternal: PRODUCT_URL_INTERNAL } }`.
@@ -136,13 +182,27 @@ Managed compact root routers must use trigger -> canonical instruction file refe
136
182
 
137
183
  ### Controllers
138
184
 
139
- - Files live under `server/controllers/**/*.ts` and default-export a class extending `Controller`.
140
- - Methods with bodies become generated client-callable endpoints.
141
- - Route path comes from the controller file path plus the method name.
142
- - `export const controllerPath = 'Custom/path'` can override the base path.
185
+ - Files live under `server/controllers/**/*.ts` and default-export `defineController({ path, actions })`.
186
+ - Actions declared with `defineAction(...)` become generated client-callable endpoints.
187
+ - Route path comes from the controller `path` plus the action name.
188
+ - Set `path: 'Custom/path'` on `defineController(...)` to override the base path.
143
189
  - Generated client calls use `POST`.
144
190
  - Prefer `proteum create controller ...` for new controller boilerplate, then adapt the generated method to real service calls.
145
191
 
192
+ ```ts
193
+ import { defineAction, defineController, schema } from '@server/app/controller';
194
+
195
+ export default defineController({
196
+ path: 'Billing',
197
+ actions: {
198
+ read: defineAction({
199
+ input: schema.object({ accountId: schema.string() }),
200
+ handler: ({ input }) => ({ accountId: input.accountId }),
201
+ }),
202
+ },
203
+ });
204
+ ```
205
+
146
206
  ### Commands
147
207
 
148
208
  - Files live under `commands/**/*.ts` and default-export a class extending `Commands` from `@server/app/commands`.
@@ -155,25 +215,47 @@ Managed compact root routers must use trigger -> canonical instruction file refe
155
215
 
156
216
  ### Client Pages
157
217
 
158
- - Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
159
- - File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
160
- - The only supported page signature is `Router.page(path, options, data, render)`.
218
+ - Proteum scans page files for default-exported `definePageRoute(...)` and `defineErrorRoute(...)` definitions.
219
+ - File path controls chunk identity and layout discovery; route path comes from the explicit definition `path` value.
220
+ - The supported page shape is `definePageRoute({ path, options, data, render })`.
161
221
  - `options` is always required. `data` is the only nullable argument and must be `null` when the page has no SSR data loader.
162
222
  - `data` returns one flat object. Route-option keys such as `auth`, `layout`, `static`, and `_static` are forbidden in page data and must live in `options`.
163
223
  - Controller fetchers and promises returned from `data` resolve before render.
164
224
  - `render` consumes resolved page data and uses generated controller methods from render args or `@/client/context`.
165
225
  - Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page data state.
166
- - Error pages use `Router.error(code, options, render)` in `client/pages/_messages/**`.
226
+ - Error pages use `defineErrorRoute({ code, options, render })` in `client/pages/_messages/**`.
167
227
  - Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path, options object, and data payload.
168
228
 
229
+ ```tsx
230
+ import { definePageRoute } from '@common/router/definitions';
231
+
232
+ export default definePageRoute({
233
+ path: '/billing',
234
+ options: { auth: true },
235
+ data: ({ BillingController }) => ({ billing: BillingController.read({ accountId: 'current' }) }),
236
+ render: ({ billing }) => <BillingPage billing={billing} />,
237
+ });
238
+ ```
239
+
169
240
  ### Manual Routes
170
241
 
171
242
  - Use `server/routes/**` only for explicit HTTP behavior that should not be a generated controller action.
172
243
  - Good fits include redirects, sitemap or RSS output, OAuth callbacks, webhooks, and public resources with custom semantics.
173
- - Import server-side app services from `@app` and use route handler context for `request`, `response`, router plugins, and custom router context.
244
+ - Receive app services through `defineServerRoutes((app) => [...])` and use handler context for `request`, `response`, router plugins, and custom router context.
174
245
  - If the route is a normal app API, prefer a controller.
175
246
  - Prefer `proteum create route ...` for new manual-route boilerplate.
176
247
 
248
+ ```ts
249
+ import { defineServerRoute } from '@common/router/definitions';
250
+
251
+ export default defineServerRoute({
252
+ method: 'GET',
253
+ path: '/health',
254
+ options: {},
255
+ handler: ({ response }) => response.json({ ok: true }),
256
+ });
257
+ ```
258
+
177
259
  ### Models And Aliases
178
260
 
179
261
  - Use Prisma typings from `@models/types`.
@@ -183,19 +265,18 @@ Managed compact root routers must use trigger -> canonical instruction file refe
183
265
  - Aliases:
184
266
  - `@/client/...`, `@/server/...`, `@/common/...`: app code
185
267
  - `@client/...`, `@server/...`, `@common/...`: Proteum core modules
186
- - `@app`: server-side application services for manual routes only
187
268
  - `@generated/*`: generated app surfaces
188
269
 
189
270
  ## Verification Matrix
190
271
 
191
272
  Verify at the correct layer:
192
273
 
193
- - Default: use the cheapest trustworthy verification for the changed surface first, then run the full project `npx proteum check` before finishing.
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.
194
275
  - Route additions: boot the app and hit the real URL.
195
276
  - Controller changes: exercise the generated client call or generated `/api/...` endpoint.
196
277
  - SSR changes: use the browser MCP to load the real page and inspect rendered HTML plus browser console.
197
278
  - Router or plugin changes: verify request context, auth, redirects, metrics, and validation on a running app.
198
- - New features or feature-behavior changes: use the cheapest trustworthy verification while iterating, use the browser MCP for browser-visible validation, then update the relevant end-to-end coverage and finish by running the full Playwright suite plus the full project `npx proteum check`.
279
+ - New features or feature-behavior changes: use the cheapest trustworthy verification while iterating, use the browser MCP for browser-visible validation, then update and run the relevant end-to-end coverage. Save the non-coverage commit gate for commit workflows and the full `npm run check` gate for push workflows unless the user or project-local instructions explicitly ask for the full gate earlier.
199
280
  - Generated, connected, or ownership-ambiguous changes: start with MCP `workflow_start`, then `orient { projectId, query }` and `explain_summary { projectId, query }` only when more detail is needed; use `npx proteum orient <query>` and `npx proteum verify owner <query>` when MCP is unavailable or terminal evidence is required.
200
281
  - Browser-visible issues: use the browser MCP after request-level verification is insufficient. Use `npx proteum e2e --port <port> ...` only when automated end-to-end coverage or a Playwright suite is required.
201
282
  - Raw browser execution outside end-to-end suites: use the browser MCP only. Keep Playwright in `npx proteum e2e --port <port>` for targeted/full end-to-end suites.
@@ -233,7 +314,7 @@ Verify at the correct layer:
233
314
  ### Discouraged Patterns
234
315
 
235
316
  - request-scoped state inside normal service methods
236
- - hiding route registration behind abstractions that remove the top-level `Router.page(...)` call
317
+ - hiding route definitions behind abstractions that remove the default-exported `definePageRoute(...)` or `defineServerRoute(...)` contract
237
318
  - editing `.proteum` directly
238
319
 
239
320
  ## Hard Stops
@@ -242,7 +323,7 @@ Verify at the correct layer:
242
323
  - For read-only SQL diagnosis, use MCP `db_query` or `npx proteum db query "<sql>"`; only one capped `SELECT`, `SHOW`, or `EXPLAIN` statement is allowed.
243
324
  - Do not run `prisma *` yourself. If a schema change requires migration, ask the user to run `npx prisma migrate dev --config ./prisma.config.ts --name <migration name>` and wait for `continue`.
244
325
  - Do not run `git restore` or `git reset`.
245
- - Do not run write-mode git commands by default. The built-in exception is an exact `commit` reply, which allows `git add` and `git commit` in every affected repository or worktree touched during the whole conversation. Any other write-mode git action requires an explicit user request.
326
+ - Do not run write-mode git commands by default. The built-in exception is an exact `commit` reply, which allows `git add` and `git commit` in every affected repository or worktree touched during the whole conversation after the repository's non-coverage commit gate passes when it defines one, such as `npm run check:commit`. Any other write-mode git action requires an explicit user request. Before any explicit push, run `npm run check` in every affected repository or worktree that defines it and report any blocker instead of pushing through a failed check.
246
327
 
247
328
  ## Appendix
248
329
 
@@ -337,10 +418,10 @@ Agents working in generated Proteum projects must use this delivery workflow for
337
418
  1. BDD / ATDD: translate the requested behavior into acceptance scenarios before changing implementation code.
338
419
  2. TDD: write or update the smallest failing unit/integration test that proves the next behavior.
339
420
  3. Implementation: make the narrowest production change that satisfies the failing test while preserving Proteum boundaries.
340
- 4. Proteum check: refresh and validate generated framework contracts after route, page, controller, service, command, or config changes.
421
+ 4. Targeted validation: refresh generated framework contracts after route, page, controller, service, command, or config changes, then run the targeted tests/checks that match the changed surface.
341
422
  5. Validate unit + E2E: run the relevant unit tests and real-world journey E2E checks before calling the work complete.
342
423
 
343
- Unit test expectation: production changes must always add or update focused unit tests and maintain 100% whole-project Vitest unit coverage. Before claiming implementation work complete, run `npx vitest run --coverage` from the repository root and make sure global statements, branches, functions, and lines all meet the configured 100% thresholds. MCP endpoint-reference coverage, touched-path-only coverage, and focused test passes are not substitutes for whole-project Vitest coverage. Any excluded generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested must be documented in the completion note, and agents must not claim the project has full unit coverage when an exception remains.
424
+ Unit test expectation: production changes must 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 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. Any excluded generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested must be documented in the completion note.
344
425
 
345
426
  E2E expectation: real-world journeys must follow the project-local instructions in `tests/e2e/REAL_WORLD_JOURNEY_TESTS.md`. These tests should model complete user workflows, role transitions, permissions, state changes, and cross-view consistency rather than isolated happy paths.
346
427
 
@@ -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 the full project `npx proteum check`; 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. 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
 
@@ -21,7 +21,7 @@ This file is the source of truth for codex coding style instructions in Proteum-
21
21
  - Keep short arrow functions and short returned object literals compact when they are easy to scan.
22
22
  - Keep JSX multiline only when it is clearly more readable; otherwise keep short JSX compact.
23
23
  - Avoid staircase formatting and unnecessary blank lines inside short callbacks.
24
- - Keep `Router.page(...)` and `Router.error(...)` registrations in the compact inline-call shape when possible, for example `Router.page('/path', {}, null, render);`.
24
+ - Keep route definition metadata compact when possible, for example `definePageRoute({ path: '/path', options: {}, data: null, render });`.
25
25
 
26
26
  ## File organization
27
27
 
@@ -8,9 +8,7 @@ Do not put here: reusable Proteum architecture contracts, shared verification ru
8
8
  ## App-Root Triggers
9
9
 
10
10
  - If you are working in a newly created Proteum worktree, before following the rest of these instructions:
11
- - Copy `.env` from the main worktree.
12
- - Run `npx proteum refresh`.
11
+ - Run `npx proteum worktree init --source <source-app-root>`.
13
12
  - Read and acknowledge the applicable `AGENTS.md` files.
14
- - Run `npm i`.
15
13
  - Run the dev server with the task-safe elevated-permissions launch workflow from the reusable root `AGENTS.md`, keep it running so user can see the results by himself, and print the live server URL as a clickable Markdown link. If `proteum dev` reports blocked instruction paths, resolve them before continuing.
16
14
  - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, use root-level `DOCUMENTATION.md` to choose the smallest relevant `./docs/` pack before editing. If a dev server is already running, print the live dev server URL as a clickable Markdown link.
@@ -25,7 +25,11 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
25
25
  - Never depend on legacy `@app` imports on the client.
26
26
  - Errors from controller calls should never be silently swallowed. Rethrow or surface them clearly.
27
27
  - Caught frontend errors must always preserve the original failure. Never write `catch {}`, `.catch(() => ...)`, or a catch handler that only shows a generic toast/state without using the caught error.
28
- - Valid frontend error handling includes rethrowing the error, passing it to `Router.app.handleError(error)`, logging/reporting it with the original error, or surfacing original detail such as `error.message` in user-visible feedback.
28
+ - Valid terminal frontend error handling is `throw error`, `useContext().app.handleError(error)`, or `context.app.handleError(error)`.
29
+ - Do not normalize caught values in app code before calling `handleError`; the app handles `unknown` values and returns a displayable message.
30
+ - If the app customizes `handleError`, keep the signature `handleError(error: unknown, fallbackMessage?: string): string`.
31
+ - Toasts and form errors are local feedback only; use `setError(context.app.handleError(error, fallbackMessage))` or rethrow the caught error.
32
+ - `console.*(error)` is not error handling and must not be the last stop for a caught error.
29
33
 
30
34
  ## Design
31
35