@happyvertical/smrt-cli 0.49.3 → 0.49.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @happyvertical/smrt-cli
2
2
 
3
- Developer CLI with lazy-loaded commands, manifest discovery, and class introspection.
3
+ CLI with lazy-loaded commands, manifest discovery, and class introspection.
4
4
 
5
5
  ## Commands
6
6
 
@@ -16,7 +16,8 @@ smrt db:migrate --postgres-safe # PostgreSQL concurrent-index mode (see below)
16
16
  smrt db:migrate --force-migration <exact-id> [--force-migration <exact-id>...] # Force exact generated migrations in one atomic batch
17
17
  smrt db:migrate --apply-unblocked / --null-orphans # agents/db-migrate-partial-apply.md
18
18
  smrt db:migrate-uuid # Convert schema-declared UUID text columns after data remap
19
- smrt db:migrate-int8 # Explicitly widen pre-#2373 int4 columns after preflight
19
+ smrt db:migrate-int8
20
+ smrt db:migrate-null-equal-indexes # ../core/agents/null-equal-indexes.md
20
21
  smrt db:drop-framework-base-tables # One-time drop of the five #2644-orphaned framework-base tables
21
22
  smrt db:drop-framework-base-tables --dry-run # Print the drop plan without executing
22
23
  smrt db:diff # Show schema differences without generating migration files
@@ -23,7 +23,7 @@ import { homedir, tmpdir } from "node:os";
23
23
  import { extract } from "tar";
24
24
  import { importWorkspaceModule } from "@happyvertical/smrt-core/utils/import-workspace-module";
25
25
  import { renderForeignKeyAddStatements } from "@happyvertical/smrt-core/schema";
26
- import { FRAMEWORK_BASE_TABLE_NAMES, buildIntegerWidthTableStatements, collectIntegerWidthTargets, dropFrameworkBaseTables, parsePostgresTimeoutMs, planFrameworkBaseTableDrop, preflightIntegerWidthWidening, widenIntegerColumnsToBigInt } from "@happyvertical/smrt-core/migrations";
26
+ import { FRAMEWORK_BASE_TABLE_NAMES, buildIntegerWidthTableStatements, collectIntegerWidthTargets, collectNullEqualIndexTargets, dropFrameworkBaseTables, migrateNullEqualIndexes, nullEqualIndexStatements, parsePostgresTimeoutMs, planFrameworkBaseTableDrop, preflightIntegerWidthWidening, preflightNullEqualIndexes, widenIntegerColumnsToBigInt } from "@happyvertical/smrt-core/migrations";
27
27
  import { buildArchitectureContext, buildKnowledgeIndex, buildReviewContext, checkKnowledgeFreshness, compactContextResult, diffKnowledgeIndex, renderFreshnessResult, renderKnowledgeIndexMarkdown } from "@happyvertical/smrt-dev-mcp/knowledge";
28
28
  import { RUNTIME_TOOLS } from "@happyvertical/smrt-dev-mcp/runtime";
29
29
  //#region src/commands/db-command-utils.ts
@@ -6952,6 +6952,59 @@ var dbMigrateInt8Command = {
6952
6952
  }
6953
6953
  };
6954
6954
  //#endregion
