@happyvertical/smrt-core 0.57.16 → 0.57.18

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.
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-core",
5
- "packageVersion": "0.57.16",
5
+ "packageVersion": "0.57.18",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-core:SmrtClass": {
8
8
  "name": "smrtclass",
@@ -40,6 +40,7 @@ async function generateManifest() {
40
40
  'src/**/*.test.ts',
41
41
  'src/**/*.spec.ts',
42
42
  'src/**/__tests__/**/*.ts',
43
+ 'src/**/__test-*/**', // Temporary test projects are never package models (#4190)
43
44
  'src/**/*.d.ts',
44
45
  'src/scanner/**/*.ts',
45
46
  'src/vite-plugin/**/*.ts',
@@ -14,6 +14,7 @@
14
14
  import { execFileSync } from 'node:child_process';
15
15
  import { existsSync } from 'node:fs';
16
16
  import { resolve } from 'node:path';
17
+ import { verifyProductionManifest } from './verify-production-manifest.js';
17
18
 
18
19
  function run(script) {
19
20
  execFileSync('npm', ['run', script], {
@@ -47,3 +48,6 @@ if (runningInCi && hasReusableBuildArtifacts()) {
47
48
  }
48
49
  run('build:fresh');
49
50
  }
51
+
52
+ // Validate both newly generated and reused CI artifacts before packaging.
53
+ verifyProductionManifest(resolve('dist/manifest.json'));
@@ -0,0 +1,25 @@
1
+ import { readFileSync } from 'node:fs';
2
+
3
+ /** Reject test authority even when prepack reuses an earlier CI build. */
4
+ export function verifyProductionManifest(manifestPath) {
5
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
6
+ if (
7
+ manifest.artifactPurpose === 'test' ||
8
+ !manifest.objects ||
9
+ typeof manifest.objects !== 'object' ||
10
+ Array.isArray(manifest.objects)
11
+ ) {
12
+ throw new Error(`Invalid production manifest: ${manifestPath}`);
13
+ }
14
+ for (const [identity, object] of Object.entries(manifest.objects)) {
15
+ const path = String(object.filePath ?? '').replaceAll('\\', '/');
16
+ if (
17
+ /(?:^|\/)(?:__tests__|__test-[^/]+)(?:\/|$)/.test(path) ||
18
+ /\.(?:test|spec)\.[cm]?[jt]sx?$/.test(path)
19
+ ) {
20
+ throw new Error(
21
+ `Test fixture in production manifest: ${identity} (${path})`,
22
+ );
23
+ }
24
+ }
25
+ }
@@ -3,12 +3,12 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-core",
6
- "packageVersion": "0.57.16",
6
+ "packageVersion": "0.57.18",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "a1153e918200a168c2f2eba805fdc0ffcc7fb0d14e4d789eaf660d2eb40149fd",
11
- "packageJson": "cbe4ad68c893bb6d289a87b49fff0c98e90294e807b8cdc9ae53c16ab01eed07",
10
+ "manifest": "a965c8c744f97ca30451c73ac7f4fca5a64805db17e154c612cc37d8a6a1b265",
11
+ "packageJson": "77b04926cc881d684a07576ebcff7f378240b22d9762a0ab00873c360e014097",
12
12
  "agents": "3a78a0babd2884ac22e4b376a3c9618037ab818ad4bdd762751f82fa53c21d04",
13
13
  "moduleDoc:agents/object-runtime.md": "fd2748649e820c2fe5960fa4a44c5f3e2a5afa57da89925e8b4cb3b53d67a07b",
14
14
  "moduleDoc:agents/revision-guard.md": "f6ea32a6860964c98aba14b93587f40b33c8f7d0deccb2c54d21bff45db3da42",
@@ -19,7 +19,7 @@
19
19
  "moduleDoc:agents/change-feed.md": "c3d6206758dd1d2e0475177e1938fb7d7b6cfe8a6c4d3c3b56ef62bc7bc7739d",
20
20
  "moduleDoc:agents/change-signals.md": "a2dbe7077483b5a19bd5ea9589b5a08fe847377c8e05d01d57f813c6d9cbc28b",
21
21
  "moduleDoc:agents/generators.md": "6eecf5c639bac7c88d7b72456f16d84dd9b69bebac76464e9329b4775c54906f",
22
- "moduleDoc:agents/build-knowledge.md": "ebf431321e0014f24df4e8b8b6f3cfc4e38626e40d5e1e37cebe802766d97964",
22
+ "moduleDoc:agents/build-knowledge.md": "b8bed0288c2fd4b525f3bc92baae1c629af02124a13fca0063d3c98ae56045b1",
23
23
  "moduleDoc:agents/memory.md": "a86bdf370403d08ecad3be86e341eb322dfe6e6b7a4e8806a6f8be9bf3421da5",
24
24
  "moduleDoc:agents/system-diagnostics.md": "b7ccae18ee312bf788d5470f95fa78d3535f1789247d5372e40ca86538290772",
25
25
  "moduleDoc:agents/registry-snapshot.md": "6234aa540427396d1dda1825a4641b1072e247187d5ddf413ae46c691344ee30",
@@ -97,6 +97,7 @@
97
97
  "@types/pluralize": "^0.0.33",
98
98
  "@xenova/transformers": "^2.17.2",
99
99
  "ajv": "8.20.0",
100
+ "reflect-metadata": "0.2.2",
100
101
  "svelte": "^5.57.1",
101
102
  "svelte-check": "^4.7.6",
102
103
  "typescript": "6.0.3",
@@ -1197,7 +1198,7 @@
1197
1198
  {
1198
1199
  "path": "agents/build-knowledge.md",
1199
1200
  "module": "build-knowledge",
1200
- "content": "# Decorators, build integration, and knowledge\n\nKey options: `tableName`, `tableStrategy` ('cti'|'sti'), `conflictColumns`, `indexes` (declared multi-column indexes; see [schema-paths.md](schema-paths.md)), `api`/`mcp`/`cli` (generation config), `ai` (callable methods), `hooks` (beforeSave/afterSave/beforeDelete/afterDelete), `embeddings` (auto-generate), `tenantScoped`, `agent`, `ui` (`{ icon, label, description }` — nav/help hints round-tripped through the manifest as plain data; `description` is the object-level seed for form-level help, #2046).\n\nRegistration sets `SMRT_TABLE_NAME` static property (survives minification).\n\nAn explicit `@smrt({ collection: 'domain.records' })` names the route/permission\nnamespace independently of `tableName`, including standalone non-STI models.\nScanner output preserves it in both `collection` and `decoratorConfig.collection`.\nGenerated registration reads the merged declaration, so older manifests with a\nderived top-level collection still agree with native decorators. Explicit runtime\nregistration options win; absent declarations retain manifest/STI/default naming.\n\n## @field() UI hints (#2046)\n\n`@field({ ui: { basic, group, order, locked } })` — a static, presentation-only\nseed for the field-policy rail (epic #2045). Carried in the manifest under the\nfield's `_meta.ui` (never a top-level `FieldDefinition` key), readable at\nruntime via `getAllFields()` at `field._meta.ui`, and emitted (sanitized) with\n`description` into generated web-collection definitions and browser MCP tool\nschemas. No schema/persistence/security effect — `sensitive`/`readPermission`\nstay the security rail, and `sensitive`/`transient` fields never emit to the\nclient at all.\n\n`ui.widget` (#3599) adds a presentation widget hint:\n`'textarea' | 'currency' | 'email' | 'url' | 'phone'`. It rides the same\n`_meta.ui` channel and is also emitted (sanitized) into web-collection\ndefinitions. The manifest generator validates it against the field type and\nfails the build otherwise: every widget needs a `text` field (`currency` is a\ncurrency-CODE picker for an ISO 4217 string such as `currency = 'USD'`, not a\nmoney amount; amounts are integer minor units and take no widget); an unknown\nvalue or a non-text field is an error. `ui.widget` is a hint only — it never changes\nthe column type or validation.\n\n`ui.format` (#3718) says how a value is presented: `money` (an `integer` of\nminor units — the amount hint record pages format and total), `date` (a\nbusiness date on a `datetime`, shown without a time), `datetime`, `percent`\n(a rate on a `decimal`/`integer`). Same channel, same emission, same build-time\ncheck against the field type. `@foreignKey(Target, { role: 'items' })` (or on\n`@crossPackageRef`) marks the declaring model as the target's line items; the\nscanner keeps it at `_meta.role`, the build rejects it on a non-reference or\nan unknown value, and the generated web relationship edge carries\n`role: 'items'` (edges without a role stay byte-stable). Both are hints: no\nschema, persistence or security effect.\n\n## Presentation metadata (#3599)\n\nPure helpers live in `src/ui-metadata.ts`, published browser-safe as\n`@happyvertical/smrt-core/ui-metadata` (also re-exported from the package\nroot). `ManifestGenerator.applyUiMetadata()` runs in `applyGenerationPasses`\nafter inheritance, so every producer (Vite plugin, `ManifestBuilder`,\n`generateManifest`) validates the same way.\n\n- **Display label.** `@smrt({ display: { label: '<field>' } })` names the own\n field generic pickers and assistants use to label a record. Own fields only —\n no paths into other packages; a model whose label lives elsewhere ships a\n selector. Undeclared, it defaults to the first of `name`, `title`, `label`,\n `code` that is a usable own field. Build fails when the declared field is\n missing, `sensitive`, `transient`, or a relationship/json field. The resolved\n field is emitted as `displayLabelField` on the manifest object and in the\n knowledge artifact, and generated MCP/WebMCP `list`/`get`/`update`/`delete`\n descriptions end with ``Records are identified by their `<field>` field.``\n (`describeAction` in `generators/tool-schema.ts`; nothing is added when the\n model has no label field).\n- **Selector slots.** `ModuleUISlot.selects: '@scope/pkg:Model'`\n (`@happyvertical/smrt-types`) marks a package component as THE selector for a\n model. The scanner reads such slots statically from `src/**/ui.ts`\n (`parseUiSelectorsFile`, independent of the class glob) and the manifest\n carries them as `uiSelectors` keyed by slot id. `selects` must be a string\n literal; a duplicate slot id, two selectors for one model, or an own-package\n target that does not exist fails the build. Hosts call\n `findSelectorFor(manifests, qualifiedName)`; generic forms use the selector\n for any `@foreignKey`/`@crossPackageRef` field targeting that model and fall\n back to a generic picker labelled by `displayLabelField`. `display` is read\n per class: an STI subclass that declares none uses the default lookup rather\n than its base's declaration, and a CTI child cannot name a parent's field.\n\n## Worker registration artifact (#3117)\n\nWith `svelteKit.enabled`, a production `vite build` compiles the generated\n`smrt-register.ts` into `.smrt/runtime/register.js` after the server build\n(`src/vite-plugin/worker-registration.ts`, called once from `closeBundle`).\nadapter-node re-bundles the server from its own entries, so the web bundle is\nnever importable by a separate Node process; this artifact is how a deployed\ntask/schedule worker registers the app's local objects (and, through the\n`.smrt/register.js` it imports, consumed packages' objects) with the same\nqualified identities and isolated manifests as the web server. It is a nested\nSSR build with no consumer plugins: only aliases pointing into the project\nsources (e.g. `$lib`) apply, and bare imports stay external so the worker\nshares the installed `@happyvertical/smrt-core` registry. The sole exception is\n`@oxc-project/runtime` and its helper subpaths: Vite injects them when lowering\ndecorators, but applications do not declare that compiler support dependency,\nso the artifact bundles them. SvelteKit\nvirtual modules (`$env/*`, `$app/*`) are not available to a worker; an object\nimporting one fails at worker startup. A failure fails the build.\n\n## Lightweight discovery\n\nFilesystem-only discovery, module-doc parsing, and graph freshness are owned by\n`@happyvertical/smrt-scanner/knowledge`. Core's knowledge exports remain compatible\nreexports. Runtime manifest projection and custom-action semantics stay in core.\n\n`src/knowledge-discovery.ts`, exported through `smrt-core/knowledge`, enumerates\ninstalled scope directories and reads canonical AGENTS/legacy CLAUDE docs without\nloading package code, artifacts, or scanning objects. CLI snapshots and MCP share\nthese primitives. Callers retain selection policy: snapshots resolve links and\nfall back to `packages/*` only when no installed SMRT package loads; MCP preserves\nnode_modules paths, deduplicates realpaths, excludes authored workspace links,\nand then enriches the selected packages. Workspace-root/glob discovery remains\nowned by each consumer.\n\n## Domain Knowledge Artifacts\n\n`smrtPlugin()` writes runtime manifests and agent/developer knowledge artifacts:\n\n- local dev/build: `.smrt/manifest.json` and `.smrt/smrt-knowledge.json`\n- package build: `dist/manifest.json` and `dist/smrt-knowledge.json`\n\nKeep `manifest.json` runtime-focused. `smrt-knowledge.json` is the deterministic\nagent contract for downstream review and architecture tools.\n\nThe CLI's schema-command gate reads that same merged file: a pure-consumer\nproject (0 local objects) qualifies on the consumed packages its manifest\nrecords, so a clobbered `objects` map is what made `smrt db:migrate` report\n`missing_local_manifest` (#2925).\n\n`.smrt/manifest.json` has two writers and neither owns all of it: `smrtPlugin()`\ncontributes the project's scanned objects and `smrtConsumer()` the consumed\npackages' entries. Both writes are merge-preserving, keyed on each entry's\nrecorded `packageName` — a plain overwrite in either direction silently drops\nthe other's objects, and the last pass of a multi-environment build is not\nreliably the aggregating one (#1760, #2925). `dist/manifest.json` stays\nlocal-only: a published package must not carry its dependencies' objects.\n\nThe schema-version-1 object projection is additive and high-signal: it retains\nnormalized tenant mode/field, explicit `cti`/`sti` strategy, conflict columns,\nmethod signatures, and field defaults/constraints/readonly/transient flags.\nSensitive fields are removed before both `fields` and `relationships` are\nderived, including legacy flags stored under `_meta`; matching field and\nsnake-case column names are also removed from projected conflict columns, and a\nsensitive custom tenant field is omitted while retaining scope and mode.\nGenerated artifacts assert this boundary with `sensitiveFieldsExcluded: true`;\nthe optional marker keeps schema version 1 additive while letting readers\nidentify older artifacts that require raw-manifest corroboration.\n\nConfig precedence for knowledge is defaults → top-level `knowledge` in\n`smrt.config.ts` → `packages[packageName].knowledge` → plugin option →\nobject-level `@smrt({ knowledge })`.\n\nTest generation uses that same effective configuration and publishes knowledge\nmatching the manifest it generated. Disabling knowledge removes a previous local\nknowledge artifact, so consumers cannot mistake it for current enabled output.\n`new ManifestBuilder(projectRoot)` keeps discovery, package identity, and output\nat that explicit root, including installed providers and external base classes;\nomitting the argument retains the current-working-directory\nbehavior. Both manifest writers retain declared package dependencies when merging\ntheir local and consumed-object projections.\n\nTest manifests carry optional `artifactPurpose: 'test'`; dependency discovery\nskips those artifacts, including `.smrt` fallbacks. Unmarked runtime manifests,\nempty published providers, and source-only development providers remain eligible.\n`ManifestBuilder` accepts explicit `outputMode: 'dev' | 'build'`; omitted mode\nretains legacy filename inference. Vitest selects dev mode explicitly, so tests\nnever replace a production `dist/manifest.json`. Relative output directories are\nresolved against the builder's project root.\n\nWith `svelteKit.enabled`, `smrtPlugin()`'s transform prepends\n`import './smrt-register.js';` to the configured config module\n(`<configPath>/<configFileName>`, `src/vite-plugin/sveltekit-register-injection.ts`)\nonce the register module exists, on the same first line so line numbers hold.\nApps therefore never hand-write the guarded registration import (#3416); a\nconfig module that still has it imports the same module twice, harmlessly.\n\nTracked `src/lib/server/smrt-register.ts` belongs to SvelteKit config/type\ngeneration. Generic library builds consume it but do not cache or restore it\nas an output; otherwise a concurrent config producer's bytes can be replayed\nover a newer registration after dependency eligibility changes.\n\nObject-level `knowledge: false` excludes an object from authored context only;\nit must not change runtime manifest registration. Use\n`knowledge: { tags, summary, risks }` for review-sensitive domain objects.\n\nHTTP knowledge routes are disabled by default. If `knowledge.api.enabled` is\ntrue, generated SvelteKit routes must stay GET-only and guarded by dev mode or\nadmin auth.\n\n\n## Vite Plugin\n\n`src/vite-preset/` (`@happyvertical/smrt-core/vite`, `smrt()`) composes the Oxc\ndecorator block, `smrtConsumer`, then `smrtPlugin` with the template path\nconventions. Its package list comes only from the `smrt({ packages })` option, or\n`smrt.config` `consumer.packages` (smrt-config schema); it never sniffs\n`package.json`, and a missing or malformed list throws. Keep its output\nbyte-identical to the two-plugin form (`src/vite-preset/index.test.ts`). It\nalso dedupes `@sveltejs/kit` (`smrt:shared-runtime`): SvelteKit matches\n`redirect()`/`fail()` by class, and a linked/workspace SMRT SvelteKit entry\nwould otherwise import its own copy and turn redirects into 500s. The preset\nalso keeps the thin `@happyvertical/smrt-app-runtime/sveltekit` entry inside\nthe SSR bundle: adapter-node bundles Kit itself, and an external runtime\nwould load a separate class through Node even at the same installed version.\nVite matches `ssr.noExternal` by package name, so a pre-resolver keeps the\nexact runtime root external and `ssr.external` keeps `./sveltekit-runtime`\nexternal. That implementation subpath is an internal composition boundary;\napps keep importing `./sveltekit`. This avoids bundling native SQL dependencies.\nThis split applies only to builds; development keeps normal SSR externalization\nand Kit dedupe because Vite's dev module runner ignores resolver external flags.\nOther runtime dependencies retain their normal externalization. Do not explicitly\nexternalize app-runtime in an app config. The production regression in\n`packages/app-runtime/src/sveltekit-production.test.ts` exercises the final\nadapter-node HTTP handler using an installed copy of the published dist entry.\n\n**Package models over REST (#3749).** `consumer.packages` registers a package's\nmodels and gives `@smrt/web` (the consumer's `collectionDefinitions`, one per\nlist-capable model, endpoint `/<collection>`) their definitions, but a package\nmodel gets generated REST routes only when it is on the consumer's hosting\nallowlist (`smrtConsumer({ svelteKit: { objects } })`, #2850: an HTTP exposure\nboundary, each model's own `api` config still applies, so `api: false` and\nempty-include models stay closed, tenancy comes with the generated route). The\npreset fills that allowlist: with `smrt.cookbook.json` present it is the models\nof the cookbook's recipes plus `features`, minus models the cookbook `exposure`\nturns off for `api` or a recipe's `options[model].exposure.api === false`\n(`vite-preset/cookbook-exposure.ts`; recipe `{ exclude }` narrowing is not\napplied by the build yet). `smrt({ expose })` replaces the derived list. No\ncookbook and no `expose` keeps `svelteKit: true` (nothing hosted). The producer's\n`@happyvertical/smrt-virt-web` still covers only the app's own models; read\npackage models from `@smrt/web`. `smrt({ objectsDir })` is passed to the hosting\ncontribution too: the producer and consumer share one `routesDir`, and the\ngenerator refuses it when their settings differ.\n\n**STI siblings (#3749).** Package STI subclasses share their base's table, and\nthe manifest gives them the base's `collection` unless they declare one\n(`consumer-plugin/hosted-sti-collections.ts`). Two hosted siblings would both\nclaim `/<base collection>`, so each hosted subclass that inherits its\ncollection gets its class-derived one (`Order` -> `orders`,\n`defaultCollectionName` in the scanner), in every manifest view the consumer\nderives: routes, `@smrt/web`, the generated client and registration. This is the\nconvention the framework already has for an independent route collection\n(`@smrt({ collection })`), applied by default for hosted subclasses; an explicit\ncollection wins. The route therefore reads through the subclass's own\ncollection (rows scoped to its `_meta_type`) and the definition for that model\nadvertises that route (`objectRef` = the model, `endpoint` = `/orders`). A hosted\nbase keeps the shared name and the base-collection semantics (every row of the\ntable, any subtype). A subclass left off the allowlist keeps the shared\ncollection and folds into the base's definition, as before. A collection class\nthat inherits another's item type (`MaterialCollection extends\nProductCollection`) resolves to the same item and collection, so only one of\nthem is hosted (the class named for the item, else the first). Subclasses that\ndeclare no `api` config get the omitted-config default (full CRUD), not the\nbase's `include`; narrow them on the subclass if the base is meant to restrict\nthem.\n\n```typescript\n// vite.config.ts — required for @smrt() decorators (Vite 8+, oxc transform)\nexport default defineConfig({\n oxc: {\n decorator: {\n legacy: true,\n emitDecoratorMetadata: true,\n },\n },\n});\n```\n\nUnder Vite 8 the oxc transform does not honor the pre-Vite-8 `esbuild.tsconfigRaw`\nrecipe (or tsconfig `experimentalDecorators` reached through SvelteKit's\n`extends \"./.svelte-kit/tsconfig.json\"` chain), so that recipe throws\n`SyntaxError: Invalid or unexpected token` on the first SSR request. Configure\ndecorators through `oxc.decorator` instead. Consumers still pinned on vite<8 need\nthe legacy `esbuild.tsconfigRaw` form with `experimentalDecorators: true,\nemitDecoratorMetadata: true`.\n\nFor independent CI invocations, both `smrtPlugin()` and `smrtConsumer()` accept\nthe same `generationSnapshot: { path, sha256, provenance, sourceRoot }`. The\nschema-v1 snapshot produced by `serializeSmrtGenerationSnapshot()` contains the\nmerged project/dependency manifest, portable source paths, and source-file\ndigests; each plugin selects its own view. Reuse mode fails closed on\nbyte/provenance/path/content drift, skips scans and manifest writes, and still\ngenerates routes, types, registration, and virtual modules. Omit it for normal\nlocal development and watch mode.\n\n## Clean consumer type checks (TypeScript 6)\n\nThe consumer config hook writes `.smrt/register.js` alongside generated types\nafter route preflight succeeds. Generated SvelteKit registration imports that\nmodule, so it must exist during `svelte-kit sync`, before Vite's `buildStart`.\nBoth hosted routes and the legacy `svelteKit: true` mode follow this order.\nThe clean-consumer regression fixture ships real provider declarations and\nchecks the generated imports with `svelte-check`.\nCore's `generate:test` task depends on its own `build`: both publish the local\n`.smrt` manifest/knowledge pair, so Turbo must serialize production before test\ngeneration instead of caching an interleaved pair.\n\n## Model descriptions\n\nEach manifest object and knowledge `objects[]` entry may carry a user-facing\n`description` (for the planner Features tab and similar). The scanner\n(`extractClassJsDocDescription` in `packages/scanner/src/oxc-parser.ts`) reads it\nfrom the parsed source, in priority order: explicit `@smrt({ description })`,\nelse the first paragraph of the class JSDoc (the JSDoc may sit above `export`\nand decorators), minus a leading `ClassName - ` / `ClassName: `, tags\n(`{@link}`, backticks, HTML) and later paragraphs, capped at 200 chars on a\nsentence boundary. `@internal` classes and classes without docs emit no key. It\nis not inherited from a parent class. Generated MCP tool descriptions are\nunchanged (they stay generic).\n"
1201
+ "content": "# Decorators, build integration, and knowledge\n\nKey options: `tableName`, `tableStrategy` ('cti'|'sti'), `conflictColumns`, `indexes` (declared multi-column indexes; see [schema-paths.md](schema-paths.md)), `api`/`mcp`/`cli` (generation config), `ai` (callable methods), `hooks` (beforeSave/afterSave/beforeDelete/afterDelete), `embeddings` (auto-generate), `tenantScoped`, `agent`, `ui` (`{ icon, label, description }` — nav/help hints round-tripped through the manifest as plain data; `description` is the object-level seed for form-level help, #2046).\n\nRegistration sets `SMRT_TABLE_NAME` static property (survives minification).\n\nAn explicit `@smrt({ collection: 'domain.records' })` names the route/permission\nnamespace independently of `tableName`, including standalone non-STI models.\nScanner output preserves it in both `collection` and `decoratorConfig.collection`.\nGenerated registration reads the merged declaration, so older manifests with a\nderived top-level collection still agree with native decorators. Explicit runtime\nregistration options win; absent declarations retain manifest/STI/default naming.\n\n## @field() UI hints (#2046)\n\n`@field({ ui: { basic, group, order, locked } })` — a static, presentation-only\nseed for the field-policy rail (epic #2045). Carried in the manifest under the\nfield's `_meta.ui` (never a top-level `FieldDefinition` key), readable at\nruntime via `getAllFields()` at `field._meta.ui`, and emitted (sanitized) with\n`description` into generated web-collection definitions and browser MCP tool\nschemas. No schema/persistence/security effect — `sensitive`/`readPermission`\nstay the security rail, and `sensitive`/`transient` fields never emit to the\nclient at all.\n\n`ui.widget` (#3599) adds a presentation widget hint:\n`'textarea' | 'currency' | 'email' | 'url' | 'phone'`. It rides the same\n`_meta.ui` channel and is also emitted (sanitized) into web-collection\ndefinitions. The manifest generator validates it against the field type and\nfails the build otherwise: every widget needs a `text` field (`currency` is a\ncurrency-CODE picker for an ISO 4217 string such as `currency = 'USD'`, not a\nmoney amount; amounts are integer minor units and take no widget); an unknown\nvalue or a non-text field is an error. `ui.widget` is a hint only — it never changes\nthe column type or validation.\n\n`ui.format` (#3718) says how a value is presented: `money` (an `integer` of\nminor units — the amount hint record pages format and total), `date` (a\nbusiness date on a `datetime`, shown without a time), `datetime`, `percent`\n(a rate on a `decimal`/`integer`). Same channel, same emission, same build-time\ncheck against the field type. `@foreignKey(Target, { role: 'items' })` (or on\n`@crossPackageRef`) marks the declaring model as the target's line items; the\nscanner keeps it at `_meta.role`, the build rejects it on a non-reference or\nan unknown value, and the generated web relationship edge carries\n`role: 'items'` (edges without a role stay byte-stable). Both are hints: no\nschema, persistence or security effect.\n\n## Presentation metadata (#3599)\n\nPure helpers live in `src/ui-metadata.ts`, published browser-safe as\n`@happyvertical/smrt-core/ui-metadata` (also re-exported from the package\nroot). `ManifestGenerator.applyUiMetadata()` runs in `applyGenerationPasses`\nafter inheritance, so every producer (Vite plugin, `ManifestBuilder`,\n`generateManifest`) validates the same way.\n\n- **Display label.** `@smrt({ display: { label: '<field>' } })` names the own\n field generic pickers and assistants use to label a record. Own fields only —\n no paths into other packages; a model whose label lives elsewhere ships a\n selector. Undeclared, it defaults to the first of `name`, `title`, `label`,\n `code` that is a usable own field. Build fails when the declared field is\n missing, `sensitive`, `transient`, or a relationship/json field. The resolved\n field is emitted as `displayLabelField` on the manifest object and in the\n knowledge artifact, and generated MCP/WebMCP `list`/`get`/`update`/`delete`\n descriptions end with ``Records are identified by their `<field>` field.``\n (`describeAction` in `generators/tool-schema.ts`; nothing is added when the\n model has no label field).\n- **Selector slots.** `ModuleUISlot.selects: '@scope/pkg:Model'`\n (`@happyvertical/smrt-types`) marks a package component as THE selector for a\n model. The scanner reads such slots statically from `src/**/ui.ts`\n (`parseUiSelectorsFile`, independent of the class glob) and the manifest\n carries them as `uiSelectors` keyed by slot id. `selects` must be a string\n literal; a duplicate slot id, two selectors for one model, or an own-package\n target that does not exist fails the build. Hosts call\n `findSelectorFor(manifests, qualifiedName)`; generic forms use the selector\n for any `@foreignKey`/`@crossPackageRef` field targeting that model and fall\n back to a generic picker labelled by `displayLabelField`. `display` is read\n per class: an STI subclass that declares none uses the default lookup rather\n than its base's declaration, and a CTI child cannot name a parent's field.\n\n## Worker registration artifact (#3117)\n\nWith `svelteKit.enabled`, a production `vite build` compiles the generated\n`smrt-register.ts` into `.smrt/runtime/register.js` after the server build\n(`src/vite-plugin/worker-registration.ts`, called once from `closeBundle`).\nadapter-node re-bundles the server from its own entries, so the web bundle is\nnever importable by a separate Node process; this artifact is how a deployed\ntask/schedule worker registers the app's local objects (and, through the\n`.smrt/register.js` it imports, consumed packages' objects) with the same\nqualified identities and isolated manifests as the web server. It is a nested\nSSR build with no consumer plugins: only aliases pointing into the project\nsources (e.g. `$lib`) apply, and bare imports stay external so the worker\nshares the installed `@happyvertical/smrt-core` registry. The sole exception is\n`@oxc-project/runtime` and its helper subpaths: Vite injects them when lowering\ndecorators, but applications do not declare that compiler support dependency,\nso the artifact bundles them. SvelteKit\nvirtual modules (`$env/*`, `$app/*`) are not available to a worker; an object\nimporting one fails at worker startup. A failure fails the build.\n\n## Lightweight discovery\n\nFilesystem-only discovery, module-doc parsing, and graph freshness are owned by\n`@happyvertical/smrt-scanner/knowledge`. Core's knowledge exports remain compatible\nreexports. Runtime manifest projection and custom-action semantics stay in core.\n\n`src/knowledge-discovery.ts`, exported through `smrt-core/knowledge`, enumerates\ninstalled scope directories and reads canonical AGENTS/legacy CLAUDE docs without\nloading package code, artifacts, or scanning objects. CLI snapshots and MCP share\nthese primitives. Callers retain selection policy: snapshots resolve links and\nfall back to `packages/*` only when no installed SMRT package loads; MCP preserves\nnode_modules paths, deduplicates realpaths, excludes authored workspace links,\nand then enriches the selected packages. Workspace-root/glob discovery remains\nowned by each consumer.\n\n## Domain Knowledge Artifacts\n\n`smrtPlugin()` writes runtime manifests and agent/developer knowledge artifacts:\n\n- local dev/build: `.smrt/manifest.json` and `.smrt/smrt-knowledge.json`\n- package build: `dist/manifest.json` and `dist/smrt-knowledge.json`\n\nKeep `manifest.json` runtime-focused. `smrt-knowledge.json` is the deterministic\nagent contract for downstream review and architecture tools.\n\nThe CLI's schema-command gate reads that same merged file: a pure-consumer\nproject (0 local objects) qualifies on the consumed packages its manifest\nrecords, so a clobbered `objects` map is what made `smrt db:migrate` report\n`missing_local_manifest` (#2925).\n\n`.smrt/manifest.json` has two writers and neither owns all of it: `smrtPlugin()`\ncontributes the project's scanned objects and `smrtConsumer()` the consumed\npackages' entries. Both writes are merge-preserving, keyed on each entry's\nrecorded `packageName` — a plain overwrite in either direction silently drops\nthe other's objects, and the last pass of a multi-environment build is not\nreliably the aggregating one (#1760, #2925). `dist/manifest.json` stays\nlocal-only: a published package must not carry its dependencies' objects.\nCore's canonical generator excludes temporary `__test-*` source roots as well\nas test files and `__tests__`; prepack verifies fresh and reused manifests\ncontain no test-artifact marker or fixture source provenance (#4190).\n\nThe schema-version-1 object projection is additive and high-signal: it retains\nnormalized tenant mode/field, explicit `cti`/`sti` strategy, conflict columns,\nmethod signatures, and field defaults/constraints/readonly/transient flags.\nSensitive fields are removed before both `fields` and `relationships` are\nderived, including legacy flags stored under `_meta`; matching field and\nsnake-case column names are also removed from projected conflict columns, and a\nsensitive custom tenant field is omitted while retaining scope and mode.\nGenerated artifacts assert this boundary with `sensitiveFieldsExcluded: true`;\nthe optional marker keeps schema version 1 additive while letting readers\nidentify older artifacts that require raw-manifest corroboration.\n\nConfig precedence for knowledge is defaults → top-level `knowledge` in\n`smrt.config.ts` → `packages[packageName].knowledge` → plugin option →\nobject-level `@smrt({ knowledge })`.\n\nTest generation uses that same effective configuration and publishes knowledge\nmatching the manifest it generated. Disabling knowledge removes a previous local\nknowledge artifact, so consumers cannot mistake it for current enabled output.\n`new ManifestBuilder(projectRoot)` keeps discovery, package identity, and output\nat that explicit root, including installed providers and external base classes;\nomitting the argument retains the current-working-directory\nbehavior. Both manifest writers retain declared package dependencies when merging\ntheir local and consumed-object projections.\n\nTest manifests carry optional `artifactPurpose: 'test'`; dependency discovery\nskips those artifacts, including `.smrt` fallbacks. Unmarked runtime manifests,\nempty published providers, and source-only development providers remain eligible.\n`ManifestBuilder` accepts explicit `outputMode: 'dev' | 'build'`; omitted mode\nretains legacy filename inference. Vitest selects dev mode explicitly, so tests\nnever replace a production `dist/manifest.json`. Relative output directories are\nresolved against the builder's project root.\n\nWith `svelteKit.enabled`, `smrtPlugin()`'s transform prepends\n`import './smrt-register.js';` to the configured config module\n(`<configPath>/<configFileName>`, `src/vite-plugin/sveltekit-register-injection.ts`)\nonce the register module exists, on the same first line so line numbers hold.\nApps therefore never hand-write the guarded registration import (#3416); a\nconfig module that still has it imports the same module twice, harmlessly.\n\nTracked `src/lib/server/smrt-register.ts` belongs to SvelteKit config/type\ngeneration. Generic library builds consume it but do not cache or restore it\nas an output; otherwise a concurrent config producer's bytes can be replayed\nover a newer registration after dependency eligibility changes.\n\nObject-level `knowledge: false` excludes an object from authored context only;\nit must not change runtime manifest registration. Use\n`knowledge: { tags, summary, risks }` for review-sensitive domain objects.\n\nHTTP knowledge routes are disabled by default. If `knowledge.api.enabled` is\ntrue, generated SvelteKit routes must stay GET-only and guarded by dev mode or\nadmin auth.\n\n\n## Vite Plugin\n\n`src/vite-preset/` (`@happyvertical/smrt-core/vite`, `smrt()`) composes the Oxc\ndecorator block, `smrtConsumer`, then `smrtPlugin` with the template path\nconventions. Its package list comes only from the `smrt({ packages })` option, or\n`smrt.config` `consumer.packages` (smrt-config schema); it never sniffs\n`package.json`, and a missing or malformed list throws. Keep its output\nbyte-identical to the two-plugin form (`src/vite-preset/index.test.ts`). It\nalso dedupes `@sveltejs/kit` (`smrt:shared-runtime`): SvelteKit matches\n`redirect()`/`fail()` by class, and a linked/workspace SMRT SvelteKit entry\nwould otherwise import its own copy and turn redirects into 500s. The preset\nalso keeps the thin `@happyvertical/smrt-app-runtime/sveltekit` entry inside\nthe SSR bundle: adapter-node bundles Kit itself, and an external runtime\nwould load a separate class through Node even at the same installed version.\nVite matches `ssr.noExternal` by package name, so a pre-resolver keeps the\nexact runtime root external and `ssr.external` keeps `./sveltekit-runtime`\nexternal. That implementation subpath is an internal composition boundary;\napps keep importing `./sveltekit`. This avoids bundling native SQL dependencies.\nThis split applies only to builds; development keeps normal SSR externalization\nand Kit dedupe because Vite's dev module runner ignores resolver external flags.\nOther runtime dependencies retain their normal externalization. Do not explicitly\nexternalize app-runtime in an app config. The production regression in\n`packages/app-runtime/src/sveltekit-production.test.ts` exercises the final\nadapter-node HTTP handler using an installed copy of the published dist entry.\n\n**Package models over REST (#3749).** `consumer.packages` registers a package's\nmodels and gives `@smrt/web` (the consumer's `collectionDefinitions`, one per\nlist-capable model, endpoint `/<collection>`) their definitions, but a package\nmodel gets generated REST routes only when it is on the consumer's hosting\nallowlist (`smrtConsumer({ svelteKit: { objects } })`, #2850: an HTTP exposure\nboundary, each model's own `api` config still applies, so `api: false` and\nempty-include models stay closed, tenancy comes with the generated route). The\npreset fills that allowlist: with `smrt.cookbook.json` present it is the models\nof the cookbook's recipes plus `features`, minus models the cookbook `exposure`\nturns off for `api` or a recipe's `options[model].exposure.api === false`\n(`vite-preset/cookbook-exposure.ts`; recipe `{ exclude }` narrowing is not\napplied by the build yet). `smrt({ expose })` replaces the derived list. No\ncookbook and no `expose` keeps `svelteKit: true` (nothing hosted). The producer's\n`@happyvertical/smrt-virt-web` still covers only the app's own models; read\npackage models from `@smrt/web`. `smrt({ objectsDir })` is passed to the hosting\ncontribution too: the producer and consumer share one `routesDir`, and the\ngenerator refuses it when their settings differ.\n\n**STI siblings (#3749).** Package STI subclasses share their base's table, and\nthe manifest gives them the base's `collection` unless they declare one\n(`consumer-plugin/hosted-sti-collections.ts`). Two hosted siblings would both\nclaim `/<base collection>`, so each hosted subclass that inherits its\ncollection gets its class-derived one (`Order` -> `orders`,\n`defaultCollectionName` in the scanner), in every manifest view the consumer\nderives: routes, `@smrt/web`, the generated client and registration. This is the\nconvention the framework already has for an independent route collection\n(`@smrt({ collection })`), applied by default for hosted subclasses; an explicit\ncollection wins. The route therefore reads through the subclass's own\ncollection (rows scoped to its `_meta_type`) and the definition for that model\nadvertises that route (`objectRef` = the model, `endpoint` = `/orders`). A hosted\nbase keeps the shared name and the base-collection semantics (every row of the\ntable, any subtype). A subclass left off the allowlist keeps the shared\ncollection and folds into the base's definition, as before. A collection class\nthat inherits another's item type (`MaterialCollection extends\nProductCollection`) resolves to the same item and collection, so only one of\nthem is hosted (the class named for the item, else the first). Subclasses that\ndeclare no `api` config get the omitted-config default (full CRUD), not the\nbase's `include`; narrow them on the subclass if the base is meant to restrict\nthem.\n\n```typescript\n// vite.config.ts — required for @smrt() decorators (Vite 8+, oxc transform)\nexport default defineConfig({\n oxc: {\n decorator: {\n legacy: true,\n emitDecoratorMetadata: true,\n },\n },\n});\n```\n\nUnder Vite 8 the oxc transform does not honor the pre-Vite-8 `esbuild.tsconfigRaw`\nrecipe (or tsconfig `experimentalDecorators` reached through SvelteKit's\n`extends \"./.svelte-kit/tsconfig.json\"` chain), so that recipe throws\n`SyntaxError: Invalid or unexpected token` on the first SSR request. Configure\ndecorators through `oxc.decorator` instead. Consumers still pinned on vite<8 need\nthe legacy `esbuild.tsconfigRaw` form with `experimentalDecorators: true,\nemitDecoratorMetadata: true`.\n\nFor independent CI invocations, both `smrtPlugin()` and `smrtConsumer()` accept\nthe same `generationSnapshot: { path, sha256, provenance, sourceRoot }`. The\nschema-v1 snapshot produced by `serializeSmrtGenerationSnapshot()` contains the\nmerged project/dependency manifest, portable source paths, and source-file\ndigests; each plugin selects its own view. Reuse mode fails closed on\nbyte/provenance/path/content drift, skips scans and manifest writes, and still\ngenerates routes, types, registration, and virtual modules. Omit it for normal\nlocal development and watch mode.\n\n## Clean consumer type checks (TypeScript 6)\n\nThe consumer config hook writes `.smrt/register.js` alongside generated types\nafter route preflight succeeds. Generated SvelteKit registration imports that\nmodule, so it must exist during `svelte-kit sync`, before Vite's `buildStart`.\nBoth hosted routes and the legacy `svelteKit: true` mode follow this order.\nThe clean-consumer regression fixture ships real provider declarations and\nchecks the generated imports with `svelte-check`.\nCore's `generate:test` task depends on its own `build`: both publish the local\n`.smrt` manifest/knowledge pair, so Turbo must serialize production before test\ngeneration instead of caching an interleaved pair.\n\n## Model descriptions\n\nEach manifest object and knowledge `objects[]` entry may carry a user-facing\n`description` (for the planner Features tab and similar). The scanner\n(`extractClassJsDocDescription` in `packages/scanner/src/oxc-parser.ts`) reads it\nfrom the parsed source, in priority order: explicit `@smrt({ description })`,\nelse the first paragraph of the class JSDoc (the JSDoc may sit above `export`\nand decorators), minus a leading `ClassName - ` / `ClassName: `, tags\n(`{@link}`, backticks, HTML) and later paragraphs, capped at 200 chars on a\nsentence boundary. `@internal` classes and classes without docs emit no key. It\nis not inherited from a parent class. Generated MCP tool descriptions are\nunchanged (they stay generic).\n"
1201
1202
  },
1202
1203
  {
1203
1204
  "path": "agents/memory.md",
@@ -1 +1 @@
1
- {"version":3,"file":"stack-frames.d.ts","sourceRoot":"","sources":["../../src/utils/stack-frames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAKvD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYjE;AAYD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnE;AAqDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUzD"}
1
+ {"version":3,"file":"stack-frames.d.ts","sourceRoot":"","sources":["../../src/utils/stack-frames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAKvD,CAAC;AAYF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmBjE;AAYD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnE;AAqDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUzD"}
@@ -35,6 +35,15 @@ var DECORATOR_RUNTIME_PACKAGES = [
35
35
  "tslib"
36
36
  ];
37
37
  /**
38
+ * Plumbing packages matched only as an installed `node_modules/<pkg>/` path.
39
+ * `reflect-metadata` (pulled in by e.g. `@simplewebauthn/server` and tsyringe)
40
+ * defines `Reflect.decorate`, which tsc-style `__decorate` helpers delegate
41
+ * to, so every decorator is then applied FROM its Reflect.js frame. The name
42
+ * is also a plausible directory in an application's own source tree, so the
43
+ * match is anchored to `node_modules` rather than any `/reflect-metadata/`.
44
+ */
45
+ var INSTALLED_ONLY_RUNTIME_PACKAGES = ["reflect-metadata"];
46
+ /**
38
47
  * Whether a file path (normalized to forward slashes) lives inside a
39
48
  * decorator-runtime helper package — i.e. a stack frame introduced by decorator
40
49
  * lowering rather than the module that declares the decorated class.
@@ -47,6 +56,7 @@ var DECORATOR_RUNTIME_PACKAGES = [
47
56
  */
48
57
  function isDecoratorRuntimeFramePath(path) {
49
58
  const lower = path.toLowerCase();
59
+ if (INSTALLED_ONLY_RUNTIME_PACKAGES.some((pkg) => lower.includes(`/node_modules/${pkg}/`))) return true;
50
60
  return DECORATOR_RUNTIME_PACKAGES.some((pkg) => lower.includes(`/${pkg}/`) || lower.includes(`\0${pkg.replace("/", "+")}@`));
51
61
  }
52
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"stack-frames.js","names":[],"sources":["../../src/utils/stack-frames.ts"],"sourcesContent":["/**\n * Decorator-runtime stack-frame detection (#1785).\n *\n * ObjectRegistry attributes a `@smrt()` class to its declaring package by\n * walking the registration call stack for the first frame OUTSIDE smrt-core —\n * the module that applied the decorator. Decorator *lowering* breaks that\n * assumption: the compiler inserts a runtime-helper frame between the `@smrt()`\n * decorator and the consumer module that declares the class.\n *\n * Under Vite 8, oxc's legacy-decorator lowering routes the decorator application\n * through `@oxc-project/runtime`'s helper (e.g.\n * `.../@oxc-project/runtime/src/helpers/esm/applyDecoratedDescriptor.js`), so a\n * naive walk stops at that frame and misattributes the class to\n * `@oxc-project/runtime` instead of the consumer package. `tslib` (tsc's\n * `__decorate`), `@swc/helpers`, and `@babel/runtime` insert the identical kind\n * of frame under their respective toolchains.\n *\n * These are pure plumbing packages — a class is applied THROUGH them, never\n * DECLARED in them — so both stack walks (source-file identity in\n * `registry/shared-state.ts` and package attribution in\n * `manifest/manifest-loader.ts`) skip them and continue to the real declaring\n * module. Kept as a leaf module (no smrt imports) so both walkers can share it\n * without risking an import cycle.\n */\n\n/**\n * Runtime-helper packages that decorator lowering routes the decorator\n * application through. Frames from these packages are never the module that\n * declares a decorated class.\n */\nexport const DECORATOR_RUNTIME_PACKAGES: readonly string[] = [\n '@oxc-project/runtime',\n '@swc/helpers',\n '@babel/runtime',\n 'tslib',\n];\n\n/**\n * Whether a file path (normalized to forward slashes) lives inside a\n * decorator-runtime helper package — i.e. a stack frame introduced by decorator\n * lowering rather than the module that declares the decorated class.\n *\n * Matches both the plain installed form (`.../node_modules/tslib/...`) and the\n * pnpm form (`.../node_modules/.pnpm/tslib@2/node_modules/tslib/...`) because\n * the real `/<package>/` segment appears in both. Case-insensitive.\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isDecoratorRuntimeFramePath(path: string): boolean {\n const lower = path.toLowerCase();\n return DECORATOR_RUNTIME_PACKAGES.some(\n (pkg) =>\n lower.includes(`/${pkg}/`) ||\n // Vite serves the helper as a virtual module whose id flattens the\n // scope separator and appends the version, e.g.\n // `<root>/\\0@oxc-project+runtime@0.138.0/helpers/esm/decorate.js`.\n // Missing it attributed every class Vitest loads to the project root's\n // package (#3098).\n lower.includes(`\\0${pkg.replace('/', '+')}@`),\n );\n}\n\n/**\n * Module and test runners that evaluate a module and so appear below it on\n * the stack. Like decorator helpers, they never declare a class.\n */\nconst MODULE_RUNNER_PATH_SEGMENTS: readonly string[] = [\n '/node_modules/@vitest/',\n '/node_modules/vitest/',\n '/node_modules/vite/dist/node/module-runner',\n];\n\n/**\n * Whether a stack-frame path belongs to a module or test runner (Vitest, the\n * Vite module runner) rather than to code that could declare a class (#3098).\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isModuleRunnerFramePath(path: string): boolean {\n const lower = path.toLowerCase();\n return MODULE_RUNNER_PATH_SEGMENTS.some((segment) => lower.includes(segment));\n}\n\n/**\n * Whether a scoped package name (as captured from a `node_modules/@scope/name`\n * stack match) is a decorator-runtime helper package.\n *\n * @param name - A scoped package name, e.g. `@oxc-project/runtime`.\n */\nexport function isDecoratorRuntimePackageName(name: string): boolean {\n return DECORATOR_RUNTIME_PACKAGES.includes(name);\n}\n\nlet smrtCoreRoot: string | null | undefined;\n\n/**\n * The directory of the smrt-core package this module belongs to (its\n * `package.json` names `@happyvertical/smrt-core`), or `null` when it cannot\n * be determined (a browser, or core inlined into a consumer's bundle).\n * Resolved once from this module's own location, so it follows the monorepo\n * checkout, a linked checkout, or an installed copy alike.\n */\nfunction getSmrtCoreRoot(): string | null {\n if (smrtCoreRoot !== undefined) return smrtCoreRoot;\n smrtCoreRoot = null;\n try {\n const getBuiltinModule = (\n globalThis as {\n process?: { getBuiltinModule?: (id: string) => unknown };\n }\n ).process?.getBuiltinModule;\n const fs = getBuiltinModule?.('node:fs') as\n | typeof import('node:fs')\n | undefined;\n const path = getBuiltinModule?.('node:path') as\n | typeof import('node:path')\n | undefined;\n const url = getBuiltinModule?.('node:url') as\n | typeof import('node:url')\n | undefined;\n if (!fs || !path || !url || !import.meta.url.startsWith('file:')) {\n return smrtCoreRoot;\n }\n let dir = path.dirname(url.fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 16; depth++) {\n const manifest = path.join(dir, 'package.json');\n if (\n fs.existsSync(manifest) &&\n (JSON.parse(fs.readFileSync(manifest, 'utf8')) as { name?: string })\n .name === '@happyvertical/smrt-core'\n ) {\n smrtCoreRoot = dir.replace(/\\\\/g, '/');\n break;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n smrtCoreRoot = null;\n }\n return smrtCoreRoot;\n}\n\n/**\n * Whether a stack-frame path is smrt-core's own code, which applies decorators\n * but never declares an application class. Both stack walks (source-file\n * identity in `registry/shared-state.ts` and package attribution in\n * `manifest/manifest-loader.ts`) skip these frames.\n *\n * Matched by where core actually lives, never by a generic substring: a\n * consumer's own `packages/core` workspace package (ergot's `@ergot/core`) or\n * a file named like a core module declares classes too. That is this core's\n * package directory (outside its `__tests__` fixtures) and any installed\n * `node_modules/@happyvertical/smrt-core` copy. With source maps enabled —\n * `tsx`, `node --enable-source-maps`, Vite SSR — an installed core's frames\n * report mapped `.../node_modules/@happyvertical/smrt-core/src/...` paths;\n * missing them attributed every class to `@happyvertical/smrt-core` (#3109,\n * #3110).\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isSmrtCoreFramePath(path: string): boolean {\n const normalized = path.replace(/^file:\\/\\//, '').replace(/\\\\/g, '/');\n if (\n normalized.toLowerCase().includes('/node_modules/@happyvertical/smrt-core/')\n ) {\n return true;\n }\n const root = getSmrtCoreRoot();\n if (!root || !normalized.startsWith(`${root}/`)) return false;\n return !normalized.slice(root.length + 1).includes('__tests__');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,6BAAgD;CAC3D;CACA;CACA;CACA;AACF;;;;;;;;;;;;AAaA,SAAgB,4BAA4B,MAAuB;CACjE,MAAM,QAAQ,KAAK,YAAY;CAC/B,OAAO,2BAA2B,MAC/B,QACC,MAAM,SAAS,IAAI,IAAI,EAAE,KAMzB,MAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,GAAG,EAAE,EAAE,CAChD;AACF;;;;;AAMA,IAAM,8BAAiD;CACrD;CACA;CACA;AACF;;;;;;;AAQA,SAAgB,wBAAwB,MAAuB;CAC7D,MAAM,QAAQ,KAAK,YAAY;CAC/B,OAAO,4BAA4B,MAAM,YAAY,MAAM,SAAS,OAAO,CAAC;AAC9E;;;;;;;AAQA,SAAgB,8BAA8B,MAAuB;CACnE,OAAO,2BAA2B,SAAS,IAAI;AACjD;AAEA,IAAI;;;;;;;;AASJ,SAAS,kBAAiC;CACxC,IAAI,iBAAiB,KAAA,GAAW,OAAO;CACvC,eAAe;CACf,IAAI;EACF,MAAM,mBACJ,WAGA,SAAS;EACX,MAAM,KAAK,mBAAmB,SAAS;EAGvC,MAAM,OAAO,mBAAmB,WAAW;EAG3C,MAAM,MAAM,mBAAmB,UAAU;EAGzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI,WAAW,OAAO,GAC7D,OAAO;EAET,IAAI,MAAM,KAAK,QAAQ,IAAI,cAAc,OAAO,KAAK,GAAG,CAAC;EACzD,KAAK,IAAI,QAAQ,GAAG,QAAQ,IAAI,SAAS;GACvC,MAAM,WAAW,KAAK,KAAK,KAAK,cAAc;GAC9C,IACE,GAAG,WAAW,QAAQ,KACrB,KAAK,MAAM,GAAG,aAAa,UAAU,MAAM,CAAC,CAAC,CAC3C,SAAS,4BACZ;IACA,eAAe,IAAI,QAAQ,OAAO,GAAG;IACrC;GACF;GACA,MAAM,SAAS,KAAK,QAAQ,GAAG;GAC/B,IAAI,WAAW,KAAK;GACpB,MAAM;EACR;CACF,QAAQ;EACN,eAAe;CACjB;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,oBAAoB,MAAuB;CACzD,MAAM,aAAa,KAAK,QAAQ,cAAc,EAAE,CAAC,CAAC,QAAQ,OAAO,GAAG;CACpE,IACE,WAAW,YAAY,CAAC,CAAC,SAAS,yCAAyC,GAE3E,OAAO;CAET,MAAM,OAAO,gBAAgB;CAC7B,IAAI,CAAC,QAAQ,CAAC,WAAW,WAAW,GAAG,KAAK,EAAE,GAAG,OAAO;CACxD,OAAO,CAAC,WAAW,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,WAAW;AAChE"}
1
+ {"version":3,"file":"stack-frames.js","names":[],"sources":["../../src/utils/stack-frames.ts"],"sourcesContent":["/**\n * Decorator-runtime stack-frame detection (#1785).\n *\n * ObjectRegistry attributes a `@smrt()` class to its declaring package by\n * walking the registration call stack for the first frame OUTSIDE smrt-core —\n * the module that applied the decorator. Decorator *lowering* breaks that\n * assumption: the compiler inserts a runtime-helper frame between the `@smrt()`\n * decorator and the consumer module that declares the class.\n *\n * Under Vite 8, oxc's legacy-decorator lowering routes the decorator application\n * through `@oxc-project/runtime`'s helper (e.g.\n * `.../@oxc-project/runtime/src/helpers/esm/applyDecoratedDescriptor.js`), so a\n * naive walk stops at that frame and misattributes the class to\n * `@oxc-project/runtime` instead of the consumer package. `tslib` (tsc's\n * `__decorate`), `@swc/helpers`, and `@babel/runtime` insert the identical kind\n * of frame under their respective toolchains.\n *\n * These are pure plumbing packages — a class is applied THROUGH them, never\n * DECLARED in them — so both stack walks (source-file identity in\n * `registry/shared-state.ts` and package attribution in\n * `manifest/manifest-loader.ts`) skip them and continue to the real declaring\n * module. Kept as a leaf module (no smrt imports) so both walkers can share it\n * without risking an import cycle.\n */\n\n/**\n * Runtime-helper packages that decorator lowering routes the decorator\n * application through. Frames from these packages are never the module that\n * declares a decorated class.\n */\nexport const DECORATOR_RUNTIME_PACKAGES: readonly string[] = [\n '@oxc-project/runtime',\n '@swc/helpers',\n '@babel/runtime',\n 'tslib',\n];\n\n/**\n * Plumbing packages matched only as an installed `node_modules/<pkg>/` path.\n * `reflect-metadata` (pulled in by e.g. `@simplewebauthn/server` and tsyringe)\n * defines `Reflect.decorate`, which tsc-style `__decorate` helpers delegate\n * to, so every decorator is then applied FROM its Reflect.js frame. The name\n * is also a plausible directory in an application's own source tree, so the\n * match is anchored to `node_modules` rather than any `/reflect-metadata/`.\n */\nconst INSTALLED_ONLY_RUNTIME_PACKAGES: readonly string[] = ['reflect-metadata'];\n\n/**\n * Whether a file path (normalized to forward slashes) lives inside a\n * decorator-runtime helper package — i.e. a stack frame introduced by decorator\n * lowering rather than the module that declares the decorated class.\n *\n * Matches both the plain installed form (`.../node_modules/tslib/...`) and the\n * pnpm form (`.../node_modules/.pnpm/tslib@2/node_modules/tslib/...`) because\n * the real `/<package>/` segment appears in both. Case-insensitive.\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isDecoratorRuntimeFramePath(path: string): boolean {\n const lower = path.toLowerCase();\n if (\n INSTALLED_ONLY_RUNTIME_PACKAGES.some((pkg) =>\n lower.includes(`/node_modules/${pkg}/`),\n )\n ) {\n return true;\n }\n return DECORATOR_RUNTIME_PACKAGES.some(\n (pkg) =>\n lower.includes(`/${pkg}/`) ||\n // Vite serves the helper as a virtual module whose id flattens the\n // scope separator and appends the version, e.g.\n // `<root>/\\0@oxc-project+runtime@0.138.0/helpers/esm/decorate.js`.\n // Missing it attributed every class Vitest loads to the project root's\n // package (#3098).\n lower.includes(`\\0${pkg.replace('/', '+')}@`),\n );\n}\n\n/**\n * Module and test runners that evaluate a module and so appear below it on\n * the stack. Like decorator helpers, they never declare a class.\n */\nconst MODULE_RUNNER_PATH_SEGMENTS: readonly string[] = [\n '/node_modules/@vitest/',\n '/node_modules/vitest/',\n '/node_modules/vite/dist/node/module-runner',\n];\n\n/**\n * Whether a stack-frame path belongs to a module or test runner (Vitest, the\n * Vite module runner) rather than to code that could declare a class (#3098).\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isModuleRunnerFramePath(path: string): boolean {\n const lower = path.toLowerCase();\n return MODULE_RUNNER_PATH_SEGMENTS.some((segment) => lower.includes(segment));\n}\n\n/**\n * Whether a scoped package name (as captured from a `node_modules/@scope/name`\n * stack match) is a decorator-runtime helper package.\n *\n * @param name - A scoped package name, e.g. `@oxc-project/runtime`.\n */\nexport function isDecoratorRuntimePackageName(name: string): boolean {\n return DECORATOR_RUNTIME_PACKAGES.includes(name);\n}\n\nlet smrtCoreRoot: string | null | undefined;\n\n/**\n * The directory of the smrt-core package this module belongs to (its\n * `package.json` names `@happyvertical/smrt-core`), or `null` when it cannot\n * be determined (a browser, or core inlined into a consumer's bundle).\n * Resolved once from this module's own location, so it follows the monorepo\n * checkout, a linked checkout, or an installed copy alike.\n */\nfunction getSmrtCoreRoot(): string | null {\n if (smrtCoreRoot !== undefined) return smrtCoreRoot;\n smrtCoreRoot = null;\n try {\n const getBuiltinModule = (\n globalThis as {\n process?: { getBuiltinModule?: (id: string) => unknown };\n }\n ).process?.getBuiltinModule;\n const fs = getBuiltinModule?.('node:fs') as\n | typeof import('node:fs')\n | undefined;\n const path = getBuiltinModule?.('node:path') as\n | typeof import('node:path')\n | undefined;\n const url = getBuiltinModule?.('node:url') as\n | typeof import('node:url')\n | undefined;\n if (!fs || !path || !url || !import.meta.url.startsWith('file:')) {\n return smrtCoreRoot;\n }\n let dir = path.dirname(url.fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 16; depth++) {\n const manifest = path.join(dir, 'package.json');\n if (\n fs.existsSync(manifest) &&\n (JSON.parse(fs.readFileSync(manifest, 'utf8')) as { name?: string })\n .name === '@happyvertical/smrt-core'\n ) {\n smrtCoreRoot = dir.replace(/\\\\/g, '/');\n break;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n smrtCoreRoot = null;\n }\n return smrtCoreRoot;\n}\n\n/**\n * Whether a stack-frame path is smrt-core's own code, which applies decorators\n * but never declares an application class. Both stack walks (source-file\n * identity in `registry/shared-state.ts` and package attribution in\n * `manifest/manifest-loader.ts`) skip these frames.\n *\n * Matched by where core actually lives, never by a generic substring: a\n * consumer's own `packages/core` workspace package (ergot's `@ergot/core`) or\n * a file named like a core module declares classes too. That is this core's\n * package directory (outside its `__tests__` fixtures) and any installed\n * `node_modules/@happyvertical/smrt-core` copy. With source maps enabled —\n * `tsx`, `node --enable-source-maps`, Vite SSR — an installed core's frames\n * report mapped `.../node_modules/@happyvertical/smrt-core/src/...` paths;\n * missing them attributed every class to `@happyvertical/smrt-core` (#3109,\n * #3110).\n *\n * @param path - A file path from a stack frame (already normalized to `/`).\n */\nexport function isSmrtCoreFramePath(path: string): boolean {\n const normalized = path.replace(/^file:\\/\\//, '').replace(/\\\\/g, '/');\n if (\n normalized.toLowerCase().includes('/node_modules/@happyvertical/smrt-core/')\n ) {\n return true;\n }\n const root = getSmrtCoreRoot();\n if (!root || !normalized.startsWith(`${root}/`)) return false;\n return !normalized.slice(root.length + 1).includes('__tests__');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,6BAAgD;CAC3D;CACA;CACA;CACA;AACF;;;;;;;;;AAUA,IAAM,kCAAqD,CAAC,kBAAkB;;;;;;;;;;;;AAa9E,SAAgB,4BAA4B,MAAuB;CACjE,MAAM,QAAQ,KAAK,YAAY;CAC/B,IACE,gCAAgC,MAAM,QACpC,MAAM,SAAS,iBAAiB,IAAI,EAAE,CACxC,GAEA,OAAO;CAET,OAAO,2BAA2B,MAC/B,QACC,MAAM,SAAS,IAAI,IAAI,EAAE,KAMzB,MAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,GAAG,EAAE,EAAE,CAChD;AACF;;;;;AAMA,IAAM,8BAAiD;CACrD;CACA;CACA;AACF;;;;;;;AAQA,SAAgB,wBAAwB,MAAuB;CAC7D,MAAM,QAAQ,KAAK,YAAY;CAC/B,OAAO,4BAA4B,MAAM,YAAY,MAAM,SAAS,OAAO,CAAC;AAC9E;;;;;;;AAQA,SAAgB,8BAA8B,MAAuB;CACnE,OAAO,2BAA2B,SAAS,IAAI;AACjD;AAEA,IAAI;;;;;;;;AASJ,SAAS,kBAAiC;CACxC,IAAI,iBAAiB,KAAA,GAAW,OAAO;CACvC,eAAe;CACf,IAAI;EACF,MAAM,mBACJ,WAGA,SAAS;EACX,MAAM,KAAK,mBAAmB,SAAS;EAGvC,MAAM,OAAO,mBAAmB,WAAW;EAG3C,MAAM,MAAM,mBAAmB,UAAU;EAGzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI,WAAW,OAAO,GAC7D,OAAO;EAET,IAAI,MAAM,KAAK,QAAQ,IAAI,cAAc,OAAO,KAAK,GAAG,CAAC;EACzD,KAAK,IAAI,QAAQ,GAAG,QAAQ,IAAI,SAAS;GACvC,MAAM,WAAW,KAAK,KAAK,KAAK,cAAc;GAC9C,IACE,GAAG,WAAW,QAAQ,KACrB,KAAK,MAAM,GAAG,aAAa,UAAU,MAAM,CAAC,CAAC,CAC3C,SAAS,4BACZ;IACA,eAAe,IAAI,QAAQ,OAAO,GAAG;IACrC;GACF;GACA,MAAM,SAAS,KAAK,QAAQ,GAAG;GAC/B,IAAI,WAAW,KAAK;GACpB,MAAM;EACR;CACF,QAAQ;EACN,eAAe;CACjB;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,oBAAoB,MAAuB;CACzD,MAAM,aAAa,KAAK,QAAQ,cAAc,EAAE,CAAC,CAAC,QAAQ,OAAO,GAAG;CACpE,IACE,WAAW,YAAY,CAAC,CAAC,SAAS,yCAAyC,GAE3E,OAAO;CAET,MAAM,OAAO,gBAAgB;CAC7B,IAAI,CAAC,QAAQ,CAAC,WAAW,WAAW,GAAG,KAAK,EAAE,GAAG,OAAO;CACxD,OAAO,CAAC,WAAW,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,WAAW;AAChE"}
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit-generator.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sveltekit-generator.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"names":[],"mappings":"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"}
@@ -1008,11 +1008,15 @@ function readKnowledgeRouteArtifact(projectRoot) {
1008
1008
  async function generateRegistrationFile(projectRoot, manifest, options) {
1009
1009
  const configDir = join(projectRoot, options.configPath || "src/lib/server");
1010
1010
  const registrationFilePath = join(configDir, "smrt-register.ts");
1011
+ const externalRuntimeDependencies = (manifest.smrtDependencies || []).filter((dependency) => dependency !== "@happyvertical/smrt-core");
1012
+ const consumerRegistrationPaths = options.consumerRegistrationPaths ?? (externalRuntimeDependencies.length > 0 ? [join(projectRoot, ".smrt", "register.js")] : []);
1013
+ const consumerOwnsExternalRegistration = consumerRegistrationPaths.length > 0;
1011
1014
  const localObjects = [];
1012
1015
  const packageObjects = /* @__PURE__ */ new Map();
1013
1016
  const registrationBindings = buildRegistrationBindings(manifest);
1014
1017
  for (const [className, objectDef] of Object.entries(manifest.objects)) if (isLocalObject(projectRoot, objectDef)) localObjects.push([className, objectDef]);
1015
1018
  else if (objectDef.packageName) {
1019
+ if (consumerOwnsExternalRegistration) continue;
1016
1020
  const externalImportPath = objectDef.importPath || objectDef.packageName;
1017
1021
  const packageEntry = packageObjects.get(externalImportPath) || {
1018
1022
  objects: [],
@@ -1057,11 +1061,12 @@ async function generateRegistrationFile(projectRoot, manifest, options) {
1057
1061
  }
1058
1062
  return imports;
1059
1063
  }).join("\n"), localImports].filter(Boolean).join("\n");
1060
- const externalRuntimeDependencies = (manifest.smrtDependencies || []).filter((dependency) => dependency !== "@happyvertical/smrt-core");
1061
- const consumerRegistrationPaths = options.consumerRegistrationPaths ?? (externalRuntimeDependencies.length > 0 ? [join(projectRoot, ".smrt", "register.js")] : []);
1062
1064
  let consumerRegistrationImport = "";
1063
1065
  if (consumerRegistrationPaths.length > 0) consumerRegistrationImport = [...new Set(consumerRegistrationPaths)].sort().map((registerPath) => {
1064
- const consumerRegistrationPath = relative(configDir, registerPath).replace(/\\/g, "/");
1066
+ const lexicalRegistrationPath = relative(projectRoot, registerPath);
1067
+ const registerPathFromProjectRoot = lexicalRegistrationPath === ".." || lexicalRegistrationPath.startsWith(`..${sep}`) || isAbsolute(lexicalRegistrationPath) ? relative(canonicalSvelteKitPath(projectRoot), canonicalSvelteKitPath(registerPath)) : lexicalRegistrationPath;
1068
+ const registrationTarget = registerPathFromProjectRoot === ".." || registerPathFromProjectRoot.startsWith(`..${sep}`) || isAbsolute(registerPathFromProjectRoot) ? registerPath : resolve(projectRoot, registerPathFromProjectRoot);
1069
+ const consumerRegistrationPath = relative(configDir, registrationTarget).replace(/\\/g, "/");
1065
1070
  return `import '${consumerRegistrationPath.startsWith(".") ? consumerRegistrationPath : `./${consumerRegistrationPath}`}';`;
1066
1071
  }).join("\n");
1067
1072
  /**
@@ -1105,7 +1110,9 @@ async function generateRegistrationFile(projectRoot, manifest, options) {
1105
1110
  }));
1106
1111
  const registrationManifests = Object.fromEntries(Object.entries(manifest.objects).flatMap(([className, objectDef]) => {
1107
1112
  if (isCollectionManifestClass(manifest, objectDef)) return [];
1108
- const packageName = getRegistrationPackageName(manifest, objectDef, isLocalObject(projectRoot, objectDef));
1113
+ const localObject = isLocalObject(projectRoot, objectDef);
1114
+ if (!localObject && consumerOwnsExternalRegistration) return [];
1115
+ const packageName = getRegistrationPackageName(manifest, objectDef, localObject);
1109
1116
  if (!packageName) return [];
1110
1117
  return [[className, {
1111
1118
  ...manifest,
@@ -1118,7 +1125,9 @@ async function generateRegistrationFile(projectRoot, manifest, options) {
1118
1125
  if (isCollectionManifestClass(manifest, objectDef)) return null;
1119
1126
  const simpleClassName = extractSimpleClassName(className);
1120
1127
  const bindingName = registrationBindings.get(className) || simpleClassName;
1121
- const packageName = getRegistrationPackageName(manifest, objectDef, isLocalObject(projectRoot, objectDef));
1128
+ const localObject = isLocalObject(projectRoot, objectDef);
1129
+ if (!localObject && consumerOwnsExternalRegistration) return null;
1130
+ const packageName = getRegistrationPackageName(manifest, objectDef, localObject);
1122
1131
  if (!packageName) return null;
1123
1132
  const packageNameLiteral = toSingleQuotedStringLiteral(packageName);
1124
1133
  const manifestKeyLiteral = toSingleQuotedStringLiteral(className);
@@ -1133,7 +1142,7 @@ async function generateRegistrationFile(projectRoot, manifest, options) {
1133
1142
  `});`
1134
1143
  ].join("\n");
1135
1144
  }).filter((registration) => registration !== null).join("\n");
1136
- const collectionRegistrations = Object.entries(manifest.objects).filter(([, objectDef]) => isCollectionActionResource(manifest, objectDef)).map(([className, objectDef]) => {
1145
+ const collectionRegistrations = Object.entries(manifest.objects).filter(([, objectDef]) => isCollectionActionResource(manifest, objectDef) && (!consumerOwnsExternalRegistration || isLocalObject(projectRoot, objectDef))).map(([className, objectDef]) => {
1137
1146
  const packageName = getRegistrationPackageName(manifest, objectDef, isLocalObject(projectRoot, objectDef));
1138
1147
  const qualifiedName = objectDef.qualifiedName || (packageName ? `${packageName}:${extractSimpleClassName(className)}` : className);
1139
1148
  const bindingName = registrationBindings.get(className) || extractSimpleClassName(className);