Logo FS-Skia-UI

Controls Boundary Refactor Process Report

This report captures the problems encountered while implementing specs/011-controls-boundary-refactor, with emphasis on process and tooling failures. The final feature work reached an implemented state, but the local aggregate verification path was degraded by memory and process pressure. The most important distinction is that focused product and governance gates passed, while the broad Verify and Ci aggregates failed in the local runner while starting test infrastructure.

Final Status

OOM And Process Pressure

The most disruptive process problem was local process exhaustion during broad test execution. Repeated ./fake.sh build -t Verify and ./fake.sh build -t Ci attempts reached the Test stage and then failed while starting Lib.Tests. The observed diagnostics included:

The failures were not assertion failures in the Controls implementation. They occurred before useful test execution, while the .NET test platform was trying to create processes, threads, sockets, or CoreCLR instances. The practical effect was that the local runner could no longer provide an authoritative broad aggregate signal without being reset.

Mitigations used during the work:

Recommended follow-up:

FAKE Runner And Package Cache Problems

Many successful FAKE target logs still began with:

Could not load types of compiled script: netstandard, Version=2.0.0.0...

Target execution usually continued after this message, so the line became noise that could obscure the real failure later in the log. It should be treated as a runner/tooling warning unless accompanied by a nonzero target exit.

Early in the work, local FAKE execution also failed because the package cache was missing FSharp.Core/6.0.7 under /home/developer/.nuget/packages. This blocked early Dev and generated guidance checks. The immediate mitigation was to restore the missing package through an ignored scratch project. After that, the affected focused checks could run far enough to expose real governance and implementation issues.

Recommended follow-up:

Target Graph Shape

The original target graph made several focused checks depend on broad build work. That increased memory pressure and made the feedback loop worse. A focused check could fail because the broad prerequisite exhausted the runner before the check itself had a chance to execute.

The clearest example was ControlsRenderingCheck. Under FAKE, the target was coupled to Build and used stale --no-build assumptions. Direct serial rendering tests passed, but the target path failed in the aggregate graph.

Mitigations used during the work:

Recommended follow-up:

Governance False Positives

Several governance checks found real process weaknesses in the check logic rather than product regressions.

Dependency Report

DependencyReport initially reported a Controls dependency leak on Lib. The cause was substring matching: the scanner saw Lib inside <OutputType>Library</OutputType>. The check was updated to inspect concrete ProjectReference and PackageReference patterns rather than arbitrary text.

Recommended follow-up:

Template Check

TemplateCheck initially failed on the generated sample-pack profile because the copied-content scanner treated intended sample-pack files under samples/ as forbidden framework sample content. The scanner now allows samples/ for the explicit sample-pack profile while still rejecting copied framework sample projects in ordinary generated products.

Recommended follow-up:

Generated Product Inventories

Generated file-list inventories initially did not include the product source markers expected by governance: RichText.create, LineChart.create, GraphView.create, DataGrid.create, and ControlsElmish.program. The inventories were expanded to include product source and tests, not only the outer generated file list.

Recommended follow-up:

Stale Boundary Evidence

The final stale scan found active references that contradicted the Controls ownership boundary:

These were resolved by updating .specify/memory/constitution.md, updating docs/reports/architecture.md, and removing the remaining tracked legacy Charts source and tests. After that cleanup, EvidenceAudit passed.

Recommended follow-up:

Evidence Handling

The evidence process worked, but it exposed a useful reporting rule: environment failures must be separated from product failures. The final aggregate logs were important, but they were not good evidence of broken Controls behavior because the failures happened while test infrastructure was starting.

What worked:

What should improve:

Recommended Next Steps

  1. Re-run ./fake.sh build -t Verify and ./fake.sh build -t Ci on a clean runner before treating the broad aggregate signal as final.
  2. Add a process-health preflight target that reports memory, process count, zombie count, thread limits, and relevant ulimit values.
  3. Keep focused gates independent and serial where they are most useful for local development.
  4. Replace remaining substring-based governance checks with syntax-aware parsing where practical.
  5. Keep generated product validation profile-aware, especially for sample-pack.
  6. Classify runner/bootstrap warnings separately from target failures so logs stay actionable.

Type something to start searching.