## Linked issue
Linear tracking explicitly waived by the operator ("skip linear").
Builds on the merged multi-file emission work in #30379 and the existing
playground scratch project.
## At a glance
```ts
import { definePrismaConfig } from '@prisma/cli-engine';
import { defineConfig as ormConfig } from '@prisma/orm-postgres/config';
export default definePrismaConfig({
orm: ormConfig({ contract: './*.prisma' }),
});
```
This [real integration
fixture](test/integration/test/fixtures/cli/cli-test-app/fixtures/lsp-emit-parity-multi-file/prisma.config.ts)
now works in the language server too: opted-in sibling files contribute
symbols and receive diagnostics without ever being opened. Previously,
the server treated the glob as a literal path.
## Summary
The editor must see the same schema as contract emission, not whichever
files happen to be open. This PR makes multi-file PSL analysis
project-wide and keeps diagnostics alive for closed members.
## Decision
This PR ships whole-project PSL language-server analysis: one
overlay-or-disk content store, shared glob expansion plus the existing
directive gate, one interpretation over all members, and pushed
diagnostics for closed files. It also preserves UNC literal authorities
in the shared input expander, which the new LSP loading path consumes.
The [design decisions](projects/multifile-psl/design-decisions.md)
describe the content-store, watcher and project-lifetime choices.
## Notes for the reviewer
- Pull-capable clients keep pulling open documents; closed members
receive push diagnostics. `interFileDependencies` is now true, but
`workspace/diagnostic` is not implemented.
- The parity test compares full normalized diagnostics from the
configured provider's real `source.load` path with combined LSP results,
including file, code, message, severity and range. It separately
exercises actual CLI emission; it does not compare two calls to the
interpreter in isolation.
- The [recorded playground
QA](projects/multifile-psl/slices/lsp-whole-project/qa-run.md) uses
Chromium, Monaco keyboard edits and captured WebSocket traffic. It
verifies closed-file diagnostics, not visual highlighting correctness.
- The existing committed diff includes project bookkeeping changes (plan
wording, trace truncation and removal of the playground slice
spec/plan). Local restored/updated project files, the closing-review
document and packaging artifacts remain uncommitted and are not part of
this PR; packaging did not alter those files or rewrite history.
## How it fits together
1. **Read current content from one place.** The [document
store](packages/1-framework/3-tooling/language-server/src/document-store.ts)
distinguishes overlays from disk entries. Open buffers win; closing
evicts the overlay; watcher invalidation cannot overwrite unsaved edits.
2. **Build one project view.**
[Membership](packages/1-framework/3-tooling/language-server/src/schema-inputs.ts)
expands the configured patterns and checks `// use prisma-8` against
current text. [Project
artifacts](packages/1-framework/3-tooling/language-server/src/project-artifacts.ts)
parse all members, build a shared symbol table, interpret once and
distribute results by source identity.
3. **Keep the view useful when files close.** The
[server](packages/1-framework/3-tooling/language-server/src/server.ts)
retains projects, registers schema watchers where supported, publishes
closed-member diagnostics and clears stale publications. Disk reads also
revalidate mtime and size. The push sweep shares project symbol
diagnostics, and generation checks dispose superseded watcher
registrations.
4. **Prove the editor and emitter agree.** The multi-file fixture
exercises cross-file relations, a namespace reopened across files,
directive exclusion and an invalid mapping attributed only to its owning
file. The existing playground demonstrates the same closed-member
behavior without new UI implementation.
## Behavior changes & evidence
- **Glob-configured schemas become active in the editor.**
[Membership](packages/1-framework/3-tooling/language-server/src/schema-inputs.ts)
and [configuration
resolution](packages/1-framework/3-tooling/language-server/src/config-resolution.ts)
are covered by [membership
tests](packages/1-framework/3-tooling/language-server/test/schema-inputs.test.ts).
- **Never-opened files contribute to cross-file analysis while unsaved
buffers remain authoritative.**
[Store](packages/1-framework/3-tooling/language-server/src/document-store.ts)
and [project
artifacts](packages/1-framework/3-tooling/language-server/src/project-artifacts.ts)
are covered by [store
tests](packages/1-framework/3-tooling/language-server/test/document-store.test.ts)
and [project
tests](packages/1-framework/3-tooling/language-server/test/project-artifacts.test.ts).
- **Editing one file produces or clears errors in a closed sibling.**
[Server publication and
lifecycle](packages/1-framework/3-tooling/language-server/src/server.ts)
are covered by [server
tests](packages/1-framework/3-tooling/language-server/test/server.test.ts)
for cross-file edits, watch/stat freshness, deletion and watcher races,
plus the [browser QA
report](projects/multifile-psl/slices/lsp-whole-project/qa-run.md).
- **The tested multi-file schema produces matching emit and editor
diagnostics.** [Parity
integration](test/integration/test/authoring/lsp-emit-parity.integration.test.ts)
checks the complete normalized diagnostic set and explicit empty results
for unaffected members, alongside successful emission and exclusion
checks.
- **UNC literal inputs preserve their authority.** The [shared
expander](packages/1-framework/3-tooling/config-loader/src/expand-contract-inputs.ts)
has [regression
tests](packages/1-framework/3-tooling/config-loader/test/expand-contract-inputs.test.ts)
for backslash and forward-slash UNC spellings.
## Compatibility / migration / risk
No new config syntax, directive migration or emitted-contract shape
change in this slice. Disk I/O is synchronous and assumes schema-sized
projects. Stat revalidation happens on reads, not by background polling;
same-size edits preserving mtime require watcher invalidation to be
noticed. Glob expansion refreshes on resolution/reload and schema watch
events. Server-side watchers, workspace-wide pull, incremental
symbol-table computation, multi-root support and prisma7 changes are
outside this PR.
## Testing performed
Final reviewed HEAD: `ac3b226579d70147620943a6c83e621c96fdb967`. These
results are carried from the implementation/verification handoff;
packaging did not rerun tests.
Latest-fix gates reported passing:
- `pnpm --config.enable-pre-post-scripts=false --filter
integration-tests test
test/authoring/lsp-emit-parity.integration.test.ts` — 14 tests.
- Integration-tests package typecheck.
- Targeted Biome, `lint:deps`, whitespace scan and commit hooks.
Earlier implementation gates, **not final-HEAD reruns**:
- Language-server tests — 650 tests — plus package typecheck and lint.
- `fixtures:check` and playground typecheck.
- Recorded browser/WebSocket QA — four checks passed before the final
parity-test fix.
Closing review: five slice conditions PASS, no open findings; the real
source-load diagnostic comparison was independently traced. Workspace
typecheck was previously blocked by a Prisma 7 engine-download network
failure and was not rerun; its claimed baseline status was not
independently verified. The LSP probe was inconclusive, not evidence of
a clean workspace; package typecheck passed.
## Skill update
No skill update is required: this completes editor support for the
existing multi-file config and directive contract without adding a new
authoring command or migration recipe. The language-server and
playground READMEs document the changed editor behavior.
## Checklist
- [x] All commits are signed off (`git commit -s`) per the
[DCO](CONTRIBUTING.md#developer-certificate-of-origin-dco); all 11
branch-only commits have author-matching trailers.
- [x] I read [CONTRIBUTING.md](CONTRIBUTING.md) and the change is scoped
to one logical concern.
- [x] Tests are updated.
- [ ] The PR title is in `TML-NNNN: <sentence-case title>` form —
intentionally waived with Linear tracking; the title is descriptive
sentence case without an invented ticket ID.
- [x] The **Skill update** section above is filled in.
## Alternatives considered
- **Analyze only open files:** closed siblings must contribute symbols
and receive cross-file errors, so project analysis reads disk members as
well.
- **Separate overlay and disk maps at each caller:** a single tagged
store centralizes overlay precedence and invalidation.
- **Read every file afresh or add a server-side watcher:** cached
synchronous reads, client watchers and mtime/size revalidation keep the
machinery bounded for schema-sized projects.
- **Make workspace pull the foundation:** client support is uneven; push
serves closed files while the existing open-document pull path remains
intact.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Language-server diagnostics and project symbols cover matching schema
files, including files not open in the editor. Membership updates as
files change, and diagnostics are cleared for files that no longer
qualify.
* Multi-file schema diagnostics align with contract generation,
including cross-file references and source locations.
* **Bug Fixes**
* UNC paths are preserved when processing contract inputs.
* Schema-file URIs are normalized consistently, and cached disk content
is refreshed when files change.
* **Documentation**
* Updated language-server and playground guidance to explain project
membership, diagnostics, and how to check unopened files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Steven McClankerton <tatarintsev@prisma.io>
Co-authored-by: Steven McClankerton <tatarintsev@prisma.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>