@happyvertical/smrt-core 0.51.32 → 0.51.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/agents/build-knowledge.md +13 -0
  2. package/dist/__tests__/fixtures/collection-coverage-fixtures.d.ts +8 -0
  3. package/dist/__tests__/fixtures/inheritance-resolver-fixtures.d.ts +9 -0
  4. package/dist/__tests__/fixtures/inheritance-test-classes.d.ts +5 -0
  5. package/dist/__tests__/fixtures/object-ai-memory-fixtures.d.ts +10 -0
  6. package/dist/__typechecks__/collection-read-plan.d.ts +2 -2
  7. package/dist/adapters/ai-usage.d.ts +5 -2
  8. package/dist/adapters/cost-rates.d.ts +1 -1
  9. package/dist/adapters/metrics.d.ts +7 -1
  10. package/dist/adapters/pubsub.d.ts +7 -1
  11. package/dist/cascade.d.ts +69 -3
  12. package/dist/change-feed-authz.d.ts +85 -2
  13. package/dist/change-feed.d.ts +133 -2
  14. package/dist/change-signals.d.ts +66 -1
  15. package/dist/child-accessors.d.ts +39 -1
  16. package/dist/class.d.ts +8 -8
  17. package/dist/collection-cache.d.ts +47 -1
  18. package/dist/collection-read-plan.d.ts +3 -3
  19. package/dist/collection.d.ts +4 -3
  20. package/dist/config.d.ts +15 -6
  21. package/dist/consumer-plugin/index.d.ts +7 -3
  22. package/dist/consumer-plugin/index.d.ts.map +1 -1
  23. package/dist/consumer-plugin/index.js +2 -0
  24. package/dist/consumer-plugin/index.js.map +1 -1
  25. package/dist/data-query.d.ts +12 -1
  26. package/dist/database.d.ts +10 -2
  27. package/dist/decisions.d.ts +9 -2
  28. package/dist/decorators/index.d.ts +11 -5
  29. package/dist/dispatch/bus.d.ts +27 -2
  30. package/dist/dispatch/collections/DispatchSubscriptions.d.ts +7 -2
  31. package/dist/dispatch/collections/Dispatches.d.ts +8 -3
  32. package/dist/dispatch/models/Dispatch.d.ts +7 -1
  33. package/dist/dispatch/types.d.ts +7 -2
  34. package/dist/embedded-write-queue.d.ts +1 -1
  35. package/dist/embeddings/provider.d.ts +8 -1
  36. package/dist/embeddings/storage.d.ts +8 -2
  37. package/dist/filesystem-loader.d.ts +16 -1
  38. package/dist/generators/changes-route.d.ts +34 -1
  39. package/dist/generators/custom-action.d.ts +10 -2
  40. package/dist/generators/events-route.d.ts +41 -4
  41. package/dist/generators/mcp-runtime-template.d.ts +13 -2
  42. package/dist/generators/mcp.d.ts +6 -1
  43. package/dist/generators/rest.d.ts +10 -5
  44. package/dist/generators/tool-schema.d.ts +1 -1
  45. package/dist/hierarchical.d.ts +37 -1
  46. package/dist/interceptors.d.ts +45 -1
  47. package/dist/junction.d.ts +24 -0
  48. package/dist/knowledge-config.d.ts +1 -1
  49. package/dist/knowledge-discovery.d.ts +2 -25
  50. package/dist/knowledge-discovery.d.ts.map +1 -1
  51. package/dist/knowledge-discovery.js +1 -53
  52. package/dist/knowledge-graph.d.ts +2 -94
  53. package/dist/knowledge-graph.d.ts.map +1 -1
  54. package/dist/knowledge-graph.js +1 -267
  55. package/dist/knowledge.d.ts +4 -23
  56. package/dist/knowledge.d.ts.map +1 -1
  57. package/dist/knowledge.js +3 -52
  58. package/dist/knowledge.js.map +1 -1
  59. package/dist/learning/memory.d.ts +21 -1
  60. package/dist/manifest/generator.d.ts +5 -1
  61. package/dist/manifest/index.d.ts +5 -1
  62. package/dist/manifest/manager.d.ts +1 -1
  63. package/dist/manifest/manifest-loader.d.ts +24 -2
  64. package/dist/manifest/sources/composite.d.ts +17 -1
  65. package/dist/manifest/sources/embedded.d.ts +10 -1
  66. package/dist/manifest/sources/explicit-paths.d.ts +13 -1
  67. package/dist/manifest/sources/fallback.d.ts +15 -1
  68. package/dist/manifest/sources/local-test.d.ts +10 -1
  69. package/dist/manifest/sources/static.d.ts +12 -1
  70. package/dist/manifest/sources/test.d.ts +9 -1
  71. package/dist/manifest/sources/types.d.ts +7 -1
  72. package/dist/manifest/static-manifest.d.ts +6 -1
  73. package/dist/manifest/static-manifest.js +1 -1
  74. package/dist/manifest/static-manifest.js.map +1 -1
  75. package/dist/manifest/store.d.ts +22 -3
  76. package/dist/manifest/store.js +1 -1
  77. package/dist/manifest.json +1 -1
  78. package/dist/migrations/backfill-tracker.d.ts +15 -1
  79. package/dist/migrations/differ.d.ts +8 -2
  80. package/dist/migrations/framework-base-tables.d.ts +57 -2
  81. package/dist/migrations/generator.d.ts +8 -2
  82. package/dist/migrations/integer-width.d.ts +10 -2
  83. package/dist/migrations/minor-units.d.ts +40 -1
  84. package/dist/migrations/null-equal-indexes.d.ts +3 -2
  85. package/dist/migrations/orchestrate.d.ts +15 -3
  86. package/dist/migrations/sqlite-rebuild.d.ts +67 -2
  87. package/dist/migrations/tracker.d.ts +9 -3
  88. package/dist/migrations/types.d.ts +7 -2
  89. package/dist/object.d.ts +7 -6
  90. package/dist/polymorphic-association.d.ts +44 -1
  91. package/dist/postgres-permissions.d.ts +1 -1
  92. package/dist/prebuild/index.d.ts +5 -1
  93. package/dist/query-bounds.d.ts +26 -0
  94. package/dist/registry/cache-config.d.ts +10 -1
  95. package/dist/registry/class-registration.d.ts +10 -2
  96. package/dist/registry/collection-resolution.d.ts +1 -1
  97. package/dist/registry/embedding-manager.d.ts +9 -1
  98. package/dist/registry/inheritance-resolver.d.ts +8 -3
  99. package/dist/registry/manifest-field-merge.d.ts +2 -2
  100. package/dist/registry/name-resolver.d.ts +22 -2
  101. package/dist/registry/relationship-graph.d.ts +9 -1
  102. package/dist/registry/schema-builder.d.ts +8 -3
  103. package/dist/registry/shared-state.d.ts +12 -2
  104. package/dist/registry/types.d.ts +15 -7
  105. package/dist/registry/validator.d.ts +10 -2
  106. package/dist/registry.d.ts +40 -11
  107. package/dist/relationship-loader.d.ts +1 -1
  108. package/dist/run-once.d.ts +110 -1
  109. package/dist/runtime/client.d.ts +4 -1
  110. package/dist/runtime/server.d.ts +5 -2
  111. package/dist/scanner/import-scanner.d.ts +1 -1
  112. package/dist/scanner/manifest-generator.d.ts +4 -1
  113. package/dist/scanner/types.d.ts +4 -1
  114. package/dist/schema/code-generator.d.ts +6 -2
  115. package/dist/schema/column-data-probes.d.ts +27 -2
  116. package/dist/schema/ddl/base-strategy.d.ts +8 -2
  117. package/dist/schema/ddl/duckdb-strategy.d.ts +14 -2
  118. package/dist/schema/ddl/index.d.ts +2 -2
  119. package/dist/schema/ddl/json-duckdb-strategy.d.ts +10 -2
  120. package/dist/schema/ddl/materialize-manifest.d.ts +1 -1
  121. package/dist/schema/ddl/null-equal-index.d.ts +1 -1
  122. package/dist/schema/ddl/postgres-strategy.d.ts +12 -2
  123. package/dist/schema/ddl/sqlite-strategy.d.ts +12 -2
  124. package/dist/schema/ddl/types.d.ts +10 -1
  125. package/dist/schema/foreign-key-ddl.d.ts +2 -2
  126. package/dist/schema/foreign-key-orphan-report.d.ts +25 -3
  127. package/dist/schema/foreign-key-planner.d.ts +2 -2
  128. package/dist/schema/foreign-key-policy.d.ts +1 -1
  129. package/dist/schema/generator.d.ts +7 -3
  130. package/dist/schema/index-utils.d.ts +11 -2
  131. package/dist/schema/live-parity.d.ts +27 -3
  132. package/dist/schema/manifest-schema.d.ts +21 -2
  133. package/dist/schema/schema-aggregator.d.ts +35 -2
  134. package/dist/schema/schema-manager.d.ts +13 -4
  135. package/dist/schema/system-table-shapes.d.ts +20 -1
  136. package/dist/schema/table-verifier.d.ts +1 -1
  137. package/dist/schema/text-cast-probe.d.ts +24 -1
  138. package/dist/schema/utils.d.ts +13 -4
  139. package/dist/schema/uuid-convergence.d.ts +32 -1
  140. package/dist/signals/bus.d.ts +8 -2
  141. package/dist/signals/sanitizer.d.ts +7 -1
  142. package/dist/smrt-knowledge.json +8 -9
  143. package/dist/system/bootstrap.d.ts +2 -1
  144. package/dist/system/compatibility.d.ts +1 -1
  145. package/dist/system/diagnostics.d.ts +17 -2
  146. package/dist/system/retention.d.ts +46 -1
  147. package/dist/system/schema.d.ts +7 -1
  148. package/dist/system-fields.d.ts +9 -1
  149. package/dist/test-utils.d.ts +7 -1
  150. package/dist/testing/database.d.ts +18 -1
  151. package/dist/testing/notifications-stub.d.ts +15 -1
  152. package/dist/tools/tool-executor.d.ts +6 -1
  153. package/dist/tools/tool-generator.d.ts +8 -2
  154. package/dist/utils/json.d.ts +9 -1
  155. package/dist/utils/qualified-names.d.ts +10 -1
  156. package/dist/utils/scanner-module.d.ts +2 -2
  157. package/dist/utils.d.ts +1 -1
  158. package/dist/vite-plugin/api-client-entries.d.ts +9 -1
  159. package/dist/vite-plugin/changes-route.d.ts +33 -2
  160. package/dist/vite-plugin/dev-plane-route.d.ts +12 -1
  161. package/dist/vite-plugin/events-route.d.ts +37 -2
  162. package/dist/vite-plugin/generated-client.d.ts +9 -1
  163. package/dist/vite-plugin/index.d.ts +9 -5
  164. package/dist/vite-plugin/resources-route.d.ts +82 -1
  165. package/dist/vite-plugin/sveltekit-generator.d.ts +8 -4
  166. package/dist/vite-plugin/sveltekit-route-coordinator.d.ts +3 -3
  167. package/dist/vite-plugin/sync-apply-route.d.ts +19 -2
  168. package/dist/vite-plugin/web-collections.d.ts +25 -2
  169. package/dist/vite-plugin/worker-registration.d.ts +21 -1
  170. package/package.json +7 -8
  171. package/dist/knowledge-discovery.js.map +0 -1
  172. package/dist/knowledge-graph.js.map +0 -1
