@mindflight/mindbrain-personal-studio 0.6.1

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 (166) hide show
  1. package/.env.example +50 -0
  2. package/README.md +134 -0
  3. package/bin/mindbrain-studio.mjs +20 -0
  4. package/build/client/_app/immutable/assets/2.BXRKVU9n.css +1 -0
  5. package/build/client/_app/immutable/assets/2.BXRKVU9n.css.br +0 -0
  6. package/build/client/_app/immutable/assets/2.BXRKVU9n.css.gz +0 -0
  7. package/build/client/_app/immutable/chunks/-OSExkSk.js +2 -0
  8. package/build/client/_app/immutable/chunks/-OSExkSk.js.br +0 -0
  9. package/build/client/_app/immutable/chunks/-OSExkSk.js.gz +0 -0
  10. package/build/client/_app/immutable/chunks/BIHI7g3E.js +1 -0
  11. package/build/client/_app/immutable/chunks/BIHI7g3E.js.br +2 -0
  12. package/build/client/_app/immutable/chunks/BIHI7g3E.js.gz +0 -0
  13. package/build/client/_app/immutable/chunks/BJB7pSge.js +1 -0
  14. package/build/client/_app/immutable/chunks/BJB7pSge.js.br +0 -0
  15. package/build/client/_app/immutable/chunks/BJB7pSge.js.gz +0 -0
  16. package/build/client/_app/immutable/chunks/BNUkRZqg.js +1 -0
  17. package/build/client/_app/immutable/chunks/BNUkRZqg.js.br +0 -0
  18. package/build/client/_app/immutable/chunks/BNUkRZqg.js.gz +0 -0
  19. package/build/client/_app/immutable/chunks/BP2JbIUZ.js +1 -0
  20. package/build/client/_app/immutable/chunks/BP2JbIUZ.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/BP2JbIUZ.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/BVrgUHq-.js +1 -0
  23. package/build/client/_app/immutable/chunks/BVrgUHq-.js.br +0 -0
  24. package/build/client/_app/immutable/chunks/BVrgUHq-.js.gz +0 -0
  25. package/build/client/_app/immutable/chunks/BmeSanva.js +1 -0
  26. package/build/client/_app/immutable/chunks/BmeSanva.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/BmeSanva.js.gz +0 -0
  28. package/build/client/_app/immutable/chunks/BnkCgNCx.js +1 -0
  29. package/build/client/_app/immutable/chunks/BnkCgNCx.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/BnkCgNCx.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/C5KYKPa8.js +311 -0
  32. package/build/client/_app/immutable/chunks/C5KYKPa8.js.br +0 -0
  33. package/build/client/_app/immutable/chunks/C5KYKPa8.js.gz +0 -0
  34. package/build/client/_app/immutable/chunks/CBDzfqXr.js +1 -0
  35. package/build/client/_app/immutable/chunks/CBDzfqXr.js.br +0 -0
  36. package/build/client/_app/immutable/chunks/CBDzfqXr.js.gz +0 -0
  37. package/build/client/_app/immutable/chunks/Cp9dXlPT.js +1 -0
  38. package/build/client/_app/immutable/chunks/Cp9dXlPT.js.br +0 -0
  39. package/build/client/_app/immutable/chunks/Cp9dXlPT.js.gz +0 -0
  40. package/build/client/_app/immutable/chunks/D0daF8Eh.js +2 -0
  41. package/build/client/_app/immutable/chunks/D0daF8Eh.js.br +0 -0
  42. package/build/client/_app/immutable/chunks/D0daF8Eh.js.gz +0 -0
  43. package/build/client/_app/immutable/chunks/D4SoBmS0.js +1 -0
  44. package/build/client/_app/immutable/chunks/D4SoBmS0.js.br +0 -0
  45. package/build/client/_app/immutable/chunks/D4SoBmS0.js.gz +0 -0
  46. package/build/client/_app/immutable/chunks/DpVrWha3.js +1 -0
  47. package/build/client/_app/immutable/chunks/DpVrWha3.js.br +0 -0
  48. package/build/client/_app/immutable/chunks/DpVrWha3.js.gz +0 -0
  49. package/build/client/_app/immutable/chunks/DyXQogav.js +1 -0
  50. package/build/client/_app/immutable/chunks/DyXQogav.js.br +0 -0
  51. package/build/client/_app/immutable/chunks/DyXQogav.js.gz +0 -0
  52. package/build/client/_app/immutable/chunks/Gs0cNFYG.js +1 -0
  53. package/build/client/_app/immutable/chunks/Gs0cNFYG.js.br +0 -0
  54. package/build/client/_app/immutable/chunks/Gs0cNFYG.js.gz +0 -0
  55. package/build/client/_app/immutable/chunks/NXeHtWpC.js +1 -0
  56. package/build/client/_app/immutable/chunks/NXeHtWpC.js.br +0 -0
  57. package/build/client/_app/immutable/chunks/NXeHtWpC.js.gz +0 -0
  58. package/build/client/_app/immutable/chunks/i0D5dc1Y.js +1 -0
  59. package/build/client/_app/immutable/chunks/i0D5dc1Y.js.br +0 -0
  60. package/build/client/_app/immutable/chunks/i0D5dc1Y.js.gz +0 -0
  61. package/build/client/_app/immutable/chunks/nnWk1BBo.js +1 -0
  62. package/build/client/_app/immutable/chunks/nnWk1BBo.js.br +0 -0
  63. package/build/client/_app/immutable/chunks/nnWk1BBo.js.gz +0 -0
  64. package/build/client/_app/immutable/entry/app.CVz6aYsT.js +2 -0
  65. package/build/client/_app/immutable/entry/app.CVz6aYsT.js.br +0 -0
  66. package/build/client/_app/immutable/entry/app.CVz6aYsT.js.gz +0 -0
  67. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js +1 -0
  68. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.br +2 -0
  69. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.gz +0 -0
  70. package/build/client/_app/immutable/nodes/0.C2sXq0eH.js +1 -0
  71. package/build/client/_app/immutable/nodes/0.C2sXq0eH.js.br +0 -0
  72. package/build/client/_app/immutable/nodes/0.C2sXq0eH.js.gz +0 -0
  73. package/build/client/_app/immutable/nodes/1.BBtxY46Q.js +1 -0
  74. package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.br +0 -0
  75. package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.gz +0 -0
  76. package/build/client/_app/immutable/nodes/2.D0pSa9ko.js +9 -0
  77. package/build/client/_app/immutable/nodes/2.D0pSa9ko.js.br +0 -0
  78. package/build/client/_app/immutable/nodes/2.D0pSa9ko.js.gz +0 -0
  79. package/build/client/_app/version.json +1 -0
  80. package/build/client/_app/version.json.br +0 -0
  81. package/build/client/_app/version.json.gz +0 -0
  82. package/build/client/robots.txt +3 -0
  83. package/build/client/robots.txt.br +0 -0
  84. package/build/client/robots.txt.gz +0 -0
  85. package/build/env.js +70 -0
  86. package/build/env.js.map +1 -0
  87. package/build/handler.js +26 -0
  88. package/build/handler.js.map +1 -0
  89. package/build/index.js +149 -0
  90. package/build/index.js.map +1 -0
  91. package/build/server/chunks/chunks/edgeLinkModes.js-CfRqrZtd.js +50 -0
  92. package/build/server/chunks/chunks/edgeLinkModes.js-CfRqrZtd.js.map +1 -0
  93. package/build/server/chunks/chunks/environment.js-Bf8x1V_n.js +16 -0
  94. package/build/server/chunks/chunks/environment.js-Bf8x1V_n.js.map +1 -0
  95. package/build/server/chunks/chunks/exports.js-DFR3riS9.js +217 -0
  96. package/build/server/chunks/chunks/exports.js-DFR3riS9.js.map +1 -0
  97. package/build/server/chunks/chunks/false.js-CRHihH2U.js +4 -0
  98. package/build/server/chunks/chunks/false.js-CRHihH2U.js.map +1 -0
  99. package/build/server/chunks/chunks/graphRepository.js-D2DARfVY.js +280 -0
  100. package/build/server/chunks/chunks/graphRepository.js-D2DARfVY.js.map +1 -0
  101. package/build/server/chunks/chunks/internal.js-D8EA_he2.js +119 -0
  102. package/build/server/chunks/chunks/internal.js-D8EA_he2.js.map +1 -0
  103. package/build/server/chunks/chunks/mindbrainClient.js-BFAJqRSL.js +108 -0
  104. package/build/server/chunks/chunks/mindbrainClient.js-BFAJqRSL.js.map +1 -0
  105. package/build/server/chunks/chunks/ontologyInspect.js-Dm3l7KgF.js +13 -0
  106. package/build/server/chunks/chunks/ontologyInspect.js-Dm3l7KgF.js.map +1 -0
  107. package/build/server/chunks/chunks/render-context.js-CTu5Wkzp.js +475 -0
  108. package/build/server/chunks/chunks/render-context.js-CTu5Wkzp.js.map +1 -0
  109. package/build/server/chunks/chunks/renderer.js-DsOhU1UZ.js +1243 -0
  110. package/build/server/chunks/chunks/renderer.js-DsOhU1UZ.js.map +1 -0
  111. package/build/server/chunks/chunks/root.js-DCnlE3XY.js +2815 -0
  112. package/build/server/chunks/chunks/root.js-DCnlE3XY.js.map +1 -0
  113. package/build/server/chunks/chunks/shared-server.js-DaWdgxVh.js +11 -0
  114. package/build/server/chunks/chunks/shared-server.js-DaWdgxVh.js.map +1 -0
  115. package/build/server/chunks/chunks/shared.js-DuDDTJVi.js +1338 -0
  116. package/build/server/chunks/chunks/shared.js-DuDDTJVi.js.map +1 -0
  117. package/build/server/chunks/chunks/utils.js-DGYJFmnf.js +39 -0
  118. package/build/server/chunks/chunks/utils.js-DGYJFmnf.js.map +1 -0
  119. package/build/server/chunks/entries/endpoints/api/brain/_...path_/_server.ts.js-MgPpKBks.js +82 -0
  120. package/build/server/chunks/entries/endpoints/api/brain/_...path_/_server.ts.js-MgPpKBks.js.map +1 -0
  121. package/build/server/chunks/entries/endpoints/api/brain/health/_server.ts.js-DnJQNmWV.js +19 -0
  122. package/build/server/chunks/entries/endpoints/api/brain/health/_server.ts.js-DnJQNmWV.js.map +1 -0
  123. package/build/server/chunks/entries/endpoints/api/graph/_server.ts.js-Bxo7qHVz.js +37 -0
  124. package/build/server/chunks/entries/endpoints/api/graph/_server.ts.js-Bxo7qHVz.js.map +1 -0
  125. package/build/server/chunks/entries/endpoints/api/graph/count/_server.ts.js-BajaLnqp.js +37 -0
  126. package/build/server/chunks/entries/endpoints/api/graph/count/_server.ts.js-BajaLnqp.js.map +1 -0
  127. package/build/server/chunks/entries/endpoints/api/graph/ontologies/_server.ts.js-BFq2mbbX.js +146 -0
  128. package/build/server/chunks/entries/endpoints/api/graph/ontologies/_server.ts.js-BFq2mbbX.js.map +1 -0
  129. package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-Dyfsc-VA.js +154 -0
  130. package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-Dyfsc-VA.js.map +1 -0
  131. package/build/server/chunks/entries/endpoints/api/projections/catalog/_server.ts.js-Ds1RymA0.js +351 -0
  132. package/build/server/chunks/entries/endpoints/api/projections/catalog/_server.ts.js-Ds1RymA0.js.map +1 -0
  133. package/build/server/chunks/entries/fallbacks/error.svelte.js-B7V4yZjo.js +51 -0
  134. package/build/server/chunks/entries/fallbacks/error.svelte.js-B7V4yZjo.js.map +1 -0
  135. package/build/server/chunks/entries/pages/_layout.svelte.js-CoC9BAeH.js +15 -0
  136. package/build/server/chunks/entries/pages/_layout.svelte.js-CoC9BAeH.js.map +1 -0
  137. package/build/server/chunks/entries/pages/_page.svelte.js-DMEbD3K6.js +891 -0
  138. package/build/server/chunks/entries/pages/_page.svelte.js-DMEbD3K6.js.map +1 -0
  139. package/build/server/chunks/handler-BjXBCd1c.js +1698 -0
  140. package/build/server/chunks/handler-BjXBCd1c.js.map +1 -0
  141. package/build/server/chunks/index.js-BJYcV8V7.js +4183 -0
  142. package/build/server/chunks/index.js-BJYcV8V7.js.map +1 -0
  143. package/build/server/chunks/manifest.js-Ddaot0P4.js +91 -0
  144. package/build/server/chunks/manifest.js-Ddaot0P4.js.map +1 -0
  145. package/build/server/chunks/nodes/0.js-87v83UX9.js +9 -0
  146. package/build/server/chunks/nodes/0.js-87v83UX9.js.map +1 -0
  147. package/build/server/chunks/nodes/1.js-BRigw_9J.js +9 -0
  148. package/build/server/chunks/nodes/1.js-BRigw_9J.js.map +1 -0
  149. package/build/server/chunks/nodes/2.js-D9-B_qyX.js +9 -0
  150. package/build/server/chunks/nodes/2.js-D9-B_qyX.js.map +1 -0
  151. package/build/shims.js +33 -0
  152. package/build/shims.js.map +1 -0
  153. package/fixtures/minimal-graph.sqlite +0 -0
  154. package/package.json +81 -0
  155. package/scripts/backend-sqlite.mjs +190 -0
  156. package/scripts/build-serenity-v6-concept-review-pack.mjs +493 -0
  157. package/scripts/build-serenity-v6-review-pack.mjs +479 -0
  158. package/scripts/create-serenity-production-v6.mjs +627 -0
  159. package/scripts/dev-sqlite.mjs +86 -0
  160. package/scripts/export-serenity-v6-backup.mjs +178 -0
  161. package/scripts/import-serenity-v6-user-decisions.mjs +543 -0
  162. package/scripts/lib/sqlite-runtime.mjs +197 -0
  163. package/scripts/materialize-serenity-v6-snapshots.mjs +675 -0
  164. package/scripts/publish-npm.mjs +134 -0
  165. package/scripts/seed-immeuble-projections.mjs +169 -0
  166. package/scripts/studio-sqlite.mjs +74 -0
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import {
4
+ chmodSync,
5
+ existsSync,
6
+ mkdtempSync,
7
+ readFileSync,
8
+ rmSync,
9
+ writeFileSync
10
+ } from "node:fs";
11
+ import { tmpdir } from "node:os";
12
+ import { dirname, join } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const repoRoot = join(__dirname, "..");
17
+ const passthroughArgs = process.argv.slice(2).filter((arg) => arg !== "--");
18
+ const isDryRun = passthroughArgs.includes("--dry-run");
19
+
20
+ function loadDotEnvAuth() {
21
+ const envPath = join(repoRoot, ".env");
22
+ if (!existsSync(envPath)) return;
23
+
24
+ const text = readFileSync(envPath, "utf8");
25
+ for (const line of text.split("\n")) {
26
+ const trimmed = line.trim();
27
+ if (!trimmed || trimmed.startsWith("#")) continue;
28
+
29
+ const eq = trimmed.indexOf("=");
30
+ if (eq < 0) continue;
31
+
32
+ const key = trimmed.slice(0, eq).trim();
33
+ if (key !== "NODE_AUTH_TOKEN" && key !== "NPM_TOKEN") continue;
34
+ if (process.env[key]?.trim()) continue;
35
+
36
+ let value = trimmed.slice(eq + 1).trim();
37
+ if (
38
+ (value.startsWith('"') && value.endsWith('"')) ||
39
+ (value.startsWith("'") && value.endsWith("'"))
40
+ ) {
41
+ value = value.slice(1, -1);
42
+ }
43
+ process.env[key] = value;
44
+ }
45
+ }
46
+
47
+ function ensureNpmAuthToken() {
48
+ const fromNode = process.env.NODE_AUTH_TOKEN?.trim();
49
+ const fromNpm = process.env.NPM_TOKEN?.trim();
50
+ if (!fromNode && fromNpm) {
51
+ process.env.NODE_AUTH_TOKEN = fromNpm;
52
+ }
53
+ if (!isDryRun && !process.env.NODE_AUTH_TOKEN?.trim()) {
54
+ console.error(
55
+ "[publish-npm] Missing NODE_AUTH_TOKEN (or NPM_TOKEN).\n" +
56
+ " Add NODE_AUTH_TOKEN=npm_... to .env at repo root, or export it in the shell.\n" +
57
+ " Use `pnpm publish:npm -- --dry-run` to validate the package without a token."
58
+ );
59
+ process.exit(1);
60
+ }
61
+ }
62
+
63
+ function createPublishUserconfig() {
64
+ const token = process.env.NODE_AUTH_TOKEN?.trim();
65
+ if (!token || isDryRun) return null;
66
+
67
+ const dir = mkdtempSync(join(tmpdir(), "mindbrain-studio-npm-publish-"));
68
+ const npmrcPath = join(dir, "npmrc");
69
+ writeFileSync(
70
+ npmrcPath,
71
+ [
72
+ "registry=https://registry.npmjs.org/",
73
+ `//registry.npmjs.org/:_authToken=${token}`,
74
+ ""
75
+ ].join("\n"),
76
+ "utf8"
77
+ );
78
+ try {
79
+ chmodSync(npmrcPath, 0o600);
80
+ } catch {
81
+ // Best effort on filesystems that do not support chmod.
82
+ }
83
+
84
+ return {
85
+ npmrcPath,
86
+ cleanup: () => rmSync(dir, { recursive: true, force: true })
87
+ };
88
+ }
89
+
90
+ function npmPublishArgs() {
91
+ const args = ["publish", "--access", "public", ...passthroughArgs];
92
+ const otp = process.env.NPM_OTP?.trim();
93
+ if (otp && !args.includes("--otp")) {
94
+ args.push("--otp", otp);
95
+ console.error("[publish-npm] using NPM_OTP for 2FA.");
96
+ }
97
+
98
+ const ci = process.env.GITHUB_ACTIONS === "true";
99
+ const noProvenance = process.env.NPM_PUBLISH_NO_PROVENANCE === "1";
100
+ const alreadyHasProvenance =
101
+ args.includes("--provenance") || args.includes("--no-provenance");
102
+ if (ci && !noProvenance && !alreadyHasProvenance) {
103
+ args.splice(1, 0, "--provenance");
104
+ console.error("[publish-npm] using --provenance (GitHub Actions).");
105
+ } else if (!ci && !alreadyHasProvenance) {
106
+ console.error(
107
+ "[publish-npm] publishing without --provenance (local or non-GitHub Actions)."
108
+ );
109
+ }
110
+
111
+ return args;
112
+ }
113
+
114
+ function runNpmPublish() {
115
+ const userconfig = createPublishUserconfig();
116
+ const args = userconfig
117
+ ? ["--userconfig", userconfig.npmrcPath, ...npmPublishArgs()]
118
+ : npmPublishArgs();
119
+
120
+ try {
121
+ const result = spawnSync("npm", args, {
122
+ cwd: repoRoot,
123
+ env: process.env,
124
+ stdio: "inherit"
125
+ });
126
+ process.exit(result.status ?? 1);
127
+ } finally {
128
+ userconfig?.cleanup();
129
+ }
130
+ }
131
+
132
+ loadDotEnvAuth();
133
+ ensureNpmAuthToken();
134
+ runNpmPublish();
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seed immeuble-demo projections into the local SQLite file.
4
+ * Idempotent: skips rows that match agent_id + scope + proj_type + content.
5
+ */
6
+ import { randomUUID } from 'node:crypto';
7
+ import { readFileSync, existsSync } from 'node:fs';
8
+ import { spawnSync } from 'node:child_process';
9
+ import { dirname, join } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
13
+ const STUDIO_ROOT = join(SCRIPT_DIR, '..');
14
+ const GHOSTCRAB_ROOT = process.env.GHOSTCRAB_ROOT ?? join(STUDIO_ROOT, '..', 'ghostcrab-personal-mcp');
15
+ const SQLITE_PATH = process.env.GHOSTCRAB_SQLITE_PATH ?? join(STUDIO_ROOT, 'data', 'immeuble-demo.sqlite');
16
+ const AGENT_ID = process.env.GHOSTCRAB_AGENT_ID ?? 'agent:self';
17
+ const LOCAL_SEED_FILE = join(STUDIO_ROOT, 'docs', 'demo-immo', 'immeuble-demo', 'projections.seed.jsonl');
18
+ const GHOSTCRAB_SEED_FILE = join(GHOSTCRAB_ROOT, 'examples', 'immeuble-demo', 'projections.seed.jsonl');
19
+ const SEED_FILE =
20
+ process.env.IMMEUBLE_PROJECTIONS_SEED ??
21
+ (existsSync(LOCAL_SEED_FILE) ? LOCAL_SEED_FILE : GHOSTCRAB_SEED_FILE);
22
+ const TYPE_B_PROJECTION_ID = 'proj_immeuble_quota_check';
23
+
24
+ function runSqlite(sql) {
25
+ const result = spawnSync('sqlite3', [SQLITE_PATH, sql], { encoding: 'utf8' });
26
+ if (result.status !== 0) {
27
+ throw new Error(result.stderr || result.stdout || 'sqlite3 failed');
28
+ }
29
+ return result.stdout.trim();
30
+ }
31
+
32
+ function escapeSql(value) {
33
+ return `'${String(value).replace(/'/g, "''")}'`;
34
+ }
35
+
36
+ function seedTypeBProjection() {
37
+ const evidenceId = runSqlite(
38
+ "SELECT entity_id FROM graph_entity WHERE workspace_id='immeuble-demo' AND deprecated_at IS NULL ORDER BY CASE entity_type WHEN 'building' THEN 0 WHEN 'unit' THEN 1 ELSE 2 END, entity_id LIMIT 1;"
39
+ );
40
+ if (!evidenceId) {
41
+ console.warn('warning: no graph_entity row found; skipped Type B projection seed');
42
+ return { typeBSeeded: false };
43
+ }
44
+
45
+ const projectionMetadata = JSON.stringify({
46
+ projection_id: TYPE_B_PROJECTION_ID,
47
+ collection_id: 'immeuble-demo',
48
+ metric: 'quota_total_check',
49
+ summary: 'Contrôle matérialisé des quotités immeuble pour le smoke Studio.'
50
+ });
51
+ const projectionEntityId = runSqlite(
52
+ `
53
+ INSERT INTO graph_entity (workspace_id, entity_type, name, confidence, metadata_json)
54
+ VALUES ('immeuble-demo', 'ProjectionResult', 'Immeuble quota check', 0.99, ${escapeSql(projectionMetadata)})
55
+ ON CONFLICT(workspace_id, entity_type, name)
56
+ DO UPDATE SET confidence=excluded.confidence, metadata_json=excluded.metadata_json, deprecated_at=NULL
57
+ RETURNING entity_id;
58
+ `
59
+ );
60
+
61
+ const deltaMetadata = JSON.stringify({
62
+ metric: TYPE_B_PROJECTION_ID,
63
+ status: 'ok',
64
+ expected_total: 1000,
65
+ actual_total: 1000
66
+ });
67
+ runSqlite(
68
+ `
69
+ INSERT INTO graph_entity (workspace_id, entity_type, name, confidence, metadata_json)
70
+ VALUES ('immeuble-demo', 'DeltaFinding', 'Quota total delta', 0.98, ${escapeSql(deltaMetadata)})
71
+ ON CONFLICT(workspace_id, entity_type, name)
72
+ DO UPDATE SET confidence=excluded.confidence, metadata_json=excluded.metadata_json, deprecated_at=NULL
73
+ RETURNING entity_id;
74
+ `
75
+ );
76
+
77
+ const relationMetadata = JSON.stringify({
78
+ projection_id: TYPE_B_PROJECTION_ID,
79
+ role: 'smoke_evidence'
80
+ });
81
+ const existingRelation = runSqlite(
82
+ `SELECT relation_id FROM graph_relation WHERE workspace_id='immeuble-demo' AND relation_type='PROVEN_BY' AND source_id=${projectionEntityId} AND target_id=${evidenceId} LIMIT 1;`
83
+ );
84
+ if (existingRelation) {
85
+ runSqlite(
86
+ `UPDATE graph_relation SET metadata_json=${escapeSql(relationMetadata)}, confidence=1.0, deprecated_at=NULL WHERE relation_id=${existingRelation};`
87
+ );
88
+ } else {
89
+ runSqlite(
90
+ `INSERT INTO graph_relation (workspace_id, relation_type, source_id, target_id, confidence, metadata_json) VALUES ('immeuble-demo', 'PROVEN_BY', ${projectionEntityId}, ${evidenceId}, 1.0, ${escapeSql(relationMetadata)});`
91
+ );
92
+ }
93
+
94
+ return { typeBSeeded: true, projectionEntityId, evidenceId };
95
+ }
96
+
97
+ function main() {
98
+ if (!existsSync(SQLITE_PATH)) {
99
+ console.error(`error: SQLite file not found: ${SQLITE_PATH}`);
100
+ console.error('Run pnpm load:demo first.');
101
+ process.exit(1);
102
+ }
103
+ if (!existsSync(SEED_FILE)) {
104
+ console.error(`error: seed file not found: ${SEED_FILE}`);
105
+ process.exit(1);
106
+ }
107
+ if (spawnSync('sqlite3', ['-version']).status !== 0) {
108
+ console.error('error: sqlite3 CLI is required');
109
+ process.exit(1);
110
+ }
111
+
112
+ const lines = readFileSync(SEED_FILE, 'utf8')
113
+ .split('\n')
114
+ .map((line) => line.trim())
115
+ .filter(Boolean);
116
+
117
+ let inserted = 0;
118
+ let updated = 0;
119
+ let skipped = 0;
120
+ const now = Math.floor(Date.now() / 1000);
121
+
122
+ for (const line of lines) {
123
+ const row = JSON.parse(line);
124
+ const scope = String(row.scope ?? 'immeuble-demo');
125
+ const projType = String(row.proj_type ?? 'STEP');
126
+ const content = String(row.content ?? '');
127
+ const weight = Number(row.weight ?? 0.7);
128
+ const status = String(row.status ?? 'active');
129
+ const sourceRef = row.source_ref == null ? null : String(row.source_ref);
130
+ const sourceType = 'seed:immeuble-demo';
131
+
132
+ if (!content) {
133
+ skipped += 1;
134
+ continue;
135
+ }
136
+
137
+ const existing = runSqlite(
138
+ `SELECT id FROM projections WHERE agent_id=${escapeSql(AGENT_ID)} AND scope=${escapeSql(scope)} AND proj_type=${escapeSql(projType)} AND content=${escapeSql(content)} LIMIT 1;`
139
+ );
140
+
141
+ if (existing) {
142
+ runSqlite(
143
+ `UPDATE projections SET weight=${weight}, status=${escapeSql(status)}, source_type=${escapeSql(sourceType)}, source_ref=${sourceRef ? escapeSql(sourceRef) : 'NULL'} WHERE id=${escapeSql(existing)};`
144
+ );
145
+ updated += 1;
146
+ continue;
147
+ }
148
+
149
+ const id = randomUUID();
150
+ runSqlite(
151
+ `INSERT INTO projections (id, agent_id, scope, proj_type, content, weight, source_ref, source_type, status, created_at_unix) VALUES (${escapeSql(id)}, ${escapeSql(AGENT_ID)}, ${escapeSql(scope)}, ${escapeSql(projType)}, ${escapeSql(content)}, ${weight}, ${sourceRef ? escapeSql(sourceRef) : 'NULL'}, ${escapeSql(sourceType)}, ${escapeSql(status)}, ${now});`
152
+ );
153
+ inserted += 1;
154
+ }
155
+
156
+ const count = runSqlite(
157
+ `SELECT COUNT(*) FROM projections WHERE agent_id=${escapeSql(AGENT_ID)} AND scope='immeuble-demo';`
158
+ );
159
+ const typeB = seedTypeBProjection();
160
+ console.log(`==> Projections seeded into ${SQLITE_PATH}`);
161
+ console.log(` inserted=${inserted} updated=${updated} skipped=${skipped} total=${count}`);
162
+ if (typeB.typeBSeeded) {
163
+ console.log(
164
+ ` type_b=${TYPE_B_PROJECTION_ID} projection_entity=${typeB.projectionEntityId} evidence_entity=${typeB.evidenceId}`
165
+ );
166
+ }
167
+ }
168
+
169
+ main();
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { loadDotEnv, resolveStudioDataTarget, runtimePathsForSqlite, studioRootFromScript } from "./lib/sqlite-runtime.mjs";
6
+
7
+ function parseMode(args) {
8
+ const filtered = [];
9
+ let serve = false;
10
+ for (const arg of args) {
11
+ if (arg === "--serve") {
12
+ serve = true;
13
+ continue;
14
+ }
15
+ if (arg === "--dev") continue;
16
+ filtered.push(arg);
17
+ }
18
+ return { serve, filtered };
19
+ }
20
+
21
+ const studioRoot = studioRootFromScript(import.meta.url);
22
+ loadDotEnv(studioRoot);
23
+ const { serve, filtered } = parseMode(process.argv.slice(2));
24
+ const { sqlitePath, passthrough, mode, fallbackReason } = resolveStudioDataTarget(studioRoot, filtered);
25
+ if (fallbackReason) {
26
+ console.error(`==> ${fallbackReason}; using packaged demo fixture.`);
27
+ }
28
+
29
+ if (mode === "brain") {
30
+ const backend = spawn(process.execPath, [
31
+ "scripts/backend-sqlite.mjs",
32
+ "--sqlite",
33
+ sqlitePath,
34
+ "--detach"
35
+ ], {
36
+ cwd: studioRoot,
37
+ env: process.env,
38
+ stdio: "inherit"
39
+ });
40
+
41
+ const backendCode = await new Promise((resolveExit) => {
42
+ backend.on("exit", (code) => resolveExit(code ?? 0));
43
+ });
44
+
45
+ if (backendCode !== 0) {
46
+ process.exit(backendCode);
47
+ }
48
+ }
49
+
50
+ const runtime = runtimePathsForSqlite(studioRoot, sqlitePath);
51
+ const env = {
52
+ ...process.env,
53
+ GHOSTCRAB_SQLITE_PATH: sqlitePath,
54
+ DATA_SOURCE: mode,
55
+ MINDBRAIN_RUNTIME_SOURCE: mode === "brain" ? "runtime-json" : "demo-fixture",
56
+ MINDBRAIN_RUNTIME_PATH: mode === "brain" ? runtime.jsonPath : ""
57
+ };
58
+ const command = serve ? resolve(studioRoot, "build", "index.js") : "scripts/dev-sqlite.mjs";
59
+ const args = serve ? passthrough : ["--sqlite", sqlitePath, ...passthrough];
60
+
61
+ if (serve && !existsSync(command)) {
62
+ console.error("error: build/index.js not found. Run pnpm build before starting the packaged Studio.");
63
+ process.exit(1);
64
+ }
65
+
66
+ const child = spawn(process.execPath, [command, ...args], {
67
+ cwd: studioRoot,
68
+ env,
69
+ stdio: "inherit"
70
+ });
71
+
72
+ child.on("exit", (code, signal) => {
73
+ process.exitCode = code ?? (signal ? 128 : 0);
74
+ });