@mindflight/mindbrain-personal-studio 0.6.2 → 0.6.3

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 (202) hide show
  1. package/README.md +16 -8
  2. package/build/client/_app/immutable/chunks/{D0UIlUGZ.js → CIErFlYG.js} +1 -1
  3. package/build/client/_app/immutable/chunks/CIErFlYG.js.br +0 -0
  4. package/build/client/_app/immutable/chunks/CIErFlYG.js.gz +0 -0
  5. package/build/client/_app/immutable/entry/{app.CR-imLox.js → app.mURYm8o_.js} +2 -2
  6. package/build/client/_app/immutable/entry/app.mURYm8o_.js.br +0 -0
  7. package/build/client/_app/immutable/entry/app.mURYm8o_.js.gz +0 -0
  8. package/build/client/_app/immutable/entry/start.D4M9ZeGO.js +1 -0
  9. package/build/client/_app/immutable/entry/start.D4M9ZeGO.js.br +2 -0
  10. package/build/client/_app/immutable/entry/start.D4M9ZeGO.js.gz +0 -0
  11. package/build/client/_app/immutable/nodes/{1.CTEedoSY.js → 1.DHKtMeFI.js} +1 -1
  12. package/build/client/_app/immutable/nodes/1.DHKtMeFI.js.br +1 -0
  13. package/build/client/_app/immutable/nodes/1.DHKtMeFI.js.gz +0 -0
  14. package/build/client/_app/version.json +1 -1
  15. package/build/client/_app/version.json.br +0 -0
  16. package/build/client/_app/version.json.gz +0 -0
  17. package/build/handler.js +4 -4
  18. package/build/index.js +4 -4
  19. package/build/server/chunks/chunks/{internal.js-WOmQXGMa.js → internal.js-C3tV0XXj.js} +2 -2
  20. package/build/server/chunks/chunks/{internal.js-WOmQXGMa.js.map → internal.js-C3tV0XXj.js.map} +1 -1
  21. package/build/server/chunks/{handler-BIDedSZq.js → handler-DlaCCnxx.js} +3 -3
  22. package/build/server/chunks/{handler-BIDedSZq.js.map → handler-DlaCCnxx.js.map} +1 -1
  23. package/build/server/chunks/{index.js-YVPJa0so.js → index.js-BGfKWHak.js} +2 -2
  24. package/build/server/chunks/{index.js-YVPJa0so.js.map → index.js-BGfKWHak.js.map} +1 -1
  25. package/build/server/chunks/{manifest.js-aGRKuiqF.js → manifest.js-CnmaNf5D.js} +3 -3
  26. package/build/server/chunks/{manifest.js-aGRKuiqF.js.map → manifest.js-CnmaNf5D.js.map} +1 -1
  27. package/build/server/chunks/nodes/{1.js-Dhh3ErZY.js → 1.js-BypjwBYB.js} +2 -2
  28. package/build/server/chunks/nodes/{1.js-Dhh3ErZY.js.map → 1.js-BypjwBYB.js.map} +1 -1
  29. package/examples/immeuble/ACCEPTANCE.yaml +82 -0
  30. package/examples/immeuble/BIM_LITE.md +15 -0
  31. package/examples/immeuble/CHECKLIST.md +128 -0
  32. package/examples/immeuble/README.md +121 -0
  33. package/examples/immeuble/bundle/immeuble.bundle.json +22786 -0
  34. package/examples/immeuble/contracts/answer_artifacts.seed.jsonl +34 -0
  35. package/examples/immeuble/contracts/business_capabilities.seed.jsonl +25 -0
  36. package/examples/immeuble/contracts/consumer_contract.yaml +131 -0
  37. package/examples/immeuble/contracts/immeuble_structured_import_model.json +310 -0
  38. package/examples/immeuble/contracts/mapping_external_to_canonical.json +375 -0
  39. package/examples/immeuble/contracts/mapping_external_to_canonical.yaml +55 -0
  40. package/examples/immeuble/contracts/mapping_external_to_canonical_ws.json +65 -0
  41. package/examples/immeuble/contracts/model_contract.json +943 -0
  42. package/examples/immeuble/contracts/projection_catalog.yaml +366 -0
  43. package/examples/immeuble/contracts/scenarios.yaml +27 -0
  44. package/examples/immeuble/contracts/semantic_proposal.golden.json +1 -0
  45. package/examples/immeuble/contracts/source_profile.yaml +38 -0
  46. package/examples/immeuble/fake_data/DeltaFinding.csv +20 -0
  47. package/examples/immeuble/fake_data/ProjectionResult.csv +13 -0
  48. package/examples/immeuble/fake_data/ag_meeting.csv +4 -0
  49. package/examples/immeuble/fake_data/agenda_item.csv +4 -0
  50. package/examples/immeuble/fake_data/architect.csv +3 -0
  51. package/examples/immeuble/fake_data/architecture_firm.csv +2 -0
  52. package/examples/immeuble/fake_data/bank_account.csv +3 -0
  53. package/examples/immeuble/fake_data/billing_group.csv +41 -0
  54. package/examples/immeuble/fake_data/block.csv +10 -0
  55. package/examples/immeuble/fake_data/budget_line.csv +3 -0
  56. package/examples/immeuble/fake_data/building.csv +6 -0
  57. package/examples/immeuble/fake_data/cellar.csv +41 -0
  58. package/examples/immeuble/fake_data/change_order.csv +2 -0
  59. package/examples/immeuble/fake_data/charge_call.csv +58 -0
  60. package/examples/immeuble/fake_data/claim.csv +4 -0
  61. package/examples/immeuble/fake_data/coda_entry.csv +49 -0
  62. package/examples/immeuble/fake_data/compliance_certificate.csv +10 -0
  63. package/examples/immeuble/fake_data/contractor.csv +4 -0
  64. package/examples/immeuble/fake_data/decision.csv +5 -0
  65. package/examples/immeuble/fake_data/defect_reserve.csv +3 -0
  66. package/examples/immeuble/fake_data/household.csv +41 -0
  67. package/examples/immeuble/fake_data/inspection.csv +3 -0
  68. package/examples/immeuble/fake_data/insurance_policy.csv +4 -0
  69. package/examples/immeuble/fake_data/intervention.csv +13 -0
  70. package/examples/immeuble/fake_data/invoice.csv +3 -0
  71. package/examples/immeuble/fake_data/lease_contract.csv +12 -0
  72. package/examples/immeuble/fake_data/maintenance_ticket.csv +13 -0
  73. package/examples/immeuble/fake_data/meter.csv +4 -0
  74. package/examples/immeuble/fake_data/meter_reading.csv +19 -0
  75. package/examples/immeuble/fake_data/milestone.csv +3 -0
  76. package/examples/immeuble/fake_data/organization.csv +12 -0
  77. package/examples/immeuble/fake_data/parking_space.csv +8 -0
  78. package/examples/immeuble/fake_data/permit.csv +3 -0
  79. package/examples/immeuble/fake_data/person.csv +85 -0
  80. package/examples/immeuble/fake_data/private_garden.csv +7 -0
  81. package/examples/immeuble/fake_data/progress_event.csv +2 -0
  82. package/examples/immeuble/fake_data/quote.csv +3 -0
  83. package/examples/immeuble/fake_data/receipt.csv +2 -0
  84. package/examples/immeuble/fake_data/reminder.csv +11 -0
  85. package/examples/immeuble/fake_data/service_contract.csv +4 -0
  86. package/examples/immeuble/fake_data/shared_equipment.csv +8 -0
  87. package/examples/immeuble/fake_data/shared_space.csv +10 -0
  88. package/examples/immeuble/fake_data/unit.csv +41 -0
  89. package/examples/immeuble/fake_data/work_package.csv +4 -0
  90. package/examples/immeuble/fake_data/worksite_project.csv +3 -0
  91. package/examples/immeuble/gap-rules/L0-patrimoine.json +57 -0
  92. package/examples/immeuble/gap-rules/L1-syndic-naive.json +36 -0
  93. package/examples/immeuble/gap-rules/L1-syndic.json +61 -0
  94. package/examples/immeuble/gap-rules/L2-chantier.json +87 -0
  95. package/examples/immeuble/gap-rules/L2-exploitation.json +87 -0
  96. package/examples/immeuble/gap-rules/L2-finance.json +48 -0
  97. package/examples/immeuble/gap-rules/L2-maintenance.json +107 -0
  98. package/examples/immeuble/gap-rules/L2-syndic-filtered.json +39 -0
  99. package/examples/immeuble/gap-rules/L3-full.json +332 -0
  100. package/examples/immeuble/gap-rules/closed-world-contract.md +76 -0
  101. package/examples/immeuble/gap-rules/demo.json +51 -0
  102. package/examples/immeuble/gap-rules/expected-findings.yaml +100 -0
  103. package/examples/immeuble/gap-rules/gap-scenarios.yaml +79 -0
  104. package/examples/immeuble/gap-rules/motifs.json +38 -0
  105. package/examples/immeuble/gap-rules/syndic.json +40 -0
  106. package/examples/immeuble/import_manifest.yaml +25 -0
  107. package/examples/immeuble/import_ready/graph_edges_import.csv +848 -0
  108. package/examples/immeuble/import_ready/mfo_facets_import.csv +559 -0
  109. package/examples/immeuble/index.md +140 -0
  110. package/examples/immeuble/model/immeuble_model.json +418 -0
  111. package/examples/immeuble/reports/01-model.validation.json +56 -0
  112. package/examples/immeuble/reports/02-mapping.validation.json +9 -0
  113. package/examples/immeuble/reports/acceptance.validation.json +161 -0
  114. package/examples/immeuble/reports/consumer_contract.validation.json +162 -0
  115. package/examples/immeuble/reports/graph_edges.jsonl +847 -0
  116. package/examples/immeuble/reports/graph_nodes.jsonl +558 -0
  117. package/examples/immeuble/reports/hybrid-compare.json +144 -0
  118. package/examples/immeuble/reports/immeuble-import-scenario.json +233 -0
  119. package/examples/immeuble/reports/live-artifacts-refresh.validation.json +51 -0
  120. package/examples/immeuble/reports/pipeline_audit.json +59 -0
  121. package/examples/immeuble/reports/projection_audit.json +69 -0
  122. package/examples/immeuble/reports/projection_audit_immeuble.json +257 -0
  123. package/examples/immeuble/reports/projection_audit_immeuble.md +122 -0
  124. package/examples/immeuble/reports/projection_candidates.json +1596 -0
  125. package/examples/immeuble/reports/projection_candidates.md +117 -0
  126. package/examples/immeuble/reports/projection_model_validation.md +115 -0
  127. package/examples/immeuble/reports/reindex.json +4 -0
  128. package/examples/immeuble/reports/reset-immeuble-workspace.json +32 -0
  129. package/examples/immeuble/reports/schema-id-prefix-check.json +5 -0
  130. package/examples/immeuble/scripts/audit-immeuble-projections.mjs +254 -0
  131. package/examples/immeuble/scripts/build-immeuble-model.mjs +308 -0
  132. package/examples/immeuble/scripts/compare-immeuble-snapshots.sh +227 -0
  133. package/examples/immeuble/scripts/enrich-immeuble-demo.mjs +1135 -0
  134. package/examples/immeuble/scripts/reset-immeuble-workspace.mjs +139 -0
  135. package/examples/immeuble/scripts/run-immeuble-backend.sh +164 -0
  136. package/examples/immeuble/scripts/run-immeuble-import.mjs +232 -0
  137. package/examples/immeuble/scripts/run-immeuble-live-lab.sh +439 -0
  138. package/examples/immeuble/scripts/seed-immeuble-gap-rules.mjs +69 -0
  139. package/examples/immeuble/scripts/start-immeuble-demo.sh +52 -0
  140. package/examples/immeuble/scripts/starterkit/analysis-lenses.mjs +181 -0
  141. package/examples/immeuble/scripts/starterkit/analyze-projection-candidates.mjs +714 -0
  142. package/examples/immeuble/scripts/starterkit/audit-ghostcrab-projections.mjs +674 -0
  143. package/examples/immeuble/scripts/starterkit/facet-prefix.mjs +166 -0
  144. package/examples/immeuble/scripts/starterkit/sqlite-utils.mjs +131 -0
  145. package/examples/immeuble/scripts/verify-immeuble-acceptance.mjs +284 -0
  146. package/examples/immeuble/scripts/verify-immeuble-live-artifacts.mjs +140 -0
  147. package/examples/immeuble/scripts/yaml-lite.mjs +96 -0
  148. package/examples/immeuble/sources/agent-prompts/prompts/00-prerequisites-immo-mcp.md +161 -0
  149. package/examples/immeuble/sources/agent-prompts/prompts/00-prerequisites.md +39 -0
  150. package/examples/immeuble/sources/agent-prompts/prompts/01-discovery-and-model-proposal.md +42 -0
  151. package/examples/immeuble/sources/agent-prompts/prompts/02-ontology-register.md +44 -0
  152. package/examples/immeuble/sources/agent-prompts/prompts/03-gap-rules-design.md +44 -0
  153. package/examples/immeuble/sources/agent-prompts/prompts/04-document-ingest.md +40 -0
  154. package/examples/immeuble/sources/agent-prompts/prompts/05-graph-extraction.md +44 -0
  155. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare-immo-mcp.md +109 -0
  156. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare-test-immo-mcp3.md +30 -0
  157. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare.md +63 -0
  158. package/examples/immeuble/sources/checklists/gap-rules-checklist.md +42 -0
  159. package/examples/immeuble/sources/checklists/ontology-checklist.md +54 -0
  160. package/examples/immeuble/sources/documents/README.md +42 -0
  161. package/examples/immeuble/sources/documents/annexes-caves-garages-jardins.md +8 -0
  162. package/examples/immeuble/sources/documents/annexes-jardins-garages.md +1 -0
  163. package/examples/immeuble/sources/documents/baux-erables.md +1 -0
  164. package/examples/immeuble/sources/documents/baux-locatifs.md +11 -0
  165. package/examples/immeuble/sources/documents/coda-janvier-2026.md +10 -0
  166. package/examples/immeuble/sources/documents/composition-menages.md +1 -0
  167. package/examples/immeuble/sources/documents/composition-occupants.md +18 -0
  168. package/examples/immeuble/sources/documents/expected-coverage.json +70 -0
  169. package/examples/immeuble/sources/documents/extrait-coda-janvier-2026.md +1 -0
  170. package/examples/immeuble/sources/documents/groupes-facturation.md +30 -0
  171. package/examples/immeuble/sources/documents/manifest.json +79 -0
  172. package/examples/immeuble/sources/documents/note-architecte-chantier-erables.md +3 -0
  173. package/examples/immeuble/sources/documents/permis-urbanisme-erables.md +3 -0
  174. package/examples/immeuble/sources/documents/procedures-operationnelles.md +3 -0
  175. package/examples/immeuble/sources/documents/pv-ag-budget-2026.md +1 -0
  176. package/examples/immeuble/sources/documents/pv-reception-reserves-erables.md +3 -0
  177. package/examples/immeuble/sources/documents/registre-coproprietaires.md +24 -0
  178. package/examples/immeuble/sources/documents/reglement-copropriete-tilleuls.md +1 -0
  179. package/examples/immeuble/sources/documents/statuts-erables.md +22 -0
  180. package/examples/immeuble/sources/documents/statuts-tilleuls.md +19 -0
  181. package/examples/immeuble/sources/documents/succession-jean-dupont.md +3 -0
  182. package/examples/immeuble/sources/documents/titre-propriete-tilleuls-a3.md +1 -0
  183. package/examples/immeuble/sources/documents/trous-pedagogiques.md +3 -0
  184. package/examples/immeuble/sources/ontology/README.md +1 -0
  185. package/examples/immeuble/sources/ontology/core.yaml +444 -0
  186. package/examples/immeuble/success-criteria.yaml +35 -0
  187. package/fixtures/immeuble-demo.sqlite +0 -0
  188. package/package.json +11 -2
  189. package/scripts/lib/sqlite-runtime.mjs +1 -1
  190. package/scripts/load-immeuble-demo.sh +103 -0
  191. package/scripts/seed-immeuble-projections.mjs +75 -148
  192. package/scripts/verify-immeuble-demo-sources.mjs +93 -0
  193. package/scripts/verify-immeuble-demo.mjs +69 -0
  194. package/build/client/_app/immutable/chunks/D0UIlUGZ.js.br +0 -0
  195. package/build/client/_app/immutable/chunks/D0UIlUGZ.js.gz +0 -0
  196. package/build/client/_app/immutable/entry/app.CR-imLox.js.br +0 -0
  197. package/build/client/_app/immutable/entry/app.CR-imLox.js.gz +0 -0
  198. package/build/client/_app/immutable/entry/start.DV-AjeAB.js +0 -1
  199. package/build/client/_app/immutable/entry/start.DV-AjeAB.js.br +0 -2
  200. package/build/client/_app/immutable/entry/start.DV-AjeAB.js.gz +0 -0
  201. package/build/client/_app/immutable/nodes/1.CTEedoSY.js.br +0 -0
  202. package/build/client/_app/immutable/nodes/1.CTEedoSY.js.gz +0 -0
