Contributing
Before you start
- Use .NET SDK
10.0.103with the roll-forward policy inUniversalToolchain/global.json. - Read canonical repo docs:
readme.mdfor project overview and scope;- Current Architecture Status and Project Map for public boundaries;
- Current Canonical Runtime Pipeline before changing Wist planning/runtime code;
internal-docs/policies-and-reports/project-positioning.mdfor repository-only positioning policy;internal-docs/policies-and-reports/PROJECT_RULES.mdfor repository-only coding standards;internal-docs/policies-and-reports/ARCHITECTURE_RULES.mdfor repository-only architecture guardrails;AGENTS.mdwhen making AI-assisted or agent-driven changes.
Choose a contribution route
If you want to work on generic language composition, begin with the independent Acme example, package model, and planning diagnostics. Then read UniversalToolchain.LanguageSdk, UniversalToolchain.Runtime, and the focused UniversalToolchain.LanguageSdk.Tests project. A useful bug report includes the language definition, registered packages, selected backend, expected provider/route, actual diagnostics, and exact revision.
For a Wist application or compiler change, start with First Program, then follow the Wist facade, dialect, frontend, and backend documentation to the owning code. Interpreter/CIL parity only applies to the shared supported semantic subset.
For research proposals, distinguish experiments from current SDK guarantees. Read limitations and alternatives, and compare proposed semantic-composition mechanisms against ordinary typed interfaces before assuming a new global abstraction is necessary. Contributor tasks should come from reproducible issues, not an inferred product roadmap.
Build and test
Run from repository root:
dotnet restore UniversalToolchain/Wist.sln
dotnet build UniversalToolchain/Wist.sln -c Release --no-restore
dotnet test UniversalToolchain/Wist.sln -c Release --no-buildThe canonical repository gate is stricter than this convenience block: build.sh/build.ps1 also enforce the exact test manifest, architecture guards and related repository contracts. Historical or quarantined tests must not be hidden from the active contract through project-file exclusions.
Change expectations
- Keep changes minimal, targeted and deterministic.
- Prefer extending existing generic contracts over adding Wist-only semantic owners.
- Avoid hardcoding dialect/module assumptions into framework-level contracts.
- Preserve universality, layering and composition boundaries.
- Do not make convenience facades easy to grow into hidden sources of framework truth.
- If behavior changes, add or update tests in the same change.
- If structure or behavior meaningfully changes, update canonical docs in the same change.
- When changing
LanguageDefinition, feature/contribution descriptors,LanguageCompiler,LanguagePlan, route assembly or runtime materialization, update the canonical runtime and language-authoring docs that describe that owner. - Runtime-manifest emitter/serializer docs describe that artifact format only. Do not treat them as authority for Wist semantic selection or execution.
- When changing module authoring patterns, aliases, parser priorities, AST visitors, bytecode tags, AIR shape, backend artifacts or parity assumptions, update the matching contract docs in the same change.
Runtime composition expectations
The canonical Wist path is:
.wistdialect/preset
→ LanguageDefinition
→ LanguageCompiler
→ LanguagePlan
→ LanguageRuntime
→ exact planned componentsContributor rules:
LanguageCompileris the only semantic planner. Do not add a second build-plan, selected-runtime-plan or backend-selection owner behind a Wist helper.- The Wist configuration frontend may translate aliases/policy into typed generic contracts, but it must not perform dependency closure or runtime selection itself.
- Feature dependency closure, contribution/provider resolution, exclusions, ordering and backend routes belong to
LanguageCompiler. LanguageRuntimematerializes the exact graph captured byLanguagePlan; materialization must not add features, change order or choose another backend.- Runtime component sources must match exact package provenance for materialized components.
- Tooling-only planned contributions must not become runtime dependencies merely because they are present in the plan.
UniversalToolchain.Dialects.IntegrationandUniversalToolchain.Dialects.Wistare retired S13 topology owners and must not be recreated or referenced; use typed Language SDK/runtime contracts instead.- Treat shipped example dialects as runnable references and keep their source/configuration semantics aligned with the canonical planner.
- Add or update architecture guardrails when changing canonical owner boundaries.
Wist configuration expectations
userequests typed features/modules; do not require callers to duplicate transitive feature dependencies that the planner owns.excludemust reachLanguageDefinition.ExcludedContributions; required excluded contributions must fail closed in planning.- Security and intrinsic directives must translate to typed policy before planning.
- Unknown aliases/capabilities must fail explicitly rather than becoming hidden activation switches.
- Source identity may affect provenance/hash identity, but semantic parity tests across different source names must compare typed semantic projections rather than
PlanHashequality.
Module and pipeline expectations
- Read
docs/guides/module-authoring.mdand Create Your First Module before adding or reshaping a Wist module. - Read Module Contracts before changing token names, parser creator priorities, AST visitors, shared state, bytecode tags or backend capability behavior.
- Read
docs/architecture/bytecode-and-air.mdbefore changing bytecode, AIR, translation or optimizer semantics. - Read
docs/architecture/backends-and-parity.mdbefore changing backend behavior, backend artifacts, intrinsics or parity tests. - Register built-in Wist features/contributions with the typed Wist LanguagePack/catalog owner; attributes or generated runtime-manifest metadata are not a substitute for the canonical
LanguagePlanregistration path. - Do not add convention-only hidden contracts when a documented contract, verifier, shared constant or test can make the rule explicit.
Test suite rules
- New tests must not inherit from
LegacyTestBaseor other historical/quarantine fixture bases. - Backend-specific checks belong in
Tests/Backends. - Public behavior tests belong in
Tests/Core. - Implementation-detail checks belong in
Tests/Internal. - Reusable helpers belong in
Tests/Infrastructure. - Repetition and parallel stability checks belong in
Tests/Stress. - New explicit single-backend tests should use canonical runtime test infrastructure rather than reconstructing retired Wist composition workflows.
- Backend parity must execute both backends from one canonical plan when that is the contract under test.
- Prefer explicit internal contracts via
InternalsVisibleTo("Tests")over reflection with type-name strings. - Avoid hidden backend result casts inside fixtures.
- Avoid mixing unrelated concerns in one fixture.
- Add architecture guardrail tests when introducing new framework-adjacent catalogs, registries or optional facade layers.
Documentation quality
- Keep docs aligned with real implementation.
- Ensure commands in docs run from repository root.
- Keep example paths and CLI flags aligned with real shipped dialect files.
- Remove stale or legacy wording instead of preserving contradictory current-state descriptions.
- Do not describe
DialectBuildPlan,SelectedRuntimePlan, manifest-backed Wist selection orWistDialectExecutionWorkflowas the current production path. - Every tracked markdown bash fence is executed in CI from repository root unless explicitly marked
ci-run=falsewith an explanation. - Long-running bash fences may declare
ci-timeoutplusci-allowed-exit-codes. - Interactive or documentation-only bash fences may declare
ci-run=false. - Command blocks that intentionally mix successful and failing commands may annotate the next command with
# ci: expect-exit=1or a comma-separated list of accepted codes.
Pull requests
- Explain what changed and why.
- Include exact validation commands/results or provider-backed workflow receipts.
- Distinguish historical/superseded diagnostic evidence from exact-head acceptance evidence.
- Keep PR scope coherent.
- Call out architectural boundaries added to preserve universality or prevent a retired owner from returning.
- Do not update exact test counts speculatively; reconcile them only from a semantically clean observed test run.