proteum 2.2.0 → 2.2.2-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.
package/AGENTS.md CHANGED
@@ -32,7 +32,7 @@ cd <worktree path>
32
32
  npx prisma migrate dev --config ./prisma.config.ts --name <migration name>
33
33
  ```
34
34
  - After implementing a framework feature or change, do not stop at code edits. Boot both reference apps, exercise the affected flow with Playwright or the smallest real Proteum surface, run the relevant `proteum` diagnostics or perf commands, and confirm there is no meaningful regression in runtime behavior, performance, load size, SEO output, or coding-style expectations before finishing.
35
- - When starting a long-lived reference app dev server for framework work, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit thread-scoped session file such as `var/run/proteum/dev/framework-<app>-<task>.json`, inspect tracked sessions plus current listeners first, for example with `npx proteum dev list --json` and `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`.
35
+ - When starting a long-lived reference app dev server for framework work, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit thread-scoped session file such as `var/run/proteum/dev/framework-<app>-<task>.json`, inspect tracked sessions plus current listeners first, for example with `npx proteum dev list --json` and `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`. After the server is ready, print the live server URL as a clickable Markdown link such as `[http://localhost:3100](http://localhost:3100)`.
36
36
  - Do not use `--replace-existing` unless you are 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.
37
37
  - When a reference app uses local `file:` connected projects for the affected flow, boot every connected producer app as well, each on its own free port and thread-scoped session file, and run every one of those `proteum dev` processes with elevated permissions outside the sandbox before starting or validating the consumer app.
38
38
  - Before retrying a boot on the same app, changing ports, or finishing the task, stop every framework-started dev session with `npx proteum dev stop --session-file <path>` or `npx proteum dev stop --all --stale`.
@@ -43,7 +43,7 @@ npx prisma migrate dev --config ./prisma.config.ts --name <migration name>
43
43
 
44
44
  [optional body]
45
45
  ```
46
- If the user replies exactly `commit`, use that Conventional Commit message, stage the task-related changed files with `git add` while avoiding unrelated user changes or incidental untracked files, then create the commit by running `git commit`.
46
+ 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.
47
47
  After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
48
48
  `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.`
49
49
 
@@ -51,12 +51,14 @@ npx prisma migrate dev --config ./prisma.config.ts --name <migration name>
51
51
 
52
52
  - Validate framework changes against the reference apps:
53
53
  - `/Users/gaetan/Desktop/Projets/crosspath/platform`: Standalone app
54
+ - `/Users/gaetan/Desktop/Projets/crosspath/website`: Standalone app
54
55
  - `/Users/gaetan/Desktop/Projets/unique.domains/platform`: Monorepo including the following apps:
55
56
  - `/Users/gaetan/Desktop/Projets/unique.domains/platform/apps/product`
56
57
  - `/Users/gaetan/Desktop/Projets/unique.domains/platform/apps/website`
57
58
  - Inspect how both apps currently use the touched feature, runtime, API, compiler behavior, or generated output before proposing or implementing changes.
58
59
  - 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.
59
- - 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 banner. 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.
60
+ - 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.
61
+ - 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 banner. 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. When the app root is missing `AGENTS.md`, the bare interactive `proteum dev` start offers to launch `proteum configure agents` before the dev loop begins.
60
62
  - 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`.
61
63
  - Prefer removing framework magic when the same result can be expressed with explicit contracts, generated code, or typed context.
62
64
  - 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
@@ -6,6 +6,12 @@ It is built for teams that want explicit server contracts, server-first renderin
6
6
 
7
7
  Migration guide for older apps: [docs/migrate-from-2.1.3.md](docs/migrate-from-2.1.3.md)
8
8
 
9
+ ## Sponsor
10
+
11
+ Proteum is sponsored by [Unique Domains](https://unique.domains/?utm_source=github&utm_medium=referral&utm_campaign=repo_proteum&utm_content=top_sponsor).
12
+
13
+ [![Unique Domains](docs/assets/unique-domains-chip.png)](https://unique.domains/?utm_source=github&utm_medium=referral&utm_campaign=repo_proteum&utm_content=top_sponsor)
14
+
9
15
  ## Why Proteum
10
16
 
11
17
  Most full-stack frameworks optimize first for human convenience.
@@ -101,6 +107,7 @@ Optional trace env vars:
101
107
  - `TRACE_EVENTS_LIMIT`
102
108
  - `TRACE_CAPTURE`
103
109
  - `TRACE_PERSIST_ON_ERROR`
110
+ - `ENABLE_PROFILER`
104
111
 
105
112
  Optional `proteum.config.ts` fields:
106
113
 
@@ -353,7 +360,7 @@ proteum build --prod --analyze
353
360
  proteum build --prod --analyze --analyze-serve --analyze-port auto
354
361
  ```
355
362
 
356
- 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.
363
+ 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. When the app root is missing `AGENTS.md`, the interactive `proteum dev` start offers to launch `proteum configure agents` before the dev loop begins.
357
364
 
358
365
  Useful inspection commands:
359
366
 
@@ -397,6 +404,8 @@ proteum create service Conversion/Plans
397
404
 
398
405
  `proteum configure agents` asks before replacing any existing non-managed instruction file or foreign symlink. If you decline, that path is left untouched.
399
406
 
407
+ Bare interactive `proteum dev` reuses that same wizard when the app root is missing `AGENTS.md`; declining the prompt continues the dev start without writing files.
408
+
400
409
  `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. For the full diagnostics and tracing model, see [docs/diagnostics.md](docs/diagnostics.md) and [docs/request-tracing.md](docs/request-tracing.md).
401
410
 
402
411
  ## Dev Commands
@@ -464,6 +473,7 @@ Default behavior:
464
473
  - payloads are summarized, long strings are truncated, and sensitive fields such as cookies, passwords, and tokens are redacted
465
474
  - `TRACE_PERSIST_ON_ERROR` can export crashing requests under `var/traces/`
466
475
  - `proteum dev` removes auto-persisted crash traces from `var/traces/` when the dev session stops
476
+ - `ENABLE_PROFILER=true` reuses the same instrumentation path to populate `request.profiling` and the router `request.finished` hook with a reduced request/API/SQL snapshot in any environment, without retaining finished requests in the global trace buffer unless dev trace is also enabled
467
477
 
468
478
  Trace env example:
469
479
 
@@ -473,6 +483,7 @@ export TRACE_REQUESTS_LIMIT=200
473
483
  export TRACE_EVENTS_LIMIT=800
474
484
  export TRACE_CAPTURE=resolve
475
485
  export TRACE_PERSIST_ON_ERROR=true
486
+ export ENABLE_PROFILER=true
476
487
  ```
477
488
 
478
489
  Capture modes:
@@ -500,7 +511,7 @@ Proteum answers those questions with explicit artifacts:
500
511
 
501
512
  - `identity.config.ts` for app identity
502
513
  - `proteum.config.ts` for compiler and connected-project setup
503
- - `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, app-chosen connected-project config values, and `TRACE_*` env vars for the environment surface
514
+ - `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, app-chosen connected-project config values, `TRACE_*`, and `ENABLE_PROFILER` env vars for the environment surface
504
515
  - `server/index.ts` for the explicit root service graph
505
516
  - `.proteum/manifest.json` for machine-readable app structure
506
517
  - `proteum explain --json` for structured framework introspection
@@ -516,7 +527,7 @@ Proteum answers those questions with explicit artifacts:
516
527
  If you are an LLM or automation agent, start here:
517
528
 
518
529
  1. Read `identity.config.ts` and `proteum.config.ts`.
519
- 2. Read `PORT`, the relevant `ENV_*`, `URL`, `URL_INTERNAL`, any env values referenced by `proteum.config.ts`, and `TRACE_*` env vars, or run `proteum explain env`.
530
+ 2. Read `PORT`, the relevant `ENV_*`, `URL`, `URL_INTERNAL`, any env values referenced by `proteum.config.ts`, plus `TRACE_*` and `ENABLE_PROFILER`, or run `proteum explain env`.
520
531
  3. Inspect `server/index.ts` and `server/config/*.ts` for the explicit app bootstrap.
521
532
  4. Read `.proteum/manifest.json` or run `proteum explain --json`.
522
533
  5. Inspect `server/controllers/**` for request entrypoints.
@@ -17,12 +17,14 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
17
17
  - Run `npx proteum refresh`.
18
18
  - Read and acknowledge the applicable `AGENTS.md` files.
19
19
  - Run `npm i`.
20
- - Run the dev server with the task-safe elevated-permissions launch workflow from `Task Lifecycle`, and keep it running so user can see the results by himself.
21
- - If the user pastes raw errors without asking for a fix, do not implement changes. List likely causes and, for each one, give probability, why, and how to fix it.
20
+ - 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.
21
+ - If the user pastes raw errors without asking for a fix, do not implement changes. List likely causes and, for each one, give probability, why, and how to fix it. After this, everytime you implemented a fix
22
+ - test, re-run analysis and give a comparizon table of before and after
23
+ - re-print the complete list of suggested fixes, but strike the ones we already implemented or not necessary anymore
22
24
  - If the task is ambiguous, generated, connected, or multi-repo, start with `npx proteum orient <query>` before reading large parts of the codebase.
23
25
  - 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`.
24
26
  - 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.
25
- - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, read the relevant files under `./docs/` first, especially `docs/PERSONAS.md`, `docs/PRODUCT.md`, and `docs/MARKETING.md` when they exist. If a dev server is already running, print the dev server URL.
27
+ - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, read the relevant files under `./docs/` first, especially `docs/PERSONAS.md`, `docs/PRODUCT.md`, and `docs/MARKETING.md` when they exist. If a dev server is already running, print the live dev server URL as a clickable Markdown link.
26
28
  - If the task needs new app or artifact boilerplate, prefer `npx proteum init ...` and `npx proteum create ...` before creating files by hand. Use `--dry-run --json` when an agent needs a machine-readable plan before writing files.
27
29
  - If you changed `schema.prisma`, do not start testing or validation yet. Ask the user to run the following command in the affected worktree directory, replacing the placeholders, and wait for the user to reply exactly `continue` before resuming validation or tests:
28
30
  ```
@@ -38,7 +40,7 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
38
40
 
39
41
  [optional body]
40
42
  ```
41
- Then use that generated message, stage the task-related changed files with `git add` while avoiding unrelated user changes or incidental untracked files, and create the commit by running `git commit`. Do not stop at only suggesting the message.
43
+ 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.
42
44
  After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
43
45
  `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.`
44
46
 
@@ -51,16 +53,16 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
51
53
  ### During Implementation
52
54
 
53
55
  - After running `npx proteum create ...`, adapt the generated code to the real feature instead of leaving placeholder logic in place.
54
- - When starting a long-lived dev server for an agent task, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit task/thread-scoped session file such as `var/run/proteum/dev/agents/<task>.json`, inspect `npx proteum dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`.
56
+ - When starting a long-lived dev server for an agent task, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit task/thread-scoped session file such as `var/run/proteum/dev/agents/<task>.json`, inspect `npx proteum dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`. After the server is ready, print the live server URL as a clickable Markdown link.
55
57
  - 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.
56
58
  - 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.
57
59
  - For raw browser automation, use `npx proteum verify browser` when it matches the task, or direct Playwright with a disposable profile when lower-level control is required. Bootstrap protected browser state through `npx proteum session`.
58
- - 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 banner. 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.
60
+ - 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 banner. 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. When the app root is missing `AGENTS.md`, the bare interactive `proteum dev` start offers to launch `proteum configure agents` before the dev loop begins.
59
61
 
60
62
  ### Before Finishing
61
63
 
62
64
  - 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.
63
- - Do not default to project-wide typecheck, `npx proteum check`, or Playwright after every change. Run them only when the user asks for them, when the changed surface specifically requires them, or when a real issue discovered during verification justifies escalation.
65
+ - Do not default to project-wide typecheck or `npx proteum check` after every change. 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.
64
66
  - 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>`.
65
67
  - 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:
66
68
  `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.`
@@ -96,6 +98,7 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
96
98
  - Root services are public class fields instantiated with `new ServiceClass(this, config, this)`.
97
99
  - Typed root-service config lives in `server/config/*.ts` via `Services.config(ServiceClass, { ... })`.
98
100
  - Router plugins are instantiated explicitly inside the `Router` config `plugins` object.
101
+ - 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`.
99
102
  - Root business services live in `server/services/<Feature>/index.ts`.
100
103
  - Root-service config lives in `server/config/*.ts` when the service needs config.
101
104
  - Business logic lives in classes that extend `Service` and use `this.services`, `this.models`, and `this.app`.
@@ -174,6 +177,7 @@ Verify at the correct layer:
174
177
  - Controller changes: exercise the generated client call or generated `/api/...` endpoint.
175
178
  - SSR changes: load the real page and inspect rendered HTML plus browser console.
176
179
  - Router or plugin changes: verify request context, auth, redirects, metrics, and validation on a running app.
180
+ - New features or feature-behavior changes: use the cheapest trustworthy verification while iterating, then update the relevant end-to-end coverage and finish by running the full Playwright suite.
177
181
  - Generated, connected, or ownership-ambiguous changes: start with `npx proteum orient <query>` and prefer `npx proteum verify owner <query>` before broad global checks.
178
182
  - Browser-visible issues: prefer `npx proteum verify browser <path>` or the narrowest targeted Playwright pass only after request-level verification is insufficient.
179
183
  - Raw browser execution beyond `npx proteum verify browser`: use direct Playwright with a disposable profile, and keep that step for the final verifier agent unless a narrower surface cannot reproduce the issue.
@@ -218,7 +222,7 @@ Verify at the correct layer:
218
222
  - Never run schema-mutating SQL such as `ALTER TABLE`, `CREATE TABLE`, `DROP TABLE`, or `CREATE INDEX` to change database structure.
219
223
  - 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`.
220
224
  - Do not run `git restore` or `git reset`.
221
- - Do not run write-mode git commands by default. The built-in exception is an exact `commit` reply, which allows only task-scoped `git add` and `git commit`. Any other write-mode git action requires an explicit user request.
225
+ - 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.
222
226
 
223
227
  ## Appendix
224
228
 
@@ -238,7 +242,7 @@ Proteum reads:
238
242
  - `package.json`
239
243
  - `identity.config.ts` for app identity via `Application.identity({ ... })`
240
244
  - `proteum.config.ts` for compiler setup via `Application.setup({ transpile, connect })`
241
- - `process.env` via `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen connected-project values referenced by `proteum.config.ts`, and `TRACE_*`
245
+ - `process.env` via `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen connected-project values referenced by `proteum.config.ts`, `TRACE_*`, and `ENABLE_PROFILER`
242
246
  - `server/config/*.ts`
243
247
  - `server/index.ts`
244
248
  - `commands/**/*.ts`
@@ -298,6 +302,6 @@ Prefer scaffold commands before hand-writing boilerplate:
298
302
  Edit these only when required, and keep changes minimal and explicit:
299
303
 
300
304
  - `tsconfig*.json`
301
- - `PORT`, `ENV_*`, `URL`, and `TRACE_*` env setup
305
+ - `PORT`, `ENV_*`, `URL`, `TRACE_*`, and `ENABLE_PROFILER` env setup
302
306
  - Prisma-generated files
303
307
  - symbolic links
@@ -12,5 +12,5 @@ Do not put here: reusable Proteum architecture contracts, shared verification ru
12
12
  - Run `npx proteum refresh`.
13
13
  - Read and acknowledge the applicable `AGENTS.md` files.
14
14
  - Run `npm i`.
15
- - Run the dev server with the task-safe elevated-permissions launch workflow from the reusable root `AGENTS.md`, and keep it running so user can see the results by himself.
16
- - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, read the relevant files under `./docs/` first, especially `docs/PERSONAS.md`, `docs/PRODUCT.md`, and `docs/MARKETING.md` when they exist. If a dev server is already running, print the dev server URL.
15
+ - 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 the bare interactive `proteum dev` start offers to launch `proteum configure agents`, finish that wizard before continuing.
16
+ - If the task changes UX, copy, onboarding, pricing, product semantics, or commercial positioning, read the relevant files under `./docs/` first, especially `docs/PERSONAS.md`, `docs/PRODUCT.md`, and `docs/MARKETING.md` when they exist. If a dev server is already running, print the live dev server URL as a clickable Markdown link.
@@ -12,9 +12,9 @@ This file is the canonical source of truth for diagnostics, temporary instrument
12
12
 
13
13
  ## Runtime Diagnostics
14
14
 
15
- - 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 dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`.
15
+ - 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 dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`. After the server is ready, print the live server URL as a clickable Markdown link.
16
16
  - 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.
17
- - 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 banner. 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.
17
+ - 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 banner. 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. When the app root is missing `AGENTS.md`, the bare interactive `npx proteum dev` start offers to launch `npx proteum configure agents` before the dev loop begins.
18
18
  - For ownership or repo discovery questions, start with `npx proteum orient <query>` instead of jumping straight into source searches.
19
19
  - For request-time issues in dev, start with `npx proteum diagnose <path> --port <port>` when you have a concrete failing route, page, controller path, or request target. It combines owner lookup, manifest diagnostics, contract diagnostics, matching trace data, and buffered server logs in one pass.
20
20
  - Prefer focused verification before global checks: `npx proteum verify owner <query>`, `npx proteum verify request <path>`, and only then `npx proteum verify browser <path>` or targeted Playwright when the bug is browser-visible.
@@ -30,7 +30,7 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
30
30
 
31
31
  [optional body]
32
32
  ```
33
- Then use that generated message, stage the task-related changed files with `git add` while avoiding unrelated user changes or incidental untracked files, and create the commit by running `git commit`. Do not stop at only suggesting the message.
33
+ 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.
34
34
  After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
35
35
  `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.`
36
36
 
@@ -43,16 +43,16 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
43
43
  ### During Implementation
44
44
 
45
45
  - After running `npx proteum create ...`, adapt the generated code to the real feature instead of leaving placeholder logic in place.
46
- - When starting a long-lived dev server for an agent task, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit task/thread-scoped session file such as `var/run/proteum/dev/agents/<task>.json`, inspect `npx proteum dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`.
46
+ - When starting a long-lived dev server for an agent task, always request elevated permissions and run `npx proteum dev` outside the sandbox. Use an explicit task/thread-scoped session file such as `var/run/proteum/dev/agents/<task>.json`, inspect `npx proteum dev list --json` plus current listeners first, for example with `lsof -nP -iTCP -sTCP:LISTEN`, then choose a port that is not currently used before starting `npx proteum dev --session-file <path> --port <port>`. After the server is ready, print the live server URL as a clickable Markdown link.
47
47
  - 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.
48
48
  - 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.
49
49
  - For raw browser automation, use `npx proteum verify browser` when it matches the task, or direct Playwright with a disposable profile when lower-level control is required. Bootstrap protected browser state through `npx proteum session`.
50
- - 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 banner. 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.
50
+ - 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 banner. 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. When the app root is missing `AGENTS.md`, the bare interactive `proteum dev` start offers to launch `proteum configure agents` before the dev loop begins.
51
51
 
52
52
  ### Before Finishing
53
53
 
54
54
  - 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.
55
- - Do not default to project-wide typecheck, `npx proteum check`, or Playwright after every change. Run them only when the user asks for them, when the changed surface specifically requires them, or when a real issue discovered during verification justifies escalation.
55
+ - Do not default to project-wide typecheck or `npx proteum check` after every change. 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.
56
56
  - 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>`.
57
57
  - 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:
58
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.`
@@ -88,6 +88,7 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
88
88
  - Root services are public class fields instantiated with `new ServiceClass(this, config, this)`.
89
89
  - Typed root-service config lives in `server/config/*.ts` via `Services.config(ServiceClass, { ... })`.
90
90
  - Router plugins are instantiated explicitly inside the `Router` config `plugins` object.
91
+ - 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`.
91
92
  - Root business services live in `server/services/<Feature>/index.ts`.
92
93
  - Root-service config lives in `server/config/*.ts` when the service needs config.
93
94
  - Business logic lives in classes that extend `Service` and use `this.services`, `this.models`, and `this.app`.
@@ -166,6 +167,7 @@ Verify at the correct layer:
166
167
  - Controller changes: exercise the generated client call or generated `/api/...` endpoint.
167
168
  - SSR changes: load the real page and inspect rendered HTML plus browser console.
168
169
  - Router or plugin changes: verify request context, auth, redirects, metrics, and validation on a running app.
170
+ - New features or feature-behavior changes: use the cheapest trustworthy verification while iterating, then update the relevant end-to-end coverage and finish by running the full Playwright suite.
169
171
  - Generated, connected, or ownership-ambiguous changes: start with `npx proteum orient <query>` and prefer `npx proteum verify owner <query>` before broad global checks.
170
172
  - Browser-visible issues: prefer `npx proteum verify browser <path>` or the narrowest targeted Playwright pass only after request-level verification is insufficient.
171
173
  - Raw browser execution beyond `npx proteum verify browser`: use direct Playwright with a disposable profile, and keep that step for the final verifier agent unless a narrower surface cannot reproduce the issue.
@@ -210,7 +212,7 @@ Verify at the correct layer:
210
212
  - Never run schema-mutating SQL such as `ALTER TABLE`, `CREATE TABLE`, `DROP TABLE`, or `CREATE INDEX` to change database structure.
211
213
  - 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`.
212
214
  - Do not run `git restore` or `git reset`.
213
- - Do not run write-mode git commands by default. The built-in exception is an exact `commit` reply, which allows only task-scoped `git add` and `git commit`. Any other write-mode git action requires an explicit user request.
215
+ - 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.
214
216
 
215
217
  ## Appendix
216
218
 
@@ -230,7 +232,7 @@ Proteum reads:
230
232
  - `package.json`
231
233
  - `identity.config.ts` for app identity via `Application.identity({ ... })`
232
234
  - `proteum.config.ts` for compiler setup via `Application.setup({ transpile, connect })`
233
- - `process.env` via `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen connected-project values referenced by `proteum.config.ts`, and `TRACE_*`
235
+ - `process.env` via `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen connected-project values referenced by `proteum.config.ts`, `TRACE_*`, and `ENABLE_PROFILER`
234
236
  - `server/config/*.ts`
235
237
  - `server/index.ts`
236
238
  - `commands/**/*.ts`
@@ -290,6 +292,6 @@ Prefer scaffold commands before hand-writing boilerplate:
290
292
  Edit these only when required, and keep changes minimal and explicit:
291
293
 
292
294
  - `tsconfig*.json`
293
- - `PORT`, `ENV_*`, `URL`, and `TRACE_*` env setup
295
+ - `PORT`, `ENV_*`, `URL`, `TRACE_*`, and `ENABLE_PROFILER` env setup
294
296
  - Prisma-generated files
295
297
  - symbolic links
@@ -10,9 +10,16 @@ Diagnostics source of truth: root-level `diagnostics.md`.
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
12
  - Verify routing, controllers, SSR, and router plugins against a running app when behavior depends on real request handling.
13
- - After implementing a browser-visible feature or change, prefer a real browser repro against a running app first. Add targeted Playwright coverage only when the user asks for automated coverage, when a stable regression path needs automation, or when manual/browser verification is insufficient.
13
+ - 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. Use a real browser repro against a running app during iteration when it is the fastest trustworthy loop.
14
14
  - Exercise real URLs, generated controller calls, or real browser flows instead of re-deriving framework internals in tests.
15
+ - Organize end-to-end tests following the Crosspath platform layout under `tests/e2e/**`.
16
+ - Put runnable scenario entrypoints in `tests/e2e/features/**`, `tests/e2e/specs/<domain>/**`, or `tests/e2e/journeys/**` depending on scope.
17
+ - Put page objects and reusable UI surface wrappers in `tests/e2e/pages/**`.
18
+ - Put reusable multi-step user flows in `tests/e2e/workflows/**`.
19
+ - Put test data builders in `tests/e2e/factories/**` and generic helpers in `tests/e2e/utils/**`.
20
+ - Keep helpers out of spec files when they are reusable, and do not create ad hoc flat test files or duplicate support abstractions when an existing page, workflow, factory, or utility already fits.
15
21
  - Locate elements with `data-testid`.
16
22
  - Add `data-testid` where needed instead of relying on brittle selectors.
23
+ - Keep end-to-end tests clean, well organized, and non-redundant. Prefer extending or reshaping the most relevant existing scenario over duplicating coverage, and remove or consolidate overlap when the suite becomes repetitive.
17
24
  - Reuse root catalog files from `/client/catalogs/**`, `/server/catalogs/**`, or `/common/catalogs/**` instead of duplicating catalog constants in tests.
18
25
  - For protected dev flows, prefer `npx proteum session <email> --role <role>` over automating login unless the login flow itself is under test.
@@ -155,7 +155,16 @@ const renderConfigureResultSections = (result: TConfigureProjectAgentSymlinksRes
155
155
  export const run = async (): Promise<void> => {
156
156
  if (cli.args.action !== 'agents') throw new UsageError('Usage: `proteum configure agents`');
157
157
 
158
- const appRoot = resolveCanonicalPath(cli.paths.appRoot);
158
+ await runConfigureAgentsWizard();
159
+ };
160
+
161
+ export const runConfigureAgentsWizard = async ({
162
+ appRoot = resolveCanonicalPath(cli.paths.appRoot),
163
+ coreRoot = cli.paths.core.root,
164
+ }: {
165
+ appRoot?: string;
166
+ coreRoot?: string;
167
+ } = {}) => {
159
168
  assertProteumAppRoot(appRoot);
160
169
 
161
170
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
@@ -197,7 +206,7 @@ export const run = async (): Promise<void> => {
197
206
 
198
207
  const preview = configureProjectAgentSymlinks({
199
208
  appRoot,
200
- coreRoot: cli.paths.core.root,
209
+ coreRoot,
201
210
  dryRun: true,
202
211
  monorepoRoot,
203
212
  });
@@ -214,7 +223,7 @@ export const run = async (): Promise<void> => {
214
223
 
215
224
  const result = configureProjectAgentSymlinks({
216
225
  appRoot,
217
- coreRoot: cli.paths.core.root,
226
+ coreRoot,
218
227
  monorepoRoot,
219
228
  overwriteBlockedPaths,
220
229
  });
@@ -7,6 +7,8 @@ import path from 'path';
7
7
  import { spawn, ChildProcess } from 'child_process';
8
8
  import fs from 'fs-extra';
9
9
  import type { FSWatcher } from 'fs';
10
+ import prompts from 'prompts';
11
+ import { UsageError } from 'clipanion';
10
12
 
11
13
  // Cor elibs
12
14
  import cli from '..';
@@ -20,9 +22,11 @@ import {
20
22
 
21
23
  // Configs
22
24
  import Compiler from '../compiler';
25
+ import { regex } from '../compiler/common';
23
26
  import { createDevEventServer } from './devEvents';
24
27
  import { renderDevSession, renderServerReadyBanner, renderDevShutdownBanner } from '../presentation/devSession';
25
28
  import { clearInteractiveConsole } from '../presentation/welcome';
29
+ import { renderWarning } from '../presentation/ink';
26
30
  import {
27
31
  createDevSessionRecord,
28
32
  inspectDevSessionFile,
@@ -37,6 +41,8 @@ import {
37
41
  } from '../runtime/devSessions';
38
42
  import { resolveFrameworkInstallInfo } from '../paths';
39
43
  import { logVerbose } from '../runtime/verbose';
44
+ import { inspectProjectAgentFiles } from '../utils/agents';
45
+ import { runConfigureAgentsWizard } from './configure';
40
46
 
41
47
  // Core
42
48
  import { app, App } from '../app';
@@ -138,6 +144,45 @@ const createIgnoredWatchMatcher = (outputPaths: string[]) => (watchPath: string)
138
144
  return ignoredWatchPathPatterns.test(normalizedWatchPath);
139
145
  };
140
146
 
147
+ const promptToConfigureAgentsIfMissing = async () => {
148
+ if (cli.args.json === true) return;
149
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
150
+
151
+ const inspection = inspectProjectAgentFiles({ appRoot: app.paths.root });
152
+ if (!inspection.missing.includes('AGENTS.md')) return;
153
+
154
+ console.info(await renderWarning('Proteum could not find the app-root `AGENTS.md` instruction file.'));
155
+ console.info(
156
+ [
157
+ 'Missing standard AGENTS files:',
158
+ ...inspection.missing.map((entry) => `- ${entry}`),
159
+ '',
160
+ 'Run `proteum configure agents` now before starting the dev server?',
161
+ ].join('\n'),
162
+ );
163
+
164
+ const response = await prompts(
165
+ {
166
+ type: 'confirm',
167
+ name: 'value',
168
+ message: 'Run the configure-agents wizard now?',
169
+ initial: true,
170
+ },
171
+ {
172
+ onCancel: () => {
173
+ throw new UsageError('Cancelled `proteum dev`.');
174
+ },
175
+ },
176
+ );
177
+
178
+ if (response.value !== true) return;
179
+
180
+ await runConfigureAgentsWizard({
181
+ appRoot: app.paths.root,
182
+ coreRoot: cli.paths.core.root,
183
+ });
184
+ };
185
+
141
186
  const getDevAppName = (app: App) =>
142
187
  app.identity.web?.fullTitle || app.identity.web?.title || app.identity.name || app.packageJson.name || app.paths.root;
143
188
 
@@ -481,10 +526,66 @@ function normalizeWatchPath(watchPath: string) {
481
526
  return path.resolve(watchPath).replace(/\\/g, '/').replace(/\/$/, '');
482
527
  }
483
528
 
484
- const indexedSourceWatchRules: { compilerName: 'server'; root: () => string; relativePathPattern: RegExp }[] = [
485
- { compilerName: 'server', root: () => app.paths.root, relativePathPattern: /^commands(?:\/|$)/ },
486
- { compilerName: 'server', root: () => cli.paths.core.root, relativePathPattern: /^commands(?:\/|$)/ },
487
- ];
529
+ type TIndexedSourceWatchEvent = 'change' | 'rename';
530
+ type TIndexedSourceWatchCompilerName = 'server' | 'client';
531
+ type TIndexedSourceWatchInvalidateTarget = 'all' | TIndexedSourceWatchCompilerName;
532
+ type TIndexedSourceWatchRule = {
533
+ compilerName: TIndexedSourceWatchCompilerName;
534
+ rootPath: string;
535
+ relativePathPattern: RegExp;
536
+ eventTypes: TIndexedSourceWatchEvent[];
537
+ invalidateTarget: TIndexedSourceWatchInvalidateTarget;
538
+ };
539
+ type TNamedWatching = { compiler: { name?: string }; invalidate: () => void };
540
+ type TMultiWatchingLike = TDevWatching & { watchings?: TNamedWatching[] };
541
+
542
+ const resolveIndexedSourceWatchRules = (): TIndexedSourceWatchRule[] => {
543
+ const transpileWatchRoots = app.transpileModuleDirectories
544
+ .map((rootPath) => {
545
+ try {
546
+ return fs.realpathSync(rootPath);
547
+ } catch {
548
+ return rootPath;
549
+ }
550
+ })
551
+ .map(normalizeWatchPath)
552
+ .filter((rootPath, index, list) => list.indexOf(rootPath) === index);
553
+
554
+ return [
555
+ {
556
+ compilerName: 'server',
557
+ rootPath: app.paths.root,
558
+ relativePathPattern: /^commands(?:\/|$)/,
559
+ eventTypes: ['rename'],
560
+ invalidateTarget: 'all',
561
+ },
562
+ {
563
+ compilerName: 'server',
564
+ rootPath: cli.paths.core.root,
565
+ relativePathPattern: /^commands(?:\/|$)/,
566
+ eventTypes: ['rename'],
567
+ invalidateTarget: 'all',
568
+ },
569
+ ...transpileWatchRoots.map(
570
+ (rootPath): TIndexedSourceWatchRule => ({
571
+ compilerName: 'server',
572
+ rootPath,
573
+ relativePathPattern: regex.scripts,
574
+ eventTypes: ['change', 'rename'],
575
+ invalidateTarget: 'server',
576
+ }),
577
+ ),
578
+ ];
579
+ };
580
+
581
+ const findCompilerWatching = (
582
+ watching: TDevWatching,
583
+ compilerName: TIndexedSourceWatchCompilerName,
584
+ ): TNamedWatching | undefined => {
585
+ const childWatchings = (watching as TMultiWatchingLike).watchings;
586
+
587
+ return childWatchings?.find((childWatching) => childWatching.compiler.name === compilerName);
588
+ };
488
589
 
489
590
  const closeFsWatcher = async (watcher: FSWatcher) => {
490
591
  await new Promise<void>((resolve) => {
@@ -501,7 +602,9 @@ const createIndexedSourceWatching = ({
501
602
  watching: TDevWatching;
502
603
  }): TIndexedSourceWatching => {
503
604
  const watchers: FSWatcher[] = [];
504
- const pendingChanges = new Map<'server', Set<string>>();
605
+ const pendingChanges = new Map<TIndexedSourceWatchCompilerName, Set<string>>();
606
+ const pendingInvalidateTargets = new Set<TIndexedSourceWatchInvalidateTarget>();
607
+ const recentQueuedChanges = new Map<string, number>();
505
608
  let invalidateTimer: NodeJS.Timeout | undefined;
506
609
 
507
610
  const flushInvalidate = () => {
@@ -512,31 +615,77 @@ const createIndexedSourceWatching = ({
512
615
  }
513
616
 
514
617
  pendingChanges.clear();
515
- logVerbose('Indexed source files changed. Invalidating the dev compiler to refresh generated artifacts.');
516
- watching.invalidate();
618
+
619
+ if (pendingInvalidateTargets.has('all')) {
620
+ pendingInvalidateTargets.clear();
621
+ logVerbose('Indexed source files changed. Invalidating the dev compiler to refresh generated artifacts.');
622
+ watching.invalidate();
623
+ return;
624
+ }
625
+
626
+ const invalidateTargets = [...pendingInvalidateTargets].filter(
627
+ (invalidateTarget): invalidateTarget is TIndexedSourceWatchCompilerName => invalidateTarget !== 'all',
628
+ );
629
+ pendingInvalidateTargets.clear();
630
+
631
+ if (invalidateTargets.length === 0) return;
632
+
633
+ logVerbose('Transpiled source files changed. Invalidating the server compiler to refresh mutable package code.');
634
+ for (const invalidateTarget of invalidateTargets) {
635
+ const compilerWatching = findCompilerWatching(watching, invalidateTarget);
636
+
637
+ if (!compilerWatching) {
638
+ watching.invalidate();
639
+ return;
640
+ }
641
+
642
+ compilerWatching.invalidate();
643
+ }
517
644
  };
518
645
 
519
- const queueInvalidate = (compilerName: 'server', filepath: string) => {
646
+ const queueInvalidate = ({
647
+ compilerName,
648
+ filepath,
649
+ invalidateTarget,
650
+ }: {
651
+ compilerName: TIndexedSourceWatchCompilerName;
652
+ filepath: string;
653
+ invalidateTarget: TIndexedSourceWatchInvalidateTarget;
654
+ }) => {
520
655
  const normalizedFilepath = normalizeWatchPath(filepath);
656
+ const queueKey = `${invalidateTarget}:${compilerName}:${normalizedFilepath}`;
657
+ const queuedAt = recentQueuedChanges.get(queueKey);
658
+
659
+ if (queuedAt !== undefined && Date.now() - queuedAt < 250) return;
660
+
661
+ recentQueuedChanges.set(queueKey, Date.now());
521
662
  const changedFiles = pendingChanges.get(compilerName) || new Set<string>();
522
663
 
523
664
  changedFiles.add(normalizedFilepath);
524
665
  pendingChanges.set(compilerName, changedFiles);
666
+ pendingInvalidateTargets.add(invalidateTarget);
525
667
 
526
668
  if (invalidateTimer) return;
527
669
  invalidateTimer = setTimeout(flushInvalidate, 40);
528
670
  };
529
671
 
530
- for (const watchRule of indexedSourceWatchRules) {
531
- const rootPath = watchRule.root();
672
+ for (const watchRule of resolveIndexedSourceWatchRules()) {
673
+ const rootPath = watchRule.rootPath;
674
+ if (!fs.existsSync(rootPath)) continue;
532
675
 
533
676
  watchers.push(
534
677
  fs.watch(rootPath, { recursive: true }, (eventType, filename) => {
535
678
  const relativePath = typeof filename === 'string' ? filename.replace(/\\/g, '/').replace(/^\.\//, '') : '';
679
+ const normalizedEventType: TIndexedSourceWatchEvent = eventType === 'change' ? 'change' : 'rename';
680
+
536
681
  if (relativePath && !watchRule.relativePathPattern.test(relativePath)) return;
537
- if (eventType !== 'rename' && relativePath) return;
682
+ if (!watchRule.eventTypes.includes(normalizedEventType) && relativePath) return;
538
683
 
539
- queueInvalidate(watchRule.compilerName, relativePath ? path.join(rootPath, relativePath) : rootPath);
684
+ queueInvalidate({
685
+ compilerName: watchRule.compilerName,
686
+ filepath: relativePath ? path.join(rootPath, relativePath) : rootPath,
687
+ invalidateTarget: watchRule.invalidateTarget,
688
+ });
540
689
  }),
541
690
  );
542
691
  }
@@ -731,5 +880,6 @@ export const run = async () => {
731
880
  return;
732
881
  }
733
882
 
883
+ await promptToConfigureAgentsIfMissing();
734
884
  await runDevLoop();
735
885
  };