@mindflight/mindbrain-personal-studio 0.6.1 → 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 (212) hide show
  1. package/README.md +16 -8
  2. package/build/client/_app/immutable/chunks/CIErFlYG.js +1 -0
  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.CVz6aYsT.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.BBtxY46Q.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-D8EA_he2.js → internal.js-C3tV0XXj.js} +2 -2
  20. package/build/server/chunks/chunks/{internal.js-D8EA_he2.js.map → internal.js-C3tV0XXj.js.map} +1 -1
  21. package/build/server/chunks/entries/endpoints/api/graph/schema-registry/{_server.ts.js-Dyfsc-VA.js → _server.ts.js-CAsXxBRq.js} +7 -2
  22. package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-CAsXxBRq.js.map +1 -0
  23. package/build/server/chunks/{handler-BjXBCd1c.js → handler-DlaCCnxx.js} +3 -3
  24. package/build/server/chunks/{handler-BjXBCd1c.js.map → handler-DlaCCnxx.js.map} +1 -1
  25. package/build/server/chunks/{index.js-BJYcV8V7.js → index.js-BGfKWHak.js} +2 -2
  26. package/build/server/chunks/{index.js-BJYcV8V7.js.map → index.js-BGfKWHak.js.map} +1 -1
  27. package/build/server/chunks/{manifest.js-Ddaot0P4.js → manifest.js-CnmaNf5D.js} +4 -4
  28. package/build/server/chunks/{manifest.js-Ddaot0P4.js.map → manifest.js-CnmaNf5D.js.map} +1 -1
  29. package/build/server/chunks/nodes/{1.js-BRigw_9J.js → 1.js-BypjwBYB.js} +2 -2
  30. package/build/server/chunks/nodes/{1.js-BRigw_9J.js.map → 1.js-BypjwBYB.js.map} +1 -1
  31. package/examples/immeuble/ACCEPTANCE.yaml +82 -0
  32. package/examples/immeuble/BIM_LITE.md +15 -0
  33. package/examples/immeuble/CHECKLIST.md +128 -0
  34. package/examples/immeuble/README.md +121 -0
  35. package/examples/immeuble/bundle/immeuble.bundle.json +22786 -0
  36. package/examples/immeuble/contracts/answer_artifacts.seed.jsonl +34 -0
  37. package/examples/immeuble/contracts/business_capabilities.seed.jsonl +25 -0
  38. package/examples/immeuble/contracts/consumer_contract.yaml +131 -0
  39. package/examples/immeuble/contracts/immeuble_structured_import_model.json +310 -0
  40. package/examples/immeuble/contracts/mapping_external_to_canonical.json +375 -0
  41. package/examples/immeuble/contracts/mapping_external_to_canonical.yaml +55 -0
  42. package/examples/immeuble/contracts/mapping_external_to_canonical_ws.json +65 -0
  43. package/examples/immeuble/contracts/model_contract.json +943 -0
  44. package/examples/immeuble/contracts/projection_catalog.yaml +366 -0
  45. package/examples/immeuble/contracts/scenarios.yaml +27 -0
  46. package/examples/immeuble/contracts/semantic_proposal.golden.json +1 -0
  47. package/examples/immeuble/contracts/source_profile.yaml +38 -0
  48. package/examples/immeuble/fake_data/DeltaFinding.csv +20 -0
  49. package/examples/immeuble/fake_data/ProjectionResult.csv +13 -0
  50. package/examples/immeuble/fake_data/ag_meeting.csv +4 -0
  51. package/examples/immeuble/fake_data/agenda_item.csv +4 -0
  52. package/examples/immeuble/fake_data/architect.csv +3 -0
  53. package/examples/immeuble/fake_data/architecture_firm.csv +2 -0
  54. package/examples/immeuble/fake_data/bank_account.csv +3 -0
  55. package/examples/immeuble/fake_data/billing_group.csv +41 -0
  56. package/examples/immeuble/fake_data/block.csv +10 -0
  57. package/examples/immeuble/fake_data/budget_line.csv +3 -0
  58. package/examples/immeuble/fake_data/building.csv +6 -0
  59. package/examples/immeuble/fake_data/cellar.csv +41 -0
  60. package/examples/immeuble/fake_data/change_order.csv +2 -0
  61. package/examples/immeuble/fake_data/charge_call.csv +58 -0
  62. package/examples/immeuble/fake_data/claim.csv +4 -0
  63. package/examples/immeuble/fake_data/coda_entry.csv +49 -0
  64. package/examples/immeuble/fake_data/compliance_certificate.csv +10 -0
  65. package/examples/immeuble/fake_data/contractor.csv +4 -0
  66. package/examples/immeuble/fake_data/decision.csv +5 -0
  67. package/examples/immeuble/fake_data/defect_reserve.csv +3 -0
  68. package/examples/immeuble/fake_data/household.csv +41 -0
  69. package/examples/immeuble/fake_data/inspection.csv +3 -0
  70. package/examples/immeuble/fake_data/insurance_policy.csv +4 -0
  71. package/examples/immeuble/fake_data/intervention.csv +13 -0
  72. package/examples/immeuble/fake_data/invoice.csv +3 -0
  73. package/examples/immeuble/fake_data/lease_contract.csv +12 -0
  74. package/examples/immeuble/fake_data/maintenance_ticket.csv +13 -0
  75. package/examples/immeuble/fake_data/meter.csv +4 -0
  76. package/examples/immeuble/fake_data/meter_reading.csv +19 -0
  77. package/examples/immeuble/fake_data/milestone.csv +3 -0
  78. package/examples/immeuble/fake_data/organization.csv +12 -0
  79. package/examples/immeuble/fake_data/parking_space.csv +8 -0
  80. package/examples/immeuble/fake_data/permit.csv +3 -0
  81. package/examples/immeuble/fake_data/person.csv +85 -0
  82. package/examples/immeuble/fake_data/private_garden.csv +7 -0
  83. package/examples/immeuble/fake_data/progress_event.csv +2 -0
  84. package/examples/immeuble/fake_data/quote.csv +3 -0
  85. package/examples/immeuble/fake_data/receipt.csv +2 -0
  86. package/examples/immeuble/fake_data/reminder.csv +11 -0
  87. package/examples/immeuble/fake_data/service_contract.csv +4 -0
  88. package/examples/immeuble/fake_data/shared_equipment.csv +8 -0
  89. package/examples/immeuble/fake_data/shared_space.csv +10 -0
  90. package/examples/immeuble/fake_data/unit.csv +41 -0
  91. package/examples/immeuble/fake_data/work_package.csv +4 -0
  92. package/examples/immeuble/fake_data/worksite_project.csv +3 -0
  93. package/examples/immeuble/gap-rules/L0-patrimoine.json +57 -0
  94. package/examples/immeuble/gap-rules/L1-syndic-naive.json +36 -0
  95. package/examples/immeuble/gap-rules/L1-syndic.json +61 -0
  96. package/examples/immeuble/gap-rules/L2-chantier.json +87 -0
  97. package/examples/immeuble/gap-rules/L2-exploitation.json +87 -0
  98. package/examples/immeuble/gap-rules/L2-finance.json +48 -0
  99. package/examples/immeuble/gap-rules/L2-maintenance.json +107 -0
  100. package/examples/immeuble/gap-rules/L2-syndic-filtered.json +39 -0
  101. package/examples/immeuble/gap-rules/L3-full.json +332 -0
  102. package/examples/immeuble/gap-rules/closed-world-contract.md +76 -0
  103. package/examples/immeuble/gap-rules/demo.json +51 -0
  104. package/examples/immeuble/gap-rules/expected-findings.yaml +100 -0
  105. package/examples/immeuble/gap-rules/gap-scenarios.yaml +79 -0
  106. package/examples/immeuble/gap-rules/motifs.json +38 -0
  107. package/examples/immeuble/gap-rules/syndic.json +40 -0
  108. package/examples/immeuble/import_manifest.yaml +25 -0
  109. package/examples/immeuble/import_ready/graph_edges_import.csv +848 -0
  110. package/examples/immeuble/import_ready/mfo_facets_import.csv +559 -0
  111. package/examples/immeuble/index.md +140 -0
  112. package/examples/immeuble/model/immeuble_model.json +418 -0
  113. package/examples/immeuble/reports/01-model.validation.json +56 -0
  114. package/examples/immeuble/reports/02-mapping.validation.json +9 -0
  115. package/examples/immeuble/reports/acceptance.validation.json +161 -0
  116. package/examples/immeuble/reports/consumer_contract.validation.json +162 -0
  117. package/examples/immeuble/reports/graph_edges.jsonl +847 -0
  118. package/examples/immeuble/reports/graph_nodes.jsonl +558 -0
  119. package/examples/immeuble/reports/hybrid-compare.json +144 -0
  120. package/examples/immeuble/reports/immeuble-import-scenario.json +233 -0
  121. package/examples/immeuble/reports/live-artifacts-refresh.validation.json +51 -0
  122. package/examples/immeuble/reports/pipeline_audit.json +59 -0
  123. package/examples/immeuble/reports/projection_audit.json +69 -0
  124. package/examples/immeuble/reports/projection_audit_immeuble.json +257 -0
  125. package/examples/immeuble/reports/projection_audit_immeuble.md +122 -0
  126. package/examples/immeuble/reports/projection_candidates.json +1596 -0
  127. package/examples/immeuble/reports/projection_candidates.md +117 -0
  128. package/examples/immeuble/reports/projection_model_validation.md +115 -0
  129. package/examples/immeuble/reports/reindex.json +4 -0
  130. package/examples/immeuble/reports/reset-immeuble-workspace.json +32 -0
  131. package/examples/immeuble/reports/schema-id-prefix-check.json +5 -0
  132. package/examples/immeuble/scripts/audit-immeuble-projections.mjs +254 -0
  133. package/examples/immeuble/scripts/build-immeuble-model.mjs +308 -0
  134. package/examples/immeuble/scripts/compare-immeuble-snapshots.sh +227 -0
  135. package/examples/immeuble/scripts/enrich-immeuble-demo.mjs +1135 -0
  136. package/examples/immeuble/scripts/reset-immeuble-workspace.mjs +139 -0
  137. package/examples/immeuble/scripts/run-immeuble-backend.sh +164 -0
  138. package/examples/immeuble/scripts/run-immeuble-import.mjs +232 -0
  139. package/examples/immeuble/scripts/run-immeuble-live-lab.sh +439 -0
  140. package/examples/immeuble/scripts/seed-immeuble-gap-rules.mjs +69 -0
  141. package/examples/immeuble/scripts/start-immeuble-demo.sh +52 -0
  142. package/examples/immeuble/scripts/starterkit/analysis-lenses.mjs +181 -0
  143. package/examples/immeuble/scripts/starterkit/analyze-projection-candidates.mjs +714 -0
  144. package/examples/immeuble/scripts/starterkit/audit-ghostcrab-projections.mjs +674 -0
  145. package/examples/immeuble/scripts/starterkit/facet-prefix.mjs +166 -0
  146. package/examples/immeuble/scripts/starterkit/sqlite-utils.mjs +131 -0
  147. package/examples/immeuble/scripts/verify-immeuble-acceptance.mjs +284 -0
  148. package/examples/immeuble/scripts/verify-immeuble-live-artifacts.mjs +140 -0
  149. package/examples/immeuble/scripts/yaml-lite.mjs +96 -0
  150. package/examples/immeuble/sources/agent-prompts/prompts/00-prerequisites-immo-mcp.md +161 -0
  151. package/examples/immeuble/sources/agent-prompts/prompts/00-prerequisites.md +39 -0
  152. package/examples/immeuble/sources/agent-prompts/prompts/01-discovery-and-model-proposal.md +42 -0
  153. package/examples/immeuble/sources/agent-prompts/prompts/02-ontology-register.md +44 -0
  154. package/examples/immeuble/sources/agent-prompts/prompts/03-gap-rules-design.md +44 -0
  155. package/examples/immeuble/sources/agent-prompts/prompts/04-document-ingest.md +40 -0
  156. package/examples/immeuble/sources/agent-prompts/prompts/05-graph-extraction.md +44 -0
  157. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare-immo-mcp.md +109 -0
  158. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare-test-immo-mcp3.md +30 -0
  159. package/examples/immeuble/sources/agent-prompts/prompts/06-validate-and-compare.md +63 -0
  160. package/examples/immeuble/sources/checklists/gap-rules-checklist.md +42 -0
  161. package/examples/immeuble/sources/checklists/ontology-checklist.md +54 -0
  162. package/examples/immeuble/sources/documents/README.md +42 -0
  163. package/examples/immeuble/sources/documents/annexes-caves-garages-jardins.md +8 -0
  164. package/examples/immeuble/sources/documents/annexes-jardins-garages.md +1 -0
  165. package/examples/immeuble/sources/documents/baux-erables.md +1 -0
  166. package/examples/immeuble/sources/documents/baux-locatifs.md +11 -0
  167. package/examples/immeuble/sources/documents/coda-janvier-2026.md +10 -0
  168. package/examples/immeuble/sources/documents/composition-menages.md +1 -0
  169. package/examples/immeuble/sources/documents/composition-occupants.md +18 -0
  170. package/examples/immeuble/sources/documents/expected-coverage.json +70 -0
  171. package/examples/immeuble/sources/documents/extrait-coda-janvier-2026.md +1 -0
  172. package/examples/immeuble/sources/documents/groupes-facturation.md +30 -0
  173. package/examples/immeuble/sources/documents/manifest.json +79 -0
  174. package/examples/immeuble/sources/documents/note-architecte-chantier-erables.md +3 -0
  175. package/examples/immeuble/sources/documents/permis-urbanisme-erables.md +3 -0
  176. package/examples/immeuble/sources/documents/procedures-operationnelles.md +3 -0
  177. package/examples/immeuble/sources/documents/pv-ag-budget-2026.md +1 -0
  178. package/examples/immeuble/sources/documents/pv-reception-reserves-erables.md +3 -0
  179. package/examples/immeuble/sources/documents/registre-coproprietaires.md +24 -0
  180. package/examples/immeuble/sources/documents/reglement-copropriete-tilleuls.md +1 -0
  181. package/examples/immeuble/sources/documents/statuts-erables.md +22 -0
  182. package/examples/immeuble/sources/documents/statuts-tilleuls.md +19 -0
  183. package/examples/immeuble/sources/documents/succession-jean-dupont.md +3 -0
  184. package/examples/immeuble/sources/documents/titre-propriete-tilleuls-a3.md +1 -0
  185. package/examples/immeuble/sources/documents/trous-pedagogiques.md +3 -0
  186. package/examples/immeuble/sources/ontology/README.md +1 -0
  187. package/examples/immeuble/sources/ontology/core.yaml +444 -0
  188. package/examples/immeuble/success-criteria.yaml +35 -0
  189. package/fixtures/immeuble-demo.sqlite +0 -0
  190. package/package.json +16 -3
  191. package/scripts/lib/sqlite-runtime.mjs +1 -1
  192. package/scripts/load-immeuble-demo.sh +103 -0
  193. package/scripts/seed-immeuble-projections.mjs +75 -148
  194. package/scripts/verify-immeuble-demo-sources.mjs +93 -0
  195. package/scripts/verify-immeuble-demo.mjs +69 -0
  196. package/build/client/_app/immutable/chunks/BmeSanva.js +0 -1
  197. package/build/client/_app/immutable/chunks/BmeSanva.js.br +0 -0
  198. package/build/client/_app/immutable/chunks/BmeSanva.js.gz +0 -0
  199. package/build/client/_app/immutable/entry/app.CVz6aYsT.js.br +0 -0
  200. package/build/client/_app/immutable/entry/app.CVz6aYsT.js.gz +0 -0
  201. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js +0 -1
  202. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.br +0 -2
  203. package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.gz +0 -0
  204. package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.br +0 -0
  205. package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.gz +0 -0
  206. package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-Dyfsc-VA.js.map +0 -1
  207. package/scripts/build-serenity-v6-concept-review-pack.mjs +0 -493
  208. package/scripts/build-serenity-v6-review-pack.mjs +0 -479
  209. package/scripts/create-serenity-production-v6.mjs +0 -627
  210. package/scripts/export-serenity-v6-backup.mjs +0 -178
  211. package/scripts/import-serenity-v6-user-decisions.mjs +0 -543
  212. package/scripts/materialize-serenity-v6-snapshots.mjs +0 -675
