Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 126 additions & 68 deletions docs/features/epics/build-ci-coverage-gate-fidelity/epic-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
Loading