Skip to content

XER/P6-lezer etappe 3: laag 1 (voltooide activiteiten), laag 3 (datums zoals opgeslagen), herpin op het volledige corpus - #109

Draft
Nozzit wants to merge 193 commits into
mainfrom
claude/file-formats-support-phase-3-a0ebe2
Draft

Nozzit wants to merge 193 commits into
mainfrom
claude/file-formats-support-phase-3-a0ebe2

Conversation

@Nozzit

@Nozzit Nozzit commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

STATUS (eigenaarsbesluit 2026-09-09): DRAFT — niet mergen zolang de productfidelity-poort rood is.
De X12-poort (tests/planning/check-xer-product-fidelity-x12.ts, mét OPS_XER_CORPUS) staat rood op
15.056 zesassige afwijkingen tegen P6's eigen uitvoer (34 entries, 47 projecten, 13.982 taken); het
nuldoel van plan §1 is nul, en pinnen-met-reden is per planregel geen uitweg. Waarom rood: ±76% van het
restant zit in rehab-2.xer (late kant en speling van niet-gestarte activiteiten, klasse (ii); de
ES/EF-regressie van 7b, dossier 7b-4), daarnaast Roads_Project_TEC, de twee MER-1-2026-varianten,
Hotel_Construction en groupdocs (sameday-conventie). Verder open: de projecteinde-fout
(sched_use_project_end_date_for_float=Y zonder einddatum ⇒ late kant verankert op de projectstart).
Deze PR is een gemeten tussenstand; het vervolg (X12-restant omlaag, per categorie escalatie) loopt op
dezelfde branch. Zie plan §9/§10.

What and why