@@ -0,0 +1,117 @@
1
+ # Projection Candidate Review
2
+
3
+ - Workspace: `immeuble`
4
+ - Generated at: `2026-06-14T14:57:25.897Z`
5
+ - Candidate count: 13
6
+ - Materialized count: 0
7
+ - Active lenses: blind_spot_manager, jtbd_human, jtbd_ai
8
+
9
+ ## competency
10
+
11
+ ### Plan d'analyse immeuble — questions métier
12
+ - Scope: `immeuble:competency:questions`
13
+ - Status: `candidate`
14
+ - Origin: `projection_catalog`
15
+ - artifact_kind: `analysis_plan`
16
+ - Required facets: `building.name`, `unit.usage_status`, `lease_contract.validFrom`, `coda_entry.amount`
17
+ - Required edges: `CONTAINS`, `LEASES`, `MATCHED_TO`
18
+
19
+ ## core
20
+
21
+ ### Annuaire immeubles gérés
22
+ - Scope: `immeuble:core:annuaire_coproprietes`
23
+ - Status: `candidate`
24
+ - Origin: `projection_catalog`
25
+ - artifact_kind: `live_answer_view`
26
+ - Required facets: `building.address`, `building.name`, `building.quota_basis`, `block.name`
27
+ - Required edges: `CONTAINS`
28
+
29
+ ### Baux locatifs actifs
30
+ - Scope: `immeuble:core:baux_actifs`
31
+ - Status: `candidate`
32
+ - Origin: `projection_catalog`
33
+ - artifact_kind: `live_answer_view`
34
+ - Required facets: `unit.usage_status`, `unit.lot`, `lease_contract.validFrom`, `lease_contract.monthly_rent`, `person.name`
35
+ - Required edges: `LEASES`, `RENTED_TO`, `OCCUPIES`
36
+
37
+ ### Quotités par immeuble
38
+ - Scope: `immeuble:core:quotites_par_immeuble`
39
+ - Status: `candidate`
40
+ - Origin: `projection_catalog`
41
+ - artifact_kind: `live_answer_view`
42
+ - Required facets: `building.quota_basis`, `unit.tantiemes`, `unit.quota_basis`
43
+ - Required edges: `CONTAINS`
44
+
45
+ ## gestionnaire_syndic
46
+
47
+ ### Impayes et relances en cours
48
+ - Scope: `immeuble:gestionnaire_syndic:impayes_et_relances`
49
+ - Status: `candidate`
50
+ - Origin: `analysis_lens`
51
+ - artifact_kind: `analysis_plan`
52
+ - Required facets: `receipt.amount`, `reminder.level`, `reminder.amount_due`, `charge_call.amount`
53
+ - Required edges: `REQUIRES_REVIEW`, `MATCHED_TO`
54
+
55
+ ### Baux proches de l'echeance
56
+ - Scope: `immeuble:gestionnaire_syndic:baux_echeance`
57
+ - Status: `candidate`
58
+ - Origin: `analysis_lens`
59
+ - artifact_kind: `analysis_plan`
60
+ - Required facets: `lease_contract.validFrom`, `lease_contract.monthly_rent`, `unit.usage_status`
61
+ - Required edges: `LEASES`, `RENTED_TO`
62
+
63
+ ### Anomalies de quotites
64
+ - Scope: `immeuble:gestionnaire_syndic:quotites_anomalie`
65
+ - Status: `candidate`
66
+ - Origin: `analysis_lens`
67
+ - artifact_kind: `analysis_plan`
68
+ - Required facets: `building.quota_basis`, `unit.tantiemes`, `unit.quota_basis`
69
+ - Required edges: `CONTAINS`
70
+
71
+ ### Lots sans occupation declaree
72
+ - Scope: `immeuble:gestionnaire_syndic:occupation_orpheline`
73
+ - Status: `candidate`
74
+ - Origin: `analysis_lens`
75
+ - artifact_kind: `analysis_plan`
76
+ - Required facets: `unit.usage_status`, `person.name`, `household.household_status`
77
+ - Required edges: `OCCUPIES`, `OWNS`, `PRIMARY_RESIDENCE_OF`
78
+
79
+ ### Top actions manager du jour
80
+ - Scope: `immeuble:gestionnaire_syndic:manager_attention_today`
81
+ - Status: `candidate`
82
+ - Origin: `analysis_lens`
83
+ - artifact_kind: `analysis_plan`
84
+ - Required facets: `reminder.level`, `decision.date`, `lease_contract.validFrom`
85
+ - Required edges: `REQUIRES_REVIEW`, `LEASES`
86
+
87
+ ### JTBD gestionnaire: arbitrer avec preuves
88
+ - Scope: `immeuble:gestionnaire_syndic:gestionnaire_decide_arbitrer`
89
+ - Status: `candidate`
90
+ - Origin: `analysis_lens`
91
+ - artifact_kind: `analysis_plan`
92
+ - Required facets: `decision.date`, `coda_entry.amount`, `coda_entry.status`
93
+ - Required edges: `MATCHED_TO`, `REQUIRES_REVIEW`
94
+
95
+ ### JTBD syndic: coordonner la prochaine intervention
96
+ - Scope: `immeuble:gestionnaire_syndic:syndic_coordinate_intervention`
97
+ - Status: `candidate`
98
+ - Origin: `analysis_lens`
99
+ - artifact_kind: `analysis_plan`
100
+ - Required facets: `unit.usage_status`, `shared_space.category`, `shared_equipment.equipment_type`
101
+ - Required edges: `CONTAINS`, `USES_COMMON`
102
+
103
+ ### JTBD agent IA: tour de controle priorisee
104
+ - Scope: `immeuble:gestionnaire_syndic:agent_watchtower_prioritize`
105
+ - Status: `candidate`
106
+ - Origin: `analysis_lens`
107
+ - artifact_kind: `analysis_plan`
108
+ - Required facets: `reminder.level`, `lease_contract.validFrom`, `unit.usage_status`
109
+ - Required edges: `REQUIRES_REVIEW`, `LEASES`
110
+
111
+ ### JTBD agent IA: detective de reconciliation CODA
112
+ - Scope: `immeuble:gestionnaire_syndic:agent_reconciliation_detective`
113
+ - Status: `candidate`
114
+ - Origin: `analysis_lens`
115
+ - artifact_kind: `analysis_plan`
116
+ - Required facets: `coda_entry.amount`, `coda_entry.status`, `charge_call.amount`, `receipt.amount`
117
+ - Required edges: `MATCHED_TO`, `ALLOCATED_TO`
@@ -0,0 +1,115 @@
1
+ # Projection Model Validation
2
+
3
+ ## Synthese
4
+
5
+ - Workspace: `immeuble`
6
+ - Projections catalogue: 4
7
+ - Questions manager: 0
8
+ - Ajouts par patterns: 9
9
+ - Scopes materialises: 0
10
+
11
+ ## Projections catalogue
12
+
13
+ ### Plan d'analyse immeuble — questions métier
14
+ - Question: Quelles questions métier le workspace immeuble doit-il pouvoir traiter ?
15
+ - Scope: `immeuble:competency:questions`
16
+ - artifact_kind: `analysis_plan`
17
+ - Statut: `candidate`
18
+ - Facettes requises: `building.name`, `unit.usage_status`, `lease_contract.validFrom`, `coda_entry.amount`
19
+ - Aretes requises: `CONTAINS`, `LEASES`, `MATCHED_TO`
20
+
21
+ ### Annuaire immeubles gérés
22
+ - Question: Quels immeubles sont gérés et où sont-ils situés ?
23
+ - Scope: `immeuble:core:annuaire_coproprietes`
24
+ - artifact_kind: `live_answer_view`
25
+ - Statut: `candidate`
26
+ - Facettes requises: `building.address`, `building.name`, `building.quota_basis`, `block.name`
27
+ - Aretes requises: `CONTAINS`
28
+
29
+ ### Baux locatifs actifs
30
+ - Question: Quels appartements sont loués, à qui, depuis quelle date ?
31
+ - Scope: `immeuble:core:baux_actifs`
32
+ - artifact_kind: `live_answer_view`
33
+ - Statut: `candidate`
34
+ - Facettes requises: `unit.usage_status`, `unit.lot`, `lease_contract.validFrom`, `lease_contract.monthly_rent`, `person.name`
35
+ - Aretes requises: `LEASES`, `RENTED_TO`, `OCCUPIES`
36
+
37
+ ### Quotités par immeuble
38
+ - Question: Les quotités de chaque immeuble totalisent-elles 1000 ?
39
+ - Scope: `immeuble:core:quotites_par_immeuble`
40
+ - artifact_kind: `live_answer_view`
41
+ - Statut: `candidate`
42
+ - Facettes requises: `building.quota_basis`, `unit.tantiemes`, `unit.quota_basis`
43
+ - Aretes requises: `CONTAINS`
44
+
45
+ ## Questions manquantes proposees
46
+
47
+ ### Impayes et relances en cours
48
+ - Categorie: `blind_spot_manager`
49
+ - Question: Quels coproprietaires ont des impayes ou relances actives ?
50
+ - Facettes requises: `receipt.amount`, `reminder.level`, `reminder.amount_due`, `charge_call.amount`
51
+ - Aretes requises: `REQUIRES_REVIEW`, `MATCHED_TO`
52
+
53
+ ### Baux proches de l'echeance
54
+ - Categorie: `blind_spot_manager`
55
+ - Question: Quels baux arrivent a echeance dans les 90 prochains jours ?
56
+ - Facettes requises: `lease_contract.validFrom`, `lease_contract.monthly_rent`, `unit.usage_status`
57
+ - Aretes requises: `LEASES`, `RENTED_TO`
58
+
59
+ ### Anomalies de quotites
60
+ - Categorie: `blind_spot_manager`
61
+ - Question: Quels immeubles ont des quotites qui ne totalisent pas le quota_basis ?
62
+ - Facettes requises: `building.quota_basis`, `unit.tantiemes`, `unit.quota_basis`
63
+ - Aretes requises: `CONTAINS`
64
+
65
+ ### Lots sans occupation declaree
66
+ - Categorie: `blind_spot_manager`
67
+ - Question: Quels lots n'ont ni proprietaire occupant ni locataire declare ?
68
+ - Facettes requises: `unit.usage_status`, `person.name`, `household.household_status`
69
+ - Aretes requises: `OCCUPIES`, `OWNS`, `PRIMARY_RESIDENCE_OF`
70
+
71
+ ### Top actions manager du jour
72
+ - Categorie: `blind_spot_manager`
73
+ - Question: Quelles 3 a 5 actions doivent remonter au gestionnaire aujourd'hui ?
74
+ - Facettes requises: `reminder.level`, `decision.date`, `lease_contract.validFrom`
75
+ - Aretes requises: `REQUIRES_REVIEW`, `LEASES`
76
+
77
+ ### JTBD gestionnaire: arbitrer avec preuves
78
+ - Categorie: `jtbd_human`
79
+ - Question: Quand plusieurs signaux se contredisent, quelle decision puis-je prendre avec suffisamment de preuves ?
80
+ - Facettes requises: `decision.date`, `coda_entry.amount`, `coda_entry.status`
81
+ - Aretes requises: `MATCHED_TO`, `REQUIRES_REVIEW`
82
+
83
+ ### JTBD syndic: coordonner la prochaine intervention
84
+ - Categorie: `jtbd_human`
85
+ - Question: Que faut-il coordonner pour la prochaine intervention sur un lot ou une zone commune ?
86
+ - Facettes requises: `unit.usage_status`, `shared_space.category`, `shared_equipment.equipment_type`
87
+ - Aretes requises: `CONTAINS`, `USES_COMMON`
88
+
89
+ ### JTBD agent IA: tour de controle priorisee
90
+ - Categorie: `jtbd_ai`
91
+ - Question: Quels signaux dois-je surveiller et remonter sans saturer le gestionnaire ?
92
+ - Facettes requises: `reminder.level`, `lease_contract.validFrom`, `unit.usage_status`
93
+ - Aretes requises: `REQUIRES_REVIEW`, `LEASES`
94
+
95
+ ### JTBD agent IA: detective de reconciliation CODA
96
+ - Categorie: `jtbd_ai`
97
+ - Question: Quelles incoherences entre paiements CODA et appels de charges dois-je investiguer ?
98
+ - Facettes requises: `coda_entry.amount`, `coda_entry.status`, `charge_call.amount`, `receipt.amount`
99
+ - Aretes requises: `MATCHED_TO`, `ALLOCATED_TO`
100
+
101
+ ## Dimensions et graphes a valider
102
+
103
+ ### Facettes nouvelles par rapport aux sources
104
+
105
+ `charge_call.amount`, `coda_entry.status`, `decision.date`, `household.household_status`, `receipt.amount`, `reminder.amount_due`, `reminder.level`, `shared_equipment.equipment_type`, `shared_space.category`
106
+
107
+ ### Aretes nouvelles par rapport aux sources
108
+
109
+ `ALLOCATED_TO`, `OWNS`, `PRIMARY_RESIDENCE_OF`, `REQUIRES_REVIEW`, `USES_COMMON`
110
+
111
+ ## Gaps versus model_contract
112
+
113
+ - Schemas inconnus: n/a
114
+ - Facettes inconnues: n/a
115
+ - Aretes inconnues: n/a
@@ -0,0 +1,4 @@
1
+ {
2
+ "graph_projected": 396,
3
+ "facet_assignments": 131
4
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "ok": true,
3
+ "db_path": "/tmp/immeuble-reset-test/immeuble.sqlite",
4
+ "steps": [
5
+ {
6
+ "step": "build",
7
+ "ok": true,
8
+ "status": 0,
9
+ "stderr": ""
10
+ },
11
+ {
12
+ "step": "import",
13
+ "ok": true,
14
+ "status": 0,
15
+ "stderr": ""
16
+ },
17
+ {
18
+ "step": "verify_acceptance",
19
+ "ok": true,
20
+ "status": 0,
21
+ "stderr": ""
22
+ },
23
+ {
24
+ "step": "audit_projections",
25
+ "ok": true,
26
+ "status": 0,
27
+ "stderr": ""
28
+ }
29
+ ],
30
+ "started_at": "2026-06-14T08:31:20.938Z",
31
+ "finished_at": "2026-06-14T08:31:44.529Z"
32
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "ok": true,
3
+ "checked": 131,
4
+ "violations": []
5
+ }
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Audit Immeuble projections after import or bundle load.
4
+ *
5
+ * Checks:
6
+ * - projection_catalog.yaml entries are present in consumer contract and seed
7
+ * - live_answer_view artifacts are listable
8
+ * - each required artifact has non-empty payload content
9
+ * - consumer_contract.yaml structure is valid
10
+ */
11
+
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ import { spawnSync } from "node:child_process";
16
+ import { parseYaml } from "./yaml-lite.mjs";
17
+
18
+ const immeubleRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
19
+ const pkgRoot = resolve(immeubleRoot, "..", "..");
20
+ const reportsDir = join(immeubleRoot, "reports");
21
+ const workspaceId = parseFlag(process.argv.slice(2), "--workspace-id", "immeuble");
22
+ const gcpPath = resolveGcp();
23
+
24
+ mkdirSync(reportsDir, { recursive: true });
25
+
26
+ const catalog = parseYaml(readFileSync(join(immeubleRoot, "contracts", "projection_catalog.yaml"), "utf8"));
27
+ const consumer = parseYaml(readFileSync(join(immeubleRoot, "contracts", "consumer_contract.yaml"), "utf8"));
28
+ const seedLines = readFileSync(join(immeubleRoot, "contracts", "answer_artifacts.seed.jsonl"), "utf8")
29
+ .trim()
30
+ .split("\n")
31
+ .filter(Boolean)
32
+ .map((line) => safeParseJson(line))
33
+ .filter(Boolean);
34
+
35
+ const expectedSeedById = Object.fromEntries(seedLines.map((row) => {
36
+ const id = row.artifact?.artifact_id;
37
+ return id ? [id, row] : null;
38
+ }).filter(Boolean));
39
+
40
+ const expectedCatalogIds = (catalog.projections ?? []).map((entry) => {
41
+ const kind = (entry.artifact_kind || "").toString();
42
+ const prefix = kind === "analysis_plan" ? "analysis_plan__" : "live_answer_view__";
43
+ return `${prefix}${entry.name}`;
44
+ });
45
+
46
+ const expectedLiveArtifactIds = seedLines
47
+ .filter((row) => row.artifact?.artifact_kind === "live_answer_view")
48
+ .map((row) => row.artifact.artifact_id)
49
+ .filter(Boolean);
50
+
51
+ const listRes = spawnSync(process.execPath, [
52
+ gcpPath,
53
+ "brain", "artifact", "list",
54
+ "--workspace-id", workspaceId,
55
+ "--kind", "live_answer_view",
56
+ "--limit", "200"
57
+ ], {
58
+ cwd: pkgRoot,
59
+ encoding: "utf8",
60
+ env: process.env
61
+ });
62
+
63
+ let listedIds = [];
64
+ let listedById = new Map();
65
+ let listOk = listRes.status === 0;
66
+ if (listOk) {
67
+ const payload = safeParseJson(listRes.stdout.trim());
68
+ if (payload) {
69
+ const artifacts = (payload.artifacts ?? payload.items ?? []).filter(Boolean);
70
+ listedIds = artifacts.map((a) => a.artifact_id ?? a.id).filter(Boolean);
71
+ listedById = new Map(artifacts.map((a) => [a.artifact_id ?? a.id, a]));
72
+ } else {
73
+ listOk = false;
74
+ }
75
+ }
76
+ if (!listOk) {
77
+ const fallback = listArtifactsFromSqlite();
78
+ if (fallback.ok) {
79
+ listOk = true;
80
+ listedIds = fallback.artifacts.map((a) => a.artifact_id).filter(Boolean);
81
+ listedById = new Map(fallback.artifacts.map((a) => [a.artifact_id, a]));
82
+ }
83
+ }
84
+
85
+ const payloadIssues = [];
86
+
87
+ function pushIssue(label, detail) {
88
+ payloadIssues.push({ label, detail });
89
+ }
90
+
91
+ function catalogIdForEntry(entry) {
92
+ const kind = (entry?.artifact_kind || "").toString();
93
+ const prefix = kind === "analysis_plan" ? "analysis_plan__" : "live_answer_view__";
94
+ return `${prefix}${entry?.name}`;
95
+ }
96
+
97
+ function isArrayOrStringArray(value) {
98
+ return Array.isArray(value) && value.length > 0;
99
+ }
100
+
101
+ for (const entry of catalog.projections ?? []) {
102
+ const expectedId = catalogIdForEntry(entry);
103
+ const seed = expectedSeedById[expectedId];
104
+ if (!seed) {
105
+ pushIssue("seed_missing", `projection ${expectedId} missing in answer_artifacts.seed.jsonl`);
106
+ continue;
107
+ }
108
+
109
+ const listed = listedById.get(expectedId);
110
+ const listedPayload = listed ? parseArtifactPayload(listed) : null;
111
+ const seedPayload = safeParseJson(seed.artifact?.payload_json) || {};
112
+
113
+ const artifactKind = seed.artifact?.artifact_kind ?? entry.artifact_kind;
114
+ if (artifactKind === "analysis_plan") {
115
+ const questions = seedPayload.competency_questions ?? listedPayload?.competency_questions;
116
+ if (!isArrayOrStringArray(questions)) {
117
+ pushIssue("payload", `${expectedId}: competency_questions missing or empty`);
118
+ }
119
+ } else if (artifactKind === "live_answer_view") {
120
+ if (!listed && listOk) {
121
+ pushIssue("registry", `${expectedId}: not found in artifact list`);
122
+ }
123
+ const summary = seedPayload.summary ?? listedPayload?.summary;
124
+ if (typeof summary !== "string" || summary.trim() === "") {
125
+ pushIssue("payload", `${expectedId}: summary missing in payload`);
126
+ }
127
+ if (!isArrayOrStringArray(seedPayload.refresh_checks ?? listedPayload?.refresh_checks)) {
128
+ pushIssue("payload", `${expectedId}: refresh_checks missing or empty`);
129
+ }
130
+ }
131
+ }
132
+
133
+ const catalogIds = expectedCatalogIds;
134
+ const listedLiveIds = listedIds;
135
+ const missingFromRegistry = expectedLiveArtifactIds.filter((id) => !listedIds.includes(id));
136
+ const missingFromSeed = catalogIds.filter((id) => !expectedSeedById[id]);
137
+
138
+ const audit = {
139
+ ok: payloadIssues.length === 0 && consumer.workspace_id === workspaceId && listOk,
140
+ workspace_id: workspaceId,
141
+ catalog_count: catalogIds.length,
142
+ seed_live_views: expectedLiveArtifactIds.length,
143
+ listed_live_views: listedLiveIds.length,
144
+ missing_from_registry: missingFromRegistry,
145
+ missing_from_seed: missingFromSeed,
146
+ required_live_views: expectedLiveArtifactIds,
147
+ listed_live_views_ids: listedLiveIds,
148
+ list_ok: listOk,
149
+ payload_issues: payloadIssues,
150
+ consumer_workspace: consumer.workspace_id,
151
+ consumer_facet_queries: (consumer.facet_queries ?? []).length,
152
+ consumer_answer_artifacts: (consumer.answer_artifacts ?? []).length,
153
+ generated_at: new Date().toISOString()
154
+ };
155
+
156
+ if (consumer.workspace_id !== workspaceId) {
157
+ payloadIssues.push({
158
+ label: "consumer_contract",
159
+ detail: `consumer workspace mismatch: expected ${workspaceId}, got ${consumer.workspace_id}`
160
+ });
161
+ }
162
+
163
+ if (!listOk) {
164
+ audit.list_skipped = true;
165
+ audit.list_stderr = (listRes.stderr || listRes.stdout || "").slice(0, 500);
166
+ payloadIssues.push({
167
+ label: "registry_list",
168
+ detail: "artifact list command failed; cannot validate live answer registry state"
169
+ });
170
+ }
171
+
172
+ if (missingFromRegistry.length > 0 && listOk) {
173
+ payloadIssues.push({
174
+ label: "missing_from_registry",
175
+ detail: `missing live_answer_view ids: ${missingFromRegistry.join(", ")}`
176
+ });
177
+ }
178
+
179
+ if (catalog.projections && catalogIds.length > 0 && expectedLiveArtifactIds.length === 0) {
180
+ payloadIssues.push({ label: "seed", detail: "no live_answer_view entries in answer_artifacts.seed.jsonl" });
181
+ }
182
+
183
+ audit.ok = payloadIssues.length === 0 && consumer.workspace_id === workspaceId && listOk;
184
+
185
+ writeFileSync(join(reportsDir, "projection_audit.json"), JSON.stringify(audit, null, 2) + "\n", "utf8");
186
+
187
+ const seedLiveViews = seedLines
188
+ .filter((row) => row.artifact?.artifact_kind === "live_answer_view")
189
+ .map((row) => ({
190
+ id: row.artifact?.artifact_id,
191
+ workspace_id: row.artifact?.workspace_id
192
+ }));
193
+
194
+ writeFileSync(join(reportsDir, "consumer_contract.validation.json"), JSON.stringify({
195
+ ok: audit.ok && (consumer.workspace_id === workspaceId),
196
+ workspace_id: consumer.workspace_id,
197
+ facet_queries: consumer.facet_queries?.length ?? 0,
198
+ answer_artifacts: consumer.answer_artifacts?.length ?? 0,
199
+ expected_live_views: expectedLiveArtifactIds,
200
+ listed_live_views: listedLiveIds,
201
+ seed_live_views: seedLiveViews
202
+ }, null, 2) + "\n", "utf8");
203
+
204
+ console.log(JSON.stringify(audit, null, 2));
205
+ process.exit(audit.ok ? 0 : 1);
206
+
207
+ function parseArtifactPayload(artifact) {
208
+ if (!artifact) return null;
209
+ const raw = artifact.payload_json ?? artifact.payload ?? artifact.payload_raw ?? artifact.payloadData;
210
+ return safeParseJson(raw);
211
+ }
212
+
213
+ function safeParseJson(value) {
214
+ if (value == null) return null;
215
+ if (typeof value === "object") return value;
216
+ if (typeof value !== "string") return null;
217
+ try {
218
+ return JSON.parse(value);
219
+ } catch {
220
+ return null;
221
+ }
222
+ }
223
+
224
+ function parseFlag(argv, name, defaultValue) {
225
+ const index = argv.indexOf(name);
226
+ if (index === -1) return defaultValue;
227
+ return argv[index + 1] ?? defaultValue;
228
+ }
229
+
230
+ function resolveGcp() {
231
+ const candidates = [
232
+ process.env.GHOSTCRAB_GCP,
233
+ process.env.GHOSTCRAB_ROOT ? join(process.env.GHOSTCRAB_ROOT, "bin", "gcp.mjs") : "",
234
+ join(pkgRoot, "bin", "gcp.mjs"),
235
+ join(pkgRoot, "node_modules", "@mindflight", "ghostcrab-personal-mcp", "bin", "gcp.mjs"),
236
+ resolve(pkgRoot, "..", "ghostcrab-personal-mcp", "bin", "gcp.mjs")
237
+ ].filter(Boolean);
238
+ const found = candidates.find((candidate) => existsSync(candidate));
239
+ return found ?? join(pkgRoot, "bin", "gcp.mjs");
240
+ }
241
+
242
+ function listArtifactsFromSqlite() {
243
+ const db = process.env.GHOSTCRAB_SQLITE_PATH;
244
+ if (!db || !existsSync(db)) return { ok: false, artifacts: [] };
245
+ const sql = `SELECT artifact_id, slug, workspace_id, artifact_kind, public_label, lifecycle, state, payload_json, legacy_ref FROM mindbrain_answer_artifacts WHERE workspace_id='${workspaceId.replace(/'/g, "''")}' AND artifact_kind='live_answer_view' LIMIT 500;`;
246
+ const res = spawnSync("sqlite3", ["-json", db, sql], { encoding: "utf8" });
247
+ if (res.status !== 0) return { ok: false, artifacts: [] };
248
+ try {
249
+ const artifacts = JSON.parse(res.stdout || "[]");
250
+ return { ok: Array.isArray(artifacts), artifacts: Array.isArray(artifacts) ? artifacts : [] };
251
+ } catch {
252
+ return { ok: false, artifacts: [] };
253
+ }
254
+ }