@happyvertical/smrt-cli 0.60.9 → 0.60.11

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 (55) hide show
  1. package/AGENTS.md +24 -53
  2. package/README.md +5 -0
  3. package/agents/app-commands.md +2 -0
  4. package/agents/db-drop-framework-base-tables.md +49 -0
  5. package/agents/db-migrate-concurrency.md +11 -0
  6. package/dist/{AuditLogCollection-BBbvr8Qc-CoDs0BaX.js → AuditLogCollection-BBbvr8Qc-mcBSLXW9.js} +1 -1
  7. package/dist/{OidcIdentity-COeMidoC-B-cVovG3.js → OidcIdentity-COeMidoC-ETkpZbIS.js} +2 -2
  8. package/dist/{OidcIdentityCollection-D4DIZv0K-CexIL7No.js → OidcIdentityCollection-D4DIZv0K-Do3bwRuw.js} +1 -1
  9. package/dist/{PasswordCredentialService-DHJNKEeJ-DQlR62e-.js → PasswordCredentialService-BSSP_kyT-t7bjBu4L.js} +40 -22
  10. package/dist/{ProfileAssetCollection-D5-tG9Mm-Bmn4-Urc.js → ProfileAssetCollection-D5-tG9Mm-FbzWS3Fo.js} +3 -3
  11. package/dist/{ProfileCollection-CmRaiE9U-52qjwbhJ.js → ProfileCollection-CmRaiE9U-BYvpJg0y.js} +17 -17
  12. package/dist/{ProfileLinkCollection-pvPTsysg-ocN3hj_M.js → ProfileLinkCollection-pvPTsysg-nDbgawOW.js} +2 -2
  13. package/dist/{ProfileMetadataCollection-CAgJyjze-FX20yKjY.js → ProfileMetadataCollection-CAgJyjze-D-5QuGnR.js} +1 -1
  14. package/dist/{ProfileMetafieldCollection-19ae6Lpf-qg7eMcJk.js → ProfileMetafieldCollection-19ae6Lpf-CgEt1gPi.js} +1 -1
  15. package/dist/{ProfileRelationshipCollection-BFSlTQ7J-DlDILj3m.js → ProfileRelationshipCollection-BFSlTQ7J-Dv0ll9S1.js} +1 -1
  16. package/dist/{ProfileTypeCollection-BRLK8cHS-QVwjfqe8.js → ProfileTypeCollection-BRLK8cHS-BKuh_ajh.js} +2 -2
  17. package/dist/app/portability-assets.d.ts +2 -0
  18. package/dist/app/portability-assets.d.ts.map +1 -1
  19. package/dist/app.js +2 -2
  20. package/dist/{cli-CtRx1_yP.js → cli-DXIN1FbA.js} +1 -1
  21. package/dist/commands/docs-claude.d.ts +1 -0
  22. package/dist/commands/docs-claude.d.ts.map +1 -1
  23. package/dist/commands/docs-knowledge-bundle.d.ts +87 -0
  24. package/dist/commands/docs-knowledge-bundle.d.ts.map +1 -0
  25. package/dist/commands/docs-skills-install.d.ts +31 -0
  26. package/dist/commands/docs-skills-install.d.ts.map +1 -0
  27. package/dist/{commands-DNssH5Dv.js → commands-DD5gexRY.js} +400 -7
  28. package/dist/{dist-BJABhykg.js → dist-CivxAJ6C.js} +2 -2
  29. package/dist/dist-DcYLLDwF.js +1854 -0
  30. package/dist/{dist-D25iWIXX.js → dist-DjG0qPkx.js} +5 -5
  31. package/dist/index.js +12 -12
  32. package/dist/knowledge/intents/audit-trail.md +63 -0
  33. package/dist/knowledge/intents/auth-and-users.md +67 -0
  34. package/dist/knowledge/intents/background-work.md +72 -0
  35. package/dist/knowledge/intents/feature-flags-and-entitlements.md +60 -0
  36. package/dist/knowledge/intents/file-and-asset-storage.md +71 -0
  37. package/dist/knowledge/intents/human-approvals.md +56 -0
  38. package/dist/knowledge/intents/index.md +41 -0
  39. package/dist/knowledge/intents/money-and-rates.md +65 -0
  40. package/dist/knowledge/intents/outbound-messages.md +67 -0
  41. package/dist/knowledge/intents/prompts-and-ai-operations.md +72 -0
  42. package/dist/knowledge/intents/relationships-and-trees.md +56 -0
  43. package/dist/knowledge/intents/scheduled-runs.md +61 -0
  44. package/dist/knowledge/intents/search-facts-knowledge.md +68 -0
  45. package/dist/knowledge/intents/secrets-and-config.md +66 -0
  46. package/dist/knowledge/intents/tenant-scoping.md +63 -0
  47. package/dist/knowledge/intents/webhooks-and-events.md +71 -0
  48. package/dist/{oidcProvisioningPrimitives-KpIiLmG4-CnRTofeV.js → oidcProvisioningPrimitives-KpIiLmG4-D5-0dAY3.js} +3 -3
  49. package/dist/{operator-fwao3Y1j.js → operator-B0ZraSEE.js} +2 -2
  50. package/dist/{portability-CbMgEnD1.js → portability-sL8U5Hld.js} +21 -13
  51. package/dist/{resolveIdentity-j2WFuKDT-C9XtigVZ.js → resolveIdentity-j2WFuKDT-BieMIOLz.js} +14 -14
  52. package/dist/smrt-knowledge.okf.md +58 -0
  53. package/package.json +16 -15
  54. package/dist/dist-B3gpMpBj.js +0 -1908
  55. package/dist/dist-BQI8s_yA.js +0 -1854
