Skip to content

The combo assembler: materialise an instance's recorded module set for the gate - #1097

Merged
rbuergi merged 3 commits into
mainfrom
feat/instance-combo-assembler
Aug 10, 2026
Merged

rbuergi merged 3 commits into
mainfrom
feat/instance-combo-assembler

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Step 2 of the Candidate Release Protocol's instance gate (Doc/Architecture/CandidateReleaseProtocol → "What is missing is only the combo assembler"). Step 1, the reader, merged as #1091.

What this adds

InstanceComboAssembler (src/MeshWeaver.PluginCatalog) turns an InstanceCombo — what an instance actually runs, as InstanceComboReader states it — into a materialised repo-root directory that mw-plugin-test verifies: every module's files at its recorded ref under <workRoot>/<ModuleId>/, plus a manifest (combo-assembly.json) naming module → resolved ref → content hash, so the gate's verdict can name its exact input (this later lands on Admin/UpdatePolicy).

mw-combo-assemble (tools/MeshWeaver.ComboAssembler) is the console boundary, mirroring mw-plugin-test's shape — the one Task bridge lives in Program.cs; everything below is reactive:

mw-combo-assemble <combo.json> <work-root> [--allow-moving] [--allow-incomplete]
                  [--source <name>=<url>]… [--default-source <url>]
                  [--fetch-timeout <s>] [--token-env <VAR>]

