Skip to content

engine: extract world synthesis into nexum-world#440

Merged
mfw78 merged 1 commit into
dev/m1from
feat/m2-nexum-world
Jul 20, 2026
Merged

engine: extract world synthesis into nexum-world#440
mfw78 merged 1 commit into
dev/m1from
feat/m2-nexum-world

Conversation

@mfw78

@mfw78 mfw78 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Closes #379

What

Extracts module/venue world synthesis and the core capability table out of nexum-macros::world into a new plain library, nexum-world. Removes the baked client (pool) and cow-api rows from the table; per-namespace rows now come from a composition root's extensions.toml registry, passed into synthesize. Rewrites WIT package resolution from a workspace-ancestor walk to crate-local wit//wit/deps lookup (nexum_world::resolve_wit_packages), falling back through ancestors for the transitional monorepo layout.

Why

The KNOWN table hardcoded a pool row and a cow-api to shepherd:cow row, leaking venue and cow knowledge into the host-adjacent macro crate. Sourcing those rows from a registered-extension manifest instead, and moving the synthesis/table into their own venue-free library, gets the host layer to zero venue/cow knowledge per the Extension seam target.

Testing

  • cargo test -p nexum-world
  • cargo test -p nexum-macros

AI Assistance

Implemented with Claude Code.

Closes #379

@lgahdl lgahdl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clean extraction overall — nexum-world stays generic (no venue/cow types leak into it), comments are accurate throughout with no stale references, and the collision/malformed-manifest error paths are properly tested. Two things worth a look before merge, one architectural note that's non-blocking:

}
dir = cur.parent();
}
None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The old resolve_wit_packages (removed from nexum-macros) located one wit/ root by requiring it to contain nexum-host, then resolved every requested package under that same root. This version resolves each package independently, walking its own ancestor chain with no shared-root invariant.

Failure scenario: a crate that vendors wit/deps/pkg-a locally but not wit/deps/pkg-b will silently pull pkg-a from crate-local and pkg-b from a differently-versioned copy in some unrelated ancestor's wit/ — no error, no indication the resolved set is incoherent. The synthesize call sites always request multiple packages at once (["nexum-host", "videre-value-flow", ...]), which is exactly where this could manifest, and no test covers a multi-package case split across ancestor levels (the existing tests all pass a single-element package list).

Worth tracking the ancestor level each package resolves at and erroring if they disagree, plus a test with ≥2 packages resolving from different levels.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed still valid at HEAD, not superseded: resolve_wit_packages (now in nexum-world) still resolves each package independently with no shared-root/level-coherence check, and every test passes a single-element package list. The split-repo layout co-locates packages under one wit/ root so it does not trigger today, but the guard and the multi-package cross-level test are absent. Tracked in #504.

Comment thread extensions.toml
# per-namespace rows the module world synthesis emits beyond the core
# nexum:host table. Each row names the WIT import a `[capabilities]`
# declaration turns into and the package directories its resolve path
# needs, in dependency order.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This introduces a second, unrelated [extensions.<name>] table. docs/design/linker-extension-seam.md already reserves that exact heading for the opaque, runtime-loaded operator config living inside engine.toml (e.g. [extensions.cow]orderbook_urls). This file's [extensions.client]/[extensions.cow-api] rows are a different schema (import/packages — WIT wiring) loaded at a different time (macro-expansion-time ancestor walk, not runtime config parsing).

Same section syntax, two unrelated files, nothing cross-referencing them — a reader who knows the engine.toml convention has no signal these aren't the same mechanism. Worth a distinct filename (wit-extensions.toml? capabilities.toml?) or a doc cross-reference in both places.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed still valid at HEAD, not superseded: extensions.toml still carries [extensions.client], and linker-extension-seam.md still reserves [extensions.<name>] for the unrelated runtime operator config. No rename or cross-reference was added. Tracked in #505.

@mfw78
mfw78 force-pushed the feat/m2-extension-seam-roles branch from e2dc469 to c68cd89 Compare July 20, 2026 06:54
Base automatically changed from feat/m2-extension-seam-roles to dev/m1 July 20, 2026 07:04
…e known table

The capability table and per-module world synthesis move into a new
plain nexum-world library carrying only the core nexum:host rows.
Per-namespace rows come from the composition root's extensions.toml
registry, parsed and passed in by the macro layer, so no host crate
carries a downstream name; synthesis rejects a row that shadows a core
capability or another registration. WIT packages resolve crate-locally
(wit/deps, then wit/) with an ancestor fallback for the transitional
monorepo layout.
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