package/AGENTS.md CHANGED
@@ -95,14 +95,8 @@ it in the same migration also run outside the transaction, in order.
95
95
  resumes at the index build — their `error_message` carries a
96
96
  `[smrt: concurrent-index phase 1 committed]` marker, so the non-index
97
97
  statements that already committed are not re-run.
98
- - INVALID indexes — the stump a cancelled or timed-out
99
- `CREATE INDEX CONCURRENTLY` leaves, which `pg_indexes` still reports as
100
- present — are detected via `pg_index.indisvalid` and dropped before the
101
- rebuild.
102
- - `migrations.postgres.useConcurrently: false` vetoes the flag; index DDL then
103
- runs inside the atomic transaction (still bounded by the timeouts).
104
- - Without the flag, a batch containing explicit `CONCURRENTLY` DDL is rejected
105
- before the transaction opens — PostgreSQL cannot run it there.
98
+ - INVALID-index cleanup, the `useConcurrently: false` veto, and the explicit-`CONCURRENTLY` rejection:
99
+ agents/db-migrate-concurrency.md.
106
100
 
107
101
  ## `doctor`'s agent-surface section (#2591)
108
102
 
@@ -283,51 +277,8 @@ exactly those five hardcoded names and nothing else — **never** derived from
283
277
  drop `includeDroppedTables` (default `false`, both call sites explicit —
284
278
  `differ.ts:450`, `db-diff.ts:210`) deliberately refuses to be.
285
279
 