Semantics — a gate run on a moving ref must never silently become evidence

  • GitSync-coordinate modules fetch repositoryUrl at lastSyncCommitSha with the recorded subdirectory — one shallow pack over the existing IGitHubRepoClient.Fetch seam (git protocol; no whole-history clone, no hand-rolled git).
  • Package-coordinate modules resolve through NodeRepoPackageSource.FetchPackageFiles against a snapshot fetched once per (repo, ref) — the same in-memory-snapshot pattern mw-plugin-test uses, inheriting its binary-preservation semantics (Registry does not publish binary content — course/plugin videos drift between git and portal storage #848). The install record names a source, not a URL, so the tool takes --source <name>=<url> mappings.
  • RefFidelity.Moving / Unrecorded are REFUSED by default, with an error naming the module and the way out; --allow-moving is the explicit opt-in, and the manifest then stamps the pin as Moving so it can never read as reproducible evidence.
  • A recorded ModuleVersion with only a movable fetch ref must PROVE itself: the fetched tree's manifest.lock module version has to match, or the module is a named failure ("the ref moved past the recorded install") — VerifiedModuleVersion pin on success.
  • IsComplete == false refuses the whole run (--allow-incomplete overrides): a known-short combo assembled silently would verify a subset while reading as though it verified the instance.
  • Breadth-complete: every fetch is bounded (--fetch-timeout), a fetch failure is a NAMED failure for exactly the modules riding it, and the run continues to collect ALL failures. The manifest is written even on refusal, documenting why nothing was materialised.

Verified

  • dotnet build -c Release -warnaserror clean on MeshWeaver.PluginCatalog, MeshWeaver.ComboAssembler, MeshWeaver.PluginCatalog.Test (re-run after merging current main, which moved Directory.Build.props).
  • 6 new tests in InstanceComboAssemblerTest (synthetic combos against in-memory fixture repos — no network, no mesh): refusal on moving/unrecorded refs before any fetch, the tester layout (<ModuleId>/index.json top-level, foreign folders excluded), manifest shape + deterministic content hashes, module-version proof (match + mismatch), named fetch failures with breadth-completeness, incomplete-combo refusal. All green, plus WhatsNewEntryIntegrityTest / DocumentationLinkIntegrityTest.
  • End-to-end smoke of the real tool: refusal path exits 1 with the manifest naming the module; a real fetch of MeshWeaver.SocialMedia at an exact sha materialised 24 files into <work>/SocialMedia/ (index.json at the tester's expected place) and exited 0.

What step 3 still needs

Wiring the gate: run mw-combo-assemble + mw-plugin-test inside the candidate image over an instance's combo (reader → combo.json → assembled root → tester), and report the verdict to Admin/UpdatePolicy as "cannot update to X — these installed modules do not compile/pass against it".

🤖 Generated with Claude Code

https://claude.ai/code/session_01CPQKMhQDpitUzsW1MqTVhH

…r the gate

Step 2 of the Candidate Release Protocol's instance gate (step 1, the
InstanceComboReader, merged as #1091). InstanceComboAssembler turns an
InstanceCombo into the repo-root layout mw-plugin-test verifies — every
module's files at its RECORDED ref under <workRoot>/<ModuleId>/ — plus a
manifest (combo-assembly.json) naming module → resolved ref → content
hash, so the gate's verdict can name its exact input.

Semantics: GitSync coordinates fetch repositoryUrl at lastSyncCommitSha
(one shallow pack via the existing IGitHubRepoClient.Fetch seam, never a
history clone); package coordinates go through
NodeRepoPackageSource.FetchPackageFiles against a snapshot fetched once
per (repo, ref). Moving/unrecorded refs are REFUSED by default — a gate
run on a moving ref is not evidence — with --allow-moving as the
explicit opt-in, stamped as Moving in the manifest; a recorded
ModuleVersion with only a movable fetch ref must PROVE itself against
the tree's manifest.lock. A known-incomplete combo refuses the whole
run. Fetches are bounded and a failure is NAMED for exactly the modules
riding it — breadth-complete, never stop-at-first.

mw-combo-assemble (tools/MeshWeaver.ComboAssembler) is the console
boundary, one Task bridge in Program.cs, everything below reactive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPQKMhQDpitUzsW1MqTVhH
Copilot AI lite review requested due to automatic review settings August 10, 2026 10:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements step 2 (“combo assembler”) of the Candidate Release Protocol instance gate by materializing an InstanceCombo into a repo-root directory suitable for mw-plugin-test, and producing a manifest (combo-assembly.json) that records the exact assembled inputs.

Changes:

  • Added InstanceComboAssembler + manifest/report model to fetch modules at recorded refs, materialize their file trees, and record resolved commits + deterministic content hashes.
  • Added mw-combo-assemble console tool as the CLI boundary for assembling combos.
  • Added an integration-style unit test suite for the assembler behavior and a What’s New entry.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/MeshWeaver.ComboAssembler/Program.cs New CLI entrypoint + argument parsing; wires Git fetch client + InstanceComboAssembler.
tools/MeshWeaver.ComboAssembler/MeshWeaver.ComboAssembler.csproj New console project definition (multi-arch RIDs) referencing PluginCatalog + GitSync.
src/MeshWeaver.PluginCatalog/InstanceComboAssembler.cs Core implementation: planning/refusal policy, grouped fetch/materialize pipeline, hashing, and manifest writing.
src/MeshWeaver.PluginCatalog/ComboAssembly.cs New public DTOs/options/enums for assembly policy and manifest/report shape.
test/MeshWeaver.PluginCatalog.Test/InstanceComboAssemblerTest.cs New tests covering refusal semantics, layout, manifest contents, proof rules, and breadth-complete failure reporting.
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-10-your-exact-plugin-set-can-be-rebuilt-for-verification.md What’s New entry describing the new capability and evidence semantics.
MeshWeaver.slnx Adds the new combo assembler tool project to the solution.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +64 to +67
case "--fetch-timeout" when i + 1 < args.Length:
fetchTimeout = TimeSpan.FromSeconds(
double.Parse(args[++i], CultureInfo.InvariantCulture));
break;
Comment on lines +497 to +499
var moduleRoot = Path.Combine(Path.GetFullPath(workRoot), moduleId);
Directory.CreateDirectory(moduleRoot);
var manifest = new StringBuilder();
@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

701 tests  ±0   701 ✅ ±0   14m 20s ⏱️ +13s
 10 suites ±0     0 💤 ±0 
 10 files   ±0     0 ❌ ±0 

Results for commit 0451c83. ± Comparison against base commit 23859fe.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 229 tests  ±0   1 229 ✅ ±0   6m 28s ⏱️ +3s
   11 suites ±0       0 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 0451c83. ± Comparison against base commit 23859fe.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 773 tests   1 581 ✅  6m 19s ⏱️
   11 suites    192 💤
   11 files        0 ❌

Results for commit 0451c83.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

1 335 tests  +6   1 330 ✅ +7   9m 43s ⏱️ +45s
   11 suites ±0       5 💤 ±0 
   11 files   ±0       0 ❌  - 1 

Results for commit 0451c83. ± Comparison against base commit 23859fe.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

   11 files  ±0     11 suites  ±0   7m 41s ⏱️ - 2m 26s
1 984 tests ±0  1 876 ✅ ±0  108 💤 ±0  0 ❌ ±0 
2 157 runs  +1  2 049 ✅ +1  108 💤 ±0  0 ❌ ±0 

Results for commit 0451c83. ± Comparison against base commit 23859fe.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 970 tests  ±0   1 968 ✅ ±0   6m 21s ⏱️ +21s
   11 suites ±0       2 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 0451c83. ± Comparison against base commit 23859fe.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

   65 files     65 suites   50m 55s ⏱️
8 992 tests 8 685 ✅ 307 💤 0 ❌
9 165 runs  8 858 ✅ 307 💤 0 ❌

Results for commit 0451c83.

♻️ This comment has been updated with latest results.

@rbuergi
rbuergi merged commit 0268860 into main Aug 10, 2026
18 checks passed
@rbuergi
rbuergi deleted the feat/instance-combo-assembler branch August 19, 2026 10:29
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.

2 participants