@@ -1,169 +1,96 @@
1
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');
2
+ import { existsSync } from "node:fs";
3
+ import { spawnSync } from "node:child_process";
4
+ import { join, resolve } from "node:path";
5
+
6
+ const STUDIO_ROOT = resolve(import.meta.dirname, "..");
7
+ const SQLITE_PATH = resolve(process.env.GHOSTCRAB_SQLITE_PATH ?? join(STUDIO_ROOT, "data", "immeuble-demo.sqlite"));
8
+ const WORKSPACE_ID = process.env.IMMEUBLE_WORKSPACE_ID ?? "immeuble";
9
+
10
+ const projections = [
11
+ {
12
+ id: "chantier_erables_synthese",
13
+ name: "Synthèse chantier Érables",
14
+ metric: "worksite_summary",
15
+ evidenceType: "worksite_project",
16
+ summary: "Chantier actif avec deux lots, un jalon en retard et une réserve ouverte."
17
+ },
18
+ {
19
+ id: "chantier_erables_budget",
20
+ name: "Budget travaux Érables",
21
+ metric: "worksite_budget",
22
+ evidenceType: "budget_line",
23
+ summary: "Budget voté 125000 EUR, prévision 132000 EUR après avenant zinguerie."
24
+ },
25
+ {
26
+ id: "chantier_erables_planning",
27
+ name: "Planning chantier Érables",
28
+ metric: "worksite_schedule",
29
+ evidenceType: "milestone",
30
+ summary: "Démarrage réel en retard de deux jours; réception provisoire ouverte."
31
+ },
32
+ {
33
+ id: "chantier_erables_reserves",
34
+ name: "Réserves chantier Érables",
35
+ metric: "worksite_reserves",
36
+ evidenceType: "defect_reserve",
37
+ summary: "Une réserve sécurité ouverte sur garde-corps échafaudage."
28
38
  }
29
- return result.stdout.trim();
39
+ ];
40
+
41
+ function sql(query) {
42
+ const res = spawnSync("sqlite3", [SQLITE_PATH, query], { encoding: "utf8" });
43
+ if (res.status !== 0) throw new Error(res.stderr || res.stdout || "sqlite3 failed");
44
+ return res.stdout.trim();
30
45
  }
