Skip to content

Fix the red eval gate, and the form-clone defect the stale row was hiding - #168

Merged
dynamics365ninja merged 1 commit into
mainfrom
fix/coverage-drift-form-clone
Aug 7, 2026
Merged

Fix the red eval gate, and the form-clone defect the stale row was hiding#168
dynamics365ninja merged 1 commit into
mainfrom
fix/coverage-drift-form-clone

Conversation

@dynamics365ninja

Copy link
Copy Markdown
Owner

Why CI is red

eval has been failing on main since #167 merged. All 51 cases passed — the failure is the job's second step:

{"ok":false,"error":{"code":"COVERAGE_DRIFT",
 "message":"eval/COVERAGE.md is stale — a family, capability, case or topic changed since it was generated."}}

#167 added the form-clone capability without regenerating eval/COVERAGE.md.

#165's red build-test (ubuntu) and knowledge-audit were not code. Both died before checkout on an Actions outage (Failed to resolve action download info. Error: Service Unavailable); macOS and Windows passed in the same run and both jobs are already green on main. Nothing to fix there.

The defect behind the stale row

Regenerating COVERAGE.md alone would have turned CI green while leaving form-clone at --T — shipped, untaught, unproven. Writing the missing eval case surfaced a real bug.

--rebind renamed the datasource and repointed the control-level <DataSource> nodes, but left the design's own <DataSource> and <TitleDataSource> naming a datasource the clone no longer has:

<DataSources>
  <AxFormDataSource xmlns="">
    <Name>FmVehicleLine</Name>          <!-- renamed -->
    <Table>FmVehicleLine</Table>        <!-- rebound -->
<Design>
  <DataSource xmlns="">FmVehicle</DataSource>        <!-- ← dangling -->
  <TitleDataSource xmlns="">FmVehicle</TitleDataSource>  <!-- ← dangling -->

A form that compiles and fails at runtime.

Cause. Those two are first-level children of <Design>, so they are written as <DataSource xmlns="">. The pattern was anchored on the bare "<DataSource>". The control-level ones nest under <Controls xmlns="">, inherit the namespace, appear bare — so they matched and the design ones did not. <JoinSource> was not handled at all, leaving a joined datasource pointing at its parent's old name.

The fix

The element list is grounded on the live installation rather than guessed. Across 300 shipped ApplicationSuite forms, these are the only elements whose value is a datasource name:

Element Occurrences Carries attributes
DataSource 6559 bare + 128 with design-level ones do
TitleDataSource 78 yes
WorkflowDataSource 4 yes
PresenceDataSource 1 no
JoinSource no

The rest of the *DataSource* family is either a container (DataSources, DataSourceLinks, ReferencedDataSources) or holds something else — DataSourceChangeGroupMode is an enum, DataSourceRelation names a relation. Names reached through a nested <Name> (root links, referenced/derived datasources) were already covered by the existing <Name> rewrite.

Matching now tolerates attributes and backreferences the closing tag, so it cannot bleed from DataSource into DataSourceLinks — there is a negative test for exactly that.

Why the tests missed it

The unit fixture's <Design> went straight to <AxFormControl>, so it never contained the nodes that break. It now carries the design properties and a joined datasource — which is what makes the four new tests fail before the fix and pass after.

The eval case

L2-form-clone-basic clones the two-datasource details-transaction form: 19 KB in, and the clone differs on exactly the root <Name> and the class declaration, byte-identical everywhere else. That is the guarantee worth locking for string surgery over a document this code does not own.

It is a plain clone rather than a rebind deliberately. MiniAot has only FmVehicle and FmVehicleLine: rebinding the simple form onto FmVehicleLine binds a <DataField>Make</DataField> that table does not have, and the richer form already uses both, so either golden would enshrine a form nobody should ship. The rebind path is covered by unit tests, which assert it more precisely anyway. Adding a third fixture table would let it graduate to an eval case — left as follow-up, since MiniAotEndToEndTests asserts the fixture's table count.

form-clone now reads -E T in COVERAGE.md, matching its control-method / datasource-method siblings.

Verification

All four CI jobs run locally:

Job Result
build-test build clean, 1178 tests pass (367 Cli + 811 Core)
knowledge-audit clean — 35 topics, 269 symbols, 61 examples, 0 defects
eval 52/52 cases, coverage --check green
skills no drift

🤖 Generated with Claude Code

…164)

The `eval` CI job has been red since #167 merged: `eval coverage --check`
reported COVERAGE_DRIFT because #167 added the `form-clone` capability
without regenerating eval/COVERAGE.md. (#165's red build-test and
knowledge-audit were an Actions outage — "Failed to resolve action
download info" — not code, and are already green on main.)

Writing the missing eval case surfaced a real defect in the capability
the stale row was hiding. `--rebind` renamed the datasource and repointed
the control-level <DataSource> nodes, but left the design's own
<DataSource> and <TitleDataSource> naming the datasource the clone no
longer has — a form that compiles and fails at runtime. The cause is that
those two are first-level children of <Design>, so they are written as
<DataSource xmlns="">, and the pattern was anchored on the bare
"<DataSource>"; the control-level ones nest under <Controls xmlns="">,
inherit the namespace, appear bare, and so were the only ones matched.
<JoinSource> was not handled at all, so a joined datasource kept pointing
at its parent's old name.

The element list is grounded on the live installation rather than guessed:
across 300 shipped ApplicationSuite forms, DataSource, TitleDataSource,
WorkflowDataSource, PresenceDataSource and JoinSource are the only
elements whose value is a datasource name — the rest of the *DataSource*
family is either a container or holds something else (
DataSourceChangeGroupMode is an enum, DataSourceRelation names a
relation). Matching now tolerates attributes and backreferences the
closing tag, so it cannot bleed from DataSource into DataSourceLinks.

The unit fixture's <Design> went straight to <AxFormControl> and so never
had the nodes that break — it now carries the design properties and a
joined datasource, which is what makes the four new tests fail before the
fix.

L2-form-clone-basic clones the two-datasource details-transaction form:
19 KB in, and the clone differs on exactly the root <Name> and the class
declaration and is byte-identical everywhere else, which is the guarantee
worth locking for string surgery over a document this code does not own.
It is a plain clone rather than a rebind because MiniAot has only
FmVehicle and FmVehicleLine: rebinding the simple form onto FmVehicleLine
binds a <DataField>Make</DataField> that table does not have, and the
richer form already uses both, so either golden would enshrine a form
nobody should ship. The rebind path is covered by the unit tests instead.
A fixture table would let it graduate to an eval case; left as follow-up.

Verified locally against all four CI jobs: build clean, 1178 tests pass,
knowledge audit clean, 52/52 eval cases with `coverage --check` green,
and no skills drift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SuTvn5ymx3HAUtGjsxBuaA
@dynamics365ninja
dynamics365ninja merged commit 1c1731e into main Aug 7, 2026
6 checks passed
@dynamics365ninja
dynamics365ninja deleted the fix/coverage-drift-form-clone branch August 7, 2026 05:18
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.

1 participant