Close Stage 5: exit audit, eight overstated verdicts, and PyFlow 0.1.0 - #48
Merged
Conversation
A separate auditor-stance pass over the thirteen-criterion verdict table TASK-034's own session wrote. Eight of the thirteen did not survive, and one of the eight was a defect in shipped behaviour rather than only in a verdict. Per-criterion record: docs/planning/roadmap.md's new Stage 5 status section, in the place all four prior stages put theirs (the generated status report had been flagging its absence on its own). Seven failures share one shape: a later clause of a criterion whose first clause was genuinely met. Criterion 13 names two ADR-003 substitution checks and only the PressureCoupling one existed -- register_linear_solver was never called outside assembly.py, so a PISO constructing its own solver would have passed everything (confirmed by mutation). Criterion 6 enumerates five rejection surfaces and four existed. Criterion 5's Ghia bullet ends by requiring a stated absolute tolerance and none was stated. Criterion 3's initial-divergence clause -- the one that stops the two assertions after it being vacuous -- was true and asserted nowhere. The eighth was real: simulation.velocity_solved meant two different things. With a scalar_pattern, bootstrap transported velocity's components like any other scalar and never pressure-corrected them, so a config saying "solved" produced a velocity that was not incompressible (max divergence 9.16 -> 8.24 -> 6.95 over 1/10/40 frames, against 2.30 -> 0.47 -> 0.057 corrected). Both tasks that touched it wrote the gap down -- in two CLAUDE.md files, and against no criterion, which is how it survived Criterion 12 being marked met. Fixed rather than recorded, at the maintainer's direction: both live paths call navier_stokes_step; a periodic boundary may no longer prescribe anything (the fourth rule of _validate_boundary_conditions_ jointly, scoped to non-default values); the Ghia cavity runs at a non-trivial origin with a stated, measured error bound at its finest resolution; and docs/planning/releases.md gains a real release process, cutting PyFlow 0.1.0 as the MVP release now that reaching the MVP has fired its own long-recorded trigger. Two checks were not doing their job. README's Current Phase had gone a full stage stale for the second time (the Stage 2 audit found the first), so it is now gated: generate_status_report.py fails make ci when the stage README names is not the roadmap's own frontier. And the Gherkin-scenario drift rule had been silently inert since a line wrap split its pattern -- the roadmap sat claiming 79 scenarios against a live 94, behind a green gate. All three claim patterns are now whitespace-tolerant, with a regression test. Also fixes six stale documentation claims in files no Stage 5 task opened, adds the Navier-Stokes timestep sequence to sequences.md (whose only job is runtime sequences and which had no mention of pressure at all), and records three new rules in docs/practices.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A separate auditor-stance pass (
prompts/common/AUDITOR.md) over thethirteen-criterion verdict table TASK-034's own session wrote as it
closed. Eight of the thirteen did not survive, and one of the eight
was a defect in shipped behaviour rather than only in a verdict.
Per-criterion record:
docs/planning/roadmap.md's new Status as of2026-08-29 section, placed where all four prior stages put theirs —
the generated status report had been flagging its absence on its own
("has no pending tasks recorded, but isn't marked complete").
Seven failures share one shape
Every one was a later clause of a criterion whose first clause was
genuinely met — a sentence the criterion had already written down.
PressureCouplingone existed.register_linear_solverwas never called outsideassembly.py, so aPISOconstructing its own solver would have passed every scenario in the repository. Confirmed by mutation, not argued.README.mdsaid "Stage 5 — not yet started" on the day Stage 5 closed.docs/architecture/sequences.md— whose only stated job is "in what order do things actually happen when PyFlow runs" — contained no mention of pressure, predictor, corrector ornavier_stokes_stepat all.mvp.mdnorreleases.mdrecorded the MVP as reached, thoughreleases.mdnames "Reaching the MVP" as a trigger it was told to act on the moment it fired.(0,0), lid speed1.0— three violations of the degenerate-fixture rule, taken and unrecorded.The eighth was real
simulation.velocity_solvedmeant two different things. With noscalar_pattern,_add_solved_velocity_renderingcallednavier_stokes_step. With one,_add_passive_scalar_transporttransported velocity's components like any other scalar and never
pressure-corrected them — so a configuration saying "solved" produced a
velocity that was not incompressible, with no error and nothing rendered
differently, selected by whether a scalar happened to be configured.
Measured rather than argued — maximum divergence over 1, 10 and 40
frames:
TASK-031 and TASK-034 both wrote the gap down — in two
CLAUDE.mdfiles,and against no criterion, which is how it survived Criterion 12 being
marked met.
docs/practices.mdgains the rule that distinction produced.Two checks that read like gates and were not
time (the Stage 2 audit found the first). Now mechanical:
generate_status_report.py's drift check failsmake ciwhen thestage README names is not the roadmap's own frontier. No second source
of truth — the roadmap decides, README is checked against it.
pattern needed a literal space before "are Gherkin scenarios"; a later
edit hard-wrapped the roadmap's line between the count and that phrase.
A pattern that stops matching reports nothing to check, which reads
exactly like a clean pass — the roadmap sat claiming 79 scenarios
against a live 94, behind a green gate. All three claim patterns are
now whitespace-tolerant, with a regression test quoting the real
wrapped sentence.
Four maintainer decisions, all taken the thorough way
releases.mdrewritten with a real process —semantic versioning with
MINORcarrying stage completion, a releasecut only after a stage's exit audit completes, an annotated tag on a
two-platform-green commit, nothing published anywhere yet (a recorded
decision, not an omission).
planning/data/releases.yamlpopulated forthe first time; its own stated trigger had fired.
_validate_boundary_conditions_jointly, scoped to non-default valuesso every periodic configuration already in the repository stays valid.
Six rejection tests, one acceptance test.
Re = 100 profiles are nondimensionalised on a unit square at unit lid
speed — two forced exceptions, now stated in the feature file. The
origin was never forced, and the cavity now runs at a non-trivial one.
Verified by a full three-resolution run first: identical errors
(0.1433, 0.0874, 0.0578), vortex centre 0.0010 from Ghia's own.
velocity_solved: routed through. Both live paths callnavier_stokes_step, with a regression test whose bound was chosenfrom both measurements above.
Verification
make cigreen locally: 688 tests, 95 scenarios across 21 featurefiles, every check passing (14m07s — the Ghia validation is ~13 of
them). Stage 5's own Criterion 9 is discharged by two real runs, both
green on
ubuntu-latestandwindows-latest:33269489214(PR #47) and33270312866(its merge tomain).This branch's own CI run is what the Merge Gate requires before it
merges — stated rather than assumed, since a local pass is not that
evidence. The
v0.1.0tag is deliberately not cut here: the process thisPR writes says a release is tagged on
mainafter the stage's exit auditcompletes, which is after this merges.
🤖 Generated with Claude Code