31
46
 
32
- function escapeSql(value) {
47
+ function escape(value) {
33
48
  return `'${String(value).replace(/'/g, "''")}'`;
34
49
  }
35
50
 
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;"
51
+ if (!existsSync(SQLITE_PATH)) {
52
+ console.error(`error: SQLite file not found: ${SQLITE_PATH}`);
53
+ console.error("Run pnpm load:demo first.");
54
+ process.exit(1);
55
+ }
56
+ if (spawnSync("sqlite3", ["-version"]).status !== 0) {
57
+ console.error("error: sqlite3 CLI is required");
58
+ process.exit(1);
59
+ }
60
+
61
+ let seeded = 0;
62
+ for (const projection of projections) {
63
+ const evidenceId = sql(
64
+ `SELECT entity_id FROM graph_entity WHERE workspace_id=${escape(WORKSPACE_ID)} AND entity_type=${escape(projection.evidenceType)} AND deprecated_at IS NULL ORDER BY entity_id LIMIT 1;`
39
65
  );
40
66
  if (!evidenceId) {
41
- console.warn('warning: no graph_entity row found; skipped Type B projection seed');
42
- return { typeBSeeded: false };
67
+ console.warn(`warning: skipped ${projection.id}; no ${projection.evidenceType} evidence found`);
68
+ continue;
43
69
  }
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.'
70
+ const metadata = JSON.stringify({
71
+ projection_id: projection.id,
72
+ collection_id: WORKSPACE_ID,
73
+ metric: projection.metric,
74
+ summary: projection.summary
50
75
  });
51
- const projectionEntityId = runSqlite(
52
- `
76
+ const projectionEntityId = sql(`
53
77
  INSERT INTO graph_entity (workspace_id, entity_type, name, confidence, metadata_json)
54
- VALUES ('immeuble-demo', 'ProjectionResult', 'Immeuble quota check', 0.99, ${escapeSql(projectionMetadata)})
78
+ VALUES (${escape(WORKSPACE_ID)}, 'ProjectionResult', ${escape(projection.name)}, 0.99, ${escape(metadata)})
55
79
  ON CONFLICT(workspace_id, entity_type, name)
56
80
  DO UPDATE SET confidence=excluded.confidence, metadata_json=excluded.metadata_json, deprecated_at=NULL
57
81
  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;`
82
+ `);
83
+ const relationMetadata = JSON.stringify({ projection_id: projection.id, role: "snapshot_evidence" });
84
+ const existingRelation = sql(
85
+ `SELECT relation_id FROM graph_relation WHERE workspace_id=${escape(WORKSPACE_ID)} AND relation_type='evidenced_by' AND source_id=${projectionEntityId} AND target_id=${evidenceId} LIMIT 1;`
83
86
  );
84
87
  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
+ sql(`UPDATE graph_relation SET metadata_json=${escape(relationMetadata)}, confidence=1.0, deprecated_at=NULL WHERE relation_id=${existingRelation};`);
88
89
  } 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
- );
90
+ sql(`INSERT INTO graph_relation (workspace_id, relation_type, source_id, target_id, confidence, metadata_json) VALUES (${escape(WORKSPACE_ID)}, 'evidenced_by', ${projectionEntityId}, ${evidenceId}, 1.0, ${escape(relationMetadata)});`);
166
91
  }
