Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
282 commits
Select commit Hold shift + click to select a range
274b8e0
Q8.33 split the fallback carriers; Q8.32(b) end the silent name drop
multiarc Jul 26, 2026
1c9436e
Rule Q8.37 (remove auto-loading in 2.1); close Q8.38 as not a question
multiarc Jul 26, 2026
9dec618
Q8.35: fold the schema-tracks-breakage rule into the window policy
multiarc Jul 26, 2026
eaf6ac0
Q8.9: map documentation authority as D10; Q8.10: reject phase 8's D9
multiarc Jul 26, 2026
775a82d
Consolidate Q8.32/Q8.33 into the 2.1 record; file Q8.39 (window confl…
multiarc Jul 26, 2026
ac8fa87
Ignore .claude/ (agent worktrees, local session state)
multiarc Jul 26, 2026
9308f4b
Land Q8.17 and Q8.19; close Q8.14 as not implementable
multiarc Jul 26, 2026
3412e2b
Q8.32 subset A: validate everything once, after configuration
multiarc Jul 26, 2026
a280f05
Thin the Q&A register to one final answer per entry
multiarc Jul 26, 2026
c95361f
Rule Q8.39 (2.1 is a window) and Q8.40 (E9 governs inputs)
multiarc Jul 26, 2026
fce234a
Schedule the two unowned docs residues as phase 8 WI16 and WI17
multiarc Jul 26, 2026
3864fba
Revert the corpus relocation; test inputs stay in TestTemplate
multiarc Jul 26, 2026
32c240c
Revise phase-7 D1: the corpus does not move
multiarc Jul 26, 2026
90b6ddc
Add the comment rule to coding standards; strip citations I wrote
multiarc Jul 26, 2026
1814ec9
Phase 7 stage 0: the sharing mechanism, without moving the corpus
multiarc Jul 26, 2026
2e9c207
Pin line endings for the relocated artifacts folder
multiarc Jul 26, 2026
b0595ef
Comments exist only when the code cannot carry the meaning
multiarc Jul 26, 2026
d685d9d
Consolidate the comment requirements into one rule set (C1-C8)
multiarc Jul 26, 2026
8060352
Sweep comments across the repo to the C1-C8 rules
multiarc Jul 26, 2026
3081cbc
Comment sweep, pass two: the files pass one left behind
multiarc Jul 26, 2026
9f13672
Rule Q8.42-Q8.44: share what is shared, leave the rest alone
multiarc Jul 26, 2026
d70e04c
Comment sweep, pass three: the last dense files
multiarc Jul 26, 2026
789581a
Finish the citation sweep: the 17 files the swarm could not
multiarc Jul 26, 2026
dc89ce8
Simplify comments: delete what earns nothing, shorten the rest
multiarc Jul 26, 2026
41ea57d
Remove assembly auto-loading; extensions come from explicit registration
multiarc Jul 26, 2026
d0e2437
Record the auto-loading removal and rewrite the docs that promised di…
multiarc Jul 26, 2026
a57c9da
Give the marker tier a member: the corpus gains an unresolvable-funct…
multiarc Jul 26, 2026
3f5c72d
Close phase 7 on the Q8.42 ruling and correct the duplicates claim in…
multiarc Jul 26, 2026
e495121
Extend the comment rules to build files and to emitted doc comments
multiarc Jul 26, 2026
7a2c4d9
State that the comment rules cover build files and emitted comments
multiarc Jul 26, 2026
606723b
Correct the four false claims in native-expressions.md
multiarc Jul 26, 2026
ad320a7
Correct the imprecise normative claims in native-expressions and prec…
multiarc Jul 26, 2026
0ff9940
Document every shipped diagnostic id, and gate that it stays documented
multiarc Jul 26, 2026
ba2afc6
Retract the 1.x-manifest rejection claim and the verbatim-doc coupling
multiarc Jul 26, 2026
49fe64d
Narrow documentation authority in the ledger, and mark what is verified
multiarc Jul 26, 2026
3922626
Carry the 2.1 breaks into the CHANGELOG, and fix two contradicted claims
multiarc Jul 26, 2026
3d4784e
Gate the documented option surface and the extension's defaults
multiarc Jul 26, 2026
e9249d1
Gate documented member mentions against the public-API golden
multiarc Jul 26, 2026
8fdc204
Gate documentation links and line citations
multiarc Jul 26, 2026
0e9d307
Land the documentation-currency rule and close phase 8
multiarc Jul 26, 2026
74a1b33
Track the agent-instruction drafts; ignore BenchmarkDotNet's output d…
multiarc Jul 26, 2026
b65df6f
Re-ratify the codegen sample's golden for the emitted doc comments
multiarc Jul 26, 2026
85a4df9
Close the gate holes the completion review demonstrated
multiarc Jul 26, 2026
1efdc05
Fix the registration race an adversarial review reproduced
multiarc Jul 26, 2026
4cef739
Fix the single-file and load-order defects, and the false claims arou…
multiarc Jul 26, 2026
2f23ff9
Record the independent review and what it says about the pins
multiarc Jul 26, 2026
4006c11
Give the C# tier metadata it can actually reach, and stable diagnostics
multiarc Jul 27, 2026
6b82a43
Make observation notice an unload followed by a load
multiarc Jul 27, 2026
0851b03
Honour the benchmark project's change-nothing ruling; pin the no-load…
multiarc Jul 27, 2026
09da690
Report an import cycle instead of dying on it
multiarc Jul 27, 2026
0ca41ff
Stop the generated tier rejecting templates the engine renders
multiarc Jul 27, 2026
8dea3aa
Guard the parse walk's depth; record the second review
multiarc Jul 27, 2026
1678984
Bound parse depth by count, in both tiers
multiarc Jul 27, 2026
d7a1bc2
Fix what the third review found, including two regressions of mine
multiarc Jul 27, 2026
15b06c7
Fix the fold's uint conversion and set the depth bound where it can fire
multiarc Jul 27, 2026
b774e7a
Pin the depth limit; close two more fold divergences
multiarc Jul 27, 2026
d9720f6
Measure the depth bound in the configuration it ships in
multiarc Jul 27, 2026
5734086
Delete a guard that never fired, and stop claiming member paths are free
multiarc Jul 27, 2026
f34b76c
Bind a null-safe hop's receiver once instead of copying it
multiarc Jul 27, 2026
b1cca37
Bound how many @<< imports one parse expands
multiarc Jul 27, 2026
49325dc
Decide shifts, bitwise operators and constant conditionals in the fold
multiarc Jul 27, 2026
d415f02
Give the compile-item catch-all an id and a message that says something
multiarc Jul 27, 2026
6f2909c
Report an unreadable @<< import instead of throwing out of the parse
multiarc Jul 27, 2026
ac1caef
Identify an import the way the reader resolves it
multiarc Jul 27, 2026
08e9b96
Drop the C#-tier preparse cache when model assemblies go
multiarc Jul 27, 2026
5b0745e
Take one parse's import state off the shared settings object
multiarc Jul 27, 2026
3da35dc
Close the P3 findings: two unpinned properties, three stale texts, on…
multiarc Jul 27, 2026
0053dd0
Stop emitting ?. on a type that has no nullable form
multiarc Jul 28, 2026
25b1f76
Give a parse begun inside an import reader its own state
multiarc Jul 28, 2026
bb05287
Close the confirmed divergences: null-safe chains, cache epoch, unmea…
multiarc Jul 29, 2026
9685dec
Fix the regression the last commit introduced, and six defects found …
multiarc Jul 29, 2026
287ea9a
Close the three the eighth cycle left open
multiarc Jul 29, 2026
46ef9f8
Wrap embedded C# too, widen three guards that were narrower than thei…
multiarc Jul 29, 2026
330e8ad
Key the path memo on symbols, and refuse three more names the consume…
multiarc Jul 29, 2026
259127c
Answer the type-nameability question once instead of enumerating it
multiarc Jul 29, 2026
e0df426
Mirror the engine's dynamic-slot rule instead of guessing it
multiarc Jul 29, 2026
f47118b
Type a dynamic definition body by the value its caller passes
multiarc Jul 30, 2026
774fa6f
Tell "the emitter cannot say" apart from "the engine has no type"
multiarc Jul 30, 2026
cb15192
Read a prop before the model inside a native expression
multiarc Jul 30, 2026
3c62923
Carry the caller's layout into caller content, and its text into a chain
multiarc Jul 30, 2026
f02e2a3
Ask an extension what it accepts instead of guessing from the value
multiarc Jul 30, 2026
45a9308
Ask the shared type facts what the runtime accepts
multiarc Jul 30, 2026
71c857d
Give a region body its host's model, not just its host's props
multiarc Jul 30, 2026
8f30d02
Share one region body where the engine compiles one
multiarc Jul 31, 2026
19d807e
Ask a region what its declared model resolves to
multiarc Jul 31, 2026
2544680
Ask whether generated code may name a bound extension, and a namespace
multiarc Jul 31, 2026
2939822
Ask each tier's own question about a name, a path and a constant
multiarc Aug 1, 2026
f463520
Make the findings register class-keyed and record cycle 23
multiarc Aug 1, 2026
4d05b3e
Execute two parser guards that no test reached
multiarc Aug 1, 2026
8a93f2a
Carry a constant's type difference, and ask the compiler four questio…
multiarc Aug 1, 2026
a6ced32
Record cycle 24, and close the class the register said to enumerate
multiarc Aug 1, 2026
da5d053
Read a @using body as the C# directive it is, so an alias binds a type
multiarc Aug 1, 2026
c23014f
Record the alias work, and a Release-only failure Debug never showed
multiarc Aug 1, 2026
f8b9d9f
Pin the model-type guard and the culture the goldens render under; ad…
multiarc Aug 1, 2026
6dc3920
Parse a probe tree the way the compilation it joins was parsed
multiarc Aug 1, 2026
b534d73
Fail a test run that executes no tests
multiarc Aug 1, 2026
b720703
Point every regression check at a filter property that exists
multiarc Aug 1, 2026
077c8eb
Rank an export call on the argument's own type, and type a list body …
multiarc Aug 1, 2026
315d3a0
Let an alias outrank the index, give three rounding built-ins their i…
multiarc Aug 1, 2026
e4411cf
Merge branch 'worktree-agent-aeb12ca01625f9796' into feature/benchmarks
multiarc Aug 1, 2026
901ae78
Merge branch 'worktree-agent-aa8fae1a8ed1fcfd9' into feature/benchmarks
multiarc Aug 1, 2026
cc8f70c
Close nine parked defects, and stop the protocol from protecting them
multiarc Aug 1, 2026
9c01dc2
Give `this` an operand arm, hand the built-in binder a symbol, and st…
multiarc Aug 1, 2026
a1b9d9c
Record the three fixes, and fail on a test case dropped as a duplicate
multiarc Aug 1, 2026
28a75bd
Re-test the last two parked reasons; one holds, one does not
multiarc Aug 1, 2026
356814e
Fix register
multiarc Aug 1, 2026
9cddf00
Improve documentation, fix tests and add missing tests
multiarc Aug 1, 2026
f71e1fd
Drive a boxed non-string through the value path as bytes, and correct…
multiarc Aug 1, 2026
72153ac
Drain the compile channel at build time, under the engine's own diagn…
multiarc Aug 1, 2026
0afb999
Refuse a model the template cannot accept, and stop precompiling past…
multiarc Aug 1, 2026
f835dc6
Separate every publish from the build that feeds it, and gate the con…
multiarc Aug 1, 2026
ee74709
Give the sweeps a cardinality guard, and let every CI leg see a dropp…
multiarc Aug 1, 2026
482a019
Retire .NET 6, and move the netstandard2.0 pins onto the 8.x line
multiarc Aug 1, 2026
38b34fe
Stop spelling the modern-BCL guard after a framework that is gone
multiarc Aug 1, 2026
7c62f40
Keep the collectible-context probes off the framework that has no suc…
multiarc Aug 1, 2026
b393012
Move the suites to xUnit v3 on Microsoft Testing Platform
multiarc Aug 1, 2026
23dff37
Take the whole tree to zero build warnings, and write down how it sta…
multiarc Aug 1, 2026
1a58baa
Re-measure the four open alias findings, and keep the one that was wrong
multiarc Aug 1, 2026
8719ab6
Rebuild the .NET benchmark leg from scratch, and delete the project i…
multiarc Aug 1, 2026
5ee570a
Budget the measurement per engine, and buy .NET the term it never sam…
multiarc Aug 1, 2026
f6e1767
Resize every leg to the per-engine budget, and correct E13's own arit…
multiarc Aug 1, 2026
4a0412a
Windows version
multiarc Aug 2, 2026
9dab0a6
Cleanup and alignment
multiarc Aug 2, 2026
9d6ab5d
New bench
multiarc Aug 2, 2026
75817ff
Stop timing the harness, and stop the runtime tier re-transcoding its…
multiarc Aug 2, 2026
1ebcf32
Take every test project green on every target framework
multiarc Aug 2, 2026
baa83eb
Ship one generator per Roslyn generation, and give it a .NET Framewor…
multiarc Aug 2, 2026
88fc245
Refuse constant division by zero at compile time, on both tiers, unde…
multiarc Aug 2, 2026
7207036
Rename the variant solution folder out of the project name it collide…
multiarc Aug 2, 2026
63abbbd
Close the shift, ternary and coalesce gaps in the operator table
multiarc Aug 2, 2026
a55362b
Adapters instead of bails: RuntimeOperators closes mixed equality and…
multiarc Aug 2, 2026
c6f034a
Table corrections: flip what the engine always refuses, emit what C# …
multiarc Aug 2, 2026
421bee7
Type identity for the shared table: same-enum and reference shapes no…
multiarc Aug 2, 2026
00a2cca
Constants speak the engine's type, user operators emit through adapters
multiarc Aug 2, 2026
a6e6858
Structural emissions: paths, indexers and call dispatch reach everywhere
multiarc Aug 2, 2026
1dbf95b
Lexer errors reach the error list instead of the console
multiarc Aug 2, 2026
7f15f76
ModelType item metadata types a template from the csproj
multiarc Aug 2, 2026
55de337
The engine's refusals fire at build: eight ids forwarded, sentences e…
multiarc Aug 2, 2026
c336153
Three known defects close, three skips lift
multiarc Aug 3, 2026
5366ad3
Retire stale defect prose the fixes left behind
multiarc Aug 3, 2026
19fef9b
HtmlEncodedRenderer stops paying for text that needs no encoding
multiarc Aug 3, 2026
f46954f
Documentation says what the code does again
multiarc Aug 3, 2026
1ee6b4f
The first protocol-machine run is published, and it is a different en…
multiarc Aug 4, 2026
d2343f3
The JS launcher can no longer mistake a null exit code for success
multiarc Aug 4, 2026
7b5823a
The sink rows say what their numbers mean where the numbers appear
multiarc Aug 7, 2026
e9f6232
The Node pin is the major line, and the strictness finally points at it
multiarc Aug 7, 2026
e4cda84
The CPython pin follows the Node ruling onto its minor line
multiarc Aug 7, 2026
7249931
The re-issued run is on every pin, and the JS verdict is real
multiarc Aug 8, 2026
2b60ab0
The layout idiom is proven at benchmark scale before any template tru…
multiarc Aug 8, 2026
295c611
The composed page finally is one, and the fragments learned four shapes
multiarc Aug 8, 2026
ea28a2d
The corpus now carries a whole page, and the fixtures travel with it
multiarc Aug 8, 2026
1421035
The templates speak only the native tier, and the emitter covers the …
multiarc Aug 8, 2026
46263b7
The fragment model forgot how to typeset, and the templates picked it up
multiarc Aug 8, 2026
dcb30bc
The floors stop pre-typesetting too, and the rule becomes the law E21
multiarc Aug 8, 2026
5ecefbd
Every word the page speaks now lives in a template
multiarc Aug 8, 2026
ffa7bbd
Five model twins forget their scripts and remember only their data
multiarc Aug 8, 2026
9c54cf7
Fifteen engines learn the whole page, and every gate in six languages…
multiarc Aug 8, 2026
b96b81f
The specs catch up with the ports, and E23 writes the landing down
multiarc Aug 8, 2026
5e14d99
The Heddle tree keeps only what runs at the top, and Linux skips net48
multiarc Aug 8, 2026
f56e36e
Every engine keeps only what runs at the top, and E24 makes it law
multiarc Aug 8, 2026
f58fb3e
The emitter learns the step-back four, and the encoded pair joins the…
multiarc Aug 8, 2026
48fc897
The last odd name falls in line: home.heddle becomes composed-page.he…
multiarc Aug 8, 2026
5450705
Go learns the two-track shape the other fifteen already keep
multiarc Aug 8, 2026
509526f
Five samples is the floor, and only .NET was under it
multiarc Aug 8, 2026
537d671
Two programs close their books: the decisions stay, the plans go to h…
multiarc Aug 8, 2026
fcb1c94
The drafts drop their suffixes: Claude's rules go live, refreshed aga…
multiarc Aug 8, 2026
c0dac34
What the rename left behind: the refreshed rule text catches up with …
multiarc Aug 8, 2026
e684be4
HED7031's reason becomes pinnable, and the probe wrapper learns the e…
multiarc Aug 8, 2026
001f39b
Embedded C# becomes a compiled fragment in the engine's own namespace…
multiarc Aug 8, 2026
76f82ed
A computed @partial name evaluates once at static init the way the en…
multiarc Aug 9, 2026
10fa784
The typing decisions step out of the emitter's walk into a pure modul…
multiarc Aug 9, 2026
838a37c
Every refusal names its class and plans queue ahead of it: the value …
multiarc Aug 9, 2026
2690325
One hidden member no longer costs the file: the node escapes to the e…
multiarc Aug 9, 2026
e8221e2
The functions the build cannot see now bind themselves, once, at firs…
multiarc Aug 9, 2026
a89fb3d
A template that names no model now says so, and the registry stops se…
multiarc Aug 9, 2026
68e683d
One declaration now reaches all three tiers: the build learns which a…
multiarc Aug 9, 2026
1f9292a
Both tiers stop writing their own ladder, and one of them was wrong a…
multiarc Aug 9, 2026
1117b32
Open generics were never the build's wall: the engine serves no such …
multiarc Aug 9, 2026
55d7b87
The table was predicting what the extensions already say, and one row…
multiarc Aug 9, 2026
a168387
The build can now ask an extension what its hook does, and only from …
multiarc Aug 9, 2026
6fe245f
Shadow mode says GO: the probe answers, the table agrees with it, and…
multiarc Aug 9, 2026
bbe466f
Four arms become one: the emitter stops knowing extension names and s…
multiarc Aug 9, 2026
78e32cb
The docs catch up with thirteen stages: the coverage story is rewritt…
multiarc Aug 9, 2026
13b07f7
The encoding a body-hosting bind carries is pinned on its own, where …
multiarc Aug 9, 2026
931a3cb
Nine hand-kept numbers come out of CI, and what a suite contains is n…
multiarc Aug 9, 2026
dc2280e
The gate against hardcoded extension names starts reading the whole a…
multiarc Aug 9, 2026
448a088
The engine stops being the assembly with the right name and becomes t…
multiarc Aug 9, 2026
6950008
The hook probe goes, and the one thing it actually found stays behind…
multiarc Aug 9, 2026
73be355
The extensions get to answer for themselves: a seam that runs the rea…
multiarc Aug 9, 2026
02b616a
The extensions stop being predicted and start being run: custom bodie…
multiarc Aug 9, 2026
2b1fe18
The refusals left standing get pinned, and the type-agnostic body's p…
multiarc Aug 9, 2026
b6432ad
The slot projection stops being reimplemented and starts being bound,…
multiarc Aug 9, 2026
c95342a
The definition invocation joins the seam, and its carriers move to th…
multiarc Aug 9, 2026
f9fd33d
The build gains a switch for observing the real engine, and an id for…
multiarc Aug 9, 2026
bb92a57
The testing rule learns what re-running a suite costs, and says to ke…
multiarc Aug 9, 2026
c4f0744
The observe cache moves back under obj, where a hand-imported targets…
multiarc Aug 9, 2026
eebf96a
The build stops guessing a hook's typing and reads it off a real engi…
multiarc Aug 9, 2026
b0e335a
Twenty ledger rows stop waiting to be deleted: the measurement says t…
multiarc Aug 9, 2026
147cdc4
The build stops refusing definition overrides: the parser had already…
multiarc Aug 9, 2026
1084844
The corpus grows a tier for the fallback that costs one call site, an…
multiarc Aug 9, 2026
1521b6f
Every refusal category is audited against its own construction sites,…
multiarc Aug 9, 2026
a106656
The published pages and the specs catch up with a build that runs the…
multiarc Aug 9, 2026
20d1a3e
The slot projection and the child template become roles an extension …
multiarc Aug 9, 2026
c3c7242
The partial stops being reimplemented and starts being run: the child…
multiarc Aug 9, 2026
db2fd58
Five verdicts about the slot projection go back to the hook that make…
multiarc Aug 9, 2026
c166080
The slot projection opens its own door: the three things @out reads s…
multiarc Aug 9, 2026
2ac1aa9
The chain stops being carriage and starts being a sequence: the build…
multiarc Aug 9, 2026
4d90b73
The body that compiles to nothing installs nothing: the build reaches…
multiarc Aug 10, 2026
0dbdbae
A hook that named no model named the dynamic one: the late accessor r…
multiarc Aug 10, 2026
3c420d0
The sixteen names go and the reference assembly stops being a wall: a…
multiarc Aug 10, 2026
e345a73
v3 spec
multiarc Sep 5, 2026
b00573d
Compiled form end to end (P1-W1..W7): contract, recording, loader, ga…
multiarc Sep 6, 2026
167d3df
Generator leaves the build (P1-W8): sln, gate, benchmark retarget
multiarc Sep 6, 2026
cfd81fb
Compiled form parity suite green (P1-W9): recording cursor, loader, g…
multiarc Sep 6, 2026
7ffdf69
heddle compile host verb (P2-W1): response file, image loading, artif…
multiarc Sep 7, 2026
bdce6d2
Typed entry points (P2-W2): BindTyped, DefaultOptions, OutputProfileM…
multiarc Sep 7, 2026
2ac2375
Heddle.Build package (P2-W3): task, targets, pack layout
multiarc Sep 7, 2026
ff7ff83
P2 build tier + precompiled-app consumer (benchmarks pending)
multiarc Sep 7, 2026
6ded143
P2-W4 consumers remainder, P2-W5 suite, P2-W6 ids (Phase 2 complete)
multiarc Sep 7, 2026
394e04b
P4-W8/W9: generator-free tree, 3.0.0 line, changelog, goldens, sample…
multiarc Sep 8, 2026
d3809e8
P4 tail: LS suite green, testing-standards artifact reword
multiarc Sep 9, 2026
f41129e
Fix EmptyExtension data path to preserve value types
multiarc Sep 9, 2026
f244eba
Precompilation v2 tail: phase 3 evidence, AOT posture, review correct…
multiarc Sep 16, 2026
af32d73
precompiled-aot builds its own tool on a clean checkout; the task nam…
multiarc Sep 16, 2026
f8a9497
Ratify the v3 records: replay materialization, measured performance p…
multiarc Sep 16, 2026
95787e5
Docs at the 3.0.0 line: benchmarks verified on v3, 2.1 retired, plans…
multiarc Sep 19, 2026
c7381dd
Markdown anchors resolve on the site and on GitHub
multiarc Sep 19, 2026
9672ee1
Benchmark corpus and engine fixtures carry no product or company names
multiarc Sep 19, 2026
36a8448
Golden corpus regenerated at the brandless navigation model
multiarc Sep 19, 2026
61daef6
VS Code extension publishes to the Marketplace from a release tag wit…
multiarc Sep 19, 2026
d77a040
Marketplace job uses Trusted Publishing and stays off until the Marke…
multiarc Sep 19, 2026
877db13
Marketplace publish runs on every release tag with a PAT held by the …
multiarc Sep 19, 2026
5323af8
Review corrections: loader bounds, opt-out contract, build inputs, pe…
multiarc Sep 19, 2026
2e62040
Review corrections: public API documented, AOT sample verified on the…
multiarc Sep 19, 2026
189cd9c
Review corrections: sandbox, printer parity, process path, build targ…
multiarc Sep 19, 2026
180f13d
Review corrections: parse cost, editor parse, language server resilie…
multiarc Sep 20, 2026
1d24c37
A member path is keyed without a metadata token, and a definition's b…
multiarc Sep 20, 2026
bca80f8
Engine review fixes: resolve path, tier parity, public surface, dead …
multiarc Sep 20, 2026
3f28ff2
Collapse the compiled-form schema to one increment and key bodies per…
multiarc Sep 20, 2026
9dd8827
Take the patched MSBuild utilities package
multiarc Sep 20, 2026
349d4d9
Declare every compile input, and take the build warning count to zero
multiarc Sep 20, 2026
edb6abd
Publish only from release tags; pull requests build and test
multiarc Sep 21, 2026
6e62247
Publish the packages that were built, and only over green suites
multiarc Sep 22, 2026
a5ed30b
Make the release path survive its first run, and pin each way it coul…
multiarc Sep 22, 2026
f699822
Fix what the previous commit broke, and three things it only half-fixed
multiarc Sep 23, 2026
c972fb0
Publish every registry from one deployment environment
multiarc Sep 23, 2026
27bb8eb
One VSIX target's runner fault must not cancel the other six
multiarc Sep 23, 2026
ca8e822
Write down the plan to bundle the VS Code extension
multiarc Sep 23, 2026
453cad5
Bundle the VS Code extension into a single dist/extension.js
multiarc Sep 23, 2026
9505f89
Ship the bundled dependencies' license texts, and load every VSIX bef…
multiarc Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 18 additions & 0 deletions .claude/rules/api-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
paths:
- "src/Heddle/**/*.cs"
- "src/Heddle.Tool/**/*.cs"
---

# API design and compatibility

Details: [coding-standards.md § API](../../docs/spec/common/coding-standards.md#api-design-and-compatibility), [breaking-windows.md](../../docs/spec/common/breaking-windows.md). Anchored in the .NET Framework Design Guidelines.

- Additive by default: new extensions, opt-in options, overloads. Existing templates and hosts compile and render byte-identically.
- Breaking changes land only in a ratified breaking window (D2), each with a migration note. Candidates go to the register in breaking-windows.md, not into code.
- Every new `TemplateOptions` property goes into the copy constructor (and `Equals`/`GetHashCode` when it keys identity) — missed before (`ProvideLanguageFeatures`); the completeness test enforces this.
- Public API additions carry XML docs + same-change updates to the affected published docs pages (`language-reference.md`, `custom-extensions.md`, `built-in-extensions.md`, `csharp-api.md`).
- Extend via the sanctioned seams (`[ExtensionName]` registry, options, function registry, output profiles, publish/read channel, resolver, encoder) — don't invent parallel mechanisms or new seams for single-implementation internals.
- The build names no extension: no compare against a built-in name in any form, no `"Heddle.Extensions."` type literal, no `"Heddle"` assembly-name compare, no name-keyed table. Read the binder, the attributes, or the hook.
- The build never predicts a compile-time hook either: the loader runs the extension's real `InitStart`/`CompleteInit` at materialization (once per request shape, over bodies served from the compiled form), so a bodied, hook-overriding, `[Prop]`-declaring or `[BranchRole]` custom extension precompiles in a default build. A call the build cannot serve costs **that template** (an `HED7031` decline with a machine-readable class), not the build — reach for a build error only where the template must not precompile silently.
- Extension instances are shared across concurrent renders: no mutable per-render state on them; per-render state lives in the `Scope` lineage.
18 changes: 18 additions & 0 deletions .claude/rules/coding-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
paths:
- "**/*.cs"
---

# Coding style

Authority order: (1) surrounding code in the file, (2) [coding-standards.md](../../docs/spec/common/coding-standards.md), (3) `.editorconfig` (editor guidance only, not a gate).

- Block-scoped namespaces (`namespace X { … }`) — not file-scoped, even in new files.
- Allman braces predominantly — match the file. Braceless single-statement guards for early returns are idiomatic; multi-line/nested bodies always braced.
- `var` when the type is apparent; explicit types otherwise and for built-ins.
- Naming: `_camelCase` private instance fields; `PascalCase` private static readonly; `I`-prefixed interfaces; extension classes `<Name>Extension` with `[ExtensionName("name")]`.
- Existing quirks (space before parameter list, space after cast) are deliberate — do not "fix" them.
- Comments follow C1–C8: default to none; write one only when the code cannot carry the meaning; never cite specs, plans, findings, or reviews in code comments (C4). XML doc comments on public API; regression tests carry a doc comment explaining the pinned scenario.
- 4-space indent, UTF-8, final newline, ~120-column wrap.
- Never mass-reformat or run whole-file IDE cleanups; diffs contain only the lines the change needs. The established style is the maintainer's deliberate choice — consistency beats modernization.
- `src/Heddle.Language/generated/` is generated (ANTLR) — never hand-edited; grammar change = `.g4` edit → regen → commit both.
17 changes: 17 additions & 0 deletions .claude/rules/errors-diagnostics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
paths:
- "src/Heddle/**/*.cs"
- "src/Heddle.Tool/**/*.cs"
- "src/Heddle.Language*/**/*.cs"
---

# Errors and diagnostics

Details: [coding-standards.md § errors](../../docs/spec/common/coding-standards.md#error-handling-and-diagnostics), [cross-cutting-decisions.md D1 + registry](../../docs/spec/common/cross-cutting-decisions.md).

- Compile-path problems are collected, not thrown: positioned `HeddleCompileError`/`HeddleCompileWarning` on the compile result, so template authors see all problems at once. The public API never surfaces raw exceptions for template mistakes.
- Host-programming errors throw at public API entry points (`ArgumentNullException` etc.).
- Every new diagnostic claims a stable `HED####` ID from the registry (feature-area blocks, D1) **in the same change**; IDs are never reused or renumbered.
- An ID whose condition becomes unreachable is **retired in place**, not deleted: the `HeddleDiagnosticIds` constant, the `HeddleDiagnosticCatalog` row, the registry row and a mention in the page the registry names as owner all stay, and the registry row says what stopped firing, why, and what replaced it (often nothing). `DiagnosticIdTests` gates all four; deleting any would free the number for a later, different fault.
- Messages name the construct, point at the remedy, and carry the template position.
- Security-sensitive failures never degrade to execution: a sandbox violation is a compile error, full stop.
16 changes: 16 additions & 0 deletions .claude/rules/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
paths:
- "src/Heddle/**/*.cs"
- "benchmarks/dotnet/**"
---

# Performance (render path is hot)

Details: [coding-standards.md § performance](../../docs/spec/common/coding-standards.md#performance-rules-the-render-path-is-hot).

- No new per-render allocations. `Scope` stays a `readonly struct` passed by `in`; optional per-render state is lazily created.
- Reflection at compile time only; render time executes pre-compiled delegates and direct calls.
- `[MethodImpl(AggressiveInlining)]` only on tiny, provably-hot transforms — with a benchmark justifying it.
- Perf claims are proven by BenchmarkDotNet (`benchmarks/dotnet`), never asserted. Hot-path changes run affected benchmarks before/after on the same machine: allocated bytes must not increase; mean must stay within reported error. Intentional trade-offs need maintainer ratification.
- Compile-time cost is "compile once, render many" — moderate compile-path allocation is fine, but startup/precompilation paths get measured too.
- No JIT-rescue assumptions for escaping allocations (D7).
15 changes: 15 additions & 0 deletions .claude/rules/spec-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
paths:
- "docs/spec/**"
---

# Spec and decision workflow

Details: [spec-conventions.md](../../docs/spec/common/spec-conventions.md), [cross-cutting-decisions.md](../../docs/spec/common/cross-cutting-decisions.md) (which also carries the condensed release and program records).

- Specs live under `docs/spec/`, indexed from `docs/spec/README.md` (update the index in the same change); they are contributor material, never published (D9).
- Plan = what/why (ratified input); spec = exactly how. A finished spec has **no open questions** — every point is a closed decision with evidence, or a most-reversible default plus a named revisit trigger.
- Implementation follows the owning plan's declared item order (D5): assume 1..N−1 merged; never depend on later items.
- Changing an earlier recorded decision goes through the amendment mechanism (evidence → maintainer ratification → implemented by the amending effort); earlier spec text is never silently retrofitted. The accumulated E1–E28 ledger is closed — new amendments are recorded as dated notes in the owning spec (see cross-cutting-decisions.md § Cross-spec amendments ledger).
- Balanced-mode principle precedence on conflicts: correctness/back-compat → sandbox security → simplicity → measured hot-path performance → abstraction/extensibility. DRY consolidates knowledge (rule of three); YAGNI cuts presumptive features, never tests/benchmarks/docs.
- Writing style: sentence-case headings, en/em dashes, relative links only, cite `path` + member name over bare line numbers.
22 changes: 22 additions & 0 deletions .claude/rules/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
paths:
- "src/*Tests*/**"
- "src/TestCorpus/**"
- "samples/**"
---

# Testing

Details: [testing-standards.md](../../docs/spec/common/testing-standards.md) — normative; this is the short form.

- Loop: write the spec's tests failing first → implement to green → run the gate → fix forward. Goldens/baselines/spec tables change only with maintainer review, never to silence a red test.
- Gate (one combined run): `dotnet build -c Release` → `dotnet test --project src/Heddle.Tests/Heddle.Tests.csproj` (all TFMs, serially; both Debug and Release when `#if DEBUG` arms are touched) → no diff under `src/Heddle.Language/generated/` (unless the spec licenses a grammar change) → benchmarks when a hot path is touched → `npm run docs:build` when docs pages changed.
- xUnit v3 on MTP: `dotnet test --project <csproj>` is the canonical form; filters are MTP syntax after `--` (`--filter-method` etc.); a filter matching nothing exits 8; CI legs run through `.github/scripts/dotnet-test-guarded.sh <project>`, which passes `--fail-skips on`.
- **Run a suite once and keep the whole output.** These suites take minutes; re-running one to see a detail you piped away is the single most expensive habit available. Always `2>&1 | tee` (or redirect) the full run to a file, then read that file — grep it for failures, open the failing case, count tests, whatever is needed. Never pipe a run through `tail`/`grep` as the only sink, and never re-run a suite to answer a question the first run already contained. Redirect per suite so runs stay separable, and prefer one combined script that captures every suite in a single pass over four separate invocations.
- **No test-count floors.** `--minimum-expected-tests` was tried on nine CI legs and withdrawn: it is satisfied by editing a digit, it names nothing when it reddens, it drifted (one commit raised `dotnet.yml` and left `lsp.yml`, and that leg then tolerated a six-test regression for four commits), and it fails a leg for the wrong reason whenever a test is legitimately quarantined. What a suite CONTAINS is gated inside the suite: `src/<Suite>/test-classes.txt`, one line per fact-declaring class, set-equality asserted by that suite's `TestClassInventoryTests` — a red gate names the class. Deliberately the same shape as corpus membership below.
- Fixtures: `.heddle` + sibling golden under `src/Heddle.Tests/TestTemplate`; every new golden/fixture directory is LF-pinned in `.gitattributes` **in the same change**.
- Negative/security tests assert positioned `HED*` diagnostics (ID + position) and prove the construct never executes.
- Descriptive PascalCase sentence test names; assert with context (`Assert.True(result.Success, result.ToString())`); tests are exempt from DRY.
- Concurrency: any state shareable across renders ships a parallel-render isolation test.
- Precompiled tier: fallback to dynamic is byte-identical, so an unpinned test proves nothing about the tier it claims to test. End-to-end tests pin the tier (`PrecompiledMismatchPolicy.Strict` + fallback sentinel); expected fallbacks are declared only via `FallbackGuard.Expect(key, reason)` (run-time) / `CompiledFormHarness.ExpectRefusal(key, class)` (build-time decline beyond the corpus row); quarantine guarded fixtures with an owning-item `Explicit = true` (reported *not run*, so it survives `--fail-skips`), never weaken them.
- Test-input single-sourcing: a template shape verified by more than one tier exists once, in the shared corpus, with declared (total) intent — duplicate copies drift silently and break the differential premise. Membership is gated by set equality — never a count or floor (a floor once hid 15 templates silently dropping out).
35 changes: 32 additions & 3 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,41 @@
# output — failing on Windows while Linux (LF everywhere) passes. Pin every such root to LF so the
# byte comparison holds identically on both platforms regardless of the developer's autocrlf setting.
# All files under these roots are text (verified: no binaries). New golden/fixture roots MUST be
# added here in the same change that introduces them — see docs/spec/common/testing-standards.md.
# added here in the same change that introduces them.
#
# eol=lf pins line endings and says nothing about byte-order marks; the two are independent, and a
# BOM drift can pass every eol=lf check there is. Templates carrying a deliberate UTF-8 BOM declare
# it in src/TestCorpus/CorpusIntent.cs, gated by CorpusIntentGateTests.
samples/**/golden/** text eol=lf
src/Heddle.Tests/TestTemplate/** text eol=lf
src/Heddle.Tests/TestOutput/** text eol=lf
src/Heddle.Tests/Streaming/** text eol=lf
src/Heddle.Generator.Tests/Snapshots/** text eol=lf
src/Heddle.Generator.IntegrationTests/Fixtures/** text eol=lf
src/Heddle.Build.Tests/Fixtures/** text eol=lf
src/Heddle.LanguageServices.Tests/Corpus/** text eol=lf
src/Heddle.Demo.Wasm/contract-fixtures/** text eol=lf

# The per-suite test-class inventories are read line by line and compared as a set on both platforms.
# Reading normalises CRLF, but pinning them keeps the diff a reviewer sees identical everywhere.
src/*/test-classes.txt text eol=lf

# Golden oracle corpus: the *.golden.html files intentionally end WITHOUT a trailing newline and must
# round-trip byte-exact on every platform, so they are pinned -text (no smudging at all) rather than
# eol=lf. The JSON sidecars are ordinary LF text.
benchmarks/dotnet/GoldenCorpus/*.golden.html -text
benchmarks/dotnet/GoldenCorpus/*.verify.json text eol=lf
benchmarks/dotnet/GoldenCorpus/manifest.json text eol=lf
# Exported model fixtures are hash-recorded in the manifest like the goldens; LF text.
benchmarks/dotnet/GoldenCorpus/fixtures/** text eol=lf

# Rust benchmark harness: composed-page fragment data must round-trip byte-exact (-text); template
# files are ordinary LF text (the harness erases their line endings, but LF keeps diffs clean).
benchmarks/rust/templates/** text eol=lf

# Python benchmark harness: template files are committed LF on every platform — Mako passes a literal
# \r\n in a template file through into rendered output, so LF-pinning keeps checked-in bytes equal to
# authored bytes.
benchmarks/python/templates/** text eol=lf

# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
Expand All @@ -41,3 +67,6 @@ src/Heddle.Demo.Wasm/contract-fixtures/** text eol=lf
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

# The stored compiled-form fixture is bytes, not text: never normalised (P4-R3).
src/Heddle.Tests/TestTemplate/*.bin binary
1 change: 1 addition & 0 deletions .github/rulesets/main-branch-protection.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"required_status_checks": [
{ "context": "build (ubuntu-latest)" },
{ "context": "build (windows-latest)" },
{ "context": "release-tests / suites" },
{ "context": "dco" }
]
}
Expand Down
38 changes: 38 additions & 0 deletions .github/scripts/dotnet-test-guarded.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Runs one test project under Microsoft.Testing.Platform, with the two guards that are worth having.
#
# Usage: dotnet-test-guarded.sh <project> [extra dotnet test args...]
#
# `--fail-skips on` turns a skipped test into a failed one. A skip is a test that stopped testing, and
# CI is the wrong place to find out quietly; the repository's protocol for a known-failing test is
# `[Fact(Explicit = true)]`, which is reported as NOT RUN rather than skipped and so survives this.
#
# Exit 8 -- a filter matched nothing, or discovery failed -- stays called out by name, because a stale
# filter that runs nothing used to pass. It is the platform's own signal, not a number anyone maintains.
#
# What this script no longer does is carry a per-suite `--minimum-expected-tests` floor. Nine of them
# were maintained by hand across two workflows and they failed at their own job: one commit added six
# tests, raised the floor in one workflow and left the other, and that leg then tolerated a six-test
# regression in silence for four commits. A floor is satisfied by editing a digit, it names nothing
# when it reddens, and it fails a leg for the wrong reason whenever a test is legitimately quarantined.
# Suite membership is gated instead by the checked-in test-class inventories (src/<Suite>/test-classes.txt,
# asserted by set equality inside each suite), which name the class that appeared or vanished.

set -uo pipefail

if [ "$#" -lt 1 ]; then
echo "usage: $0 <project> [extra args...]" >&2
exit 64
fi

project=$1
shift 1

dotnet test --project "$project" "$@" -- --fail-skips on
status=$?

if [ "$status" -eq 8 ]; then
echo "::error::Zero tests ran in ${project} -- a filter matched nothing, or discovery failed."
fi

exit "$status"
Loading
Loading