Workflow CUMCM
Gardez les affirmations qui comptent traçables jusqu'aux sources officielles et à l'exécution réelle, sans transformer chaque brouillon en un dossier d'audit.
Deux règles guident tout ce qui suit :
- Les outils enregistrent les faits machine ; vous écrivez le jugement. Ne tapez jamais un hachage, un nombre de pages, un code de sortie, un instantané de source ou une valeur de résultat.
record_run.py,index_result.py,record_compile.pyetrefresh_evidence.pys'en chargent. Vous écrivez les faits du problème, le modèle, les affirmations et le document. - Le modèle est choisi tardivement, et le choix se gagne. Le mode de travail accepte un contrat de modèle provisoire. Vous nommez les modèles candidats, expliquez quelles preuves les distingueraient, les évaluez avec des exécutions exploratoires peu coûteuses, et seulement ensuite vous en sélectionnez un et figez le contrat.
Démarrer ou reprendre
- Localisez
.cumcm/state.json. Reprenez un projet exactement en version0.6.0. Les espaces de travail plus anciens ne sont pas pris en charge ; démarrez un nouveau projet à partir des fichiers officiels. - Si aucun état n'existe et que l'utilisateur fournit les fichiers officiels, lisez 01-intake.md, choisissez un objectif sûr, et exécutez
scripts/init_project.pypour lui. Ne demandez pas à l'utilisateur d'assembler la commande. - Lisez uniquement le guide de l'étape active ainsi que handoffs.md lorsque vous franchissez les étapes. Une nouvelle tâche lit d'abord son handoff, pas l'ensemble de l'espace de travail.
- Gardez les six responsabilités distinctes : orchestration, modélisation, calcul, validation, rédaction, livraison. Ne simulez pas la séparation en inventant de nombreuses petites compétences.
Les deux boutons
mode (dans l'état) détermine ce qui doit être complet. --gate-mode décide si les portes humaines comptent.
working: modélisation rapide, calcul exploratoire, débogage. La protection des entrées officielles, l'exécution réelle, les localisateurs de résultats exacts et la non-fabrication sont appliqués. Un contrat de modèle provisoire suffit ;CROSS_QUESTION_LEDGER.jsonest facultatif ; l'ordre des étapes est indicatif.enforcesignale iciworking_ready, jamais une approbation formelle.finalizing: geler les résultats porteurs d'affirmations. Le contrat de modèle doit être complet et son plan de vérification doit correspondre à des assertions enregistrées par une exécution officielle. Nécessite les décisions et instantanés d'étape en cours, des handoffs frais, une revue indépendante limitée, une QA du document/PDF et une liaison de livraison.enforcene peut réussir que si chaque étape jusqu'à celle demandée estpassedavec une décision acceptée actuelle.
Basculez avec scripts/set_mode.py. Il n'y a pas de profil strict/sprint dans v0.6 ; un seul ensemble de règles s'applique.
Où une personne est sollicitée
Trois points de contrôle, un par bloc, et chacun enregistre ce qui a été présenté à la personne, pas seulement ce qu'elle a décidé. Une décision sans rien de présenté n'est pas une preuve que quelqu'un a regardé. Ils se trouvent devant les trois étapes coûteuses : rejeter un choix de modèle coûte une conversation, rejeter une conclusion coûte un recalcul, rejeter un document fini coûte une réécriture.
MODEL_CONTRACT.selection_check, avant qu'un candidat ne devienneselected: le critère de jugement, lesdiscriminating_evidencede chaque candidat, et lascopeque le gagnant revendiquera.presented_candidate_idsdoit couvrir chaque candidat (MODEL-E018) — ne montrer que le gagnant n'est pas une comparaison.CLAIM_LEDGER.conclusion_check, avantvalidation-paper: les conclusions elles-mêmes — texte de l'affirmation,scope, état des preuves, P0/P1 ouverts. Pas d'IDs de run, pas de hachages.presented_claim_idsdoit couvrir chaque affirmation déclarée (CLAIM-E023). C'est l'endroit peu coûteux pour entendre non ; la même objection lors de la livraison coûte un document réécrit.DELIVERY_MANIFEST.final_check, avant la soumission : l'objet fini — pages rendues, réponse à chaque sous-problème, résultats ouverts.presented_pagesdoit couvrir chaque page rendue (DELIVERY-E020), ethuman_userne peut pas être réclamé sans rien de présenté (DELIVERY-E019).
Le rapport du document ne porte aucune approbation propre : content_report et layout_report sont des rapports. La sélection du relecteur est enregistrée, non confirmée — la séparation provient des deux transitions de coupure à la place (references/handoffs.md).
Les statuts des étapes sont not_started, in_progress, passed, needs_revision.
Rôles et handoffs
| Responsabilité | Référence principale | Handoff sortant |
|---|---|---|
| Modélisation | 02-problem-analysis.md, 03-model-design.md | modeling-computation |
| Calcul | 04-computation.md | computation-validation |
| Validation | 05-validation.md | validation-paper |
| Rédaction | 06-paper-writing.md, latex-template.md | paper-delivery |
| Livraison | 07-compile-delivery.md | Paquet final |
Construisez les handoffs avec scripts/build_handoff.py. Ils transportent des chemins canoniques, une charge utile aval compacte et un digest amont. Ne copiez jamais les journaux complets, les exécutions échouées, l'historique de débogage ou les anciennes conversations de revue. Un digest obsolète nécessite une reconstruction.
Choisir le modèle
La conception du modèle ne choisit pas un modèle. Elle propose des candidats et explique comment le choix sera tranché :
"candidates": [
{"candidate_id": "CAND-ENUM", "method": "énumération complète",
"why_considered": "la classe de politique déclarée est finie et petite",
"discriminating_evidence": ["si le choix glouton est égal au minimum énuméré"],
"status": "under_evaluation"},
{"candidate_id": "CAND-GREEDY", "method": "premier ajustement glouton",
"why_considered": "temps constant, adéquat si l'ensemble est déjà ordonné par coût",
"discriminating_evidence": ["si le choix glouton est égal au minimum énuméré"],
"status": "under_evaluation"}
]
Ensuite, tranchez avec des preuves plutôt qu'avec une opinion :
python3 scripts/record_run.py --project <p> --candidate CAND-ENUM -- python3 code/enum.py
python3 scripts/record_run.py --project <p> --candidate CAND-GREEDY -- python3 code/greedy.py
Définissez le gagnant sur status: "selected", les autres sur "rejected", donnez à chacun un decision_rationale qui se réfère à ce que ces exécutions ont montré, et listez les exécutions dans evaluation_run_ids. Ce n'est qu'alors que le modèle sélectionné reçoit une exécution officielle.
Le vérificateur vous y tient : exactement un candidat peut se retrouver selected (MODEL-E013), une sélection doit citer une exécution qui l'a évaluée (MODEL-W014), un candidat sélectionné ou rejeté nécessite une raison enregistrée (MODEL-E014), et un candidat sans rien pour le distinguer est signalé (MODEL-W012). En mode working, ce sont des avertissements ; le gel les transforme en erreurs. cumcm_check.py imprime la comparaison sous model_candidates.
Deux choses que cela ne fait délibérément pas : cela n'exige pas plus d'un candidat quand un seul est évidemment correct (c'est MODEL-W007, un avertissement), et cela ne juge pas quel candidat est meilleur — cela insiste seulement pour que le choix ait été fait sur la base de preuves enregistrées.
Enregistrer le calcul
# l'exploration ne coûte rien à enregistrer
python3 scripts/record_run.py --project <p> -- python3 code/try.py
# geler une exécution pour des résultats formels coûte quelques déclarations
python3 scripts/record_run.py --project <p> --official \
--capability CAP-Q1-001 --source code/solve.py \
--input data/q1.csv:formal --output results/q1.json:claim \
--assert "feasibility=pass" -- python3 code/solve.py
# la valeur est lue depuis la sortie, jamais transcrite
python3 scripts/index_result.py --project <p> --result-id RES-Q1-001 \
--run RUN-Q1-001 --locator results/q1.json#/minimum_cost \
--name "Coût minimum" --unit CNY --scope "candidats déclarés uniquement"
# une réexécution ajoute un successeur ; le parent et ses preuves restent intacts
python3 scripts/record_run.py --project <p> --rerun RUN-Q1-001 --official
python3 scripts/index_result.py --project <p> --follow-lineage
Les exécutions exploratoires sont enregistrées, jamais fiables, et ne bloquent jamais : une assertion échouée ou un code de sortie non nul à l'intérieur est un fait sur l'expérience, pas sur la chaîne formelle. Seule une exécution réussie avec official_run: true peut soutenir un résultat formel.
Les exécutions sont en ajout seulement. --rerun ajoute RUN-Q1-002 avec parent_run_id: RUN-Q1-001 ; il n'écrase jamais, car le parent est le seul enregistrement de ce que l'exécution remplacée a exécuté et produit. Chaque exécution gèle sa source et ses sorties déclarées dans runs/<id>/source/… et runs/<id>/outputs/…, en miroir de la disposition originale, et hache ces copies — de sorte qu'une exécution préservée reste vérifiable quelle que soit l'évolution de l'espace de travail, et output_locator nomme un fichier immuable.
Une exécution ne peut revendiquer que ce qu'elle a produit et ce qu'elle a vérifié : l'enregistreur compare l'horodatage de chaque sortie déclarée pendant l'exécution et refuse d'enregistrer un fichier résiduel comme preuve porteuse d'affirmation de cette exécution, et une réexécution n'hérite jamais des verdicts d'assertion de son parent. Seule une réexécution officielle réussie remplace son parent, et tout consommateur formel résout l'exécution actuelle via le même code.
Cela n'affaiblit pas la détection de dérive, cela l'aiguise. RUN-E020 compare maintenant la copie gelée avec le fichier actif et indique que l'arbre de travail a évolué depuis l'exécution soutenant vos résultats ; les exécutions remplacées sont exemptées, et modifier une copie gelée est RUN-E021. Le remplacement est dérivé de la chaîne parent et jamais réécrit — tamponner l'ancien manifeste changerait son hachage et rendrait obsolètes toutes les décisions qui y sont liées. RESULT-E017 détecte un résultat citant encore une exécution remplacée ; index_result.py --follow-lineage le re-pointe, explicitement, car quelle exécution soutient une affirmation est un jugement plutôt qu'un fait machine.
Choisir un backend
L'état du projet par défaut est {"preferred":"matlab","fallback":"python","selection":"auto"}. Utilisez scripts/backend_selection.py ou les mêmes critères : méthodes numériques, optimisation, EDO/EDP, traitement du signal, nettoyage de données, Excel/CSV, apprentissage automatique, boîtes à outils disponibles, code existant, complexité, stabilité d'exécution. La préférence MATLAB ne départage qu'en cas d'égalité. Un backend préféré indisponible peut utiliser le fallback ; une tâche avec required_backend indisponible doit échouer. Implémentez et exécutez officiellement un langage. Ne construisez pas d'implémentations en parallèle sauf si l'utilisateur le demande.
Portes de preuves
- invariant dur /
P0: données ou calcul erronés, inadéquation de tâche (une capacité que personne n'a prise en charge, ou une encore inachevée alors que le document se dit final, est la moitié visible par la machine de cela :CAP-E013,CAP-E014), une affirmation dont la portée déclarée dépasse la plage réellement vérifiée, désaccord code/résultat/document, une hypothèse contredisant une condition stipulée, provenance obsolète, approbation ou revue fabriquée, données simulées présentées comme observées, inadéquation de version finale. Ceux-ci bloquent. - avertissement /
P1, jugé dans la plage vérifiée : hypothèses fortes, base de référence faible, validation ou sensibilité plus maigre qu'idéale, ajustement limité, section mince. Visible, jamais bloquant. - suggestion /
P2: formulation, mise en page, graphique facultatif, expérience supplémentaire. Pas dans la porte.
La validation indépendante utilise accepted, accepted_with_concerns, revision_required, inconclusive. Seul un P0 ouvert permet revision_required. Après qu'une revue complète a trouvé des problèmes P0, le paquet suivant par défaut est une re-revue ciblée exactement de ces résultats.
Le paquet de revue ne copie que les preuves canoniques pour les résultats formellement indexés et enregistre context_excluded — le raisonnement antérieur qu'il a physiquement omis. Il ne prétend pas que le relecteur n'a pas d'opinion. Le modèle de résultat laisse chaque champ d'indépendance à null : le relecteur doit les affirmer, et un null échoue IREVIEW-E027. L'utilisateur ne confirme plus le relecteur ; la séparation provient plutôt de la coupure — computation-validation et validation-paper transportent la tâche qui les a construits, et une tâche consommatrice qui correspond est HANDOFF-E010. Voir references/handoffs.md.
Itérer
Rouvrir une étape amont est une commande, pas une modification manuelle de state.json :
python3 scripts/record_decision.py --project <p> --stage model-design \
--decision revision_requested --decision-id DEC-007 --reviewer <nom> \
--task-turn-ref <ref> --summary "Le modèle Q2 ne correspond pas au régime observé"
Cela invalide l'étape et tout ce qui est en aval. Pour savoir ce qu'un changement coûte réellement avant de tout refaire :
python3 scripts/plan_redo.py --project <p> --changed code/solve_q2.py
plan_redo.py parcourt source -> run officiel -> résultat -> affirmation -> section -> PDF et nomme les runs, résultats et sections spécifiques qui sont affectés — et ceux qui ne le sont pas. Il ne supprime jamais une vérification ; cumcm_check.py valide toujours tout jusqu'à l'étape demandée, car c'est peu coûteux. Le travail coûteux est la réexécution, la re-revue et la réécriture, et c'est ce que le plan délimite.
Invariants de la compétition
- Préservez et identifiez par bytes les sources officielles. La ROC dirige l'attention ; les pages rendues décident des formules, des tableaux et de la notation ambiguë.
- N'inventez jamais de données observées, d'approbations, de revue indépendante ou d'exécution réussie. Étiquetez les simulations authentiques et enregistrez leur générateur et leur graine.
- Gardez le modèle mathématique et les contrats de résultats neutres en termes de langage.
- Utilisez SHA-256 uniquement pour l'identité critique des preuves : sources officielles, entrées formelles, sorties porteuses d'affirmations, instantanés/handoffs compacts, paquets de revue, arbres sources sélectionnés et le PDF final revu.
- Gardez les IDs internes, les états de preuves, les chemins locaux, la couverture des runs et le langage du workflow hors du document visible.
- Les limitations du handoff du document proviennent uniquement des limitations prises en charge des affirmations éligibles au document, des préoccupations P1 actuelles et des champs explicites d'applicabilité/hypothèse/limitation connue — pas des affirmations contredites ou de la portée du modèle.
- Liez le PDF final à ses bytes revus et à l'instantané exact des sources LaTeX modifiables utilisé pour la compilation.
- L'absence de règles ou de modèles officiels courants bloque la livraison ; elle n'autorise pas la recherche autonome ou la soumission.
- La livraison finale contient le PDF revu, les sources LaTeX modifiables et les sources de calcul en tant que rôles séparés.
Lisez artifact-contracts.md lors de la création de fichiers lisibles par machine et evidence-rules.md pour les règles détaillées d'enregistrement.
Enregistrer pour la première fois — actions du calculateur
Quelqu'un qui calcule, pas quelqu'un qui vérifie : record_compile.py verrouille la compilation LaTeX et produit un paquet de revue. Pour un premier paquet, enregistrez le résultat et coupez la revue indépendante. refresh_evidence.py ne rafraîchit rien avant que le calculateur n'ait enregistré un résultat.
(La section suivante est omise car elle était tronquée dans l'entrée originale.)