@@ -1,4 +1,23 @@
1
- import { DatabaseEngine } from './ddl/types.js';
1
+ /**
2
+ * System-table shape parsing (#2368)
3
+ *
4
+ * `_smrt_*` tables are created from hand-written DDL in `src/system/schema.ts`
5
+ * rather than from decorated classes, so they never enter the manifest and the
6
+ * manifest-driven differ has never compared them against a live database.
7
+ *
8
+ * This module parses that DDL back into a structural description — columns,
9
+ * declared indexes, and inline `UNIQUE (...)` constraints — so the live-schema
10
+ * parity check can hold system tables to the same standard as application
11
+ * tables. The DDL is the source of truth for these tables; parsing it (rather
12
+ * than duplicating a hand-maintained expectation table) keeps the two from
13
+ * drifting apart.
14
+ *
15
+ * The parser is deliberately narrow: it understands the portable subset SMRT
16
+ * actually writes (`CREATE TABLE IF NOT EXISTS`, `CREATE [UNIQUE] INDEX IF NOT
17
+ * EXISTS`, simple column definitions, inline `UNIQUE`/`PRIMARY KEY` table
18
+ * constraints) and ignores anything else rather than guessing.
19
+ */
20
+ import type { DatabaseEngine } from './ddl/types.js';
2
21
  /** One column as declared by hand-written system-table DDL. */