92
+ seeded += 1;
167
93
  }
168
94
 
169
- main();
95
+ console.log(`==> Projection snapshots seeded into ${SQLITE_PATH}`);
96
+ console.log(` workspace=${WORKSPACE_ID} seeded=${seeded}`);
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+
5
+ const root = resolve(import.meta.dirname, "..");
6
+ const demo = join(root, "examples", "immeuble");
7
+ const bundlePath = join(demo, "bundle", "immeuble.bundle.json");
8
+
9
+ function fail(message) {
10
+ console.error(`error: ${message}`);
11
+ process.exit(1);
12
+ }
13
+
14
+ if (!existsSync(bundlePath)) fail(`missing ${bundlePath}`);
15
+
16
+ const bundle = JSON.parse(readFileSync(bundlePath, "utf8"));
17
+ const entityTypes = new Set(bundle.entities_raw?.map((row) => row.entity_type) ?? []);
18
+ const artifactIds = new Set(bundle.mindbrain_answer_artifacts?.map((row) => row.artifact_id) ?? []);
19
+ const entityCount = bundle.entities_raw?.length ?? 0;
20
+ const relationCount = bundle.relations_raw?.length ?? 0;
21
+ const documentCount = bundle.documents_raw?.length ?? 0;
22
+ const answerArtifactCount = bundle.mindbrain_answer_artifacts?.length ?? 0;
23
+
24
+ for (const path of [
25
+ "README.md",
26
+ "BIM_LITE.md",
27
+ "sources/ontology/core.yaml",
28
+ "contracts/projection_catalog.yaml",
29
+ "contracts/answer_artifacts.seed.jsonl",
30
+ "contracts/business_capabilities.seed.jsonl",
31
+ "contracts/consumer_contract.yaml",
32
+ "gap-rules/L2-chantier.json",
33
+ "gap-rules/L3-full.json",
34
+ "gap-rules/expected-findings.yaml",
35
+ "sources/documents/note-architecte-chantier-erables.md",
36
+ "sources/documents/permis-urbanisme-erables.md",
37
+ "sources/documents/pv-reception-reserves-erables.md",
38
+ "sources/documents/procedures-operationnelles.md",
39
+ "sources/documents/trous-pedagogiques.md"
40
+ ]) {
41
+ if (!existsSync(join(demo, path))) fail(`missing examples/immeuble/${path}`);
42
+ }
43
+
44
+ for (const type of [
45
+ "ag_meeting",
46
+ "agenda_item",
47
+ "service_contract",
48
+ "maintenance_ticket",
49
+ "intervention",
50
+ "insurance_policy",
51
+ "claim",
52
+ "meter",
53
+ "meter_reading",
54
+ "compliance_certificate",
55
+ "worksite_project",
56
+ "architect",
57
+ "contractor",
58
+ "work_package",
59
+ "permit",
60
+ "budget_line",
61
+ "ProjectionResult",
62
+ "DeltaFinding"
63
+ ]) {
64
+ if (!entityTypes.has(type)) fail(`bundle missing entity type ${type}`);
65
+ }
66
+
67
+ for (const artifactId of [
68
+ "live_answer_view__lots_sans_proprietaire",
69
+ "live_answer_view__coda_a_rapprocher",
70
+ "live_answer_view__interventions_en_retard",
71
+ "live_answer_view__chantier_actif",
72
+ "live_answer_view__planning_chantier",
73
+ "live_answer_view__budget_travaux",
74
+ "live_answer_view__reserves_reception",
75
+ "answer_snapshot__chantier_erables_synthese"
76
+ ]) {
77
+ if (!artifactIds.has(artifactId)) fail(`bundle missing artifact ${artifactId}`);
78
+ }
79
+
80
+ if (entityCount < 400) fail(`bundle entities_raw < 400 (${entityCount})`);
81
+ if (relationCount < 800) fail(`bundle relations_raw < 800 (${relationCount})`);
82
+ if (documentCount < 20) fail(`bundle documents_raw < 20 (${documentCount})`);
83
+ if (answerArtifactCount < 33) fail(`bundle answer_artifacts < 33 (${answerArtifactCount})`);
84
+
85
+ console.log(JSON.stringify({
86
+ ok: true,
87
+ bundle: bundlePath,
88
+ workspace: bundle.scope?.workspace_id,
89
+ entities: entityCount,
90
+ relations: relationCount,
91
+ documents: documentCount,
92
+ answer_artifacts: answerArtifactCount
93
+ }, null, 2));
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync } from "node:fs";
3
+ import { spawnSync } from "node:child_process";
4
+ import { resolve } from "node:path";
5
+
6
+ function parseArgs(argv) {
7
+ let sqlite = process.env.GHOSTCRAB_SQLITE_PATH ?? "data/immeuble-demo.sqlite";
8
+ let workspace = process.env.IMMEUBLE_WORKSPACE_ID ?? "immeuble";
9
+ for (let i = 0; i < argv.length; i += 1) {
10
+ const arg = argv[i];
11
+ if (arg === "--sqlite" || arg === "--db") sqlite = argv[++i] ?? sqlite;
12
+ else if (arg.startsWith("--sqlite=")) sqlite = arg.slice("--sqlite=".length);
13
+ else if (arg.startsWith("--db=")) sqlite = arg.slice("--db=".length);
14
+ else if (arg === "--workspace") workspace = argv[++i] ?? workspace;
15
+ else if (arg.startsWith("--workspace=")) workspace = arg.slice("--workspace=".length);
16
+ }
17
+ return { sqlite: resolve(sqlite), workspace };
18
+ }
19
+
20
+ function sql(db, query) {
21
+ const res = spawnSync("sqlite3", ["-readonly", db, "-json", query], { encoding: "utf8" });
22
+ if (res.status !== 0) throw new Error(res.stderr || res.stdout || "sqlite3 failed");
23
+ return JSON.parse(res.stdout || "[]");
24
+ }
25
+
26
+ function scalar(db, query) {
27
+ const rows = sql(db, query);
28
+ return Number(Object.values(rows[0] ?? { value: 0 })[0] ?? 0);
29
+ }
30
+
31
+ const { sqlite, workspace } = parseArgs(process.argv.slice(2));
32
+ if (!existsSync(sqlite)) {
33
+ console.error(`error: SQLite not found: ${sqlite}`);
34
+ process.exit(1);
35
+ }
36
+ if (spawnSync("sqlite3", ["-version"]).status !== 0) {
37
+ console.error("error: sqlite3 CLI is required");
38
+ process.exit(1);
39
+ }
40
+
41
+ const checks = {
42
+ workspace_rows: scalar(sqlite, `SELECT COUNT(*) AS value FROM workspaces WHERE workspace_id='${workspace}'`),
43
+ graph_entities: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}'`),
44
+ raw_entities: scalar(sqlite, `SELECT COUNT(*) AS value FROM entities_raw WHERE workspace_id='${workspace}'`),
45
+ documents: scalar(sqlite, `SELECT COUNT(*) AS value FROM documents_raw WHERE workspace_id='${workspace}'`),
46
+ answer_artifacts: scalar(sqlite, `SELECT COUNT(*) AS value FROM mindbrain_answer_artifacts WHERE workspace_id='${workspace}' OR scope='${workspace}'`),
47
+ projection_results: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}' AND entity_type='ProjectionResult'`),
48
+ delta_findings: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}' AND entity_type='DeltaFinding'`),
49
+ worksite_projects: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}' AND entity_type='worksite_project'`),
50
+ units: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}' AND entity_type='unit'`),
51
+ maintenance_tickets: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_entity WHERE workspace_id='${workspace}' AND entity_type='maintenance_ticket'`),
52
+ gap_rules: scalar(sqlite, `SELECT COUNT(*) AS value FROM graph_gap_rules WHERE workspace_id='${workspace}'`)
53
+ };
54
+
55
+ const failures = [];
56
+ if (checks.workspace_rows < 1) failures.push("workspace missing");
57
+ if (checks.graph_entities < 400) failures.push(`graph_entities < 400 (${checks.graph_entities})`);
58
+ if (checks.raw_entities < 400) failures.push(`raw_entities < 400 (${checks.raw_entities})`);
59
+ if (checks.documents < 20) failures.push(`documents < 20 (${checks.documents})`);
60
+ if (checks.answer_artifacts < 33) failures.push(`answer_artifacts < 33 (${checks.answer_artifacts})`);
61
+ if (checks.projection_results < 8) failures.push(`projection_results < 8 (${checks.projection_results})`);
62
+ if (checks.delta_findings < 12) failures.push(`delta_findings < 12 (${checks.delta_findings})`);
63
+ if (checks.worksite_projects < 2) failures.push(`worksite_projects < 2 (${checks.worksite_projects})`);
64
+ if (checks.units < 40) failures.push(`units < 40 (${checks.units})`);
65
+ if (checks.maintenance_tickets < 10) failures.push(`maintenance_tickets < 10 (${checks.maintenance_tickets})`);
66
+ if (checks.gap_rules < 25) failures.push(`gap_rules < 25 (${checks.gap_rules})`);
67
+
68
+ console.log(JSON.stringify({ ok: failures.length === 0, sqlite, workspace, checks, failures }, null, 2));
69
+ if (failures.length) process.exit(1);
@@ -1 +0,0 @@
1
- import{l as o,a as r}from"../chunks/D0UIlUGZ.js";export{o as load_css,r as start};
@@ -1,2 +0,0 @@
1
- )�import{l as o,a as r}from"../chunks/D0UIlUGZ.js";export{o as load_css,r as start};
2
-