feat(published-language): l'instrument émet la correspondance de rangs déclarée
Percursus lit les strates en rangs (1–5, échelle fermée par ses ADR-003/004) ; openathle les nomme (domaine, application, infrastructure, interface). La clause loci de Percursus, déclarée à la main, est devenue inférable depuis que la coupe existe — et l'humain ne saisit pas l'inférable (P4). Le réglage de la juridiction peut désormais porter rang: N par strate. Le constat émet rangs_constates — seulement si TOUTES les strates constatées en déclarent un : une correspondance partielle laisserait deviner, et deviner n'est pas constater. Le journal publie la table complète (correspondance_rangs) pour joindre les constats anciens, qui ne se réécrivent jamais. Champ optionnel, additif : aucun réglage existant ne change de comportement. Auto-épreuve : dix-huit vérifications, dont l'ordre des rangs, l'absence de rangs sur l'invariant sans locus, et la table du journal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-1
@@ -71,9 +71,12 @@ function loadConfig(repo, path) {
|
||||
if (cfg?.[key] === undefined) refuse(`le réglage « ${path} » ne déclare pas « ${key} »`);
|
||||
if (!Array.isArray(cfg.strates) || cfg.strates.length === 0)
|
||||
refuse(`le réglage « ${path} » doit déclarer au moins une strate`);
|
||||
for (const s of cfg.strates)
|
||||
for (const s of cfg.strates) {
|
||||
if (typeof s?.nom !== 'string' || !Array.isArray(s?.chemins))
|
||||
refuse(`chaque strate du réglage porte « nom » et « chemins » — l'une des deux manque`);
|
||||
if (s.rang !== undefined && typeof s.rang !== 'number')
|
||||
refuse(`la strate « ${s.nom} » déclare un rang qui n'est pas un nombre — le rang est une correspondance vers une échelle tierce, ou rien`);
|
||||
}
|
||||
const due = cfg.strates.find((s) => s.due === true) ?? cfg.strates[0];
|
||||
return { ...cfg, due: due.nom, raw: readFileSync(full, 'utf8'), path };
|
||||
}
|
||||
@@ -232,6 +235,7 @@ function constatItem(cfg, inv, verdict, hits, seq, meta) {
|
||||
etat: verdict.etat,
|
||||
constat: sentence(inv.id, verdict, cfg.due),
|
||||
strates_constatees: verdict.strates,
|
||||
...rangsConstates(cfg, verdict.strates),
|
||||
pieces: kept,
|
||||
...(omitted > 0 ? { pieces_omises: omitted } : {}),
|
||||
citations_hors_epreuve: hits.filter((h) => !h.isTest).length,
|
||||
@@ -247,6 +251,18 @@ function constatItem(cfg, inv, verdict, hits, seq, meta) {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* La correspondance vers une échelle tierce (p. ex. les rangs de Percursus),
|
||||
* si la juridiction la déclare dans son réglage. Émise SEULEMENT quand toutes
|
||||
* les strates constatées portent un rang : une correspondance partielle
|
||||
* laisserait le consommateur deviner — deviner n'est pas constater.
|
||||
*/
|
||||
function rangsConstates(cfg, strates) {
|
||||
const rang = new Map(cfg.strates.filter((s) => typeof s.rang === 'number').map((s) => [s.nom, s.rang]));
|
||||
if (strates.length === 0 || !strates.every((n) => rang.has(n))) return {};
|
||||
return { rangs_constates: strates.map((n) => rang.get(n)) };
|
||||
}
|
||||
|
||||
function gitRevision(repo) {
|
||||
try {
|
||||
return execFileSync('git', ['-C', repo, 'rev-parse', 'HEAD'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
||||
@@ -292,6 +308,9 @@ function emit(args, cfg, r) {
|
||||
...(typeof cfg.cadence_heures === 'number' ? { cadence_heures: cfg.cadence_heures } : {}),
|
||||
parcours_lus: r.journeys,
|
||||
invariants: r.invariants,
|
||||
...(cfg.strates.some((s) => typeof s.rang === 'number')
|
||||
? { correspondance_rangs: Object.fromEntries(cfg.strates.filter((s) => typeof s.rang === 'number').map((s) => [s.nom, s.rang])) }
|
||||
: {}),
|
||||
etats: r.tally,
|
||||
constats_nouveaux: r.fresh.length,
|
||||
reglage_empreinte: r.meta.reglageHash,
|
||||
|
||||
Reference in New Issue
Block a user