6955
+ //#region src/commands/db-migrate-null-equal-indexes.ts
6956
+ var dbMigrateNullEqualIndexesCommand = {
6957
+ name: "db:migrate-null-equal-indexes",
6958
+ description: "Upgrade framework nullable conflict indexes on PostgreSQL 15+ in an explicit maintenance window. Run after db:migrate.",
6959
+ args: [],
6960
+ options: { "dry-run": {
6961
+ type: "boolean",
6962
+ default: false,
6963
+ description: "Inspect readiness, duplicates and proposed DDL without writing."
6964
+ } },
6965
+ handler: async (_args, options) => {
6966
+ let db;
6967
+ try {
6968
+ const { getPackageConfig } = await import("@happyvertical/smrt-config");
6969
+ const { DEFAULT_CLI_CONFIG } = await import("./config-DfBo4hHU.js").then((n) => n.n);
6970
+ const config = getPackageConfig("cli", DEFAULT_CLI_CONFIG);
6971
+ if (!config.database?.url || config.database.url === ":memory:") throw new Error("Database configuration required: set database.url in smrt.config.ts (or DATABASE_URL).");
6972
+ await autoDiscoverAndLoad();
6973
+ const schemas = ObjectRegistry.getAllSchemasAsDefinitions();
6974
+ if (!Object.keys(schemas).length) throw new Error("No SMRT schemas discovered. Run from the project root after generating manifests.");
6975
+ const type = config.database.type || "sqlite";
6976
+ const { getDatabase } = await import("@happyvertical/sql");
6977
+ db = await getDatabase({
6978
+ type,
6979
+ url: config.database.url
6980
+ });
6981
+ console.log(`Connected to ${formatDatabaseDisplayUrl(type, config.database.url)}`);
6982
+ const targets = collectNullEqualIndexTargets(schemas);
6983
+ const preflight = await preflightNullEqualIndexes(db, targets, { engineHint: type });
6984
+ console.log(preflight.summary);
6985
+ for (const index of preflight.indexes) {
6986
+ console.log(`${index.table}.${index.index}: ${index.state}${index.reason ? ` — ${index.reason}` : ""}`);
6987
+ if (index.state === "blocked") console.log(`Detector: ${index.detectorSql};`);
6988
+ if (index.state === "pending") for (const sql of nullEqualIndexStatements(index)) console.log(`${sql};`);
6989
+ }
6990
+ if (preflight.indexes.some((index) => index.state === "blocked")) throw new Error("Preflight blocked. Resolve the reported identities or dependencies; no changes applied.");
6991
+ if (!preflight.supported || options["dry-run"]) return;
6992
+ const result = await migrateNullEqualIndexes(db, targets, {
6993
+ engineHint: type,
6994
+ lockTimeout: config.migrations?.postgres?.lockTimeout,
6995
+ statementTimeout: config.migrations?.postgres?.statementTimeout
6996
+ });
6997
+ console.log(`Applied ${result.statements.length} index statements atomically.`);
6998
+ console.log("Refresh/restart database connections in EVERY application process to clear cached index capability probes. Until then the existing upsert fallback remains correct.");
6999
+ } catch (error) {
7000
+ console.error(`NULL-equal conflict-index migration failed: ${error instanceof Error ? error.message : String(error)}`);
7001
+ process.exitCode = 1;
7002
+ } finally {
7003
+ await closeDatabaseConnection(db);
7004
+ }
7005
+ }
7006
+ };
7007
+ //#endregion
6955
7008
  //#region src/commands/db-migrate-uuid.ts
