@mindflight/mindbrain-personal-studio 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/client/_app/immutable/chunks/D0UIlUGZ.js +1 -0
- package/build/client/_app/immutable/chunks/D0UIlUGZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/D0UIlUGZ.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.CVz6aYsT.js → app.CR-imLox.js} +2 -2
- package/build/client/_app/immutable/entry/app.CR-imLox.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CR-imLox.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DV-AjeAB.js +1 -0
- package/build/client/_app/immutable/entry/start.DV-AjeAB.js.br +2 -0
- package/build/client/_app/immutable/entry/start.DV-AjeAB.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.BBtxY46Q.js → 1.CTEedoSY.js} +1 -1
- package/build/client/_app/immutable/nodes/1.CTEedoSY.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.CTEedoSY.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +4 -4
- package/build/index.js +4 -4
- package/build/server/chunks/chunks/{internal.js-D8EA_he2.js → internal.js-WOmQXGMa.js} +2 -2
- package/build/server/chunks/chunks/{internal.js-D8EA_he2.js.map → internal.js-WOmQXGMa.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/graph/schema-registry/{_server.ts.js-Dyfsc-VA.js → _server.ts.js-CAsXxBRq.js} +7 -2
- package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-CAsXxBRq.js.map +1 -0
- package/build/server/chunks/{handler-BjXBCd1c.js → handler-BIDedSZq.js} +3 -3
- package/build/server/chunks/{handler-BjXBCd1c.js.map → handler-BIDedSZq.js.map} +1 -1
- package/build/server/chunks/{index.js-BJYcV8V7.js → index.js-YVPJa0so.js} +2 -2
- package/build/server/chunks/{index.js-BJYcV8V7.js.map → index.js-YVPJa0so.js.map} +1 -1
- package/build/server/chunks/{manifest.js-Ddaot0P4.js → manifest.js-aGRKuiqF.js} +4 -4
- package/build/server/chunks/{manifest.js-Ddaot0P4.js.map → manifest.js-aGRKuiqF.js.map} +1 -1
- package/build/server/chunks/nodes/{1.js-BRigw_9J.js → 1.js-Dhh3ErZY.js} +2 -2
- package/build/server/chunks/nodes/{1.js-BRigw_9J.js.map → 1.js-Dhh3ErZY.js.map} +1 -1
- package/package.json +6 -2
- package/build/client/_app/immutable/chunks/BmeSanva.js +0 -1
- package/build/client/_app/immutable/chunks/BmeSanva.js.br +0 -0
- package/build/client/_app/immutable/chunks/BmeSanva.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CVz6aYsT.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CVz6aYsT.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.Bt5tVOz8.js +0 -1
- package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.br +0 -2
- package/build/client/_app/immutable/entry/start.Bt5tVOz8.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.BBtxY46Q.js.gz +0 -0
- package/build/server/chunks/entries/endpoints/api/graph/schema-registry/_server.ts.js-Dyfsc-VA.js.map +0 -1
- package/scripts/build-serenity-v6-concept-review-pack.mjs +0 -493
- package/scripts/build-serenity-v6-review-pack.mjs +0 -479
- package/scripts/create-serenity-production-v6.mjs +0 -627
- package/scripts/export-serenity-v6-backup.mjs +0 -178
- package/scripts/import-serenity-v6-user-decisions.mjs +0 -543
- package/scripts/materialize-serenity-v6-snapshots.mjs +0 -675
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
|
|
6
|
-
const ROOT = process.cwd();
|
|
7
|
-
const DAY_DIR = path.join(ROOT, "docs/demo/export-audit/2026-06-26");
|
|
8
|
-
const MIGRATION_DIR = path.join(DAY_DIR, "serenity-production-v6-migration");
|
|
9
|
-
const TECHNICAL_REVIEW_DIR = path.join(DAY_DIR, "serenity-production-v6-review-pack");
|
|
10
|
-
const OUT_DIR = path.join(DAY_DIR, "serenity-production-v6-concept-review");
|
|
11
|
-
|
|
12
|
-
const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
|
|
13
|
-
const write = (name, content) => {
|
|
14
|
-
fs.writeFileSync(path.join(OUT_DIR, name), `${content.trim()}\n`);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const schemas = readJson(path.join(TECHNICAL_REVIEW_DIR, "schema_decision_pack.json"));
|
|
18
|
-
const relations = readJson(path.join(TECHNICAL_REVIEW_DIR, "relation_decision_pack.json"));
|
|
19
|
-
const rejected = readJson(path.join(TECHNICAL_REVIEW_DIR, "rejected_relation_audit.json"));
|
|
20
|
-
const scenarios = readJson(path.join(MIGRATION_DIR, "scenario_sop_map.json"));
|
|
21
|
-
|
|
22
|
-
fs.mkdirSync(OUT_DIR, { recursive: true });
|
|
23
|
-
|
|
24
|
-
const relationGloss = {
|
|
25
|
-
activer: "declenche ou rend applicable un objet metier",
|
|
26
|
-
assigner_gestion: "attribue la gestion operationnelle a une equipe ou un gestionnaire",
|
|
27
|
-
composer: "compose un ensemble a partir d'elements metier",
|
|
28
|
-
contenir: "exprime une inclusion structurelle stable",
|
|
29
|
-
declencher: "cree un evenement ou une mission a partir d'un fait initial",
|
|
30
|
-
donne_lieu_a: "cree une suite operationnelle ou administrative",
|
|
31
|
-
est_actee_par: "formalise une decision ou une action par une piece",
|
|
32
|
-
est_calcule_a_partir_de: "garde la lignee de calcul entre pieces comptables",
|
|
33
|
-
est_composee_d: "detaille les sous-parties d'un objet de suivi",
|
|
34
|
-
est_emise_par: "identifie l'emetteur d'une piece",
|
|
35
|
-
evalue: "relie une expertise ou verification a l'objet evalue",
|
|
36
|
-
fonde_une: "sert de base a une decision, action ou demande",
|
|
37
|
-
peut_generer: "peut creer un objet aval selon les conditions SOP",
|
|
38
|
-
peut_preceder: "modele l'ordre possible des etapes",
|
|
39
|
-
porte_sur: "indique l'objet metier concerne",
|
|
40
|
-
produit_des: "produit des livrables ou effets attendus",
|
|
41
|
-
rattacher: "rattache un objet a son contexte metier principal",
|
|
42
|
-
referencer: "relation generique de reference; trop large sans decomposition",
|
|
43
|
-
resulte_de: "indique la cause ou l'origine metier",
|
|
44
|
-
supporter: "relation generique de support/preuve; trop large sans decomposition",
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const domainGloss = {
|
|
48
|
-
accounting_closeout: "Cloture comptable et appels de fonds",
|
|
49
|
-
administrative: "Administration et mutations",
|
|
50
|
-
ag_decision_cycle: "Assemblee generale et decisions",
|
|
51
|
-
comptabilite: "Comptabilite",
|
|
52
|
-
decisionnel: "Assemblee generale et decisions",
|
|
53
|
-
finance: "Finance et tresorerie",
|
|
54
|
-
missions: "Missions, incidents et sinistres",
|
|
55
|
-
production: "Vue copropriete 360 et production",
|
|
56
|
-
technique: "Travaux, equipements et interventions",
|
|
57
|
-
meta: "Gouvernance du modele",
|
|
58
|
-
mapping_profile_governance: "Gouvernance du mapping",
|
|
59
|
-
mappingprofile: "Gouvernance du mapping",
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const scenarioQuestion = {
|
|
63
|
-
accounting_closeout:
|
|
64
|
-
"Veut-on tracer la lignee comptable complete, ou seulement produire des controles et ecarts calcules ?",
|
|
65
|
-
administrative:
|
|
66
|
-
"Veut-on modeler les mutations comme un workflow metier, ou seulement comme des dossiers et documents historises ?",
|
|
67
|
-
ag_decision_cycle:
|
|
68
|
-
"Les decisions d'AG doivent-elles generer des objets aval typés comme travaux, appels de fonds ou mandats ?",
|
|
69
|
-
comptabilite:
|
|
70
|
-
"Quels controles comptables sont des objets SOP persistants, et lesquels sont seulement des resultats de verification ?",
|
|
71
|
-
decisionnel:
|
|
72
|
-
"Les decisions d'AG doivent-elles generer des objets aval types comme travaux, appels de fonds ou mandats ?",
|
|
73
|
-
finance:
|
|
74
|
-
"Quels mouvements financiers doivent etre relies a leur origine metier, et lesquels restent des lignes comptables ?",
|
|
75
|
-
missions:
|
|
76
|
-
"La mission est-elle une timeline documentaire, un workflow d'etats, ou les deux ?",
|
|
77
|
-
production:
|
|
78
|
-
"La vue copropriete 360 doit-elle devenir une carte structurelle de reference ou rester une projection de consultation ?",
|
|
79
|
-
technique:
|
|
80
|
-
"Le cycle travaux doit-il etre une chaine SOP typee de bout en bout, ou une vue de suivi alimentee par documents ?",
|
|
81
|
-
meta:
|
|
82
|
-
"Ces elements servent-ils au modele metier ou seulement a gouverner l'import et la couverture ?",
|
|
83
|
-
mapping_profile_governance:
|
|
84
|
-
"Ces elements doivent-ils rester hors modele metier comme regles de mapping et qualite ?",
|
|
85
|
-
mappingprofile:
|
|
86
|
-
"Ces elements doivent-ils rester hors modele metier comme regles de mapping et qualite ?",
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const choiceBlock = [
|
|
90
|
-
"A. Rapatrier dans V6 comme concept/relation SOP canonique.",
|
|
91
|
-
"B. Ne pas ajouter: mapper vers un concept ou une relation V6 deja existante.",
|
|
92
|
-
"C. Rejeter: bruit V4, fake data, ou relation trop generique.",
|
|
93
|
-
"D. Bloquer: demander une phrase SOP source -> relation -> cible avant decision.",
|
|
94
|
-
].join("\n");
|
|
95
|
-
|
|
96
|
-
const md = (value) =>
|
|
97
|
-
String(value ?? "")
|
|
98
|
-
.replaceAll("|", "\\|")
|
|
99
|
-
.replace(/\s+/g, " ")
|
|
100
|
-
.trim();
|
|
101
|
-
|
|
102
|
-
const familyFromScope = (scope) => {
|
|
103
|
-
if (!scope) return "unknown";
|
|
104
|
-
const cleaned = scope.replace(/^serenity-production-v5:/, "");
|
|
105
|
-
const [family] = cleaned.split(":");
|
|
106
|
-
return family || "unknown";
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const labelFromScope = (scope) => {
|
|
110
|
-
if (!scope) return "Sans scenario";
|
|
111
|
-
return scope.replace(/^serenity-production-v5:/, "").replaceAll(":", " / ");
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const schemaLabel = (schemaId) =>
|
|
115
|
-
schemaId
|
|
116
|
-
.replace(/^serenity-v4:/, "")
|
|
117
|
-
.replace(/^serenity-v4-s2:/, "")
|
|
118
|
-
.replace(/^serenity-production-v6:/, "")
|
|
119
|
-
.replaceAll(":", " / ")
|
|
120
|
-
.replaceAll("_", " ");
|
|
121
|
-
|
|
122
|
-
const schemaDisplayKey = (schema) => schemaLabel(schema.schema_id).toLowerCase();
|
|
123
|
-
|
|
124
|
-
const relationRecommendation = (relation) => {
|
|
125
|
-
if (["referencer", "supporter"].includes(relation.relation_type)) {
|
|
126
|
-
return "Ne pas rapatrier tel quel. Decomposer en relations SOP precises avec source, cible et preuve.";
|
|
127
|
-
}
|
|
128
|
-
if (relation.source_quality === "mixed_or_generated") {
|
|
129
|
-
return "Candidat seulement. Rapatrier uniquement si une phrase SOP confirme source, cible et direction.";
|
|
130
|
-
}
|
|
131
|
-
return "Candidat a valider par scenario SOP.";
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const schemaRecommendation = (schema) => {
|
|
135
|
-
if (schema.current_v6_equivalent) {
|
|
136
|
-
return `Mapper vers ${schema.current_v6_equivalent}; pas de nouveau schema a creer.`;
|
|
137
|
-
}
|
|
138
|
-
if (schema.decision === "rename_and_add_if_sop_valid") {
|
|
139
|
-
return "Concept potentiellement utile, mais le nom doit etre renomme en V6 et confirme par SOP.";
|
|
140
|
-
}
|
|
141
|
-
if (schema.decision === "add_or_rename_after_sop_review") {
|
|
142
|
-
return "Decision metier requise: nouveau concept V6 ou decomposition vers concepts existants.";
|
|
143
|
-
}
|
|
144
|
-
return "Verifier si c'est un alias V4, un concept manquant, ou du bruit.";
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const families = new Map();
|
|
148
|
-
const ensureFamily = (family) => {
|
|
149
|
-
if (!families.has(family)) {
|
|
150
|
-
families.set(family, {
|
|
151
|
-
family,
|
|
152
|
-
label: domainGloss[family] || family,
|
|
153
|
-
question: scenarioQuestion[family] || "Quelle decision metier faut-il prendre pour ce groupe ?",
|
|
154
|
-
scenarioLabels: new Set(),
|
|
155
|
-
schemas: [],
|
|
156
|
-
relations: [],
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
return families.get(family);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
for (const scenario of scenarios) {
|
|
163
|
-
const family = ensureFamily(familyFromScope(scenario.scope));
|
|
164
|
-
family.scenarioLabels.add(labelFromScope(scenario.scope));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
for (const schema of schemas) {
|
|
168
|
-
for (const scope of schema.required_by_scopes || []) {
|
|
169
|
-
const family = ensureFamily(familyFromScope(scope));
|
|
170
|
-
family.schemas.push(schema);
|
|
171
|
-
family.scenarioLabels.add(labelFromScope(scope));
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
for (const relation of relations) {
|
|
176
|
-
for (const supported of relation.supported_scenarios || []) {
|
|
177
|
-
const family = ensureFamily(familyFromScope(supported.scope));
|
|
178
|
-
family.relations.push(relation);
|
|
179
|
-
family.scenarioLabels.add(labelFromScope(supported.scope));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const uniqBy = (items, keyFn) => {
|
|
184
|
-
const seen = new Set();
|
|
185
|
-
return items.filter((item) => {
|
|
186
|
-
const key = keyFn(item);
|
|
187
|
-
if (seen.has(key)) return false;
|
|
188
|
-
seen.add(key);
|
|
189
|
-
return true;
|
|
190
|
-
});
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
for (const family of families.values()) {
|
|
194
|
-
family.schemas = uniqBy(family.schemas, schemaDisplayKey);
|
|
195
|
-
family.relations = uniqBy(family.relations, (relation) => relation.relation_type);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const orderedFamilies = [...families.values()]
|
|
199
|
-
.filter((family) => family.schemas.length || family.relations.length)
|
|
200
|
-
.sort((a, b) => {
|
|
201
|
-
const score = (family) => family.schemas.length * 2 + family.relations.length;
|
|
202
|
-
return score(b) - score(a) || a.family.localeCompare(b.family);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const immediateMappings = schemas.filter((schema) => schema.current_v6_equivalent);
|
|
206
|
-
const conceptDecisions = uniqBy(
|
|
207
|
-
schemas.filter((schema) => !schema.current_v6_equivalent),
|
|
208
|
-
schemaDisplayKey,
|
|
209
|
-
);
|
|
210
|
-
const genericRelations = relations.filter((relation) =>
|
|
211
|
-
["referencer", "supporter"].includes(relation.relation_type),
|
|
212
|
-
);
|
|
213
|
-
const sopRelationCandidates = relations.filter(
|
|
214
|
-
(relation) => !["referencer", "supporter"].includes(relation.relation_type),
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
const summary = {
|
|
218
|
-
generated_at: new Date().toISOString(),
|
|
219
|
-
source_directories: {
|
|
220
|
-
migration: path.relative(ROOT, MIGRATION_DIR),
|
|
221
|
-
technical_review: path.relative(ROOT, TECHNICAL_REVIEW_DIR),
|
|
222
|
-
},
|
|
223
|
-
output_directory: path.relative(ROOT, OUT_DIR),
|
|
224
|
-
counts: {
|
|
225
|
-
scenarios: scenarios.length,
|
|
226
|
-
schema_cases: schemas.length,
|
|
227
|
-
schema_alias_or_mapping_cases: immediateMappings.length,
|
|
228
|
-
schema_concept_decision_cases: conceptDecisions.length,
|
|
229
|
-
relation_cases: relations.length,
|
|
230
|
-
generic_relations_not_to_import_as_is: genericRelations.length,
|
|
231
|
-
sop_relation_candidates: sopRelationCandidates.length,
|
|
232
|
-
rejected_relation_cases_kept_out: rejected.length,
|
|
233
|
-
},
|
|
234
|
-
conclusion:
|
|
235
|
-
"Rien ne doit etre importe automatiquement depuis V4. Les vrais candidats sont des decisions conceptuelles par scenario: mappings de schemas, quelques concepts manquants, et relations SOP a rediger.",
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
write(
|
|
239
|
-
"README.md",
|
|
240
|
-
`# Serenity Production V6 - revue conceptuelle
|
|
241
|
-
|
|
242
|
-
Ce dossier remplace la lecture technique du pack precedent pour la decision metier.
|
|
243
|
-
|
|
244
|
-
Le point important: **il n'y a pas une masse de choses a rapatrier automatiquement depuis V4**. V4 contient beaucoup de relations generiques, de fake data, de references techniques et de liens trop larges. La revue utile est donc:
|
|
245
|
-
|
|
246
|
-
1. confirmer les concepts qui sont deja couverts par V6 et doivent seulement etre mappes;
|
|
247
|
-
2. identifier les vrais concepts manquants par scenario;
|
|
248
|
-
3. refuser les relations generiques comme \`referencer\` et \`supporter\` tant qu'elles ne sont pas decomposees;
|
|
249
|
-
4. accepter une relation uniquement si elle peut etre formulee comme une phrase SOP: **source -> verbe -> cible**.
|
|
250
|
-
|
|
251
|
-
Fichiers a lire dans l'ordre:
|
|
252
|
-
|
|
253
|
-
- \`00-quoi-rapatrier.md\`: synthese actionnable.
|
|
254
|
-
- \`01-questions-decision.md\`: questions metier avec choix A/B/C/D.
|
|
255
|
-
- \`02-scenarios.md\`: revue par scenario/famille.
|
|
256
|
-
- \`03-schemas-concepts.md\`: concepts manquants ou a mapper.
|
|
257
|
-
- \`04-relations-candidates.md\`: relations candidates traduites en langage metier.
|
|
258
|
-
- \`concept_review_matrix.json\`: meme contenu en structure exploitable par script.
|
|
259
|
-
`,
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
write(
|
|
263
|
-
"00-quoi-rapatrier.md",
|
|
264
|
-
`# Quoi rapatrier depuis V4 ?
|
|
265
|
-
|
|
266
|
-
## Conclusion courte
|
|
267
|
-
|
|
268
|
-
**Rien a rapatrier automatiquement.** Le bon resultat de la revue actuelle est conservateur: V6 reste a 300 schemas/entites parce que les 400+ de V4 incluent beaucoup de bruit, de donnees generees et de relations non SOP.
|
|
269
|
-
|
|
270
|
-
## A rapatrier maintenant sans changer le modele
|
|
271
|
-
|
|
272
|
-
Ces cas ne demandent pas de nouveau schema V6: ils doivent etre traites comme alias, renommages ou mappings de reference.
|
|
273
|
-
|
|
274
|
-
| Concept V4/SOP | Decision proposee |
|
|
275
|
-
|---|---|
|
|
276
|
-
${immediateMappings
|
|
277
|
-
.map((schema) => `| ${md(schemaLabel(schema.schema_id))} | ${md(schemaRecommendation(schema))} |`)
|
|
278
|
-
.join("\n") || "| Aucun | Aucun mapping immediat detecte |"}
|
|
279
|
-
|
|
280
|
-
## A decider au niveau concept/scenario
|
|
281
|
-
|
|
282
|
-
Ces concepts ne doivent pas etre ajoutes sur base du JSON seul. Il faut dire s'ils existent vraiment dans une SOP.
|
|
283
|
-
|
|
284
|
-
| Concept candidat | Scenarios touches | Decision proposee |
|
|
285
|
-
|---|---:|---|
|
|
286
|
-
${conceptDecisions
|
|
287
|
-
.map(
|
|
288
|
-
(schema) =>
|
|
289
|
-
`| ${md(schemaLabel(schema.schema_id))} | ${schema.required_by_count ?? (schema.required_by_scopes || []).length} | ${md(schemaRecommendation(schema))} |`,
|
|
290
|
-
)
|
|
291
|
-
.join("\n") || "| Aucun | 0 | Aucun concept a decider |"}
|
|
292
|
-
|
|
293
|
-
## A ne pas rapatrier tel quel
|
|
294
|
-
|
|
295
|
-
| Relation V4 | Pourquoi |
|
|
296
|
-
|---|---|
|
|
297
|
-
${genericRelations
|
|
298
|
-
.map(
|
|
299
|
-
(relation) =>
|
|
300
|
-
`| ${md(relation.relation_type)} | ${md(relationGloss[relation.relation_type])}. ${md(relationRecommendation(relation))} |`,
|
|
301
|
-
)
|
|
302
|
-
.join("\n") || "| Aucune | Aucun cas generique majeur |"}
|
|
303
|
-
|
|
304
|
-
## A transformer en phrase SOP avant decision
|
|
305
|
-
|
|
306
|
-
Une relation candidate devient acceptable seulement si on peut l'ecrire ainsi:
|
|
307
|
-
|
|
308
|
-
\`<concept source> -> <relation metier> -> <concept cible>\`
|
|
309
|
-
|
|
310
|
-
Exemple de decision attendue: \`Decision AG -> genere -> Demande de travaux\`.
|
|
311
|
-
|
|
312
|
-
Relations candidates a revoir: ${sopRelationCandidates.map((relation) => `\`${relation.relation_type}\``).join(", ")}.
|
|
313
|
-
`,
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
write(
|
|
317
|
-
"01-questions-decision.md",
|
|
318
|
-
`# Questions de decision
|
|
319
|
-
|
|
320
|
-
Pour chaque bloc, choisis A/B/C/D. Tu peux aussi repondre par une phrase SOP si tu connais la relation exacte.
|
|
321
|
-
|
|
322
|
-
${orderedFamilies
|
|
323
|
-
.map((family) => {
|
|
324
|
-
const schemaLines = family.schemas
|
|
325
|
-
.slice(0, 8)
|
|
326
|
-
.map((schema) => `- ${schemaLabel(schema.schema_id)}: ${schemaRecommendation(schema)}`)
|
|
327
|
-
.join("\n");
|
|
328
|
-
const relationLines = family.relations
|
|
329
|
-
.slice(0, 10)
|
|
330
|
-
.map(
|
|
331
|
-
(relation) =>
|
|
332
|
-
`- ${relation.relation_type}: ${relationGloss[relation.relation_type] || "relation a clarifier"}; ${relationRecommendation(relation)}`,
|
|
333
|
-
)
|
|
334
|
-
.join("\n");
|
|
335
|
-
return `## ${family.label}
|
|
336
|
-
|
|
337
|
-
Question metier: ${family.question}
|
|
338
|
-
|
|
339
|
-
Concepts a trancher:
|
|
340
|
-
${schemaLines || "- Aucun concept manquant detecte pour ce bloc."}
|
|
341
|
-
|
|
342
|
-
Relations a trancher:
|
|
343
|
-
${relationLines || "- Aucune relation candidate detectee pour ce bloc."}
|
|
344
|
-
|
|
345
|
-
Choix possibles:
|
|
346
|
-
${choiceBlock}`;
|
|
347
|
-
})
|
|
348
|
-
.join("\n\n")}
|
|
349
|
-
`,
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
write(
|
|
353
|
-
"02-scenarios.md",
|
|
354
|
-
`# Revue par scenario/famille
|
|
355
|
-
|
|
356
|
-
${orderedFamilies
|
|
357
|
-
.map((family) => {
|
|
358
|
-
const scenarioList = [...family.scenarioLabels].sort().slice(0, 20);
|
|
359
|
-
return `## ${family.label}
|
|
360
|
-
|
|
361
|
-
Question de fond: ${family.question}
|
|
362
|
-
|
|
363
|
-
Scenarios couverts:
|
|
364
|
-
${scenarioList.map((label) => `- ${label}`).join("\n")}
|
|
365
|
-
${family.scenarioLabels.size > scenarioList.length ? `\n- ... ${family.scenarioLabels.size - scenarioList.length} autres scenarios` : ""}
|
|
366
|
-
|
|
367
|
-
Concepts manquants ou a mapper:
|
|
368
|
-
${family.schemas
|
|
369
|
-
.map(
|
|
370
|
-
(schema) =>
|
|
371
|
-
`- ${schemaLabel(schema.schema_id)} -> ${schemaRecommendation(schema)} Scenarios touches: ${schema.required_by_count ?? (schema.required_by_scopes || []).length}.`,
|
|
372
|
-
)
|
|
373
|
-
.join("\n") || "- Aucun."}
|
|
374
|
-
|
|
375
|
-
Relations candidates:
|
|
376
|
-
${family.relations
|
|
377
|
-
.map(
|
|
378
|
-
(relation) =>
|
|
379
|
-
`- ${relation.relation_type}: ${relationGloss[relation.relation_type] || "a clarifier"}. Recommendation: ${relationRecommendation(relation)}`,
|
|
380
|
-
)
|
|
381
|
-
.join("\n") || "- Aucune."}
|
|
382
|
-
|
|
383
|
-
Decision attendue:
|
|
384
|
-
- choisir A/B/C/D pour chaque concept et relation;
|
|
385
|
-
- si A, fournir une phrase SOP source -> relation -> cible;
|
|
386
|
-
- si B, indiquer le concept ou la relation V6 cible.`;
|
|
387
|
-
})
|
|
388
|
-
.join("\n\n")}
|
|
389
|
-
`,
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
write(
|
|
393
|
-
"03-schemas-concepts.md",
|
|
394
|
-
`# Concepts et schemas
|
|
395
|
-
|
|
396
|
-
## Cas de mapping/alias
|
|
397
|
-
|
|
398
|
-
| Concept reference | Equivalent V6 propose | Scenarios | Action |
|
|
399
|
-
|---|---|---:|---|
|
|
400
|
-
${immediateMappings
|
|
401
|
-
.map(
|
|
402
|
-
(schema) =>
|
|
403
|
-
`| ${md(schemaLabel(schema.schema_id))} | ${md(schema.current_v6_equivalent)} | ${schema.required_by_count ?? (schema.required_by_scopes || []).length} | Mapper, ne pas creer de nouveau schema |`,
|
|
404
|
-
)
|
|
405
|
-
.join("\n") || "| Aucun | - | 0 | - |"}
|
|
406
|
-
|
|
407
|
-
## Cas de decision conceptuelle
|
|
408
|
-
|
|
409
|
-
| Concept candidat | Domaine | Scenarios | Question |
|
|
410
|
-
|---|---|---:|---|
|
|
411
|
-
${conceptDecisions
|
|
412
|
-
.map((schema) => {
|
|
413
|
-
const family = domainGloss[schema.domain] || schema.domain || "inconnu";
|
|
414
|
-
return `| ${md(schemaLabel(schema.schema_id))} | ${md(family)} | ${schema.required_by_count ?? (schema.required_by_scopes || []).length} | ${md(schemaRecommendation(schema))} |`;
|
|
415
|
-
})
|
|
416
|
-
.join("\n") || "| Aucun | - | 0 | - |"}
|
|
417
|
-
`,
|
|
418
|
-
);
|
|
419
|
-
|
|
420
|
-
write(
|
|
421
|
-
"04-relations-candidates.md",
|
|
422
|
-
`# Relations candidates
|
|
423
|
-
|
|
424
|
-
## Relations a rejeter telles quelles
|
|
425
|
-
|
|
426
|
-
| Relation | Lecture metier | Decision |
|
|
427
|
-
|---|---|---|
|
|
428
|
-
${genericRelations
|
|
429
|
-
.map(
|
|
430
|
-
(relation) =>
|
|
431
|
-
`| ${md(relation.relation_type)} | ${md(relationGloss[relation.relation_type])} | ${md(relationRecommendation(relation))} |`,
|
|
432
|
-
)
|
|
433
|
-
.join("\n") || "| Aucune | - | - |"}
|
|
434
|
-
|
|
435
|
-
## Relations SOP candidates
|
|
436
|
-
|
|
437
|
-
Ces relations ne sont pas encore acceptees. Elles sont seulement des hypotheses a reformuler en SOP.
|
|
438
|
-
|
|
439
|
-
| Relation V4 | Lecture metier | Scenarios | Decision proposee |
|
|
440
|
-
|---|---|---|---|
|
|
441
|
-
${sopRelationCandidates
|
|
442
|
-
.map((relation) => {
|
|
443
|
-
const scopes = (relation.supported_scenarios || [])
|
|
444
|
-
.map((scenario) => labelFromScope(scenario.scope))
|
|
445
|
-
.join(", ");
|
|
446
|
-
return `| ${md(relation.relation_type)} | ${md(relationGloss[relation.relation_type] || "a clarifier")} | ${md(scopes)} | ${md(relationRecommendation(relation))} |`;
|
|
447
|
-
})
|
|
448
|
-
.join("\n") || "| Aucune | - | - | - |"}
|
|
449
|
-
|
|
450
|
-
## Format de validation
|
|
451
|
-
|
|
452
|
-
Pour accepter une relation, fournir une phrase de ce type:
|
|
453
|
-
|
|
454
|
-
\`Decision AG -> genere -> Demande de travaux\`
|
|
455
|
-
|
|
456
|
-
Puis preciser:
|
|
457
|
-
|
|
458
|
-
- source: schema V6 source;
|
|
459
|
-
- cible: schema V6 cible;
|
|
460
|
-
- cardinalite: un vers un, un vers plusieurs, plusieurs vers plusieurs;
|
|
461
|
-
- preuve SOP: nom du scenario ou procedure qui l'exige.
|
|
462
|
-
`,
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
const matrix = orderedFamilies.map((family) => ({
|
|
466
|
-
family: family.family,
|
|
467
|
-
label: family.label,
|
|
468
|
-
business_question: family.question,
|
|
469
|
-
scenario_count: family.scenarioLabels.size,
|
|
470
|
-
scenarios: [...family.scenarioLabels].sort(),
|
|
471
|
-
schema_cases: family.schemas.map((schema) => ({
|
|
472
|
-
schema_id: schema.schema_id,
|
|
473
|
-
business_label: schemaLabel(schema.schema_id),
|
|
474
|
-
recommendation: schemaRecommendation(schema),
|
|
475
|
-
current_v6_equivalent: schema.current_v6_equivalent ?? null,
|
|
476
|
-
decision: schema.decision,
|
|
477
|
-
required_by_count: schema.required_by_count ?? (schema.required_by_scopes || []).length,
|
|
478
|
-
})),
|
|
479
|
-
relation_cases: family.relations.map((relation) => ({
|
|
480
|
-
relation_type: relation.relation_type,
|
|
481
|
-
business_reading: relationGloss[relation.relation_type] || null,
|
|
482
|
-
recommendation: relationRecommendation(relation),
|
|
483
|
-
decision: relation.decision,
|
|
484
|
-
v4_instances: relation.v4_instances,
|
|
485
|
-
source_quality: relation.source_quality,
|
|
486
|
-
})),
|
|
487
|
-
choices: ["rapatrier", "mapper_existing", "reject", "needs_sop_sentence"],
|
|
488
|
-
}));
|
|
489
|
-
|
|
490
|
-
write("concept_review_matrix.json", JSON.stringify({ summary, families: matrix }, null, 2));
|
|
491
|
-
write("review_summary.json", JSON.stringify(summary, null, 2));
|
|
492
|
-
|
|
493
|
-
console.log(JSON.stringify(summary, null, 2));
|