3
22
  export interface SystemTableColumnShape {
4
23
  name: string;
@@ -1,4 +1,4 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
2
  /**
3
3
  * Verify that a model table already exists.
4
4
  *
@@ -1,4 +1,27 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ /**
2
+ * Shared "probe, then cast" helpers for text-column type convergence (#2771,
3
+ * #2772).
4
+ *
5
+ * Two drift shapes on a table SMRT itself creates share one problem: a live
6
+ * `text` column holds values that would parse losslessly into the manifest's
7
+ * declared PostgreSQL type (`timestamptz` or `jsonb`), but the differ cannot
8
+ * know that without looking at the data. `probeCastSafety()` answers that with
9
+ * a genuine, exception-safe cast attempt — not a shape heuristic — over every
10
+ * non-null value, and returns one sample so a fail-closed diagnostic can name
11
+ * the offending value without dumping the whole column into JS.
12
+ *
13
+ * PostgreSQL has no `TRY_CAST`/safe-cast builtin before 17 (`pg_input_is_valid`),
14
+ * and this fleet targets 16 (see `.github/workflows/postgres-tests.yml`), so a
15
+ * real per-row safe cast needs PL/pgSQL's exception handling. That handler is
16
+ * created as a session-scoped (`pg_temp`) function, which is why the create
17
+ * statement and the probe query run inside one `db.transaction()` — the two
18
+ * must land on the same physical connection, and a pooled adapter only
19
+ * guarantees that within one transaction. `target_type` is never derived from
20
+ * column data (always the literal `'jsonb'`/`'timestamptz'` this module
21
+ * passes), so the dynamic `EXECUTE format(...)` it builds cannot be steered by
22
+ * a row value; `%L` quotes the probed value as a literal.
23
+ */
24
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
25
  /** Outcome of a server-side cast-safety probe over one column's non-null values. */
3
26
  export type ShapeProbeResult = {
4
27
  status: 'clean';
@@ -1,7 +1,16 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
2
- import { SmrtObject } from '../object.js';
3
- import { FieldDefinition } from '../scanner/types.js';
4
- import { DatabaseEngine } from './ddl/index.js';
1
+ /**
2
+ * Schema generation utilities - Node.js only
3
+ *
4
+ * These functions use SchemaGenerator which depends on node:crypto.
5
+ * Separated from main utils.ts to prevent bundling in browser builds.
6
+ *
7
+ * SMRT handles ALL database maintenance directly.
8
+ * SDK SQL remains a pure query/CRUD layer.
9
+ */
10
+ import type { DatabaseInterface } from '@happyvertical/sql';
11
+ import type { SmrtObject } from '../object.js';
12
+ import type { FieldDefinition } from '../scanner/types.js';
13
+ import { type DatabaseEngine } from './ddl/index.js';
5
14
  export { materializeManifestDDLForEngine, tokenizeSQLDDLBody, } from './ddl/materialize-manifest.js';
6
15
  export { assertIdentifierFits, identifierByteLength, isJsonPathIndex, isStiSubtypeUniqueIndex, MAX_IDENTIFIER_BYTES, renderIndexTarget, shortenIdentifier, } from './index-utils.js';
7
16
  export { type CollectedManifestTable, collectManifestTables, type ManifestColumnLike, type ManifestIndexLike, type ManifestSchemaLike, manifestColumnsToDefinitions, manifestIndexesToDefinitions, manifestSchemaToDefinition, mergeSchemaDefinitionInto, renderCollectedManifestTable, } from './manifest-schema.js';
@@ -1,4 +1,35 @@
1
- import { SchemaDefinition } from './types.js';
1
+ /**
2
+ * UUID convergence for pre-R11 PostgreSQL databases (#2608).
3
+ *
4
+ * R11 made SMRT identifiers and references native `uuid` on PostgreSQL.
5
+ * Databases created before that change still carry `text` id columns, while
6
+ * every column added afterwards materializes as `uuid`. PostgreSQL cannot
7
+ * implement a `FOREIGN KEY` across those two physical types — there is no
8
+ * cast inside FK DDL — so `ALTER TABLE … ADD CONSTRAINT … NOT VALID` fails
9
+ * with SQLSTATE 42804 and takes the rest of the migration batch with it.
10
+ *
11
+ * This module owns the deterministic half of the repair:
12
+ *
13
+ * - {@link renderUuidColumnConversion} renders the one-time
14
+ * `ALTER COLUMN … TYPE uuid USING …::uuid` (plus the `DROP DEFAULT` a live
15
+ * text default would otherwise block), and
16
+ * - {@link planUuidConvergence} decides *which* columns must convert, by
17
+ * grouping every manifest-declared UUID relationship into connected
18
+ * components and converging a component only when the live database already
19
+ * proves the target shape (at least one side is native `uuid`).
20
+ *
21
+ * The planner never coerces data: a component converges only when a caller
22
+ * supplied probe confirms every non-null value is uuid-shaped, no live
23
+ * foreign key depends on a column being rewritten, and no member carries some
24
+ * third physical type. Anything else is returned as a *block* with an
25
+ * operator-facing reason, so `db:status` can report "blocked" instead of
26
+ * "pending" and `db:migrate` never attempts DDL PostgreSQL will reject.
27
+ *
28
+ * A database whose relationship is `text` on *both* sides is left alone: that
29
+ * is the tolerated pre-R11 shape (see the R11 uuid/text equivalence in
30
+ * `migrations/differ.ts`), and its foreign keys apply fine.
31
+ */
32
+ import type { SchemaDefinition } from './types.js';
2
33
  /** One physical column participating in a manifest UUID relationship. */
3
34
  export interface UuidConvergenceNode {
4
35
  table: string;
@@ -1,5 +1,11 @@
1
- import { Signal, SignalAdapter } from '@happyvertical/smrt-types';
2
- import { SanitizationConfig } from './sanitizer.js';
1
+ /**
2
+ * Signal Bus for Universal Event Distribution
3
+ *
4
+ * This module provides the central SignalBus for distributing signals
5
+ * to registered adapters (logging, metrics, pub/sub, etc.).
6
+ */
7
+ import type { Signal, SignalAdapter } from '@happyvertical/smrt-types';
8
+ import type { SanitizationConfig } from './sanitizer.js';
3
9
  /**
4
10
  * Central signal distribution bus
5
11
  *
@@ -1,4 +1,10 @@
1
- import { Signal } from '@happyvertical/smrt-types';
1
+ /**
2
+ * Signal payload sanitization for security
3
+ *
4
+ * Prevents sensitive data (passwords, tokens, PII) from being leaked
5
+ * into logs, metrics, or other signal outputs.
6
+ */
7
+ import type { Signal } from '@happyvertical/smrt-types';
2
8
  /**
3
9
  * Sanitization configuration
4
10
  */
@@ -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.51.32",
6
+ "packageVersion": "0.51.33",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "f9e723deaba5c04c0d53aafb9d5b421a85f5aa63a1887d0b0a1c18db46bc65de",
11
- "packageJson": "560664073fbfefcc74a2914f6036c9250394cffc57cdf2fe37e27408a6ff2fd3",
10
+ "manifest": "0e598c41a70d94e0f311ca2c6c717499d7d360bfde2a10c982e722bd8cc6e928",
11
+ "packageJson": "624a187e41615d1b71afb40c725502618367487547cf4fe00127265c02c2c2cc",
12
12
  "agents": "79356014d92fdf656f648e5c765374913104445a5542243f4819ef362c77a8e5",
13
13
  "moduleDoc:agents/object-runtime.md": "34a4e740c109467cd5486c4af0e3bf4b63915697721ab584df0e5506ea9290ca",
14
14
  "moduleDoc:agents/revision-guard.md": "aa6b1ddb5b6b49fa27ebbe575ec7fcd6d5ceb35ee25acc702f877a226eb9a99a",
@@ -19,7 +19,7 @@
19
19
  "moduleDoc:agents/change-feed.md": "2151843f5d059cff54d7f6a32a6d57c43b9551fc4673edce13209764a09a9ae1",
20
20
  "moduleDoc:agents/change-signals.md": "a2dbe7077483b5a19bd5ea9589b5a08fe847377c8e05d01d57f813c6d9cbc28b",
21
21
  "moduleDoc:agents/generators.md": "4bc7787947fbcb5c084ce3e7849eff7a240580226e6b64271de7493870683cdf",
22
- "moduleDoc:agents/build-knowledge.md": "6705af33224b60521be741144a08f7a0db311a2d63e2b93b0e875280c7f72951",
22
+ "moduleDoc:agents/build-knowledge.md": "41eff6b3603f00e59eb91820c5ad9e50fb103d25bb5b9947f5b09b59d54a79ea",
23
23
  "moduleDoc:agents/memory.md": "a86bdf370403d08ecad3be86e341eb322dfe6e6b7a4e8806a6f8be9bf3421da5",
24
24
  "moduleDoc:agents/system-diagnostics.md": "b7ccae18ee312bf788d5470f95fa78d3535f1789247d5372e40ca86538290772",
25
25
  "moduleDoc:agents/registry-snapshot.md": "6234aa540427396d1dda1825a4641b1072e247187d5ddf413ae46c691344ee30",
@@ -71,6 +71,7 @@
71
71
  "oxc-transform": "0.150.0",
72
72
  "pluralize": "^8.0.0",
73
73
  "tsx": "^4.23.13",
74
+ "vite": "8.1.4",
74
75
  "yaml": "^2.9.1",
75
76
  "@faker-js/faker": "^10.6.0",
76
77
  "@huggingface/transformers": ">=3.0.0 <5.0.0",
@@ -80,10 +81,8 @@
80
81
  "@types/pluralize": "^0.0.33",
81
82
  "@xenova/transformers": "^2.17.2",
82
83
  "svelte": "^5.57.1",
83
- "svelte-check": "4.7.6",
84
- "typescript": "5.9.3",
85
- "vite": "8.1.4",
86
- "vite-plugin-dts": "5.1.0",
84
+ "svelte-check": "^4.7.6",
85
+ "typescript": "6.0.3",
87
86
  "vitest": "4.1.10"
88
87
  },
89
88
  "smrtDependencies": [
@@ -1108,7 +1107,7 @@
1108
1107
  {
1109
1108
  "path": "agents/build-knowledge.md",
1110
1109
  "module": "build-knowledge",
1111
- "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\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## 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 every other bare import stays external so the\nworker shares the installed `@happyvertical/smrt-core` registry. 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\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\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```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"
1110
+ "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\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## 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 every other bare import stays external so the\nworker shares the installed `@happyvertical/smrt-core` registry. 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\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```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`.\n"
1112
1111
  },
1113
1112
  {
1114
1113
  "path": "agents/memory.md",
@@ -1,4 +1,5 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ /** Canonical, idempotent SMRT system-table provisioning. */
2
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
3
  /**
3
4
  * Run `work` serialized against concurrent SMRT system-table bootstrap.
4
5
  *
@@ -1,4 +1,4 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
2
  import { detectEngine } from '../schema/ddl/index.js';
3
3
  export declare function tableExists(db: DatabaseInterface, tableName: string, typeHint?: string): Promise<boolean>;
4
4
  export declare function getDatabaseEngine(db: DatabaseInterface, typeHint?: string): ReturnType<typeof detectEngine>;
@@ -1,5 +1,20 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
2
- import { ChangeFeedEntry } from '../change-feed.js';
1
+ /**
2
+ * SMRT system-diagnostics reader.
3
+ *
4
+ * A typed, SELECT-only view over the framework-owned `_smrt_*` system tables
5
+ * for development tooling (smrt-dev-mcp runtime diagnostics). Every read is a
6
+ * bounded SELECT against explicitly projected safe columns; sensitive columns
7
+ * are never selected and no statement here writes.
8
+ *
9
+ * The reader takes a `DatabaseInterface` (connection resolution lives with the
10
+ * caller) and degrades per category to a `CategoryUnavailable` result when its
11
+ * table is missing or a read fails — it never throws for missing tables and
12
+ * never fabricates data. `_smrt_registry` is a retired system table
13
+ * ({@link RETIRED_SYSTEM_TABLES}) and is reported as retired rather than
14
+ * queried.
15
+ */
16
+ import type { DatabaseInterface } from '@happyvertical/sql';
17
+ import { type ChangeFeedEntry } from '../change-feed.js';
3
18
  /** Physical `_smrt_*` tables the diagnostics reader knows about. */
4
19
  export declare const SYSTEM_DIAGNOSTICS_TABLES: {
5
20
  readonly migrations: "_smrt_schema_migrations";
@@ -1,4 +1,49 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ /**
2
+ * System-table retention — bounded growth for framework-owned tables (#2375).
3
+ *
4
+ * Several `_smrt_*` tables are append-only by construction and were, until
5
+ * this module, unbounded by default: `_smrt_changes` grew one row per
6
+ * framework save/delete, `_smrt_ai_usage` one row per AI call (persistence is
7
+ * on by default, see `config.ts`), `_smrt_contexts` accumulated rows whose
8
+ * `expires_at` nothing ever enforced, `_smrt_dispatch` retained completed
9
+ * work until an operator remembered to run `smrt dispatch:cleanup`, and
10
+ * `_smrt_run_once_claims` (#3080) gains one row per `runOnce()` submission
11
+ * with nothing pruning completed ones.
12
+ *
13
+ * This module supplies the missing half:
14
+ *
15
+ * - {@link pruneAiUsage} — the retention API `_smrt_ai_usage` never had.
16
+ * - {@link pruneExpiredContexts} — enforcement for `_smrt_contexts.expires_at`.
17
+ * - {@link runRetentionSweep} — one entry point that applies a documented,
18
+ * opt-out {@link RetentionPolicy} across every framework-owned table, plus
19
+ * any task other packages contribute via {@link registerRetentionTask}
20
+ * (`@happyvertical/smrt-jobs` registers job/job-event cleanup;
21
+ * `@happyvertical/smrt-users` registers session and token expiry).
22
+ *
23
+ * Scheduling is the caller's: `smrt db:prune` is the cron entry point, and a
24
+ * running `TaskRunner` sweeps on an interval unless configured otherwise.
25
+ *
26
+ * ## Failure policy
27
+ *
28
+ * A sweep is maintenance, not a transaction. One failing task never aborts the
29
+ * rest — the failure is captured on that task's {@link RetentionTaskResult}
30
+ * and the sweep continues. Callers decide what a partial sweep means; the CLI
31
+ * exits non-zero when any task failed.
32
+ *
33
+ * ## Predicate indexes
34
+ *
35
+ * Every predicate below is indexed by the system DDL in `system/schema.ts`
36
+ * (`_smrt_contexts(expires_at)`, `_smrt_ai_usage(tenant_id, created_at)`,
37
+ * `_smrt_dispatch(status, processed_at)` / `(status, updated_at)`,
38
+ * `_smrt_run_once_claims(status, completed_at)`) or by the jobs compatibility
39
+ * path in `system/compatibility.ts` (`_smrt_jobs(status, completed_at)`,
40
+ * `_smrt_job_events(created_at)`). A new retention predicate must ship with
41
+ * its index.
42
+ *
43
+ * @see https://github.com/happyvertical/smrt/issues/2375
44
+ * @packageDocumentation
45
+ */
46
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
47
  /** Retention for the append-only change feed (`_smrt_changes`). */
3
48
  export interface ChangeFeedRetentionPolicy {
4
49
  /** Run this task (default `true`). */
@@ -1,4 +1,10 @@
1
- import { DatabaseEngine } from '../schema/ddl/types.js';
1
+ /**
2
+ * SMRT System Tables Schema
3
+ *
4
+ * System tables use _smrt_ prefix to avoid conflicts with user tables.
5
+ * All system tables are created in the same database as user data.
6
+ */
7
+ import type { DatabaseEngine } from '../schema/ddl/types.js';
2
8
  /**
3
9
  * Context memory storage
4
10
  * Stores remembered context (learned strategies, patterns, selectors) for reuse
@@ -1,4 +1,12 @@
1
- import { FieldDefinition } from './scanner/types.js';
1
+ /**
2
+ * Canonical SMRT system fields inherited from `SmrtObject`.
3
+ *
4
+ * These fields exist on every persistent object at runtime even when they are
5
+ * not declared in a child class manifest. Keep this definition lightweight:
6
+ * presence matters for metadata consumers, while schema generation still owns
7
+ * the exact SQL defaults and constraints for these columns.
8
+ */
9
+ import type { FieldDefinition } from './scanner/types.js';
2
10
  export declare const SMRT_SYSTEM_FIELDS: Readonly<Record<string, FieldDefinition>>;
3
11
  export declare function isInjectedSmrtSystemField(field: unknown): boolean;
4
12
  export declare function cloneSmrtSystemFields(): Record<string, FieldDefinition>;
@@ -1,4 +1,10 @@
1
- import { Mock } from 'vitest';
1
+ /**
2
+ * Comprehensive test utilities for SMRT framework testing
3
+ *
4
+ * Provides unified mocking for collections, objects, and database operations
5
+ * to support both CLI and API generator testing scenarios.
6
+ */
7
+ import { type Mock } from 'vitest';
2
8
  /**
3
9
  * Snapshot ObjectRegistry state and return a restore function for manifest-heavy
4
10
  * tests that mutate registry internals at runtime.
@@ -1,4 +1,21 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ /**
2
+ * Test database utilities for SMRT framework
3
+ *
4
+ * Provides `getTestDatabase()` which creates an in-memory database with all
5
+ * registered SMRT object schemas. Uses the same schema generation logic as
6
+ * the migration system to ensure consistency between test and production.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { getTestDatabase } from '@happyvertical/smrt-core/testing';
11
+ *
12
+ * beforeEach(async () => {
13
+ * const db = await getTestDatabase();
14
+ * collection = await MyCollection.create({ db });
15
+ * });
16
+ * ```
17
+ */
18
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
19
  /**
3
20
  * Options for creating a test database
4
21
  */
@@ -1,4 +1,18 @@
1
- import { DatabaseInterface } from '@happyvertical/sql';
1
+ /**
2
+ * In-process test double for the sql package's optional notification
3
+ * capability (`db.notifications`, e.g. Postgres LISTEN/NOTIFY).
4
+ *
5
+ * Attaches a push-driven `notify`/`listen` pair to a database handle so tests
6
+ * can exercise the cross-process / cross-replica paths of the collection cache
7
+ * (#1498) and the change-signal bus (#1763) against a real in-memory SQLite
8
+ * database that has no native notification support. `notify` records every
9
+ * broadcast; `listen` exposes an async iterable that yields whatever `push`
10
+ * delivers.
11
+ *
12
+ * Extracted from `__tests__/issue-1498-collection-cache.test.ts` so the same
13
+ * double backs the change-signal bus tests without duplicating the stub.
14
+ */
15
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
16
  /** One notification as delivered over the stubbed channel. */
3
17
  export interface StubNotification {
4
18
  channel: string;
@@ -1,4 +1,9 @@
1
- import { SignalBus } from '../signals/bus.js';
1
+ /**
2
+ * Tool Call Execution for AI Function Calling
3
+ *
4
+ * This module handles runtime execution of AI tool calls on SMRT object instances.
5
+ */
6
+ import type { SignalBus } from '../signals/bus.js';
2
7
  /**
3
8
  * A dynamically-dispatched tool target (typically a SmrtObject instance, but
4
9
  * typed structurally so any object whose method names are resolved at runtime
@@ -1,5 +1,11 @@
1
- import { AITool } from '@happyvertical/ai';
2
- import { MethodDefinition } from '../scanner/types.js';
1
+ /**
2
+ * Tool Manifest Generation for AI Function Calling
3
+ *
4
+ * This module converts TypeScript method definitions from the AST scanner
5
+ * into AI tool format at build time for use with LLM function calling.
6
+ */
7
+ import type { AITool } from '@happyvertical/ai';
8
+ import type { MethodDefinition } from '../scanner/types.js';
3
9
  /**
4
10
  * A JSON Schema fragment. The shape is open-ended (different keywords appear
5
11
  * for primitives, arrays, unions, etc.), so values are `unknown`; callers
@@ -1,4 +1,12 @@
1
- import { JSONAdapter, ParseError, Result, StringifyError } from '@happyvertical/json';
1
+ /**
2
+ * JSON utilities with optional SIMD acceleration
3
+ *
4
+ * Uses @happyvertical/json for faster parsing when available,
5
+ * with automatic fallback to native JSON.
6
+ *
7
+ * Performance: 2-3x faster parsing on large JSON files (680KB manifests)
8
+ */
9
+ import { type JSONAdapter, type ParseError, type Result, type StringifyError } from '@happyvertical/json';
2
10
  /**
3
11
  * Parse JSON string with optional SIMD acceleration
4
12
  *
@@ -1,4 +1,13 @@
1
- import { QualifiedClassName } from '../scanner/types.js';
1
+ /**
2
+ * Utilities for working with qualified class names in the SMRT framework.
3
+ *
4
+ * Qualified names follow the format: "@package/name:ClassName"
5
+ * Example: "@happyvertical/smrt-core:Product"
6
+ *
7
+ * This format uniquely identifies classes across packages, eliminating
8
+ * name collisions when multiple packages define classes with the same name.
9
+ */
10
+ import type { QualifiedClassName } from '../scanner/types.js';
2
11
  /**
3
12
  * Creates a qualified class name from package name and class name.
4
13
  *
@@ -1,5 +1,5 @@
1
- import { CapabilityClassification, DomainKnowledgePlaybookStep } from '@happyvertical/smrt-types';
2
- import { SmartObjectManifest } from '../scanner/types.js';
1
+ import type { CapabilityClassification, DomainKnowledgePlaybookStep } from '@happyvertical/smrt-types';
2
+ import type { SmartObjectManifest } from '../scanner/types.js';
3
3
  /**
4
4
  * The scanner's declared agent surface (#2591), mirrored structurally like the
5
5
  * rest of this module.
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SmrtObject } from './object';
1
+ import type { SmrtObject } from './object';
2
2
  import { classnameToTablename, pluralize, toSnakeCase } from './utils/naming.js';
3
3
  import { toSafeBooleanInteger, toSafeInteger } from './utils/safe-integer.js';
4
4
  export { classnameToTablename, pluralize, toSafeBooleanInteger, toSafeInteger, toSnakeCase, };
@@ -1,4 +1,12 @@
1
- import { SmartObjectDefinition, SmartObjectManifest } from '../scanner/types.js';
1
+ /**
2
+ * Manifest -> generated API-client entry selection.
3
+ *
4
+ * Runtime client values, Vite ambient declarations, and physical prebuild
5
+ * declarations must agree on which manifest object owns a collection's
6
+ * canonical endpoint. Collection classes describe access methods, not row
7
+ * payloads, so a populated model always wins the shared collection key.
8
+ */
9
+ import type { SmartObjectDefinition, SmartObjectManifest } from '../scanner/types.js';
2
10
  export type ApiClientCrudMethod = 'list' | 'get' | 'create' | 'update' | 'delete' | 'search';
3
11
  export interface ApiClientEntry {
4
12
  /** Original key in manifest.objects. */
@@ -1,5 +1,36 @@
1
- import { SmartObjectManifest } from '../scanner/types';
2
- import { SvelteKitOptions } from './sveltekit-generator.js';
1
+ /**
2
+ * SvelteKit `_changes` route generation for the change feed (issue #1758).
3
+ *
4
+ * Emits `{routesDir}/_changes/+server.ts` — an auth-guarded, tenant-scoped
5
+ * GET endpoint over the `_smrt_changes` log, part of the client/mobile sync
6
+ * contract (PRD #1755). Kept in its own module so `sveltekit-generator.ts`
7
+ * only carries a one-line registration.
8
+ *
9
+ * Design notes:
10
+ * - **Fail-closed auth** (#1540 posture): the handler requires an
11
+ * authenticated principal on `locals`. The feed spans every table, so
12
+ * per-model `api: { public }` opt-outs deliberately do not apply.
13
+ * - **Tenant scoping**: when the project has tenant-scoped objects, the
14
+ * route establishes tenant context from `locals` exactly like generated
15
+ * collection routes, then reads through
16
+ * `getAuthorizedTenantScopedChangesSince()` — a tenant only ever sees its
17
+ * own changes plus global rows.
18
+ * - **Table/row authorization** (#3020): the same call additionally applies
19
+ * the consumer-supplied `authorizeChangeFeed`/`isChangeFeedEntryVisible`
20
+ * hooks (`@happyvertical/smrt-core`'s `change-feed-authz.ts`), if
21
+ * registered — a table-level and row-level seam beyond tenant scope (e.g. a
22
+ * station principal reading only its own rows of a table the office can
23
+ * read in full). Unregistered, behavior is unchanged from pre-#3020.
24
+ * - **Database resolution**: the route anchors on the project's first
25
+ * generated collection (alphabetical) via the consumer's existing
26
+ * `getCollection()` helper, inheriting its configuration, request-scoped
27
+ * database support and system-table bootstrap. Multi-database projects
28
+ * (per-object `db` overrides) see the anchor collection's feed.
29
+ * - Cleanup rides the existing generated-route sweep: the emitted file
30
+ * starts with {@link AUTO_GENERATED_ROUTE_HEADER}.
31
+ */
32
+ import type { SmartObjectManifest } from '../scanner/types';
33
+ import type { SvelteKitOptions } from './sveltekit-generator.js';
3
34
  /**
4
35
  * Pick the class the route resolves its database through: the first
5
36
  * non-collection object by sorted manifest key, for determinism across
@@ -1,4 +1,15 @@
1
- import { SvelteKitOptions } from './sveltekit-generator.js';
1
+ /**
2
+ * Generated `_dev/[...tool]/+server.ts` route: the in-app runtime dev-plane
3
+ * (#2782). Opt-in via `svelteKit: { devPlaneRoute: { enabled: true } }`.
4
+ *
5
+ * The route is dev-only twice over: it 404s unless SvelteKit's `dev` flag is
6
+ * set, and it refuses to start without `SMRT_DEV_MCP_TOKEN`. Everything else
7
+ * — loopback checks, bearer auth, the positive read-only catalog, the MCP
8
+ * endpoint — lives in `@happyvertical/smrt-dev-mcp/dev-plane`, which the
9
+ * generated file imports at consumer runtime. Like `_resources`, the route is
10
+ * only emitted when that subpath resolves from the consumer.
11
+ */
12
+ import type { SvelteKitOptions } from './sveltekit-generator.js';
2
13
  /** Whether `@happyvertical/smrt-dev-mcp/dev-plane` resolves from the consumer. */
3
14
  export declare function consumerHasSmrtDevMcp(projectRoot: string): boolean;
4
15
  /** Whether this invocation will own the `_dev/[...tool]` output file. */
@@ -1,5 +1,40 @@
1
- import { SmartObjectManifest } from '../scanner/types';
2
- import { SvelteKitOptions } from './sveltekit-generator.js';
1
+ /**
2
+ * SvelteKit `_events` route generation — live change signals (issue #1763,
3
+ * SERVER half; parent PRD #1755).
4
+ *
5
+ * Emits `{routesDir}/_events/+server.ts` — an auth-guarded, tenant-scoped
6
+ * Server-Sent-Events endpoint that streams coarse change signals (no row
7
+ * payloads). It is the push companion to the generated `_changes` route
8
+ * (#1758). Kept in its own module so `sveltekit-generator.ts` only carries a
9
+ * one-line registration.
10
+ *
11
+ * The stream lifecycle (subscribe, catch-up, heartbeat, teardown) lives in
12
+ * core's `buildChangeEventStream`, imported by the generated file — so the
13
+ * emitted route stays THIN and the stream logic is written and tested once.
14
+ *
15
+ * Design notes (mirror `changes-route.ts`):
16
+ * - **Fail-closed auth** (#1540 posture): the handler requires an authenticated
17
+ * principal on `locals`. The signal stream spans every table, so per-model
18
+ * `api: { public }` opt-outs deliberately do not apply.
19
+ * - **Tenant scoping**: when the project has tenant-scoped objects, the route
20
+ * establishes tenant context from `locals` exactly like the `_changes` route,
21
+ * then captures the resolved scope ONCE at connection open and passes it to
22
+ * the stream (delivery filters against that fixed value — it cannot
23
+ * re-resolve per signal outside the request's ALS context).
24
+ * - **Table/row authorization** (#3020): `locals` is forwarded to
25
+ * `buildChangeEventStream`, which — if the consumer registered
26
+ * `authorizeChangeFeed`/`isChangeFeedEntryVisible`
27
+ * (`@happyvertical/smrt-core`'s `change-feed-authz.ts`) — resolves the
28
+ * allowed tables ONCE at connection open (same reasoning as tenant scope)
29
+ * and applies both hooks to catch-up replay AND every live signal before it
30
+ * is enqueued. Unregistered, behavior is unchanged from pre-#3020.
31
+ * - **Database resolution**: anchors on the project's first generated
32
+ * collection (alphabetical) via `getCollection()`, exactly as `_changes`.
33
+ * - Cleanup rides the generated-route sweep: the file starts with
34
+ * {@link AUTO_GENERATED_ROUTE_HEADER}.
35
+ */
36
+ import type { SmartObjectManifest } from '../scanner/types';
37
+ import type { SvelteKitOptions } from './sveltekit-generator.js';
3
38
  /**
4
39
  * Generate the `_events/+server.ts` route. Returns true when a route was
5
40
  * written. Disabled with `sveltekit: { eventsRoute: { enabled: false } }`;
@@ -1,4 +1,12 @@
1
- import { SmartObjectManifest } from '../scanner/types.js';
1
+ /**
2
+ * Shared runtime generator for producer and consumer `@smrt/client` modules.
3
+ *
4
+ * Keep runtime values on the same manifest-derived contract as physical and
5
+ * virtual declarations. In particular, disabled objects, partial CRUD
6
+ * allowlists, stable collection keys, and custom route signatures must not
7
+ * diverge between the two plugin entry points.
8
+ */
9
+ import type { SmartObjectManifest } from '../scanner/types.js';
2
10
  export declare const GENERATED_CLIENT_CRUD_METHODS: Set<string>;
3
11
  export declare const GENERATED_CLIENT_BASE_METHODS: Set<string>;
4
12
  export declare function generateClientModule(manifest: SmartObjectManifest, options?: {