fsharp-build-orchestration
Drive FAKE targets from the compiled front-end; golden-diff parity with DiffPlex; property/unit tests with Expecto + FsCheck.
- License 许可
- MIT
- 最近更新
- 2026-06-16
- Stars
- ★ 2
- Forks
- 0
01 前言 Front Matter
- name
- fsharp-build-orchestration
- metadata
- { "author": "fs-skia-ui", "source": "docs/reports/2026-05-31-1714-foundations-fsharp-capabilities-and-libraries.md" }
- description
- Drive FAKE targets from the compiled front-end; golden-diff parity with DiffPlex; property/unit tests with Expecto + FsCheck.
- compatibility
- F# governance library (build/Governance) + build/Build.fsproj under net10.0; build-tooling scope only.
03 SKILL.md 正文
fsharp-build-orchestration
Cookbook for the compiled build front-end, the parity gates, and the test harness. Owns C18
(build orchestration / CLI), C19 (golden-output text diffing), and C20 (property/unit
testing). Verdicts come from the capability report (metadata.source) §8.
When to use
- Registering and dispatching FAKE targets from the compiled
build/Build.fsprojexe (no FSX runner, no FCS). - The Stage-4/5 golden-parity gate: prove ported output is byte-identical to the Stage-0 fixtures.
- Unit- and property-testing the ported parsers/algorithms in
tests/Governance.Tests.
Library verdicts
- Orchestration / CLI (C18) →
Fake.Core.Target6.1.4 (present). The D2 spike proved it drives targets from the compiled exe with no FSX runner and noFSharp.Compiler.*transitive (FR-008). Dispatch viaTarget.runOrDefaultWithArguments; delegate each target body to a library function. Argu (typed CLI) and Spectre.Console (tables/colour) are optional — adopt only if theRouteCLI grows. - Golden diff (C19) → DiffPlex 1.9.0. Readable unified/side-by-side diffs for the parity gate and the Stage-2 generation-currency check. Adopt DiffPlex.
- Testing (C20) → Expecto 10.2.2 (in-tree) + FsCheck 3.3.3. Re-point moved-logic tests at the
real library functions (assert typed errors, not strings).
Expecto.FsCheckadds the ergonomictestProperty; until referenced, call FsCheck'sCheckdirectly inside an Expectotest.
API walkthrough + runnable examples
C18 — targets and dependency edges (Fake.Core.Target)
Target.create name body registers a target; ==> (from Fake.Core.TargetOperators) declares a
dependency edge. Bodies delegate to library functions so a mistyped target/predicate fails to compile.
open Fake.Core
open Fake.Core.TargetOperators
/// C18 — register two targets and the edge Build -> Test. Dispatch (elsewhere)
/// via Target.runOrDefaultWithArguments "Test".
let defineTargets () =
Target.create "Build" (fun _ -> ())
Target.create "Test" (fun _ -> ())
"Build" ==> "Test" |> ignore
C19 — golden-output parity gate (DiffPlex)
Every ported parser/algorithm/renderer must produce byte-identical output to the Stage-0 golden fixtures before the Python/Bash is deleted (Invariant 6). Return both the verdict and readable drift for the failure report.
open DiffPlex
open DiffPlex.DiffBuilder
open DiffPlex.DiffBuilder.Model
/// C19 — true when ported output equals the committed golden, with readable drift.
let goldenParity (golden: string) (ported: string) =
let model = InlineDiffBuilder(Differ()).BuildDiffModel(golden, ported)
let drift =
model.Lines
|> Seq.filter (fun line -> line.Type <> ChangeType.Unchanged)
|> Seq.map (fun line -> sprintf "%A | %s" line.Type line.Text)
|> Seq.toList
List.isEmpty drift, drift
C20 — unit tests (Expecto)
open Expecto
let parserTests =
testList "parser parity" [
test "task id is extracted from a well-formed line" {
let line = "- [X] T024 [skillist: []] do the thing"
let id = line.Split(' ') |> Array.tryItem 2
Expect.equal id (Some "T024") "the id token is the third field"
}
]
C20 — property tests (FsCheck inside Expecto)
Without Expecto.FsCheck referenced, call FsCheck's Check.QuickThrowOnFailure inside a normal
Expecto test — it throws on a counterexample (failing the test), exactly the gate behaviour. With
Expecto.FsCheck, prefer testProperty "name" prop.
open Expecto
open FsCheck
let propertyTests =
testList "graph properties" [
test "reverse is an involution" {
Check.QuickThrowOnFailure(fun (xs: int list) -> List.rev (List.rev xs) = xs)
}
]
Cautions
- FAKE concurrency: never run FAKE-backed targets concurrently (shared
.fakestate); use the deterministic serialized order fromCLAUDE.md/AGENTS.md. Expecto.FsCheckis a separate package —testPropertyneeds it; otherwise callCheckdirectly (as above).- Build-tooling scope. All packages are referenced by
build/**ortests/Governance.Tests, never shipped in a generated product; versions go inDirectory.Packages.props(Central Package Management). No FCS. - Record warm/cold build wall-clock vs the Stage-0 baseline; the compiled library should beat the 207 KB script recompilation.
Consuming stages
Stage 5 (compiled build front-end + routing), Stage 4/5 (golden-parity exit gates), all stages
(Expecto + FsCheck regression/property tests). See the plan in metadata.source.
Persistent problems
When a problem outlasts reasonable in-repo attempts, extensive external research is
mandatory — consult official online docs first (the F#/.NET docs and the driven
library's own documentation/API reference), then community sources (forums, Reddit, Q&A
sites, issue trackers and changelogs). Record the findings and resolving links in the
feature's specs/<feature>/feedback/ folder and, for durable lessons, in this skill's
Sources line. Offline, the mandate degrades to recording "research blocked — <why>"
rather than hard-failing the phase.
Sources / links
- Fake.Core.Target: https://fake.build/reference/fake-core-target.html
- DiffPlex: https://github.com/mmanela/diffplex
- Expecto: https://github.com/haf/expecto · FsCheck 3: https://fscheck.github.io/FsCheck/
- Capability report:
docs/reports/2026-05-31-1714-foundations-fsharp-capabilities-and-libraries.md§8.
Related
[[fsharp-parsing]], [[fsharp-graph-algorithms]] (the ported logic under test), [[fsharp-code-generation]] (DiffPlex also backs the currency check), [[fsharp-io-globbing]], [[fsharp-shell-process]] (the residual processes the front-end drives).
04 同仓库更多 Skills
fs-skia-ui-widgets
Generated product guidance for Skia-rendered FS.Skia.UI Controls, rich text, chart controls, graph controls, DataGrid, and custom wrappers.
fs-skia-testing
Assert generated-product expectations and evidence in a governed FS.Skia.UI product.
fs-skia-skiaviewer
Wire a generated FS.Skia.UI product to the desktop viewer host.
fs-skia-scene
Build pure scene descriptions in a generated FS.Skia.UI product.
fs-skia-keyboard-input
Map keyboard input to product commands in a generated FS.Skia.UI product.
fs-skia-elmish
Drive a generated FS.Skia.UI product through the pure Elmish adapter.