286
- - Execute-or-refuse, like `db:rollback`: it refuses (non-zero exit, nothing
287
- dropped) if any target table has rows, has anything but that table's own
288
- expected columns and types, or is referenced by a foreign key anywhere in
289
- the live database. A consumer's own unrelated table sharing one of these
290
- five names is exactly what the shape check protects.
291
- - The expected shape is **per table, not one universal baseline**:
292
- `smrt_objects`/`smrt_classes`/`smrt_collections` are exactly `id`/`slug`/
293
- `context`/`created_at`/`updated_at`, but `smrt_hierarchicals` also
294
- requires `parent_id` and `smrt_polymorphic_associations` also requires
295
- `meta_type`/`meta_id`/`role`/`sort_order` — `SmrtHierarchical`'s and
296
- `SmrtPolymorphicAssociation`'s own real fields, confirmed against a
297
- genuine pre-#2644 `db:migrate` run. A table under either of those two
298
- names with *only* the plain five columns is refused as unexpected shape,
299
- not treated as safe.
300
- - Companion indexes are enumerated from each table's live schema (never
301
- guessed). `smrt_hierarchicals`/`smrt_polymorphic_associations` do not
302
- carry the `created_at` list-ordering index the other three do (also
303
- empirically confirmed, not assumed).
304
- - Bounded PostgreSQL execution reuses the same `SET LOCAL lock_timeout` /
305
- `statement_timeout` pattern as every other DDL path (#2362). Every target
306
- is locked `IN ACCESS EXCLUSIVE MODE` before re-checking it — a plain
307
- `SELECT COUNT(*)` alone would not block a concurrent writer — and shape,
308
- type, and emptiness are all re-verified inside that transaction
309
- immediately before dropping anything, via raw `information_schema.columns`
310
- / `PRAGMA table_info` (`getTableSchema()` is not available on the
311
- transaction-scoped connection). Only `DROP TABLE` is ever executed —
312
- never a `DROP INDEX` by name — so `DROP TABLE`'s own cascade removes the
313
- table's indexes identity-safely instead of trusting a possibly-stale
314
- planned index name.
315
- - `--dry-run` prints the exact plan (which tables exist, their companion
316
- indexes, and the DROP statements) without executing.
317
- - Skipping it is safe: a table left behind is inert and permanently orphaned,
318
- never written to or read from again. Documented, narrow residual risk, all
319
- schema-integrity (never data loss — the target is always verified empty
320
- first): DuckDB's adapter does not report foreign keys through
321
- `getTableSchema()` at all; this module's reverse-FK scan (like every other
322
- PostgreSQL schema tool in this package) only looks at the `public` schema;
323
- and foreign keys are checked at planning time only, not re-scanned inside
324
- the execution transaction. On PostgreSQL a foreign key that appeared after
325
- planning is still caught there — `DROP TABLE` refuses when a real
326
- dependent exists, dependency-based, empty parent or not. **This does not
327
- hold on SQLite**: its FK enforcement on `DROP TABLE` is row-based, so an
328
- empty parent (this command's precondition) drops cleanly past a real
329
- foreign key, verified directly. The plan-time scan is the only gate on
330
- SQLite/DuckDB, narrower than PostgreSQL's.
280
+ Execute-or-refuse, per-table shape checks, lock/timeout behavior, `--dry-run`, and the residual risks of
281
+ skipping it: agents/db-drop-framework-base-tables.md.
331
282
 
332
283
  ## Architecture
333
284
 
@@ -344,6 +295,26 @@ drop `includeDroppedTables` (default `false`, both call sites explicit —
344
295
  - `src/loaders/` — class-loader, local-loader, npm-loader, git-loader, template-loader
345
296
  - `src/discovery/manifest-discovery.ts` — manifest auto-discovery
346
297
  - `src/commands/docs-claude.ts` — downstream AGENTS.md generation + Claude alias; no object scanning
298
+ - `src/commands/docs-knowledge-bundle.ts` — knowledge-bundle half of `docs:agents`
299
+ - `src/commands/docs-skills-install.ts` — skill-installation half of `docs:agents` (#4708)
300
+
301
+ ## docs:agents knowledge bundle (consumer contract)
302
+
303
+ Beside the output file, `docs:agents` writes `smrt-knowledge/` (`.agents/smrt-knowledge/`; `docs:claude` → `.claude/`):
304
+ `bundle.json` (`smrt-okf-bundle/1`: `exportedAt` kept while content is unchanged, `packages[{name,version,concept}]`,
305
+ `intents`), `components/<unscoped>.md` per installed package shipping `dist/smrt-knowledge.okf.md` with
306
+ `package_version` re-stamped from the installed `package.json`, and `intents/*` limited to intents with ≥1 installed
307
+ home. `smrt-framework.md` leads with `## Find it by intent` over those same intents. Pages come from the published
308
+ artifacts — `scripts/ship-knowledge-pages.mjs` (root `pnpm build`, `prepack-package.js`) copies the committed
309
+ `docs/knowledge` pages into `dist/`; intents ship in smrt-cli `dist/knowledge/intents/` — never from a checkout (monorepo
310
+ runs fall back to `docs/knowledge`). Links to uninstalled packages' pages dangle by design. The shape lives in
311
+ `@happyvertical/smrt-dev-mcp/knowledge` (`okf-bundle.ts`); `dev:knowledge-check` reads it (`stale-okf-bundle`).
312
+
313
+ Skill install (#4708): unless `--no-install-skills`, `docs:agents` also writes the `smrt-catalog` skill from
314
+ `@happyvertical/smrt-dev-mcp` to `.claude/skills/smrt-catalog/SKILL.md` and `.agents/skills/smrt-catalog/SKILL.md`
315
+ under the working directory (skipped on `--dry-run`). The copy carries a `<!-- smrt-generated: … smrt-dev-mcp@<version> … -->`
316
+ marker after the frontmatter: a rerun replaces a marked copy, a copy without the marker is left alone with a warning.
317
+ The shipped text names `.agents/smrt-knowledge/`; the installer substitutes the real bundle dir (`docs:claude`, custom `--output`). Only the smrt repository itself (root `package.json` name `@happyvertical/smrt`, not any pnpm monorepo) also gets `smrt-contribute`; an unmarked copy byte-identical to the shipped skill (the repo's own `.agents/skills/smrt-contribute`) counts as current. Destinations go through `containedPath` and are refused when any path segment is a symlink, before any write.
347
318
 
348
319
  ## Gotchas
349
320
 
package/README.md CHANGED
@@ -186,6 +186,11 @@ alias supports the same flag and retains its historical output path.
186
186
  Regenerate snapshots after moving the project or updating dependencies so the
187
187
  local source paths remain current.
188
188
 
189
+ `docs:agents` also installs the `smrt-catalog` agent skill into
190
+ `.claude/skills/` and `.agents/skills/` so an agent consults the knowledge
191
+ catalog before hand-rolling infrastructure. Pass `--no-install-skills` to skip
192
+ it. A copy you edited (the generated marker removed) is never overwritten.
193
+
189
194
  Review and architecture prompt bundles include package guidance and modules
190
195
  matched by file or focus hints. Add `--complete` to either context command to
191
196
  include every module for the selected packages. These commands still build the
@@ -97,6 +97,8 @@ config loading; `bin/smrt.js` imports `dist/` in-process so SIGTERM reaches
97
97
  publishes via `link()` (never replaces); import requires a 0600 regular
98
98
  bundle for the same app, an exactly matching manifest schema, and an empty
99
99
  target; deployed import requires `SMRT_MAINTENANCE_MODE=true`.
100
+ Local relative asset locators resolve against the approved asset root during
101
+ export and stay relative after import. Legacy file URLs import as file URLs.
100
102
  - **Process identity**: `app.pid` is trusted only when the live command
101
103
  line's last two tokens are a path with basename `smrt-web.mjs` and exactly
102
104
  `--smrt-instance=<record instance>` (an app started by the template's former
@@ -0,0 +1,49 @@
1
+ # `db:drop-framework-base-tables` details (#2647)
2
+
3
+ Detail for the one-time remediation described in `AGENTS.md`.
4
+
5
+ - Execute-or-refuse, like `db:rollback`: it refuses (non-zero exit, nothing
6
+ dropped) if any target table has rows, has anything but that table's own
7
+ expected columns and types, or is referenced by a foreign key anywhere in
8
+ the live database. A consumer's own unrelated table sharing one of these
9
+ five names is exactly what the shape check protects.
10
+ - The expected shape is **per table, not one universal baseline**:
11
+ `smrt_objects`/`smrt_classes`/`smrt_collections` are exactly `id`/`slug`/
12
+ `context`/`created_at`/`updated_at`, but `smrt_hierarchicals` also
13
+ requires `parent_id` and `smrt_polymorphic_associations` also requires
14
+ `meta_type`/`meta_id`/`role`/`sort_order` — `SmrtHierarchical`'s and
15
+ `SmrtPolymorphicAssociation`'s own real fields, confirmed against a
16
+ genuine pre-#2644 `db:migrate` run. A table under either of those two
17
+ names with *only* the plain five columns is refused as unexpected shape,
18
+ not treated as safe.
19
+ - Companion indexes are enumerated from each table's live schema (never
20
+ guessed). `smrt_hierarchicals`/`smrt_polymorphic_associations` do not
21
+ carry the `created_at` list-ordering index the other three do (also
22
+ empirically confirmed, not assumed).
23
+ - Bounded PostgreSQL execution reuses the same `SET LOCAL lock_timeout` /
24
+ `statement_timeout` pattern as every other DDL path (#2362). Every target
25
+ is locked `IN ACCESS EXCLUSIVE MODE` before re-checking it — a plain
26
+ `SELECT COUNT(*)` alone would not block a concurrent writer — and shape,
27
+ type, and emptiness are all re-verified inside that transaction
28
+ immediately before dropping anything, via raw `information_schema.columns`
29
+ / `PRAGMA table_info` (`getTableSchema()` is not available on the
30
+ transaction-scoped connection). Only `DROP TABLE` is ever executed —
31
+ never a `DROP INDEX` by name — so `DROP TABLE`'s own cascade removes the
32
+ table's indexes identity-safely instead of trusting a possibly-stale
33
+ planned index name.
34
+ - `--dry-run` prints the exact plan (which tables exist, their companion
35
+ indexes, and the DROP statements) without executing.
36
+ - Skipping it is safe: a table left behind is inert and permanently orphaned,
37
+ never written to or read from again. Documented, narrow residual risk, all
38
+ schema-integrity (never data loss — the target is always verified empty
39
+ first): DuckDB's adapter does not report foreign keys through
40
+ `getTableSchema()` at all; this module's reverse-FK scan (like every other
41
+ PostgreSQL schema tool in this package) only looks at the `public` schema;
42
+ and foreign keys are checked at planning time only, not re-scanned inside
43
+ the execution transaction. On PostgreSQL a foreign key that appeared after
44
+ planning is still caught there — `DROP TABLE` refuses when a real
45
+ dependent exists, dependency-based, empty parent or not. **This does not
46
+ hold on SQLite**: its FK enforcement on `DROP TABLE` is row-based, so an
47
+ empty parent (this command's precondition) drops cleanly past a real
48
+ foreign key, verified directly. The plan-time scan is the only gate on
49
+ SQLite/DuckDB, narrower than PostgreSQL's.
@@ -53,3 +53,14 @@ are written after the diff, when both runs have already planned.
53
53
  — two concurrent CLI runs apply one batch; a held lock blocks a run before it
54
54
  touches schema. Each run gets its own pool (`getDatabase` caches one pool per
55
55
  identity in-process, which two real processes would not share).
56
+
57
+ ## Index and flag details
58
+
59
+ - INVALID indexes — the stump a cancelled or timed-out
60
+ `CREATE INDEX CONCURRENTLY` leaves, which `pg_indexes` still reports as
61
+ present — are detected via `pg_index.indisvalid` and dropped before the
62
+ rebuild.
63
+ - `migrations.postgres.useConcurrently: false` vetoes the flag; index DDL then
64
+ runs inside the atomic transaction (still bounded by the timeouts).
65
+ - Without the flag, a batch containing explicit `CONCURRENTLY` DDL is rejected
66
+ before the transaction opens — PostgreSQL cannot run it there.
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { i as tenantId, r as TenantScoped } from "./dist-BJABhykg.js";
2
+ import { i as tenantId, r as TenantScoped } from "./dist-CivxAJ6C.js";
3
3
  import { n as __exportAll$1 } from "./NostrIdentity-RJaATTCt-BbRHWyee.js";
4
4
  import { SmrtCollection, SmrtObject, field, foreignKey, smrt } from "@happyvertical/smrt-core";
5
5
  //#region ../profiles/dist/chunks/AuditLogCollection-BBbvr8Qc.js
@@ -42,7 +42,7 @@ var OidcIdentity = class extends SmrtObject {
42
42
  * Find identity by issuer and subject
43
43
  */
44
44
  static async findBySubject(issuer, subject, options = {}) {
45
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D4DIZv0K-CexIL7No.js").then((n) => n.r).then((n) => n.r);
45
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D4DIZv0K-Do3bwRuw.js").then((n) => n.r).then((n) => n.r);
46
46
  return await (await OidcIdentityCollection.create(options)).findBySubject(issuer, subject);
47
47
  }
48
48
  /** Build the collision-free natural key for one OIDC issuer subject. */
@@ -65,7 +65,7 @@ var OidcIdentity = class extends SmrtObject {
65
65
  static async findOrCreate(profile, oidcData, options = {}) {
66
66
  const profileId = profile.id;
67
67
  if (typeof profileId !== "string" || !profileId) throw new Error("OidcIdentity.findOrCreate() requires a saved Profile.");
68
- const { reuseExistingOidcIdentityForProfile } = await import("./resolveIdentity-j2WFuKDT-C9XtigVZ.js").then((n) => n.t).then((n) => n.i);
68
+ const { reuseExistingOidcIdentityForProfile } = await import("./resolveIdentity-j2WFuKDT-BieMIOLz.js").then((n) => n.t).then((n) => n.i);
69
69
  const profileOptions = profile.options ?? {};
70
70
  return (await reuseExistingOidcIdentityForProfile(profileId, {
71
71
  email: oidcData.email,
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { n as __exportAll$1 } from "./NostrIdentity-RJaATTCt-BbRHWyee.js";
3
- import { t as OidcIdentity } from "./OidcIdentity-COeMidoC-B-cVovG3.js";
3
+ import { t as OidcIdentity } from "./OidcIdentity-COeMidoC-ETkpZbIS.js";
4
4
  import { SmrtCollection } from "@happyvertical/smrt-core";
5
5
  //#region ../profiles/dist/chunks/OidcIdentityCollection-D4DIZv0K.js
6
6
  var OidcIdentityCollection_D4DIZv0K_exports = /* @__PURE__ */ __exportAll({