diff --git a/docs/features/epics/build-ci-coverage-gate-fidelity/epic-status.md b/docs/features/epics/build-ci-coverage-gate-fidelity/epic-status.md index 30ef8fe7..e818a4a7 100644 --- a/docs/features/epics/build-ci-coverage-gate-fidelity/epic-status.md +++ b/docs/features/epics/build-ci-coverage-gate-fidelity/epic-status.md @@ -5,25 +5,31 @@ this file is regenerated by `epic-orchestrator` at epic kickoff, at every `merge transition, at every wave transition, and at final integration-PR completion. The checkpoint JSON is the machine-authoritative source; `epic.md` is the human-authored manifest and narrative. -- Integration branch: `epic/build-ci-coverage-gate-fidelity-integration` +- Integration branch: `epic/build-ci-coverage-gate-fidelity-integration` (merged, retired) - Manifest: `docs/features/epics/build-ci-coverage-gate-fidelity/epic.md` -- Current wave: 2 (all waves complete; awaiting integration PR) -- Last updated: 2026-08-14T22-55 +- Status: **COMPLETE** — all three waves fanned in, integration PR #566 merged to `main` +- Last updated: 2026-08-15T05-52 -This projection was regenerated from `git` and `gh` rather than from -`artifacts/orchestration/epic-orchestrator-state.json`, which is not present in this worktree. Per -the cache doctrine, the checkpoint is a cache of durable state and `git worktree list`, -`git branch`, and `gh pr view` are authoritative when the two disagree. +The `features[]` rows below were reconstructed from `git` and `gh` rather than observed at the time +they occurred, because the original run completed without persisting an epic checkpoint. Per the +cache doctrine, `git worktree list`, `git branch`, and `gh pr view` are authoritative when the +checkpoint and the repository disagree. `merge_confirmed_at` values come from `gh` `mergedAt` and +are authoritative; `worktree_created_at` and `pr_opened_at` are best-effort reconstructions. ## Features | feature_folder | issue_num | wave | merge_status | pr_url | merge_commit_sha | worktree_created_at | pr_opened_at | merge_confirmed_at | worktree_removed_at | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| 2026-08-10-cobertura-coverage-arithmetic-441 | 441 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/538 | fb257cd6e0c56cbf5eacf7e6a73641cc0414c930 | 2026-08-11T02-28 | 2026-08-11T03-45 | 2026-08-11T04-00 | 2026-08-11T04-01 | -| 2026-08-10-csharp-toolchain-gate-fidelity-512 | 512 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/540 | 22eaee849263515e4a66e0f654baf162a27018b2 | 2026-08-11T02-28 | 2026-08-11T03-55 | 2026-08-11T04-20 | 2026-08-11T04-21 | -| 2026-08-10-utilitiescs-test-cs2002-duplicate-compile-entry-394 | 394 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/533 | c1fe3565a8677184831a4e33917852cd02f8d521 | 2026-08-11T02-28 | 2026-08-11T03-20 | 2026-08-11T03-32 | 2026-08-11T03-35 | -| 2026-08-10-excludefromcodecoverage-nested-lambdas-457 | 457 | 1 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/542 | ee082ba1c078c5f2721b3ef5306172047daa1a09 | 2026-08-11T04-05 | 2026-08-11T05-35 | 2026-08-11T05-50 | 2026-08-11T05-51 | -| 2026-08-10-coverage-threshold-policy-reconciliation-494 | 494 | 2 | merged | https://github.com/drmoisan/TaskMaster/pull/551 | 85ff0c34a60b13e0399fc7a6c8e4f9ded7e397f0 | 2026-08-11T05-55 | 2026-08-13T21-13 | 2026-08-15T02-27 | — | +| 2026-08-10-cobertura-coverage-arithmetic-441 | 441 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/538 | fb257cd6e0c56cbf5eacf7e6a73641cc0414c930 | 2026-08-11T02-28 | 2026-08-11T03-45 | 2026-08-11T03-51 | 2026-08-11T04-01 | +| 2026-08-10-csharp-toolchain-gate-fidelity-512 | 512 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/540 | 22eaee849263515e4a66e0f654baf162a27018b2 | 2026-08-11T02-28 | 2026-08-11T03-55 | 2026-08-11T04-00 | 2026-08-11T04-21 | +| 2026-08-10-utilitiescs-test-cs2002-duplicate-compile-entry-394 | 394 | 0 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/533 | c1fe3565a8677184831a4e33917852cd02f8d521 | 2026-08-11T02-28 | 2026-08-11T03-20 | 2026-08-11T03-26 | 2026-08-11T03-35 | +| 2026-08-10-excludefromcodecoverage-nested-lambdas-457 | 457 | 1 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/542 | ee082ba1c078c5f2721b3ef5306172047daa1a09 | 2026-08-11T04-05 | 2026-08-11T05-35 | 2026-08-11T05-41 | 2026-08-11T05-51 | +| 2026-08-10-coverage-threshold-policy-reconciliation-494 | 494 | 2 | worktree_removed | https://github.com/drmoisan/TaskMaster/pull/551 | 85ff0c34a60b13e0399fc7a6c8e4f9ded7e397f0 | 2026-08-11T05-55 | 2026-08-13T21-13 | 2026-08-15T02-27 | 2026-08-15T05-01 | + +Feature 457 has a second merged pull request from the same head branch, **#543** (`8d0d1fec`, merged +2026-08-11T05-44). It is a `chore(memory)` commit recording two orchestrator lessons from the #457 +child run, in the same class as #534, #539, and #541 — not a second delivery pull request. #542 is +the delivery PR and is the one recorded above. ## Waves @@ -37,80 +43,132 @@ the cache doctrine, the checkpoint is a cache of durable state and `git worktree | field | value | | --- | --- | -| head | `epic/build-ci-coverage-gate-fidelity-integration` | +| pr | [#566](https://github.com/drmoisan/TaskMaster/pull/566) | +| head | `epic/build-ci-coverage-gate-fidelity-integration` @ `3e61c67e` | | base | `main` | -| pr_url | — | -| ci_gate | — | -| merge_commit_sha | — | -| merged_at | — | +| ci_gate | **success** — [run 31867645467](https://github.com/drmoisan/TaskMaster/actions/runs/31867645467), head `3e61c67e`, all 5 required checks passed on first run | +| merge_commit_sha | `8bd23551e30649899f02f121f614f9007482000f` | +| merged_at | 2026-08-15T05:49:25Z | + +Required check results, matching the `main` ruleset contexts exactly: -## Verification Note — CI Coverage of Child PRs +| context | result | duration | +| --- | --- | --- | +| `actionlint / actionlint` | pass | 34s | +| `format-check / Verify formatting` | pass | 1m54s | +| `build-analyzers / Build with analyzers and code style enforcement` | pass | 2m57s | +| `build-nullable / Build with nullable warnings treated as errors` | pass | 2m45s | +| `mstest-coverage / Run MSTest suite with coverage` | pass | 4m23s | -`.github/workflows/ci.yml` triggers `pull_request` only on `[main, development]`. A child PR whose -base is `epic/build-ci-coverage-gate-fidelity-integration` is therefore ineligible for every -workflow and receives an empty `statusCheckRollup`. Child merge-on-green degrades to local -CI-equivalent verification recorded as feature evidence. The integrated tree is gated separately by -a `workflow_dispatch` CI run against the integration branch at each wave boundary, and the final -integration-to-`main` PR receives full CI because it is `main`-based. +The run `head_sha` equals the pull request `head_sha`, so CI was observed against the live head. +This is the first full-suite CI signal covering feature 494 and the `main` merge at `fb8eff9b`. -## Integrated-Tree CI Gate +## Fan-In Review -Child PRs based on the integration branch are ineligible for `ci.yml` (its `pull_request` trigger -lists only `[main, development]`), so the integrated tree is gated separately by `workflow_dispatch` -runs against the integration branch. +The composed 404-file integration diff and the hand-resolved conflicts in the `main` merge at +`fb8eff9b` had never been reviewed — each child was reviewed only against the integration branch. +Two independent `feature-review` passes were run against base `main` at merge-base `0569ac0b`: -| run | head | features covered | conclusion | +| pass | artifacts | Blocking | Major | | --- | --- | --- | --- | -| [31456943481](https://github.com/drmoisan/TaskMaster/actions/runs/31456943481) | `1c221399` | 394, 441/478 | failure — one intermittent case, see below | -| [31493339489](https://github.com/drmoisan/TaskMaster/actions/runs/31493339489) | `c7d398c2` | 394, 441/478, 512/492/509/522, 457 | **success** (actionlint + full build/analyze/test) | +| 1 | `policy-audit` / `code-review` / `feature-audit` `.2026-08-15T05-11.md` | 0 | 5 | +| 2 | `policy-audit` / `code-review` / `feature-audit` `.2026-08-15T05-25.md` | 0 | 5 | + +Both confirmed the `fb8eff9b` conflict resolutions dropped no incoming hunk from `main`. No +`remediation-inputs` artifact was written by either pass, which is the on-disk confirmation of zero +blocking findings. An `epic-review` pass (`epic-audit.2026-08-15T09-30.md`) found no acceptance +criterion whose check-off state is unsupported by evidence; all 67 ACs across the five `full-bug` +specs evaluate PASS. + +Local Pester on the integrated tree: 70/70 passing +(`evidence/qa-gates/pester-integrated-tree.2026-08-15T05-10.md`). -Run 31493339489 is the first green full-CI signal for any of this epic's work. +## Known Gaps Merged With This Epic -**The tree has moved since that green run.** Two changes landed after `c7d398c2`: feature 494 -(PR #551, merge commit `85ff0c34`) and a merge of `main` (`fb8eff9b`) that brought in the CI -parallel job split (#553, PR #556) and the `TimeOutTask` changes. Neither is covered by run -31493339489, and the job split replaced `ci.yml`'s inline steps with the reusable -`_actionlint` / `_format-check` / `_build-analyzers` / `_build-nullable` / `_mstest-coverage` -workflows, so the check-run names differ from those in the table above. The integration PR against -`main` is the gate for the current tree; no separate `workflow_dispatch` run is needed for it. +Filed rather than absorbed, because remediating them inside a fan-in would widen its scope. + +| gap | issue | +| --- | --- | +| The coverage-threshold contradiction was **not** removed. `CLAUDE.md` and `.claude/rules/csharp.md` say 80%; `.claude/rules/general-unit-test.md` and `.claude/rules/quality-tiers.md` say 85%/75%. `Assert-CoberturaLineCoverageThreshold` enforces 80% while `validate-feature-review-coverage.ps1` fails below 85, so a figure in [80, 85) passes one live gate and fails the other. | [#563](https://github.com/drmoisan/TaskMaster/issues/563) | +| `CLAUDE.md` cites `ci.yml` for three toolchain commands the #553 split relocated into reusable workflows. | [#564](https://github.com/drmoisan/TaskMaster/issues/564) | +| `Invoke-MSTestWithCoverage.ps1` asserts the threshold before `Set-Content`, leaving the raw un-post-processed Cobertura on disk when the gate fails. | [#565](https://github.com/drmoisan/TaskMaster/issues/565) | +| CI collects coverage but enforces no threshold: `_mstest-coverage.yml` never converts to Cobertura or compares a floor. | [#561](https://github.com/drmoisan/TaskMaster/issues/561) | +| No Pester job in CI, so this epic's four PowerShell scripts have zero CI coverage. | [#562](https://github.com/drmoisan/TaskMaster/issues/562) | + +Because of #563, leading indicator 2 of the epic `intent` block ("a deliberately introduced coverage +regression fails the documented coverage gate") is only **partially discharged**: the gate does +mechanically fail a regression, but at a threshold that disagrees with two of the three documents +#494 was chartered to reconcile. Leading indicators 1, 3, and 4 are fully discharged. + +Repository-wide PowerShell line coverage measures roughly 69-72% against the 85% floor. The reviewer +dispositioned this non-blocking: the shortfall sits entirely in five never-tested scripts absent from +this epic's diff, changed-line coverage is 100%, and the branch raises the figure from roughly 67.2%. + +## Checkpoint Completion Status + +The epic checkpoint passes plain validation. It **cannot** pass `require_complete`, which demands a +per-feature `launch_binding` carrying `worktree_path`, `launch_receipt_path`, `launch_status_path`, +`delegation_receipt`, and `model_routing_receipt` — 25 errors, five per feature. + +That launch evidence was never produced: the five children were launched in an earlier session that +did not persist an epic checkpoint, `artifacts/orchestration/epic-child-launches/` does not exist, +`artifacts/` is gitignored so nothing survived in history, and every child worktree was removed +before the fan-in session began. The gap is recorded rather than closed, because populating it would +mean asserting launch evidence that never existed. The other three completion requirements are +satisfied and independently verifiable from `git` and `gh`. ## Dispositioned: Main-Inherited Intermittent Test `TimeoutAfter_GenericTask_ShouldPropagateFaultedSourceException_WhenSourceFaultsLater` -(`UtilitiesCS.Test/Threading/TimeOutTask_AdditionalTests.cs:12`) was raised as a blocker for the -final gate. It is now dispositioned as **confirmed intermittent, pre-existing, and not a blocker to -this epic**, on four samples against unchanged test code: +(`UtilitiesCS.Test/Threading/TimeOutTask_AdditionalTests.cs:12`) is **confirmed intermittent, +pre-existing, and not a blocker to this epic**, on five samples against unchanged test code: | ref | run | result | | --- | --- | --- | | `main` @ `cee6a1ca` | 31379345104 | pass | -| `main` @ `a682c7a2` (this branch's base) | 31409582674 | fail — this single case, 6435 total | +| `main` @ `a682c7a2` | 31409582674 | fail — this single case, 6435 total | | integration @ `1c221399` | 31456943481 | fail — this single case, 6435 total | | integration @ `c7d398c2` | 31493339489 | pass — full suite | +| integration @ `3e61c67e` | 31867645467 | pass — final integration PR, full suite | The failure originates on `main` and is timing-dependent; no feature in this epic introduces or -worsens it. The underlying defect is nonetheless real and remains open: the test races a 100 ms real -wall-clock timeout (`source.Task.TimeoutAfter(100)`) against fault propagation from a -`TaskCompletionSource`, so under load the timer wins and the proxy throws the timeout instead of the -expected `InvalidOperationException`. That violates the determinism requirements in -`.claude/rules/general-unit-test.md`, which ban real wall-clock waits in tests and require a -`FakeTimeProvider` or virtual scheduler. Three sibling tests in the same file share the pattern. - -It is out of scope for every child of this epic and is recorded here rather than silently absorbed. -If the final integration PR trips it, the correct response is a re-run plus this record — never a -threshold or gate adjustment. - -## Issues — Pending Closure - -Nine issues across five features: 441 and 478 (feature 441); 492, 509, 512 and 522 (feature 512); -394; 457; 494. Issue 513 is out of scope and must be fixed upstream in the `drm-copilot` -repository. - -All nine are **still open** on GitHub as of 2026-08-14. This is structural, not an oversight: -GitHub auto-closes a referenced issue only when the closing PR merges into the repository's default -branch, and every child PR in this epic targeted the integration branch instead. The child work is -merged; the issue records simply have not been closed by it. - -They close when the integration PR merges into `main`, which makes that PR's closing-keyword list a -correctness-critical artifact rather than boilerplate. If any issue remains open after that merge, -close it manually against the integration merge commit. +worsens it. The underlying defect remains real and open: the test races a 100 ms real wall-clock +timeout (`source.Task.TimeoutAfter(100)`) against fault propagation from a `TaskCompletionSource`, +violating the determinism rules in `.claude/rules/general-unit-test.md`, which ban real wall-clock +waits and require a `FakeTimeProvider` or virtual scheduler. Three sibling tests share the pattern. +It did not trip on the final integration run. + +## Issues — Closed + +All nine closed automatically as `COMPLETED` when PR #566 merged into `main` at 2026-08-15T05:49:25Z: + +| issue | feature | closed_at | +| --- | --- | --- | +| 441, 478 | 441 | 2026-08-15T05:49:26Z / 05:49:27Z | +| 492, 509, 512, 522 | 512 | 2026-08-15T05:49:27Z / 05:49:28Z | +| 394 | 394 | 2026-08-15T05:49:28Z | +| 457 | 457 | 2026-08-15T05:49:28Z | +| 494 | 494 | 2026-08-15T05:49:28Z | + +They stayed open through the entire epic because every child pull request targeted the integration +branch, and GitHub auto-closes only on merge into the default branch. The closing keywords in the +#566 body were therefore the sole mechanism that closed them. + +Issue 513 is out of scope and must be fixed upstream in the `drm-copilot` repository. The PR-context +collector additionally drops all 55 `.claude/agent-memory/**` files from its classification, +accounting for only 344 of 404 changed files — a further data point for that issue. + +## Retained Branches + +Two local-only branches were deliberately not deleted during cleanup because they are not fully +merged. Neither has a remote counterpart. + +| branch | commits absent from integration head | without patch-equivalents | disposition | +| --- | --- | --- | --- | +| `backup/494-accidental-main-rebase` | 58 | 11 | retain pending maintainer review | +| `recovery/494-pre-main-rebase` | 10 | 0 | safe to delete | + +The 11 commits unique to `backup/494-accidental-main-rebase` are all superseded 2026-08-10 +preparation snapshots — in-progress preparation outputs, round-2 plan revisions, and agent-memory +records. The one substantive-looking commit, `94f21408 fix(toolchain)`, landed in the epic through +PR #540 as a different commit. Nothing substantive is stranded on either branch.