6956
7009
  /**
6957
7010
  * db:migrate-uuid Command
@@ -10623,6 +10676,7 @@ export default testManifest;
10623
10676
  "db:generate": dbGenerateCommand,
10624
10677
  "db:migrate-uuid": dbMigrateUuidCommand,
10625
10678
  "db:migrate-int8": dbMigrateInt8Command,
10679
+ "db:migrate-null-equal-indexes": dbMigrateNullEqualIndexesCommand,
10626
10680
  "db:migrate-agent-schedule-slugs": dbMigrateAgentScheduleSlugsCommand,
10627
10681
  "db:drop-framework-base-tables": dbDropFrameworkBaseTablesCommand,
10628
10682
  "db:orphans": dbOrphansCommand,
package/dist/index.js CHANGED
@@ -49,63 +49,63 @@ var _playgroundCommands = null;
49
49
  var _workbenchCommands = null;
50
50
  async function getGnodeCommands() {
51
51
  if (!_gnodeCommands) {
52
- const { gnodeCommands } = await import("./commands-DEHkYYWF.js");
52
+ const { gnodeCommands } = await import("./commands-DxvVdCOS.js");
53
53
  _gnodeCommands = gnodeCommands;
54
54
  }
55
55
  return _gnodeCommands;
56
56
  }
57
57
  async function getGitCommands() {
58
58
  if (!_gitCommands) {
59
- const { gitCommands } = await import("./commands-DEHkYYWF.js");
59
+ const { gitCommands } = await import("./commands-DxvVdCOS.js");
60
60
  _gitCommands = gitCommands;
61
61
  }
62
62
  return _gitCommands;
63
63
  }
64
64
  async function getGenerateCommands() {
65
65
  if (!_generateCommands) {
66
- const { generateCommands } = await import("./commands-DEHkYYWF.js");
66
+ const { generateCommands } = await import("./commands-DxvVdCOS.js");
67
67
  _generateCommands = generateCommands;
68
68
  }
69
69
  return _generateCommands;
70
70
  }
71
71
  async function getInitCommands() {
72
72
  if (!_initCommands) {
73
- const { initCommands } = await import("./commands-DEHkYYWF.js");
73
+ const { initCommands } = await import("./commands-DxvVdCOS.js");
74
74
  _initCommands = initCommands;
75
75
  }
76
76
  return _initCommands;
77
77
  }
78
78
  async function getUtilityCommands() {
79
79
  if (!_utilityCommands) {
80
- const { utilityCommands } = await import("./commands-DEHkYYWF.js");
80
+ const { utilityCommands } = await import("./commands-DxvVdCOS.js");
81
81
  _utilityCommands = utilityCommands;
82
82
  }
83
83
  return _utilityCommands;
84
84
  }
85
85
  async function getDispatchCommands() {
86
86
  if (!_dispatchCommands) {
87
- const { dispatchCommands } = await import("./commands-DEHkYYWF.js");
87
+ const { dispatchCommands } = await import("./commands-DxvVdCOS.js");
88
88
  _dispatchCommands = dispatchCommands;
89
89
  }
90
90
  return _dispatchCommands;
91
91
  }
92
92
  async function getDocsCommands() {
93
93
  if (!_docsCommands) {
94
- const { docsCommands } = await import("./commands-DEHkYYWF.js");
94
+ const { docsCommands } = await import("./commands-DxvVdCOS.js");
95
95
  _docsCommands = docsCommands;
96
96
  }
97
97
  return _docsCommands;
98
98
  }
99
99
  async function getPlaygroundCommands() {
100
100
  if (!_playgroundCommands) {
101
- const { playgroundCommands } = await import("./commands-DEHkYYWF.js");
101
+ const { playgroundCommands } = await import("./commands-DxvVdCOS.js");
102
102
  _playgroundCommands = playgroundCommands;
103
103
  }
104
104
  return _playgroundCommands;
105
105
  }
106
106
  async function getWorkbenchCommands() {
107
107
  if (!_workbenchCommands) {
108
- const { workbenchCommands } = await import("./commands-DEHkYYWF.js");
108
+ const { workbenchCommands } = await import("./commands-DxvVdCOS.js");
109
109
  _workbenchCommands = workbenchCommands;
110
110
  }
111
111
  return _workbenchCommands;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-cli",
3
- "version": "0.49.3",
3
+ "version": "0.49.5",
4
4
  "description": "Developer CLI for SMRT framework - introspection, testing, and project management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,12 +28,12 @@
28
28
  "@happyvertical/ai": "^0.89.6",
29
29
  "@happyvertical/files": "^0.89.6",
30
30
  "@happyvertical/logger": "^0.89.6",
31
- "@happyvertical/smrt-agents": "0.49.3",
32
- "@happyvertical/smrt-config": "0.49.3",
33
- "@happyvertical/smrt-core": "0.49.3",
34
- "@happyvertical/smrt-dev-mcp": "0.49.3",
35
- "@happyvertical/smrt-playground": "0.49.3",
36
- "@happyvertical/smrt-types": "0.49.3",
31
+ "@happyvertical/smrt-agents": "0.49.5",
32
+ "@happyvertical/smrt-config": "0.49.5",
33
+ "@happyvertical/smrt-core": "0.49.5",
34
+ "@happyvertical/smrt-dev-mcp": "0.49.5",
35
+ "@happyvertical/smrt-playground": "0.49.5",
36
+ "@happyvertical/smrt-types": "0.49.5",
37
37
  "@happyvertical/sql": "^0.89.6",
38
38
  "@happyvertical/utils": "^0.89.6",
39
39
  "acorn": "^8.17.0",