@@ -1121,22 +1121,57 @@ Surfaced as background findings while building the quartets above, not something
11211121needs to re-derive. Candidate real fixes, independent of whether the architecture-exploration
11221122track above goes anywhere:
11231123
1124- - ** Generated code is invisible to the IDE until a real build — partially addressed, see item 8 /
1125- Q022.** ` MyriadSdkGenerateCode ` is gated ` Condition="'$(DesignTimeBuild)' != 'true'" ` and
1126- ` MyriadSdkIncludeCodegenOutputDuringDesignTimeBuild ` is an empty target
1127- (` src/Myriad.Sdk/build/Myriad.Sdk.targets ` ). Both the type-provider route (Q006, REVISE — structurally
1128- can't reach a same-project attributed type) and the direct DTB-hook route (` Q022 ` , REVISE — real
1129- mechanism, real capability against a literal FSAC process, but only at project load/reload time, not
1130- live source editing) have now been tried; see item 8 above for the full Q022 account. Removing the
1131- gate in ` src/ ` for real would be a genuine, well-understood, low-risk fix for the load/reload case
1132- (Round 1 confirmed it never breaks DTB and the existing rebuild cache still governs cost correctly),
1133- not yet applied to the shared ` src/Myriad.Sdk/build/Myriad.Sdk.targets ` itself — that remains a real
1134- candidate change, separate from and cheaper than any further spike, worth doing regardless of whether
1135- the live-source-edit half is ever solved.
1136- - ** Codegen runs one cold process per input file.** ` MyriadSdkGenerateCode ` 's
1137- ` Outputs="%(MyriadCodegen.OutputPath)" ` triggers MSBuild's per-item batching, so the target (and
1138- its ` <Exec> ` ) runs once per file, each paying full JIT + Fantomas-parse startup cost. Fixable
1139- without touching the plugin API: batch the CLI invocation, or publish it ReadyToRun/AOT.
1124+ - ** Generated code is invisible to the IDE until a real build — DTB gate removed for real,
1125+ 2026-07-17 (see item 8 / Q022 for the full mechanism account).** ` MyriadSdkGenerateCode ` 's
1126+ ` Condition="'$(DesignTimeBuild)' != 'true'" ` gate and the empty
1127+ ` MyriadSdkIncludeCodegenOutputDuringDesignTimeBuild ` target are both gone from the real, shared
1128+ ` src/Myriad.Sdk/build/Myriad.Sdk.targets ` — not just the Q022 scratch copy. Re-verified directly
1129+ against this repo's own test project via a real `-p: DesignTimeBuild =true
1130+ -p: SkipCompilerExecution =true` invocation: codegen runs, the compiled ` .dll`'s mtime never moves
1131+ (the real F# compiler is never invoked), and a repeat DTB call still correctly no-ops. Still only
1132+ closes the gap at project load/reload time, exactly as Q022 found — an ordinary source-file save
1133+ does not itself re-run codegen in an already-running IDE session; only a project reload does.
1134+ - ** Codegen runs one cold process per input file — SHIPPED, 2026-07-17.** ` MyriadSdkGenerateCode ` now
1135+ runs Myriad exactly once per project (not once per file) via a new ` --manifest <file>.toml ` CLI
1136+ mode: MSBuild writes one small TOML file (one ` [[unit]] ` table per attributed file, built in a new
1137+ ` _MyriadSdkFlattenParams ` target) and a single ` <Exec> ` processes all of them in one process,
1138+ loading plugins once. This was not a pure size-preserving refactor — the old per-item
1139+ ` Outputs="%(MyriadCodegen.OutputPath)" ` batching turned out to already be a false promise of
1140+ per-file incrementality: ` _MyriadSdkCodeGenInputCache ` is one combined hash over every codegen
1141+ input, so editing any single attributed file already forced every other generated file to
1142+ regenerate too (confirmed directly: editing one file caused four unrelated generated files to be
1143+ rewritten). Batching into one process therefore loses no real granularity, only removes N-1
1144+ redundant cold-process launches. Two non-obvious MSBuild traps found only by testing end-to-end,
1145+ not by reasoning about the XML: a ` <Target> ` 's own ` Condition ` is evaluated * before* its
1146+ ` DependsOnTargets ` /` BeforeTargets ` chain runs, so a naive ` Condition="'@(MyriadCodegen)' != ''" `
1147+ guard always saw an empty list and skipped the whole target, silently — the guard has to live on
1148+ the ` <Exec> ` task itself instead; and forcing MSBuild to batch a helper target per-item has to key
1149+ off ` %(MyriadCodegen.OutputPath) ` (guaranteed unique per ` <Compile> ` item), not
1150+ ` %(MyriadCodegen.Identity) ` (the * input* file, which several different ` <Compile> ` items can
1151+ legitimately share via ` MyriadFile ` ) — keying on the wrong one silently merged multiple files'
1152+ ` MyriadParams ` /` Generators ` together. Full account: ` DEVNOTES.md ` 's "Why one process, not one per
1153+ file" and "A target's ` Condition ` runs before its own dependencies" sections. All 58 existing tests
1154+ plus ` samples/Example ` verified passing; committed as ` 793bc98 ` .
1155+ - ** The project-context TOML writer no longer depends on MSBuild's implicit ` ; ` -splitting of
1156+ ` Include ` attributes — SHIPPED, 2026-07-17.** ` _MyriadContext ` 's multi-line TOML arrays
1157+ (` referencePaths ` , ` compile ` , etc.) used to be built as ` [;$(_ReferencePaths);] ` , relying on
1158+ MSBuild silently splitting that one string into three separate items at the unescaped ` ; `
1159+ characters so ` WriteLinesToFile ` would render them across multiple physical lines — the same class
1160+ of fragility this repo's own git history already shows repeated fixes for ("escape with a single
1161+ apostrophe," "try msbuild escaping targets," "fix for windows (again)"). Replaced with explicit
1162+ ` %0a ` -embedded construction. Verified: item counts round-trip exactly (11 compile items matching 9
1163+ explicit ` <Compile> ` entries plus MSBuild's 2 auto-generated assembly-info files), and a real
1164+ embedded comma inside a path (` ...AssemblyAttributes.fs ` ) doesn't break parsing, since the
1165+ single-quoted TOML literal-string quoting (unchanged) protects it regardless of the outer
1166+ delimiter mechanism. Committed as ` 793bc98 ` .
1167+ - ** ` Myriad.Sdk.targets ` ' ` OutputPath ` for ` MyriadInlineGeneration ` files had a stray trailing ` ) ` —
1168+ FIXED, 2026-07-17.** Left over from a 2022 refactor (` c818a70 ` ) that removed a
1169+ ` [System.IO.Path]::GetFullPath(...) ` wrapper but left its closing paren behind, producing an
1170+ ` OutputPath ` metadata value that could never exist on disk. Since that value fed directly into
1171+ MSBuild's own up-to-date check for the target, every build regenerated every
1172+ ` MyriadInlineGeneration ` file regardless of whether anything had changed — confirmed by a direct
1173+ before/after comparison (4 of 5 vs. 5 of 5 batched items correctly skipped on a no-op rebuild).
1174+ One-character fix; committed as ` 793bc98 ` .
11401175- ** No ` #line ` pragmas in generated output.** Errors in generated code point at the generated
11411176 file, not the source declaration that produced it. Cheap, mechanical fix.
11421177- ** Config lives behind an indirection.** An attribute carries a string key, which is looked up
0 commit comments