XER/P6-lezer, etappe 3 (fase file-formats-support): Primavera P6 .xer openen als volwaardig
formaat — multi-project-import, baselines, kalenders (incl. 7b-reconstructie), resources/contouren,
bronarchief in het IFC, MCP-leestools, én P6-getrouwheid in drie lagen (X-O7): laag 1 klasse (i)
"voltooide activiteiten krijgen echte speling" (7a) en laag 3 "Datums zoals opgeslagen" (bak 4:
P6's eigen rekenuitvoer als weergave, nooit als solverinvoer). Roadmap en besluiten:
docs/superpowers/plans/2026-08-20-plan-xer-p6-lezer.md (§5 eigenaarsbesluiten, §9 dossiers,
§10 overdrachtsstand). PR #101 (taaktypes) merget ná deze PR.

Gemeten

  • Corpus: OpenAEC-Foundation/ops-xer-corpus@e141664 + zes gepinde clones (plan §10.a) ⇒ 93/93
    sha256-treffers, 45/45 orakel.
  • X12 productfidelity (34 entries/47 projecten/13.982 taken): 18.398 (v2-baseline, vóór 7b) →
    17.421 (kop 1206e010) → 15.056 (deze PR). Alle beweging in rehab-2.xer, 33 entries
    byte-identiek. 7b: es +322/ef +127 slechter (gedocumenteerde X-O7-uitzondering), ls/lf/tf/ff
    beter. 7a: ls −969, lf −969 (0 cellen andersom), tf netto −427 (642 beter, 215 slechter: alle
    TK_Complete/DT_FixedDUR2 met P6 tf 0), drivingPath 80→86. Laag 3 en main: 15.056 → 15.056.
  • Herpin in één commit (c6f4ac2a): v2-baseline, in-bron pin, blast-radius, replay-pin,
    v1-herbasis (harness gaf tot 7a de P6-opties niet door). Reden per as/bestand in het commit.
  • Sameday corpusbreed 415 (ongewijzigd; 280 in groupdocs-conversion/sample.xer). Driving
    path
    417/13.596 (301× P6 false/wij true). Beide open categorieën; per bestand in plan §9.
  • Dossier 7b-4: 7b maakte 344 ES + 327 EF fout op rehab-2; 247 taken dragen de forward-anker-
    signatuur (venster behouden, 1–2 werkdagen naar rechts); bovengrens 690 van 1.880 ES/EF-cellen.
    Niet gebouwd — eigenaarsbesluit.
  • P6-23.12-casussen: brongetrouwe transcriptie 156/160; echte bytes 77/160 zoals gelezen,
    156/160 zonder useProjectEndDateForFloat (productfout geregistreerd, docs/TODO.md).
  • Poorten (kop van deze PR): typecheck, lint, planning 560/560 + 5-TZ-matrix, library, mcp 39,
    dev-server, examples, docs, i18n, store-/gantt-boundaries, cycles: groen. test:browser:
    120 passed, 2 failed — beide just-updated-dialog.spec.ts op net::ERR_CERT_AUTHORITY_INVALID
    (de TLS-proxy van de sessieomgeving vóór de GitHub Releases-API; die spec en de updater zijn in
    deze PR niet geraakt). Mét corpus: uitsluitend de drie X12-nuldoel-regels rood (by design).
    test:browser:x11: niet uitvoerbaar vanuit deze clone — het script pint PHASE_2A_BASE = 790d6cd8… en die commit bestaat in geen enkele ref of tag op origin (na een volledige fetch, 1.948 commits); het git-bewijs stopt daar met "fase-2A-basis niet leesbaar", alle vier de scenario's. Dat is een eigenschap van het script (de basis is een niet-gepushte commit), niet van deze PR; de X11-uitkomsten uit §10.c van de ochtend zijn dus van de machine van de eigenaar (AFGELEID).
  • Gebruikstest in de browser (gids als meetlat, plan §10.c): northstar-current.xer opent in de
    modus (strook + melding met 21 taken, "Not recorded"/"Partly unrecorded" in tabel, badge,
    Recalculate verlaat de modus); rehab-2: 940 verschoven taken; ná herberekenen tonen 1.679 van
    2.037 voltooide taken echte speling (7a-effect, bv. V3101090 tf 59 dagen).

Beredeneerd

  • Laag 3 raakt de solve niet (bak 4 alleen weergave): gemeten 15.056 vóór/ná, plus het
    X12-mutatiebewijs (nu óók met de zes floats).
  • De completed-late-poort (7a) is correlationeel: het enige directe P6-bewijs (casus 09) spreekt
    de regel tegen zodra de poort opengaat; op de echte bron blijft hij toevallig dicht. Plan §5,
    docblok types/project.ts.

Open

  • Nuldoel niet gehaald (15.056); zie plan §9/§10 voor wat het residu is.
  • Waarnemingen uit de gebruikstest: samenvattingsrijen tonen in de modus een opgerolde late start
    terwijl hun kinderen "Niet vastgelegd" zeggen; rehab-2's Arabische namen renderen als 1252-
    mojibake (X-O4-heuristiek, pre-existent).
  • Reviewdossiers (plan §10.f): bandrand-asymmetrie SS/SF, klemdoorgifte naar voorgangers (VERMOED),
    kalendermix in de floatformule (VERMOED), bibliotheek-refresh in de modus (VERMOED).

Eigenaarsbesluiten die bevestiging nodig hebben (plan §10.f)

  1. Heropen-beleid: alleen een verse .xer zet de modus zelf aan; een heropende IFC met XER-archief
    biedt alleen aan ('xer' vs 'xer-archive'). Beantwoord 2026-09-09: optie B (automatisch aan
    zolang ongewijzigd sinds import) — gebouwd op zijbranch claude/recorded-all-formats, aparte PR ná deze.
  2. Crashherstel behoudt de modus alleen als de vlag in het recovery-manifest staat (v4).
  3. CSV/MCP geven bij een niet-vastgelegde as leeg resp. null (en crit: null in de leestools).
  4. MCP-provenance-tool toont name/code zonder opt-in (geaccepteerd risico: persoonsnaam).
  5. 7b landde met een per-as-regressie op ES/EF onder de X-O7-uitzondering.
  6. Nieuw: samenvattingen zonder eigen vastlegging rollen in de modus op uit de kinderen;
    isCritical is "niet vastgelegd" onder longest-path-kritiek of niet-omrekenbare speling.
  7. Driving-path-as als poort, en het bouwen van dossier 7b-4.
  8. Uit de eindreview: (a) onbegrensde bronretentie in projectbestand én auto-save — begrenzen,
    één keer schrijven, of bewust accepteren; (b) uitleveren mét de projecteinde-fout (fix is drie
    regels in deriveXerScheduleOptions, maar vraagt corpusmeting + herpin); (c) lagCalendar is
    sinds X5 effectief voor bestaande niet-XER-documenten (stille herplanning bij upgrade;
    releasenotitie nodig); (d) de weekend-klemreconstructie (n=1) blijft als heuristiek staan, nu
    mét herstelcode en gidstekst.

How it was verified

  • npm run verify green — op 1339d9b9 alles groen behalve test:browser 119/121: de twee
    falers (just-updated-dialog.spec.ts) vallen op net::ERR_CERT_AUTHORITY_INVALID van de TLS-proxy
    in de sessieomgeving; spec en updater zijn in deze PR niet geraakt. De poorten ná test:browser
    (examples, docs, i18n, store-/gantt-boundaries, cycles) los gedraaid: groen. Op de fixcommit
    78399699 (kop van deze PR) opnieuw, los: typecheck, lint, planning corpusloos exit 0 (0 rood,
    5 tijdzones), library, mcp 39, i18n, docs, cycles, examples, store-/gantt-boundaries groen;
    test:browser 120/122 met dezelfde twee proxy-falers; X12 mét corpus opnieuw 15.056.
  • Mét corpus (OPS_XER_CORPUS, 93/93): tests/planning/run.sh rood op uitsluitend de drie
    X12-nuldoel-regels (15.056 ≠ 0) — by design zolang het nuldoel niet gehaald is.
  • Met de hand in de browser: zie "Gebruikstest" hierboven.
  • Eindreview (hele diff t.o.v. d808fdec, incl. whitelist-sluiproute-scan §4.1): oordeel
    landen-met-fixes — vier blokkers en negen kleinere bevindingen, verwerkt in de fixcommit
    78399699 (plan §10.e heeft het volledige verslag). Blokkers: (1) de sluiproute-scan dekte
    alleen bak 4 — mutant M-B (restart_date achter task_type === 'TT_Rsrc') kwam door álle
    corpusloze poorten; nu grept check-xer-field-whitelist.ts ook bak 2 over heel src/ (twee
    gepinde andere-tabel-uitzonderingen), gemeten: mutant ⇒ rood. (2) extractSchedulingOptions
    deed JSON.parse + cast — nu sanitizeSchedulingOptions (sleutels/enums/getallen), en het
    p6SourceActive-commentaar in CPMSolver.ts claimt niet meer dat de XER-lezer de enige
    schrijver is. (3) De projecteinde-fout is niet gefixt (solverwijziging ⇒ corpusmeting +
    herpin; de etappe had er één) maar nu in de gids benoemd — eigenaarsbesluit. (4)
    check-mpp-fidelity.ts alsnog gedraaid tegen joniles/mpxj junit-data: 164 van 213 pins gezien,
    0 verbeterd / 0 verslechterd; de 49 OzBuild-pins zijn niet publiek (ONBEKEND). Kleiner:
    rapportmelding in de modus (14 talen, browser-assertie), herstelcode voor het weekend-klemherstel
    (119, alle in rehab-2; baseline +1 sleutel), Engelse holidaynamen (digest herpind om de naam
    alleen), dode lagCalendar.ts weg, importSource-toelichting, serialisatiepoort ≤ 1,6, CLAUDE.md
    XER-sectie. Niet gebouwd (eigenaar): onbegrensde archiefretentie (17,7 MB .xer ⇒ 50 MB IFC,
    73 s / 3,1 GB herstelronde), moment van de exportverliesmelding, documentaantal-cap.

Does this touch

  • Project data — round-trips through the IFC layer, and tested? — recordedTimes/
    datesAsRecorded/XER-bronarchief via DOCUMENT_FIELDS, recovery-manifest v4, IFC-round-trip
    (check-xer-recorded-roundtrip.ts, check-document-contract.ts, check-recovery-*.ts).
  • Scheduling logic — case added to tests/planning/? — o.a. check-xer-completed-late.ts,
    check-p6-verified-cases-engine.ts, check-recorded-dates*.ts, check-xer-calendar-data.ts,
    corpusgebonden X12-poorten; niet-XER-formaten byte-identiek (vlaggen alleen door de XER-lezer).
  • User-visible text — goes through t(...), and all fourteen locales filled in? —
    verify:i18n groen (o.a. properties.recordedDatesActiveNeutral, notifications.xerImport*,
    tableReports.recordedDatesNote, extConsent.permImportSource).
  • @tauri-apps/* — niet geraakt.

Documentation

Gidsen gids-xer-import.md en datums-zoals-opgeslagen.md (nl+en; sinds de eindreview ook de
projecteinde-fout, de prijs van het bronarchief, het weekend-klemherstel en de rapportmelding),
CLAUDE.md (formaatregistratie, documentcontract, nieuwe XER-sectie), docs/TODO.md
(projecteinde-fout, reststart-ES, v1-poort hersteld, eindreview-items), plan §5/§9/§10.
verify:docs groen.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW

Nozzit and others added 30 commits August 20, 2026 10:03
…ariteit/uurmodus als kernbesluit, SCHEDOPTIONS-defaults-programma, whitelist-invoerregel, projectselectie herzien, X-O5 getalnotatie, mutatiebewijzen per taak
…ti-project-import, baselines verplicht bewaard, float-vangrails bekrachtigd
…ijk (Hotel-paar via schema-vingerafdruk), X-O1/X-O2 doorvertaald (X4a/X4b-knip, per-project-meting, lege-projectregel, baseline-begrenzing), defaults op de meting, generieke enum-regel
…e-eis op drie plekken (docblok, 14-talige foutmelding, gidsparagraaf)
…ECT-rij terug in X4a, enum-regel gesplitst naar §4.7, X4b→X10-pijl, stale zinnen gelijkgetrokken
XER-etappe, taak X0 (SERIEEL VOORAF). Geen lezer, geen registry-entry — alleen
typecontract + corpustooling, conform de X0-brief en plan §4.1/§6.

- src/types/task.ts: P6DurationType/P6ActivityType + Task.p6DurationType/
  p6ActivityType/p6SuspendResume (veld-als-signaal naast mspTaskType, met de
  vastgelegde superset-afspraak voor de latere taaktypes-etappe; suspend/
  resume-herkomstvlag is een stub, X7 vult hem).
- Doorgevoerd op alle compile-gedekte plekken die anders stil hadden kunnen
  verouderen: extTypes.ts/extMappers.ts (Ext-contract, leeskant-alleen zoals
  mspTaskType/effortDriven), check-ext-contract.ts (sleutellijsten),
  moveProject.ts (TASK_VERDICTS, 'n/a'), check-ifc-roundtrip.ts (Required<Task>-
  getuige + TASK_CANON skip-cellen, IFC-wiring is X9), taskFields.ts
  (REJECT_HINTS, MCP-zetbaarheid).
- tests/planning/check-xer-field-whitelist.ts: de drie §4.1-bakken (whitelist/
  verboden/genegeerd) als getypeerde constanten + een eigen, onafhankelijke
  %T/%F-corpusscan (OPS_XER_CORPUS) die de union van alle TASK-kolommen tegen
  de bakken toetst — het gatenkaas-mechanisme. Skip-OK zonder corpus, geen
  CI-poort (zelfde conventie als OPS_MPP_CORPUS).
- tests/planning/xerFidelityTypes.ts + xer-fidelity-baseline.json +
  check-xer-fidelity-baseline-schema.ts: het harness-skelet — de §3-baselinevorm
  (zes assen, deviations/measurable) vastgelegd via een compile-locked
  sleutellijst + runtime-structuurvalidator, met een lege-lezer-run
  (createEmptyXerFidelityBaseline) die de committe lege baseline produceert.
  De dedup-logica zelf (§2) is X1-werk.
- run.sh: beide nieuwe checks bedraad naast check-mpp-fidelity.

Mutatiebewijzen (uitgevoerd, teruggedraaid): whitelist-veld schrappen ⇒
corpusscan ROOD; baseline-vorm muteren (JSON) ⇒ schema-check ROOD; veld uit
XerFidelityBaselineEntry schrappen ⇒ compile-fout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nozzit and others added 29 commits September 5, 2026 14:09
…, 14 talen

De MODUS-ACTIEF-strook zei altijd "zoals Primavera ze opsloeg", maar diezelfde strook draagt ook de
#63-route voor IFC/CSV/MSPDI/MPP/P6XML — daar weet niemand uit welk pakket de datums komen en is die
zin een verkeerde bewering. Er is nu een tweede sleutelfamilie `recordedDates.activeCountNeutral`
("de datums zoals ze in het bestand staan"), in alle veertien talen met de juiste CLDR-
pluralcategorieën; de Primavera-tekst blijft voor beide XER-herkomsten ('xer' en 'xer-archive' —
allebei echt P6's vastlegging, ze verschillen alleen in het heropen-beleid).

De keuze zelf staat in de React-vrije `recordedDatesActiveKey` (`recordedDatesNoticeText.ts`), zodat
ze headless getest kan worden in plaats van als inline ternary op het oog beoordeeld te worden; het
retourtype is de literale sleutelunie, dus een niet-bestaande sleutel is een compile-fout.

Tests: check-recorded-dates sectie 14 — de keuze per herkomst (14a–14c) en de INHOUD in alle veertien
talen (14f–14h: de neutrale familie noemt Primavera nergens, de Primavera-familie juist overal, met
gelijke pluralvormen), plus 7w2/7ai2 die vastleggen dat het document de herkomst draagt die de tekst
stuurt. Mutatiebewijs: de keuze altijd op de Primavera-sleutel zetten ⇒ 14c rood; de Primavera-zin in
een neutrale sleutel plakken (de) ⇒ 14g rood.
…voor de completed-late-regel

Reviewpunten 1, 3, 4 en 6 van de hyperkritische review op dd8782d/34031a41/f6db6f79.

1 (P1, verify rood): `XER_SCHEDULING_DEFAULTS` kreeg de sleutel
  `p6CompletedLateFromRemainingWindow`; `check-xer-schedule-options.ts` (4/47 rood) en
  `check-xer-schedule-options-wiring.ts` pinnen dat object letterlijk en zijn bijgewerkt, net als
  de onafhankelijke afleiding in `xerScheduleOptionsGroundTruth.ts`. Beide checks draaien
  corpusloos en zijn dus wat CI/live/release draaien.

3 (P1, rekenfout): `backwardConstraint` geeft voor START_START/START_FINISH de late START van de
  voorganger terug via `finishFromStart(pe, predLS, predTask)` — dus predLS plus de VOLLE geplande
  duur. De nieuwe tak behandelde dat als een late finish van een taak met nul restduur en telde de
  duur zo dubbel: een voltooide voorganger met PR_SS lag 0 kreeg een late start twee werkdagen NA
  die van haar opvolger. Nu krijgt de voorganger voor die twee relatietypen expliciet nul restduur
  mee (`zeroRemainingPredTask`), waardoor `finishFromStart` een no-op is, en slaat de conversie
  `nextWorkInstant` over. FS/FF ongewijzigd. Fixture uitgebreid met SS/SF/FF-gevallen (SSA/FSA en
  SFA/FFA delen exact dezelfde afgeleide late start) plus absolute datumankers.

4 (P2, poortdivergentie): `CPMSolver` poortte op `backwardActualPin.eligible && completedWindow`,
  `scheduleAnalysis` alleen op `completedWindow` — een `TK_Complete`/`TK_Active` met completion 1
  maar zonder `act_end_date` viel ertussen: de solver deed niets, de weergave verschoof ls/lf/tf
  toch. Beide draaien nu op één functie, `explainP6CompletedLateRemainingWindowEligibility`, ook
  voor de opvolgeruitsluiting in de generieke backwardtak. Fixture: taak NX (completion 1, geen
  actualFinish) is met de vlag aan byte-identiek aan met de vlag uit.

6 (P2, bewijsbasis): élk gemeten corpusbestand draait RETAINED_LOGIC; er is geen enkele meting van
  P6-gedrag onder `sched_progress_override = Y`. `deriveXerScheduleOptions` zet de vlag daarom
  weer uit zodra de bron progress override declareert (fail-closed, byte-identiek aan vóór deze
  etappe). Het docblok bij het veld legt nu ook vast dat 2.040 van de 2.042 poort-eligible taken
  in één bestand staan en dat de nauwte van de poort de rest van het corpus beschermt.

Corpuspin `xer-schedoptions-blast-radius.json` herpind (xerDefaults ls 4791→3901, lf 4781→3891,
tf 4592→4235; netto −2.137 cellen, één bestand), met de verklaring in
`check-xer-schedule-options-corpus.ts`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rpuspin herpind

Reviewpunten 2 en 7.

2 (P1, verouderde corpuspin): `check-xer-task-replay.ts` was met OPS_XER_CORPUS rood op de
  negatieve kandidaat `drop-p6-finish-milestone-boundary` (ls 690 → 1466, lf 704 → 1480,
  tf 629 → 1363, overall 704 → 1481). Herpind mét de verklaring in de check: het instrument meet
  hoeveel PRODUCTcellen een mutant kapotmaakt, en sinds `p6CompletedLateFromRemainingWindow` zijn
  er corpusbreed ~890 meer exacte late-zijde-cellen om kapot te maken. De positieve kandidaat
  `synthetic-zero-regression` blijft ongewijzigd op 0 regressies — de nulmeting is dus niet
  meeverschoven.

7 (P2, X12 tegenover cases-p6-verified.json): de dertien P6-23.12-geverifieerde casussen werden
  alleen als DATA gepind en nooit door de motor gehaald, waardoor een corpusloze X12-assertie het
  tegenovergestelde kon beweren van P6's eigen opname zonder dat iets dat meldde. Nieuwe check
  `check-p6-verified-cases-engine.ts` (in run.sh): alle dertien casussen worden corpusloos als
  XER-fixture opgebouwd uit de INVOERzijde van het publieke cpp-cpm-engine-raamwerk, door lezer +
  `solveProject` gehaald en cel voor cel tegen `cases-p6-verified.json` gelegd.

  Uitkomst (gemeten, niet naar P6 toe geschreven): 157 van de 160 door P6 vastgelegde cellen
  kloppen. Casus 09 `09-completed-successor` staat op 10/10 — wij geven de open voorganger A
  `LS = ES` en `TF = 0`, exact zoals P6 23.12. De review-tegenspraak is daarmee opgelost en het is
  géén tegenspraak: in casus 09 kent de bron geen targetvenster en geen `rem_target_link_flag`, dus
  het completed-statusdatumvenster blijft dicht (assertie 1: in alle dertien casussen
  `remainingStartOff`) en `p6CompletedLateFromRemainingWindow` is er inert. De X12-fixture heeft wél
  een expliciet targetvenster, `rem_target_link_flag=Y` en een `act_end_date` NA de statusdatum;
  assertie 3/3a/3b legt die tegenhanger expliciet vast. De twee fixtures staan aan weerszijden van
  dezelfde poort.

  Enig bekend verschil: casus 10 (out-of-sequence voortgang), drie cellen op activiteit A — P6 geeft
  `LS = ES`, `TF = 0`, wij `LS 2025-12-25`, `LF 2026-01-07`, `TF −12`. Niet door deze etappe
  veroorzaakt (poort dicht ⇒ vlag inert), cel voor cel gepind als klasse (ii)-materiaal.

  Met OPS_P6_COMPARISON of OPS_XER_CORPUS wordt de handmatige invoertranscriptie bovendien veld voor
  veld tegen de bron-`input.json` gelegd, zodat ze niet stil kan afdrijven (11e check).

  Mutatiebewijs: de `remainingStartOff`-poort weghalen ⇒ 2/10 rood; ook de
  `missingExplicitTargetWindow`-poort weghalen ⇒ 5/10 rood en casus 09 zakt van 10/10 naar 3/10
  agreement met P6. De check bewaakt dus precies de poortgrens waar de review op wees.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ind, plan/gids bijgewerkt

Reviewpunten 5, 8 en 11.

5 (P2, per-cel-regressie): de −358 tf was NETTO. Per cel gemeten op rehab-2 (vlag uit vs. aan):
  ls 890 exact erbij / 0 kapot, lf 890 / 0, tf 572 / **215**, ff 0 / 0. Van die 215 hebben er 214
  minstens één directe opvolger waarvan de LS zélf nog fout is — voltooide taken waar P6 `tf = 0`
  geeft en waar onze `tf = 0` vóór deze etappe degeneratie was (LS = de historische actual-start),
  dus per ongeluk goed. Dat is de bekende koppeling met klasse (ii): een fixpunt op P6's eigen
  opvolgerwaarden dekt 98,8%, op de onze 44,4%. Eén cel (88690) heeft wél alle opvolgers exact; de
  laatste twee zijn doorwerking. Vastgelegd in het commentaar bij beide corpuspins en in het plan.

  De v1-harness `check-xer-product-fidelity.ts` — de enige plek met een per-cel
  `cellTransitions.previouslyExact`-mechanisme — riep `solveProject` aan zónder
  `progressMode`/`schedulingOptions`, waardoor élke brongebonden P6-optie er per constructie inert
  was. Rechtgezet. Diezelfde harness crasht met corpus op een kale TypeError omdat
  `xer-product-fidelity-baseline.json` inmiddels het v2-schema draagt; dat is niet door deze branch
  veroorzaakt (gemeten op 92e98b8 én hier) en is nu een leesbare rode regel die de oorzaak benoemt,
  plus een TODO-item. De poort meet sinds die schemawissel niets — precies de klasse die hier met de
  hand gemeten moest worden.

  Poortpariteit-herpin: de v2-productbaseline en haar corpusloze spiegel schuiven één cel
  (lf 9.660 → 9.659, tf 9.270 → 9.269 exact). Dat is rehab-2 `87620`, `TK_Active` met completion 1
  maar zonder `act_end_date` — de taak die vóór de fix tussen de solver- en de weergavepoort in viel
  en daardoor toevallig P6's lf/tf kreeg. Corpusbreed staat het zesassige totaal nu op 16.261
  (was 18.398 vóór de etappe, 16.259 met de divergente poort).

8 (P3, drivingPath +6): de verklaring in `check-xer-corpusless-fidelity-gate.ts` was vaag en
  onjuist. Het zijn precies zes OPEN taken (87418, 87419, 87420, 87421, 87422, 87426) waarvan
  ls/lf/tf nu exact P6 worden inclusief `tf = 0`, waarna onze `isCritical = tf ≤ drempel` ze kritiek
  maakt terwijl P6's `driving_path_flag` `false` zegt. Een systematisch gat tussen OPS-kritiek en
  P6's driving-padbegrip, blootgelegd dóór de verbetering — geen ruis.

11 (P3, geen docwijziging): X-O7 laag 1 in het plan heeft een "Stand 2026-09-05"-blok met de vier
  dingen die je moet weten vóór je hier verder bouwt (klasse (ii)-koppeling, drivingPath-gat,
  bewijsbasis van één bestand, de poort tussen deze regel en casus 09). De opgeleverde O6-bronvlaggen
  staan nu ook in de §4.2-lijst, inclusief de progress-override-afwijking. Gebruikersgids
  `gids-xer-import.md` (nl + en) heeft een eigen paragraaf: een voltooide XER-activiteit toont
  voortaan echte speling in plaats van nul, met de voorwaarden waaronder dat geldt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…g echte berekende waarden

Critreview laag 3, bevinding 1 (P1, BEVESTIGD). `FullTaskGrid` bedraadde `recordedUnrecordedAxes` op
`recordedDates !== null` in plaats van `datesAsRecorded`. Maar `recordedDates !== null &&
!datesAsRecorded` IS de aanbodstand: er is gewoon gesolved, dus `task.time.lateStart` en de floats
zijn echte CPM-uitvoer — en die werden door `recordedAxisFormat` vervangen door "Niet vastgelegd", in
beide rasteroppervlakken. Permanent bovendien: `runCPM` wist `recordedDates` alleen bij het VERLATEN
van de modus, dus ook F5 haalde het niet weg. Een IFC vult zelden LateStart/TotalFloat, dus dit trof
zo goed als elk document met een #63-aanbod — een regressie op de bestaande #63-route, niet iets
XER-specifieks.

Dezelfde poort geldt voor de `partly-unrecorded`-tak van `recordedTaskMark` (en dus de badge in het
eigenschappenpaneel): "deels niet vastgelegd" is een uitspraak over wat er OP HET SCHERM staat, niet
over het bestand. Buiten de modus staat onze eigen berekening daar. "Wijkt af" blijft wél buiten de
modus gelden — die markering vervangt geen waarde, hij staat ernaast.

De poort staat nu in één gedeelde `recordedGridBinding` (`recordedDatesSelectors.ts`), gebruikt door
`FullTaskGrid` én `gridTransaction`, zodat de bedrading headless te toetsen is in plaats van alleen
in een React-memo te leven.

Tests (check-recorded-dates-mark, 41 checks): de bindingpoort per stand, plus een einde-tot-eind-pin
door de ECHTE store — een gewone IFC-fixture in de aanbodstand toont de berekende lateStart/
totalFloat, en na `showRecordedDates()` toont dezelfde kolom wél "Niet vastgelegd". Mutatiebewijs:
poort terug op `recorded ? … : undefined` ⇒ 3 van 41 rood.
…project.ts houdt zijn regeleindes

Twee nabranders op 3a9caee.

1. `relationBoundaryFlags` leidt `predStartsNextDay` af uit `scheduleDuration <= 0` PLUS
   `milestoneKind === 'FINISH'`. De SS/SF-kloon zet de duur op 0, dus de eerste helft werd altijd
   waar — waardoor uitgerekend een voltooide EINDmijlpaal-met-duur (T15-vorm) in deze tak een extra
   werkdaggrens-sprong (`snapStrictBefore`) zou krijgen die een gewone voltooide taak niet krijgt.
   De kloon zet `milestoneKind` nu expliciet op `undefined`, zodat alle voltooide taken hier
   dezelfde, grensloze route volgen — consistent met de aanname van de tak zelf (nul restduur, LS is
   het anker, `LF = prevWorkInstant(LS)`; die aparte finishgrens bestaat daar niet). Corpus- en
   fixture-neutraal: een gewone voltooide taak heeft geen `milestoneKind`, en een nulduurmijlpaal
   komt sowieso niet door `explainP6CompletedDataDateWindow` (`zeroDurationMilestone`).

2. `src/types/project.ts` staat in CRLF; de docblokbewerking van 3a9caee normaliseerde het hele
   bestand naar LF (86 → 0 CR-regels) en blies de diff op tot 203 regels. Teruggezet: het bestand
   is weer CRLF en de diff tegen f6db6f7 is nu precies het toegevoegde docblok.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ta i.p.v. heuristiek

Critreview laag 3, bevindingen 2 en 3 (P2, beide BEVESTIGD).

(2) De terugleesmeting "0 verschoven op de rauwe taken ⇒ de modus stond aan" bewees niet wat ze
beweerde: ze bewijst alleen dat de opgeslagen datums gelijk zijn aan de vastlegging, en dat kan ook
zonder modus. Reproduceerbaar gat: een bewerking verlaat de modus en zet `scheduleStale`, maar de
herberekening staat pas op `setTimeout(0)` (`useExitRecordedDates`) — valt de auto-save-snapshot
daartussen, dan zette het herstel de modus wéér aan, wiste het de verouderd-vlag, en presenteerde
het een half bewerkte planning als "zoals Primavera hem opsloeg".

(3) `restoreDocuments` paste de vastlegging bovendien alleen op het ACTIEVE document toe. Slapende
documenten kwamen terug met P6's datums in `task.time`, zonder modus, zonder markering en mét
`scheduleStale` — waarna automatisch berekenen (of de eerste F5) die datums stil wegrekende.

`datesAsRecorded` reist nu als expliciet veld in de recovery-metadata mee (`RecoveryDocMetadata`/
`RecoveryDocContent`/`RecoveryManifestDoc`, manifestversie 4), net als `filePath`/`isDirty`: van
`useAutoSave` → `recoveryDelta` → beide backends → `loadRecovery` → `recoveryInputFromParsed` →
`restoreDocuments`. Oudere manifesten (v1–v3) blijven leesbaar; een ontbrekend veld betekent
`false`, dus het gewone #63-aanbod en nooit stilzwijgend de modus. De vlag telt mee in de
metadatavergelijking van de delta, zodat een modus­wissel zonder inhoudswijziging ook echt een
manifestcommit geeft.

De twee bijna-identieke laadfuncties zijn samengevoegd (bevinding 12): `applyRecordedDatesOnLoad`
met één expliciete `restoredMode`-parameter, plus `applyRestoredRecordedMode` voor slapende
documenten — die worden bewust niet doorgerekend, dus daar is geen verschiltellertje mogelijk en
krijgt de payload de modus zonder verzonnen `shifted: 0`.

Tests: check-xer-recorded-roundtrip 6h–6n (het bewerkings­gat ⇒ modus blijft uit, bewerking en
aanbod overleven) en 6o–6v (twee documenten in de modus ⇒ ook het slapende komt terug in de modus,
niet stale, met een cpmResult uit de vastlegging); check-recovery-isolation 5o–5r (v3-manifest
zonder het veld blijft leesbaar en levert false; nieuw manifest schrijft de vlag);
check-recovery-delta 6b–6d (moduswissel = manifest-only commit). Mutatiebewijzen: metadatavlag niet
doorgeven ⇒ 6b/6q rood; slapende tak weghalen ⇒ 6r–6t rood; vlag uit de metadatavergelijking ⇒ 6b
van recovery-delta rood.
…odus echt aanging

Critreview laag 3, bevinding 4 (P2, BEVESTIGD). `applyOpenedImport` telde `recordedDates.shifted`
op ongeacht of de modus aanging, en gaf dat aan `notifications.xerImportDatesAsRecorded` — een
regel die letterlijk "(niet herberekend)" zegt. Een heropende IFC met XER-archief draagt óók
`xer`-metadata, dus die melding verscheen daar eveneens, terwijl er per heropen-beleid juist WÉL
herberekend is en de modus uit staat.

De teller is nu gesplitst: alleen documenten waar de modus daadwerkelijk aanging tellen in de
bestaande regel; de aanbodroute krijgt `notifications.xerImportDatesAsRecordedOffer` ("N taken
wijken af van de datums in het bestand — je kunt ze tonen"), in alle veertien talen met de juiste
CLDR-pluralcategorieën.

Test: check-xer-open-wiring T4-25..29 (heropende XER-archief-IFC ⇒ één melding, zonder de
"niet herberekend"-regel, mét de aanbodregel en dezelfde teller). Mutatiebewijs: de aanbodstand
weer bij de oude teller optellen ⇒ T4-27..29 rood.
Critreview laag 3, bevinding 5 (P2, BEVESTIGD). De XER-gids (nl+en) beloofde dat opslaan als IFC
"deze weergave bewaart" in het projectbestand. De datums gaan inderdaad mee, maar het heropen-beleid
zet de weergave juist NIET meer uit zichzelf aan — de gebruiker krijgt de melding met de knop en
kiest zelf. De docs-commit was geschreven vóór dat besluit; `verify:docs` controleert vorm, geen
waarheid.

Tweede, kleinere overpromise in `datums-zoals-opgeslagen.md` (nl+en): "Zodra je herberekent … vult de
kolom zich met de eigen berekening" wekte de indruk dat "Niet vastgelegd" een toestand van het
document is. Het is een uitspraak over déze weergave; buiten de weergave staat er gewoon het
berekende getal (zie ook de P1-fix van deze reeks).
…leestools

Critreview laag 3, bevinding 6 (P2). In de modus schrijft `applyRecordedTimesToTasks` de bewuste
terugvallen (`lateStart ?? rec.start`, `totalFloat ?? 0`, `isCritical ?? false`) als echte
veldwaarde in `Task.time`. Plan §3.4 verdedigde dat met "niets in de zichtbare productinterface
toont dat getal", maar die mitigatie zat uitsluitend in `taskColumnRegistry`. Zolang #63 een knop
was, was dat een bewuste gebruikershandeling; sinds standaard-aan is het de standaardtoestand van
elke XER met restverschillen (rehab-2: 813 van 6.976 taken).

Twee uitgangen buiten de tabel om dragen nu dezelfde eerlijkheid, via één gedeelde poort
`unrecordedExportGate` (`recordedDatesSelectors.ts`, `undefined` buiten de modus ⇒ byte-identiek
gedrag):
- CSV-export: lege cel voor "Total Float" en "Critical" wanneer het bestand die as niet vastlegde —
  een CSV-lezer kan een verzonnen `0` niet van een echte nulspeling onderscheiden;
- MCP: `planner_get_task` geeft `null` voor elke niet-vastgelegde as plus een expliciete
  `datesAsRecordedUnrecordedFields`-opsomming (want `null` alleen is dubbelzinnig), en
  `planner_get_critical_path` geeft `null` i.p.v. een `?? 0`-speling. Anders dan een gebruiker ziet
  een AI-client de strook boven de planning niet.

MSPDI- en P6-XML-export bleken géén late datums of speling te schrijven (de `totalFloat`-treffer in
`mspdiWriter.ts` is de projectinstelling `totalFloatMode`, geen taakuitvoer) — daar was dus niets te
repareren.

Tests: check-recorded-dates 13Ba–13Bh (lege cellen in de modus, berekende waarden erbuiten, en
byte-identieke export zonder poort) en tests/mcp/cases-recorded-dates (null + veldopsomming in de
modus, onveranderde respons erbuiten). Mutatiebewijzen: CSV-poort weg ⇒ 13Bb rood; MCP-poort weg ⇒
de leestool-case rood. Eén regel in de gids (nl+en).
7. Isolatiescan (`check-xer-field-whitelist.ts`) had twee gaten: hij kende alleen `cells.<veld>` en
   `'<veld>')` als leespatroon — `const { early_start_date } = row.cells` glipte er ongezien
   doorheen — en hij scande alleen `src/services/xer/`, dus een lezer in `src/services/ifc/` viel
   erbuiten. Nu drie patronen (destructurering erbij) over heel `src/`. Mutatiebewijzen: beide
   lekvormen ⇒ exit 1, elk op de juiste bestandsnaam.
8. Bak 4 was dubbel fail-open zonder corpus: de corpusscan slaat over zonder OPS_XER_CORPUS, en de
   isolatiescan itereert over diezelfde constante — een naam eruit halen verwijderde hem stil uit
   béide poorten. De zes namen staan nu ook met de hand gepind. Mutatiebewijs: `early_start_date`
   uit de lijst ⇒ ZONDER corpus exit 1.
9. `noRecordedAxisLeak` (X12) vergeleek alleen rauwe strings en kon dus een lek van een gemuteerde
   FLOAT of van een genormaliseerde datumrepresentatie niet zien. Vergelijkt nu per type, met
   `parseInstant`-genormaliseerde instants en de dag als grovere terugval.
10. `docs/library.md`: de aangekondigde regel over `pinnedReason: 'dates-as-recorded'` —
   met standaard-aan is een gepind, niet-efemeer doorgerekend document de normale toestand van een
   zojuist geopend P6-bestand, niet een randgeval.
11. De kolom `recorded.source` had geen eigen `copy`, dus het klembord kreeg het rauwe token
   (`deviates`) terwijl de cel "Wijkt af" toont. `format` en `copy` delen nu één tekstfunctie; een
   lege markering kopieert als lege cel, niet als em-dash. Test + mutatiebewijs in
   check-recorded-dates-mark.

Bevinding 12 (de twee bijna-identieke apply-functies) is al opgelost in de recovery-commit van deze
reeks.
De v1-check (check-xer-product-fidelity.ts, per-cel-regressiebewaking op
previouslyExact/improvements) en de v2-check (check-xer-product-fidelity-x12.ts,
34-entry-karakterisering) deelden per ongeluk één bestandsnaam
(xer-product-fidelity-baseline.json); baan 3a overschreef 'm stil met het
v2-schema, waardoor de v1-check crashte met een ongevangen TypeError
(STATUS=1 zonder XX-regel).

Besluit: v1 blijft. Hij bewaakt iets dat v2 niet dekt — de EXACTE identiteit
van cellen die eerder exact waren (per bronproject/taak/as), niet alleen een
geaggregeerd telleraantal per bestand. Twee cellen die van plek ruilen binnen
dezelfde as/bestand (een regressie gemaskeerd door een toevallige verbetering
elders) verandert v2's tellersom niet, maar breekt v1's previouslyExact-set wel.

- v2-baseline hernoemd naar xer-product-fidelity-baseline-v2.json; de drie
  v2-lezers (check-xer-product-fidelity-x12.ts,
  check-xer-corpusless-fidelity-gate.ts) en hun docblokken volgen.
- v1-baseline hersteld op de oude naam uit 8f09520 (bevestigd identiek aan
  f53de7d, de laatste v1-commit vóór de v2-overschrijving in 87dab10).
  Geen herpin nodig: de v1-check draait groen (13 pins) op deze HEAD — v1 pint
  alleen p6diff-baseline.xer en sample-target.xer, geen van de door 7b
  gewijzigde bestanden (rehab-2 zit niet in de v1-set).
- check-xer-fidelity-baseline-schema.ts: nieuwe sectie 0 asserteert dat het
  v1-bestand version 1 + label-sleutels + cellTransitions heeft en het
  v2-bestand version 2 + manifestSha256/characterization — mutatiebewezen
  door de twee bestanden te verwisselen (rood, 2 XX-regels, exit 1).

Gerichte checks (corpus + tests/planning/-bundel, exitcode leidend):
- check-xer-product-fidelity.ts (v1): OK, 13 pins groen, exit 0
- check-xer-product-fidelity-x12.ts (summary): 17421 zesassige afwijkingen
  (verwacht), 76 corpusloze checks groen, exit 0
- check-xer-corpusless-fidelity-gate.ts: OK, 57 checks groen, exit 0
- check-xer-fidelity-baseline-schema.ts: OK, 37 checks groen, exit 0
- npm run typecheck: exit 0
- npm run lint: exit 0

Niet aangeraakt: de volledige (poort-)modus van check-xer-product-fidelity-x12.ts
staat al vóór deze commit rood door de bekende, elders beheerde v2-
karakteriseringsstatus (characterization.finalZeroGate: red, accepted: false na
7b's rehab-2-wijziging); bevestigd bytegelijk aan de inhoud vóór hernoeming,
dus geen regressie hier. Dat repin-vraagstuk hoort bij de X12-v2-lane.

(cherry picked from commit adda0ee)
Vervolg op de P1-fix van deze reeks. Door `partly-unrecorded` op `datesAsRecorded` te poorten werd
die tak in `TaskRecordedDatesNotice` onbereikbaar: buiten de modus levert `recordedTaskMark` hem
niet meer, en ín de modus koos de component onvoorwaardelijk 'active'. Over dezelfde taak zei de
kolom `recorded.source` dan "Deels niet vastgelegd" terwijl de badge "Datums zoals opgeslagen"
toonde.

De keuze staat nu in de pure `recordedNoticeState`: in de modus wint "deels niet vastgelegd" van
het kale "actief" — dat is daar het informatieve signaal en het is exact wat de kolom toont —,
buiten de modus is het precies `recordedTaskMark`. Vijf gevallen vastgelegd in
check-recorded-dates-mark (48 checks).
…1-stand, dossier 7b-4, verify-uitkomst, losse eindjes
…mbord, samenvattingen, slapend herstel, badge

Verwerkt de bevindingen van de her-check op laag 3 ("Datums zoals opgeslagen" voor XER):

1. `taskGridAdapter.getCell` sloeg `descriptor.format` over zodra `dateNotation` gezet was (in het
   product altijd), waardoor laat-start/-einde van een niet-vastgelegde as als verzonnen datum op
   het scherm stond. "Niet vastgelegd" is nu een eigenschap van de LEESWAARDE (`recordedAxisRead`
   ⇒ `undefined`), zodat celtekst, titel, klembord en sortering hetzelfde zien; de test meet nu op
   `adapter.getCell().text` i.p.v. op `descriptor.format()`.
2. De vier as-kolommen kregen een eigen `copy`: klembord = celtekst, leeg bij "niet vastgelegd".
3. Samenvattingen (XER-WBS-rijen) rollen in de modus op uit de vastgelegde kinderen —
   `rollupSummaryTasks` uitgefactoriseerd uit `applyCpmResult` en gedeeld door
   `applyRecordedTimesToTasks`. Gemeten vóór de fix: hoofd-WBS een half jaar ná `projectEnd`.
4. Slapend hersteld document: `RecordedDatesState.shifted` is optioneel, `applyRestoredRecordedMode`
   zet de vastlegging (zonder verzonnen teller), zodat export-poort, "niet vastgelegd"-kolommen en
   badge ook daar werken; de strook valt terug op de tellerloze tekst.
5. De per-taak-badge noemt Primavera alleen bij een XER-herkomst (`recordedDatesTaskActiveKey`,
   neutrale variant in 14 talen; sectie 14 van `check-recorded-dates.ts` scant nu ook `task.json`).
7. `isCritical` in de vastlegging volgt dezelfde `criticalDefinition` als de solver krijgt
   (drempel uit `critical_drtn_hr_cnt`; longest-path ⇒ "niet vastgelegd").
8. Het X12-lekbewijs krijgt de zes gemuteerde floats mee (de `n:`-tak was dode code).
9. Eerste browserdekking: `tests/browser/recorded-dates.spec.ts` (openen via bestandskiezer,
   strook, celtekst mét datumnotatie, badge, herberekenen verlaat de modus).
10. De overige MCP-leestools poorten `isCritical` in de modus (`crit: null`, apart geteld,
    filter `kritiek` laat onbekend buiten beide).
11/12. Documentatieclaims rechtgezet (isolatienuance `xerTables.ts`, dood mutatiebewijs 7C,
    manifest v4 in `recoveryPaths.ts`, `UnrecordedExportField`-type in `csvWriter.ts`);
    `check-xer-open-wiring.ts` meldt een ontbrekend corpusbestand netjes.

Bevinding 6 (ordetoets `einde < start`) is GEMETEN EN VERWORPEN: dat is P6's eigen conventie voor
voltooide activiteiten (25 orakelbestanden: 2.049 van 11.953 taken met early-paar, 2.036 daarvan
TK_Complete; rehab-2 2.042 van 6.976). Een guard zou 29% van rehab-2's vastlegging weggooien;
vastgelegd in het docblok van `readXerRecordedTimes` en als mutatiebewijs 9a.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…SF, fail-closed klem, eerlijke labels

Verwerkt de her-review op laag 1 klasse (i) (`p6CompletedLateFromRemainingWindow`):

1. `check-p6-verified-cases-engine.ts` volgt nu de ÉCHTE P6-export van de dertien casussen
   (`cases-import.xer`): `rem_target_link_flag = Y`, `duration_type = DT_FixedDrtn`,
   `target_start_date` = projectstart, leeg `target_end_date`. De eerdere transcriptie verzon
   `DT_FixedDUR2` en liet de vlag weg — twee elkaar opheffende afwijkingen. Poortreden is nu
   `missingExplicitTargetWindow` (geen `remainingStartOff`); agreement 156/160 i.p.v. "157/160".
   Sectie 7 draait de echte bytes (corpusgebonden): 77/160 zoals gelezen, 156/160 met
   `useProjectEndDateForFloat` uit — het gat is een productfout (leeg projecteinde ⇒ projectstart
   als anker), zichtbaar gepind.
   De vier resterende cellen (casus 08 A, casus 10 B: ES/LS) hebben één oorzaak: onder
   `rem_target_link_flag = Y` wordt de vroege start van een bezig zijnde taak de reststart, waar P6
   de werkelijke start opneemt — klasse (ii)-dossier, niet deze vlag.
2. Bewijsstatus expliciet: de poort is correlationeel; het enige directe P6-bewijs voor de
   topologie (casus 09/10) spreekt de regel tegen zodra de poort opengaat (docblok in
   `types/project.ts`).
3. Klem fail-closed op "aantoonbaar retained logic" (`declaresRetainedLogic`): ook N/N (Actual
   Dates), Y/Y en onbekende tokens zetten de vlag uit; leeg/leeg en Y/N houden hem aan.
   Onafhankelijke grondwaarheid gelijkgetrokken; zeven corpusloze checks erbij.
4. Procentuele lag op SS/SF uit een voltooide voorganger verdween stil (opgelost tegen de
   nulrestduur-kloon); nu vóór de kloon tegen de ongewijzigde taak vastgezet, per lag-eenheid.
   Fixture: SS/FS/SF/FF met 8 u lag en SS/FS met 50%-lag — SS+50% = SS+8u = FS+8u = FS+50%.
5. Bandrand-asymmetrie SS/SF vs FS/FF met lag gepind als karakterisering (niet gesymmetriseerd:
   P6-conventie ongemeten).
6. De `milestoneKind`-reset eerlijk gelabeld als defensief en via de XER-lezer onbereikbaar.
8. "214 van 215" → alle 215 (`TK_Complete`, `DT_FixedDUR2`), op de drie plekken.

Gemeten op het volledige corpus (93/93): 16.261 zesassige afwijkingen op deze branch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…de etappebranch

Tellers X12 (volledig corpus, 93/93, 34 entries/47 projecten/13.982 taken):
- vóór (kop 1206e01, ná 7b):            17.421 zesassige afwijkingen
- 7a alleen (merge-base 92e98b8 + 7a):  16.261
- ná (7a + 7b samen, deze merge):        15.056  (§10.b verwachtte ≈15,3k — "meten, niet aannemen")

Conflicten: de drie corpuspins (`xer-product-fidelity-baseline.json` v1, `xer-schedoptions-blast-
radius.json`, `xer-task-replay-public-pin.json`) op de etappezijde gehouden; ze worden in de ene
herpin van stap 4 samen met de v2-baseline en de in-bron pin van `check-xer-corpusless-fidelity-
gate.ts` opnieuw gemeten (die laatste staat tot dan zichtbaar rood: 7a's in-bron pin tegen de
nog niet herpinde v2-baseline). `check-xer-completed-late.ts` gebruikt `workMinutesBetween` i.p.v.
de door 7b verwijderde `p6XerProjectedWorkMinutesBetween`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…heckfixes in de etappebranch

Tellers X12 (volledig corpus): vóór 15.056, ná 15.056 — laag 3 raakt de solve per constructie
niet (bak 4 is weergave/meetlat, nooit solverinvoer); dat is hier opnieuw gemeten, niet aangenomen.
Conflictvrij; één naadje: `tests/mcp/cases-xer-provenance.ts` volgt de T5-hernoeming
`reconstructXerSourceFromBytes(...).archive`. Layer-3-checks (recorded-dates, -mark,
xer-recorded-times, -roundtrip, open-wiring, field-whitelist, document-contract,
recovery-isolation) groen mét corpus; typecheck, lint en test:mcp (39/0) groen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
Bevat PR #100 (takeover-small-fixes), #103/#107 (downloadstatistieken), #105 (relatiekleuren
#94, weekendonafhankelijke milestone-duration-render) en #106 (zeven tabelrapporten uit
discussie #31). Conflictvrij (X-O6: merge, geen rebase). Tellers X12 (volledig corpus):
vóór 15.056, ná 15.056 — main raakt de XER-solve niet. Typecheck en lint groen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
… pin, blast-radius, replay-pin en v1-herbasis

Volledig corpus (93/93 sha, 45/45 orakel; 34 entries/47 projecten/13.982 taken), per bestand en per
as gemeten met de detailrapporten van de v2-baseline, de kop 1206e01 en deze boom:

  totaal zesassig: 18.398 (v2-baseline, vóór 7b) → 17.421 (kop, ná 7b) → 15.056 (nu)

Alle beweging zit in rehab-2.xer; de overige 33 entries zijn byte-identiek aan de v2-baseline.
Reden per as:
- 7b (kalenderreconstructie, X-O7-uitzondering): es 618→940, ef 813→940 SLECHTER (compensatiefout
  blootgelegd, dossier 7b-4); ls 4.358→3.889, lf 4.350→3.889, tf 4.200→3.903, ff 473→274 beter;
  drivingPath 79→80.
- 7a (completed-late): ls −969 en lf −969 (diff→exact, 0 andersom), tf netto −427 (642 beter, 215
  slechter — alle 215 TK_Complete/DT_FixedDUR2 met P6 tf 0, klasse (ii)); es/ef/ff ongewijzigd;
  drivingPath 80→86 (+6, de zes benoemde open taken; rapportage-as, geen poort).
- laag 3 en main: 15.056 → 15.056.
Sameday corpusbreed ongewijzigd: es 96, ef 97, ls 129, lf 93, tf 0, ff 0 (open categorie).

Bestanden: `xer-product-fidelity-baseline-v2.json` (regeneratie via OPS_XER_FIDELITY_REPORT=
baseline), in-bron `EXPECTED` van `check-xer-corpusless-fidelity-gate.ts` (tellers + drie sha's,
toelichting herschreven), `xer-schedoptions-blast-radius.json` (OPS_XER_SCHEDOPTIONS_REPORT=baseline
+ causalProductEffects uit dezelfde meting; expectedFinishVariant ongewijzigd),
`xer-task-replay-public-pin.json` (kandidaat drop-p6-finish-milestone-boundary: ls/lf/tf regressed
731/742/706 → 1559/1570/1487 — de kandidaat raakt nu ook de completed-late-tak), en de v1-herbasis:
de v1-harness gaf tot 7a progressMode/schedulingOptions niet door (optieloze solve); sinds die
correctie meet hij dezelfde solve als X12. Op de twee v1-bestanden is de PRODUCTsolve tussen de
v2-baseline en nu byte-identiek; de v1-tellers zijn de harnascorrectie (p6diff-baseline 8→4,
sample-target 34→32 afwijkingen; tf/ff daar +1 t.o.v. de optieloze pin, gedocumenteerd in
`reason`), cellTransitions herstart vanaf de huidige exacte set (44+16, 0 verbeteringen).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…en staan, cpmResult volgt de rollup, kritiek zonder speling is onbekend

R1 (blokkerend): `rollupSummaryTasks` kreeg een `skip`-predikaat; `applyRecordedTimesToTasks` rolt
alleen samenvattingen ZONDER eigen vastlegging op (de #63-IFC-route legt fasen wél vast), en
`cpmResultFromRecorded` neemt de opgerolde voorouders van vastgelegde taken op, zodat
`task.time` en `cpmResult` (Gantt/raster vs rapporten/`projectEnd`) hetzelfde zeggen.
Tests 15f–15h in `check-recorded-dates.ts`, met mutatiebewijs.
R2: de verworpen ordetoets eerlijk gemotiveerd (97,4% voltooid-conventie; de rest nul-duur/
mijlpaal/scheve bron — ook letterlijk getoond) plus fixture 9b (`TK_NotStart` + inversie).
R3: `isCritical` is "niet vastgelegd" zodra de speling niet omrekenbaar is (`minutesPerDay ≤ 0`);
fixture 9c.
R4: `tests/mcp/cases-recorded-dates.ts` pint `crit: null`, `criticalUnrecordedTasks` en het
driewegfilter, plus byte-identiteit buiten de modus.
R5: dode identifier `applyRecordedDatesOnRestore` uit `check-xer-recorded-roundtrip.ts`.

X12 (volledig corpus) ongewijzigd: 15.056. typecheck, lint, test:mcp groen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…4 (gemeten), reststart-ES, projecteinde-fout, sameday en driving path

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…scriminatoren gepind, ELAPSEDTIME-lagvoorrang, kalenderkop

- Plan §5 X-O7 laag 1: de alinea over casus 09/10 sprak de brongetrouwe engine-check tegen
  ("die bron kent geen targetvenster", "157/160", "enige afwijking casus 10"); herschreven naar de
  gemeten stand (poort dicht op missingExplicitTargetWindow, 156/160, vier cellen met één oorzaak
  buiten deze regel, 77/160 op de echte bytes door de projecteinde-fout).
- `check-p6-verified-cases-engine.ts` sectie 3b pint de vier discriminatoren van de transcriptie
  letterlijk (DT_FixedDrtn, rem_target_link_flag=Y, target_start=projectstart, leeg target_end),
  zodat mutatie M3 (terug naar DT_FixedDUR2) rood slaat.
- CPMSolver: de ELAPSEDTIME-tak van de procentlag-fix laat `lagMinutes` staan (N4) — de voorrang
  van `resolveElapsedMinutes` kantelt niet meer.
- `check-xer-completed-late.ts`: kalenderkop "ma–vr" → zo–do (P6-dagindex 1 = zondag) (N5).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
… 3, main en de herpin

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…anch

Conflictvrij. Tellers X12 (volledig corpus): vóór 15.056, ná 15.056. Typecheck en lint groen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…n de verify-uitkomst

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…ptions-validator, rapportmelding in de modus, herstelcode weekendherstel

Verwerkt de hyperkritische eindreview van de hele etappe t.o.v. origin/main
(oordeel landen-met-fixes; rapport in plan §10.e). Per bevinding:

3 (blokker) — de whitelist-sluiproute-scan dekte alleen bak 4. Mutatiebewijs
  M-B (`restart_date` gelezen achter `task_type === 'TT_Rsrc'`) kwam door X12,
  de whitelist-check, de corpusloze fidelity-poort én de reader-check. Nu grept
  `check-xer-field-whitelist.ts` óók `XER_TASK_FORBIDDEN` over heel src/, met
  precies twee gepinde andere-tabel-uitzonderingen (PROJECT.plan_end_date in
  xerReader.ts, SCHEDOPTIONS.critical_drtn_hr_cnt in xerScheduleOptions.ts —
  bak 2 is een TASK-tabel-lijst) die zelf op bestaan getoetst worden. Het
  aanroepargument-patroon herkent nu elke positie binnen de haakjes op één regel
  (`[^()\n]`), zodat lijst-lidmaatschap in xerTables.ts niet vals aanslaat; vier
  zelftoetsen van de regexen, incl. de M-B-mutant. Gemeten: mutant ⇒ rood.
4 (blokker) — `extractSchedulingOptions` deed JSON.parse + cast. Nieuw
  `sanitizeSchedulingOptions` (schedulingOptionsRead.ts): bekende sleutels,
  enums, eindige getallen, booleans; compile-time volledigheid tegen
  `SchedulingOptions`; invoervolgorde behouden zodat de round-trip byte-gelijk
  blijft. `p6Source: 'XER'` blijft toegestaan — het IFC round-tript de
  P6-opties legitiem — en het commentaar bij `p6SourceActive` in CPMSolver.ts
  zegt niet meer dat de XER-lezer de enige schrijver is. Drie vijandige
  IFC-cases in check-ifc-roundtrip.ts.
2 (blokker) — projecteinde-fout NIET gefixt: een solverwijziging vraagt een
  corpusmeting en herpin en de etappe had er één. Wél benoemd in
  gids-xer-import.md (nl+en, "Grenzen") als bekende fout zonder schakelaar.
4b (blokker) — check-mpp-fidelity.ts gedraaid tegen een sparse clone van
  joniles/mpxj junit/data: 164 van 213 pins gezien, 0 verbeterd / 0
  verslechterd / 164 ongewijzigd; de 49 OzBuild-pins zijn niet publiek.
5 — dode `lagCalendar.ts` weg; docblokken in CPMSolver.ts, relationMath.ts en
  types/project.ts beschrijven de werkelijkheid (instelling effectief voor élk
  formaat; eigenaarsbesluit, plan §10.f, docs/TODO.md).
6 — de rapporten kennen de "niet vastgelegd"-cel niet; in de modus staat nu
  één melding bovenaan elk rapport: tabelrapporten via `spec.notes` (dus ook in
  de PDF), Gantt/mijlpalen/afwijkingen via ReportPanel. Sleutel
  `tableReports.recordedDatesNote` in 14 talen; browser-assertie in
  recorded-dates.spec.ts. De poort zelf blijft open (TODO).
7 — weekend-klemherstel laat nu een herstelcode achter
  (`WEEKEND_CLAMP_RECONSTRUCTED` → `XER_CALENDAR_WEEKEND_CLAMP_RECONSTRUCTED`,
  RECOVERED), telt mee in de kalenderbevindingen van de openingsmelding;
  sectie 22 pint hem positief én negatief; gids nl+en. Corpus: 119, alle in
  rehab-2.xer (= de 119 DUPLICATE_EXCEPTION-kalenders daar); baseline-issueTotals
  uitgebreid met die ene sleutel, bestaande tellers ongewijzigd.
8 — drie Nederlandse holidaynamen in het IFC ⇒ 'Calendar exception' /
  'Calendar exception (weekend reconstruction)'. De 124-dossierdigest in
  xer-calendar-hour-mode-baseline.json is herpind: hij hasht holidaynamen mee;
  datums, banden en tellers zijn identiek.
9 — `importSource` krijgt in de consentdialoog een vertaalde toelichting
  (`extConsent.permImportSource`, 14 talen); docblok genuanceerd.
10 — check-xer-archive-scale.ts bewaakt de serialisatieverhouding (≤ 1,6
  IFC-tekens per bronbyte, gemeten 1,33; marginaal 8→32 chunks idem) i.p.v.
  "eindig en positief".
11 — CLAUDE.md heeft een XER-sectie (bronarchief, bak 4, fail-closed p6Source,
  corpusmeting).
1/12/13 — niet gebouwd (eigenaar): onbegrensde archiefretentie (nu benoemd in
  de gids en TODO), moment van de exportverliesmelding, documentaantal-cap.

Poorten: typecheck, lint, planning (corpusloos), library, mcp, i18n, docs,
cycles groen; recorded-dates.spec.ts groen; mét corpus alleen de drie
X12-nuldoel-regels rood (15.056, ongewijzigd — geen solverwijziging in deze
commit).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…atums zoals opgeslagen' voor alle formaten, meetlat per formaat als aparte etappe

Vraag 1 van de eigenaarslijst is beantwoord (optie B: heropend eigen IFC automatisch in de
modus zolang het document sinds de import niet is bewerkt) en de eigenaar besloot daarbovenop
dat elk formaat zich als XER moet gedragen: automatisch de weergave aan bij afwijkingen, met
melding en strook, 'vergelijk wat er is' per formaat (ook CSV); de nul-afwijkingen-meetlat per
formaat volgt als aparte etappe (optie 3). Beide als etappe-items in docs/TODO.md, met de
gemeten huidige stand van de lezers (MSPDI/P6 XML/.mpp/CSV lezen alleen start/einde en vullen
late datums en speling), de volgorde en het beschikbare corpusmateriaal. Plan §10.f verwijst.
Niet gebouwd in deze PR.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
…e TODO; het mechanisme voor alle formaten wordt gebouwd (plan §10.f)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhTSYksdWG5Ljgg9hSZhW
@Nozzit
Nozzit marked this pull request as draft September 9, 2026 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants