MDS Roadmap
Master tracking issue for all planned work after the v0.1.0 release. Each item links to a detailed issue with its own PRD.
Status Key
✅ Complete
🚧 In Progress
⚪ Not Started
v0.2.0 — Language Enrichment ✅
The core language gets the features users will hit first. Focus: make templates self-sufficient without external preprocessing.
feat: built-in functions (upper, lower, join, trim, length, etc.) #53 — Built-in functions (upper, lower, join, trim, length, etc.)
feat: default function arguments #54 — Default function arguments
feat: logical operators in @if conditions (&&, ||) #55 — Logical operators in @if conditions (&&, ||)
chore: re-enable wasm-opt for WASM size optimization #68 — Re-enable wasm-opt for WASM size optimization
feat: expression support in @for and @if directives #74 — Expression support in @for and @if directives
feat: frontmatter imports #75 — Frontmatter imports
Add CODE_OF_CONDUCT.md (Contributor Covenant 2.1) #38 — Add CODE_OF_CONDUCT.md
Released: 2026-06-06 — v0.2.0
v0.3.0 — Production Readiness ✅
Bridge MDS from "template language" to "production LLM input format." Add the developer workflow tooling that makes daily use pleasant.
Released: 2026-06-28 — v0.3.0
Headline Features (Complete)
Tech-Debt Sweep (Complete)
Do-set — all 11 landed in PR #117 (88ddbcc):
Already Closed (verified done): #98 , #101 , #80 , #77
v0.4.0 — Ecosystem Expansion 🚧
Expand reach beyond JS/TS. Add the quality-of-life tooling that mature languages provide.
Release state (2026-08-12). All v0.4.0 code is merged on main at 113f472; the tag has not been cut. Workspace version is still 0.3.0, and everything below the line is staged under [Unreleased]. CI at 113f472 is green as measured: both CI / CI and CodeQL / Push on main report status=completed, conclusion=success. There was a brief red window at c8b4062 — a rustfmt violation in crates/mds-cli/src/output.rs that rode in on an --admin merge over a cancelled CI run, fixed by cb44b56. That is precisely the failure mode #289 exists to close, which is why it sits in Wave 1. The remaining work is not features — it is the set of decisions and fixes that get materially more expensive once the tag makes them public surface.
Headline Features — landed ✅
Fix / hardening waves — landed ✅
Indented code fences are not recognized; {…} inside them is interpolated #149 Blank line after frontmatter is stripped on compile #150 Blank lines at @block/@end boundaries are consumed (blank runs collapse to 1) #151 --set x=true coerces to boolean, silently breaking x == "true" #152 Interpolation error suggests the wrong escape; hint \{{ fails, \{ works #153 Base-only frontmatter keys are in scope but omitted from the child output frontmatter #154 — v0.4.0 bug batch: indented + wide fences, interior-verbatim whitespace, --set-string type safety, merged @extends frontmatter, \{ hint — PR fix!: v0.4.0 bug batch — fences, whitespace, type safety, @extends FM (#149–#154) #161 (3ce9f1d)
core: base_path relative imports fail on Windows for string sources (verbatim canonicalize + '/' join) #133 — Windows base_path relative-import resolution for string sources — PR fix(core): resolve string-source @import on Windows verbatim paths #146
Add per-branch offset to IfBlock.elseif_branches for precise @elseif diagnostics #181 — per-branch offsets on IfBlock.elseif_branches for precise @elseif diagnostics — PR fix: v0.4.0 remediation — dogfooding blockers, bug batch, UX polish, docs sweep #196 (3aef465)
First dogfood remediation: blockers, bug batch, span attribution, UX polish, docs sweep — PR fix: v0.4.0 remediation — dogfooding blockers, bug batch, UX polish, docs sweep #196 (3aef465)
lint --fix: full-block-span removal for block-spanning Tier A fixes (empty-block, unreachable-branch) #172 — lint --fix full-block-span removal for block-spanning Tier A fixes; CLI/config UX; typed Python lint; WASM guard → 850K — PR fix: v0.4.0 dogfooding remediation — block-span lint fixes, span attribution, CLI/config UX, binding alignment, docs (#172 batch) #228 (f06a2d1)
Harden terminal-escape rendering across all MdsError variants (CWE-150) #176 — Harden terminal-escape rendering across all MdsError variants (CWE-150) — PR fix: harden terminal-escape rendering across all MdsError variants (CWE-150) #253 (b681129). Render path rebuilt per PF-014: sanitize inputs, not frames.
atomic_write_file: metadata() failure silently yields mode 0600 via .ok() #225 — atomic_write_file warns on metadata() failure instead of silently falling back to mode 0600 — PR fix: atomic_write_file: warn on metadata failure instead of silently using 0600 #240 (de8857d)
atomic_write_file: rename-based write does not preserve platform ACLs, xattrs, or owner/group #226 (doc half) — doc comment recording that rename-based writes do not preserve hard links, ACLs, xattrs, or owner/group — PR doc: add note about atomic_write_file not preserving hard links, ACLs, xattrs, owner/group #239 (acb8a86)
PRE-TAG DECISION: mark LintDiagnostic as #[non_exhaustive] #259 — BREAKING : LintDiagnostic marked #[non_exhaustive] + constructor added — PR feat(mds-core)!: mark LintDiagnostic #[non_exhaustive] and add constructor [#259] #286 (d8766af)
release: workflow_dispatch path fails GH006 on protected main (prepare can't push) #127 — release machinery hardened: broken workflow_dispatch -f version= path deleted, cargo publish idempotency check, bounded crates.io index poll, bump-version.mjs CHANGELOG link-table corruption fixed, examples/ outputs gitignored + examples-gitignore-coverage CI job — PR chore: harden release machinery (5 independent fixes) #287 (cb44b56)
fix(deps): clear Dependabot dev-dep advisories (vite, js-yaml, esbuild) #125 (partial) — relax 30-day soak pins for vite and js-yaml — PR chore: relax 30-day soak pins for vite and js-yaml (deferred from #125) #266 (c8b4062)
⚪ Wave 1 — everything remaining before the tag
13 issues. This list is exactly the open v0.4.0 milestone as of 2026-08-12 — no more, no less.
Wire format — bytes consumers parse; cheap today, a semver event after the tag
⚠️ Decisions needed — nobody is blocked on code here; somebody has to choose
Deprecation window — miss it and removal costs a major bump
TS public surface
Community / release hygiene
Release-safety gates
Build shape — 6 PRs on one wave branch
PRs squash-merge back into the wave branch in dependency order.
PR
Issues
Primary files
1. Lint JSON wire contract
#211 , #202 , #203
crates/mds-cli/src/lint.rs, mds-core/src/lint/diagnostic.rs, rules/unused_import.rs, formatter.rs
2. Unknown rule-name ruling
#224
mds-core/src/lint/config.rs, crates/mds-python/README.md
3. TS public surface
#180 , #215 , #213
packages/mds/src/util/options.ts, browser.ts, types.ts, backend/native.ts
4. CLI quiet/summary contract
#216
crates/mds-cli/src/build.rs:1596, lint.rs
5. Deprecate apply_fixes
#209
crates/mds-core/src/lint/fix.rs:691
6. Community + release-safety
#38 , #288 , #289
CODE_OF_CONDUCT.md, .github/workflows/
v0.4.0 gate = MEDIUM (decided 2026-08-09)
The milestone now holds only :
semver-breaking or window-limited items — wire formats, exported type surface, deprecation windows
the one live shipped bug — Expose basePath on CompileOptions to match LintOptions #180
community / release hygiene — Add CODE_OF_CONDUCT.md (Contributor Covenant 2.1) #38 , Register mdscript name on PyPI (pre-tag prerequisite) #292
release-safety gates — ci: reject control bytes and bidi codepoints in tracked source (authoring toolchain injects live ESC) #288 , process: CI checks can be cancelled and an --admin squash-merge will not notice #289
Everything else moved to v0.5.0 on a single criterion: none of it becomes more expensive after the tag. A quality or infra fix costs the same after v0.4.0 ships as it does today; a wire-format or exported-type change does not.
Moved out:
Correctness / reliability queue — output.rs path helpers fail-open on strip_prefix edge cases and non-UTF-8 paths #217 , build: stale .map sidecar left behind when switching --source-map to --inline #199 , build: empty directory build exits 0 — silent success hazard in CI #204 , debug_assert!-only invariants silently degrade in release builds (3 sites) — PF-005 #220 , build::write_output still uses truncate-then-write (non-atomic) for compiled artifacts #227
Release infrastructure — ci: SHA-pin GitHub Actions + assert lockfile version in verify-versions.mjs #163 , ci: add cargo-deny / cargo-audit supply-chain gate #136 , test: flaky cli_watch.rs::watch_ctrl_c_prints_stopped_watching (timing) #129 , ci: add a windows-latest leg to the rust CI job (Rust suite is ubuntu-only) #147 , ci(wasm): pin wasm build toolchain for deterministic size; re-tighten size budget #128 , Release hygiene: fix config drift and close gold-standard gaps #182
Carried tech-debt block — tech-debt: reduce Value cloning in evaluate_expr Var lookups #81 , tech-debt: carry base-source identity through splice_skeleton for base-default block spans #114 , tech-debt: minimize FileSystem trait — remove production-dead normalize base!="" branch #155 , tech-debt: centralize block-opener keyword literals (A1) #156 , tech-debt: mirror broken-pipe handling to stderr (R3) #157 , tech-debt: write-path TOCTOU hardening — openat/O_NOFOLLOW (S1) #160 , perf: Arc<str> hoist for per-file source in render_diag_human #255
⚪ Explicitly deferred past v0.4.0
Everything here is out of scope for the tag. Listed so the boundary is unambiguous.
Source maps follow-ups : Refactor oversized source-map core functions (CX-1, CX-2, CX-3) #184 , Source-map architecture hardening (ARCH-2, ARCH-3) #185 , Source-map performance polish (PERF-2, PERF-3, PERF-4) #186 , Source-map test-coverage gaps (TEST-4, TEST-5, TEST-6) #187 , Source-map cosmetic/consistency nits (TS-1, TS-2, CON-2, CON-4, CX-6, PY-2) #188 , source maps: --out-dir far from source produces root-climbing relative sources (sourceRoot design) #197 , source maps: static-run mapping granularity — multi-line static runs map only their first line #198 , Python: refactor source-map tests toward per-surface golden files to prevent cross-surface divergence #221
Lint internals : Refactor mds lint CLI per-file dispatch spine #173 , Centralize Severity string parsing across bindings #175 , Consolidate lint entry-file reads through NativeFs (single source of truth) #179 , Restructure apply_fixes_incremental: decompose 135-line function, collapse impossible-state guard, deduplicate regression triple #208 , lint fix-pipeline test hardening: dedup coverage and cross-rule validation #230 , cosmetic consistency sweep: tone/naming/style across lint rules and docs #231 , lint rules: simplify check_if_block and sortedness guard logic #235
Escape/render follow-ups from Harden terminal-escape rendering across all MdsError variants (CWE-150) #176 : refactor: constrain complexity of run_watch_file #256 , refactor: unify eprint_error settle patterns in watch.rs #257 , perf: eliminate double allocation in render_error_sanitized #260 , refactor: rename render_error_sanitized to clarify it is the sanitization boundary #261 , refactor: relocate sanitize_control_chars to dedicated module #262 , docs: add normative spec section for serialized error shape #263 , test: adopt pytest.raises idiom for E11 error test #264 , Reject control characters in filenames at the input boundary #265
Errors and spans : errors: remaining span-less errors — frontmatter name collisions and other sites without byte offsets #205 , resolver: messages-mode @extends type_mismatch span can mis-attribute base-origin conditions (same class as PR #196 markdown fix) #207 , evaluator: body_origin manual LIFO restore → RAII guard (future-proofing) #233
CLI/UX open questions : --set duplicate key silently last-wins — warn? #200 , find_project_root fallback UX in unmarked trees (.mdsroot discoverability) #201 , build tooling: wasm-opt local version drift (self-provisioned 117 vs CI-pinned Binaryen 129) — add a version check #206
Bindings and ecosystem : tech-debt: bound depythonize recursion depth in native bindings (stack-overflow hardening) #134 , tech-debt: centralize MAX_MODULE_COUNT (duplicated in mds-python and mds-wasm) #135 , test: cross-binding parity gaps — type_mismatch (napi) + @extends merged-FM (python) #164 , Python test: mds_cli_bin fixture silently falls through on malformed MDS_CLI_BIN env var — support CARGO_TARGET_DIR/--target layouts #214 , Python binding polish: optimize to_dict() and simplify files() closure chain #232 , examples/python/demo.py: harden None-safety for strict mypy/pyright #234
Python packaging : Python bindings: cross-platform wheel matrix + PyPI publishing (+ cp314t) #132 (wheel matrix, OIDC, cp314t) — post-tag; its pre-tag half is tracked separately as Register mdscript name on PyPI (pre-tag prerequisite) #292
Rust cleanups and module decomposition : Consolidate MAX_DEPTH from 4 per-file constants to one shared constant adjacent to collect_mds_files #218 , Rust minor cleanups from PR #196 review: bounded-loop form, discarded infallible Result, saturating_sub, unwrap_or defensibility, error label wording #219 , Tech debt: decompose oversized modules — resolver.rs (2554L) and build.rs (2020L) block safe incremental work #223 , build.rs DRY: consolidate embed_sources warnings and sidecar/stdout ladder duplication #229 , perf: collect_mds_files eagerly walks excluded dirs to count .mds files — fixed FS cost per run #238
Security hardening : security: frontmatter YAML parse exposed to alias-bomb / deep-nest DoS (uncatchable at FFI) #162 (frontmatter YAML alias-bomb / deep-nest DoS)
Write path : atomic_write_file: rename-based write does not preserve platform ACLs, xattrs, or owner/group #226 (hard links / ACLs / xattrs / owner-group — doc half landed in doc: add note about atomic_write_file not preserving hard links, ACLs, xattrs, owner/group #239 )
Repo hygiene : examples/ gitignore footgun: hand-authored .md/.json silently ignored by the catch-alls #290 (examples/ gitignore footgun — local discipline; CI structurally cannot catch it)
Type rename : Public TS: rename FileOptions to CompileFileOptions for intent clarity (breaking — target v0.5.0) #222 → v0.5.0, conditional on shipping a deprecated FileOptions alias
Closed as duplicate — tracked by the survivor:
#178 and #210 are likewise closed as duplicates; their analysis now lives in the surviving issues.
v0.5.0 — Advanced Features
Enable sharing and reuse across projects and teams.
v1.0.0 — Editor Experience (Deferred)
Full editor integration. Intentionally last — language features and production readiness come before distribution overhead. These items require significant DevOps, testing, and maintenance investment beyond the code itself.
Completed Milestones
v0.3.0 (2026-06-28) ✅
mds watch, template inheritance (@extends / @block ), HMR across all four bundler plugins
Intrinsic output format (breaking): template content decides Markdown vs JSON message array
Full 11-item tech-debt sweep
v0.2.0 (2026-06-06) ✅
18 built-in functions, default args, logical operators
Expression support in @for and @if directives
Frontmatter imports
wasm-opt re-enabled (Binaryen v129, -Oz)
Published to crates.io, npm (with SLSA provenance), and GitHub Releases
v0.1.0 (2026-05-31) ✅
Core compiler (lexer, parser, resolver, validator, evaluator)
CLI: build, check, init
JS/TS ecosystem: WASM bindings, napi-rs, universal package, Vite/Rollup/Webpack plugins
Automated release pipeline (workflow dispatch)
591+ tests, full CI/CD
Published to crates.io, npm, and GitHub Releases
Notes
Editor experience (v1.0.0) is intentionally deferred. Language enrichment and production readiness take priority — we want to ship features users can use before investing in distribution and tooling overhead.
The v0.4.0 pre-tag set is deliberately biased toward things that become expensive after the tag : wire formats, exported type names, and deprecation windows. Pure-quality tech debt is listed but is not a blocker.
Release path is tag-push : node scripts/bump-version.mjs 0.4.0 → land on main via PR → git tag -a v0.4.0 && git push origin v0.4.0. The workflow_dispatch -f version= path was deleted in chore: harden release machinery (5 independent fixes) #287 ; bare gh workflow run release.yml is now the dry-run.
MDS Roadmap
Master tracking issue for all planned work after the v0.1.0 release. Each item links to a detailed issue with its own PRD.
Status Key
v0.2.0 — Language Enrichment ✅
The core language gets the features users will hit first. Focus: make templates self-sufficient without external preprocessing.
Released: 2026-06-06 — v0.2.0
v0.3.0 — Production Readiness ✅
Bridge MDS from "template language" to "production LLM input format." Add the developer workflow tooling that makes daily use pleasant.
Released: 2026-06-28 — v0.3.0
Headline Features (Complete)
@messagetemplates compile to a JSON array, all others to Markdown; mixed content is a hard error (mds::mixed_content)^1.0.0 || ^2.0.0#106 — rspack-loader: verify @rspack/core 2.x compat + widen peer to^1.0.0 || ^2.0.0— merged in feat(ecosystem): verify & harden HMR across bundler plugins + add @mdscript/rspack-loader #105Tech-Debt Sweep (Complete)
Do-set — all 11 landed in PR #117 (
88ddbcc):Already Closed (verified done): #98, #101, #80, #77
v0.4.0 — Ecosystem Expansion 🚧
Expand reach beyond JS/TS. Add the quality-of-life tooling that mature languages provide.
Headline Features — landed ✅
{x}→{{x}}double-brace interpolation, with a lint--fixmigration path — PR feat!: double-brace {{x}} interpolation with lint --fix migration (v0.4.0) #237 (aac4070)Fix / hardening waves — landed ✅
{…}inside them is interpolated #149 Blank line after frontmatter is stripped on compile #150 Blank lines at@block/@endboundaries are consumed (blank runs collapse to 1) #151--set x=truecoerces to boolean, silently breakingx == "true"#152 Interpolation error suggests the wrong escape; hint\{{fails,\{works #153 Base-only frontmatter keys are in scope but omitted from the child output frontmatter #154 — v0.4.0 bug batch: indented + wide fences, interior-verbatim whitespace,--set-stringtype safety, merged@extendsfrontmatter,\{hint — PR fix!: v0.4.0 bug batch — fences, whitespace, type safety, @extends FM (#149–#154) #161 (3ce9f1d)base_pathrelative-import resolution for string sources — PR fix(core): resolve string-source @import on Windows verbatim paths #146IfBlock.elseif_branchesfor precise@elseifdiagnostics #181 — per-branch offsets onIfBlock.elseif_branchesfor precise@elseifdiagnostics — PR fix: v0.4.0 remediation — dogfooding blockers, bug batch, UX polish, docs sweep #196 (3aef465)3aef465)--fixfull-block-span removal for block-spanning Tier A fixes; CLI/config UX; typed Python lint; WASM guard → 850K — PR fix: v0.4.0 dogfooding remediation — block-span lint fixes, span attribution, CLI/config UX, binding alignment, docs (#172 batch) #228 (f06a2d1)MdsErrorvariants (CWE-150) — PR fix: harden terminal-escape rendering across all MdsError variants (CWE-150) #253 (b681129). Render path rebuilt per PF-014: sanitize inputs, not frames.atomic_write_filewarns onmetadata()failure instead of silently falling back to mode 0600 — PR fix: atomic_write_file: warn on metadata failure instead of silently using 0600 #240 (de8857d)acb8a86)LintDiagnosticmarked#[non_exhaustive]+ constructor added — PR feat(mds-core)!: mark LintDiagnostic #[non_exhaustive] and add constructor [#259] #286 (d8766af)workflow_dispatch -f version=path deleted,cargo publishidempotency check, bounded crates.io index poll,bump-version.mjsCHANGELOG link-table corruption fixed,examples/outputs gitignored +examples-gitignore-coverageCI job — PR chore: harden release machinery (5 independent fixes) #287 (cb44b56)c8b4062)⚪ Wave 1 — everything remaining before the tag
13 issues. This list is exactly the open
v0.4.0milestone as of 2026-08-12 — no more, no less.Wire format — bytes consumers parse; cheap today, a semver event after the tag
--format jsoncontract.@importkeyword: wrong offset/length in JSON output, wrong squiggle for any future LSP client.build --quietprints summary while lint/check/fmt suppress;linthas no directory summary #216 —build.rs:1596prints the directory summary unconditionally, violating the documented--quietcontract;linthas no aggregate summary at all.--format jsonwire format #211 — stdin labels. Four contexts, three conventions:<source>(build/check),input.mds(lint, including the JSON"file"key),<stdin>(fmt). Two of those are wire surfaces. Options A–D are written up in the issue. Deciding after the tag makesmds lint --format json -a breaking change.crates/mds-python/README.md:70), so this needs a ruling — hard error, warning, or keep-and-own-it — not a patch.Deprecation window — miss it and removal costs a major bump
apply_fixesfrom publicmds-coreAPI and schedule removal — 0 callers sinceapply_fixes_incrementalshipped #209 — deprecateapply_fixes(0 production callers). This is the pre-tag half of deprecate-at-0.4 / remove-at-0.5.TS public surface
basePathonCompileOptionsto matchLintOptions#180 — BUG (live, shipped):basePathis accepted byassertKnownKeysand then silently discarded bycompileOpt()/varsOpt(). Affects bothcompileandcheckin the published npm package. The only shipped-bug item on the milestone.lint/lintFile/lintVirtualexports tobrowser.ts(pre-existing gap) #215 —browser.tsis missing lint exports. Scope tolint+lintVirtualonly —lintFileis not implementable in a browser, so the issue title overreaches.varsOpttype narrowing #213 —options.tssecond pass: value-type validation, indexed-access safety, andvarsOpttype narrowing.Community / release hygiene
CODE_OF_CONDUCT.md(Contributor Covenant 2.1). Carried since v0.2.0.mdscriptname on PyPI (pre-tag prerequisite) #292 — register themdscriptname on PyPI. The README advertisespip install mdscript, the name is unclaimed, and the squatting window widens on announcement.Release-safety gates
0x1Bthree times;b94ef80stripped the most recent one from the escape-handling PR itself. Note the detection trap documented in the issue: BSD grep has no-P, exits 2 silently, and makes a dirty tree look clean.--adminsquash-merge will not notice. PRs doc: add note about atomic_write_file not preserving hard links, ACLs, xattrs, owner/group #239 and fix: atomic_write_file: warn on metadata failure instead of silently using 0600 #240 merged on cancelled runs and leftmainred on rustfmt untilcb44b56.Build shape — 6 PRs on one wave branch
PRs squash-merge back into the wave branch in dependency order.
crates/mds-cli/src/lint.rs,mds-core/src/lint/diagnostic.rs,rules/unused_import.rs,formatter.rsmds-core/src/lint/config.rs,crates/mds-python/README.mdpackages/mds/src/util/options.ts,browser.ts,types.ts,backend/native.tscrates/mds-cli/src/build.rs:1596,lint.rsapply_fixescrates/mds-core/src/lint/fix.rs:691CODE_OF_CONDUCT.md,.github/workflows/--format jsonwire format #211 deliberately. All three mutate the same lint JSON object; splitting them would churn the published contract twice.mdscriptname on PyPI (pre-tag prerequisite) #292 is MANUAL and cannot be delegated. Registering a PyPI name is an account action, not a code change — no agent and no PR can close it. It must happen before the tag.v0.4.0 gate = MEDIUM (decided 2026-08-09)
The milestone now holds only:
basePathonCompileOptionsto matchLintOptions#180mdscriptname on PyPI (pre-tag prerequisite) #292Everything else moved to v0.5.0 on a single criterion: none of it becomes more expensive after the tag. A quality or infra fix costs the same after v0.4.0 ships as it does today; a wire-format or exported-type change does not.
Moved out:
output.rspath helpers fail-open onstrip_prefixedge cases and non-UTF-8 paths #217, build: stale .map sidecar left behind when switching --source-map to --inline #199, build: empty directory build exits 0 — silent success hazard in CI #204,debug_assert!-only invariants silently degrade in release builds (3 sites) — PF-005 #220, build::write_output still uses truncate-then-write (non-atomic) for compiled artifacts #227debug_assert!-only invariants silently degrade in release builds (3 sites) — PF-005 #220 — the assert lives atresolver.rs:2437and guards a UTF-8 char-boundary precondition, not a sortedness invariant. It is also not the last remaining instance: there are 3 sites —resolver.rs:2437,resolver/inheritance.rs:77,resolver/inheritance.rs:174. The issue has been retitled accordingly.build::write_outputthroughatomic_write_filetrips themetadata()warning branch fix: atomic_write_file: warn on metadata failure instead of silently using 0600 #240 added atoutput.rs:459-472, which spuriously fires on first build when the output file does not yet exist. Fix that branch in the same change.rustCI job (Rust suite is ubuntu-only) #147, ci(wasm): pin wasm build toolchain for deterministic size; re-tighten size budget #128, Release hygiene: fix config drift and close gold-standard gaps #182uses:refs are SHA-pinned; 51 float.cli_watch.rs:1152(assert!(status.success(), ...)), and a separate fixed 100 ms sleep at:1157-1158gating a later stderr-content assert at:1161-1164.rustCI job (Rust suite is ubuntu-only) #147 — the never-executed#[cfg(windows)]test is atcrates/mds-core/src/resolver_tests.rs:2896. The file lives insrc/, nottests/.FileSystemtrait break in v0.5.0 is cheaper than a security regression before the tag.⚪ Explicitly deferred past v0.4.0
Everything here is out of scope for the tag. Listed so the boundary is unambiguous.
mds lintCLI per-file dispatch spine #173, Centralize Severity string parsing across bindings #175, Consolidate lint entry-file reads through NativeFs (single source of truth) #179, Restructureapply_fixes_incremental: decompose 135-line function, collapse impossible-state guard, deduplicate regression triple #208, lint fix-pipeline test hardening: dedup coverage and cross-rule validation #230, cosmetic consistency sweep: tone/naming/style across lint rules and docs #231, lint rules: simplify check_if_block and sortedness guard logic #235mds_cli_binfixture silently falls through on malformedMDS_CLI_BINenv var — supportCARGO_TARGET_DIR/--targetlayouts #214, Python binding polish: optimize to_dict() and simplify files() closure chain #232, examples/python/demo.py: harden None-safety for strict mypy/pyright #234cp314t) — post-tag; its pre-tag half is tracked separately as Registermdscriptname on PyPI (pre-tag prerequisite) #292MAX_DEPTHfrom 4 per-file constants to one shared constant adjacent tocollect_mds_files#218, Rust minor cleanups from PR #196 review: bounded-loop form, discarded infallible Result, saturating_sub, unwrap_or defensibility, error label wording #219, Tech debt: decompose oversized modules —resolver.rs(2554L) andbuild.rs(2020L) block safe incremental work #223, build.rs DRY: consolidate embed_sources warnings and sidecar/stdout ladder duplication #229, perf: collect_mds_files eagerly walks excluded dirs to count .mds files — fixed FS cost per run #238examples/gitignore footgun — local discipline; CI structurally cannot catch it)FileOptionstoCompileFileOptionsfor intent clarity (breaking — target v0.5.0) #222 → v0.5.0, conditional on shipping a deprecatedFileOptionsaliasClosed as duplicate — tracked by the survivor:
#178 and #210 are likewise closed as duplicates; their analysis now lives in the surviving issues.
v0.5.0 — Advanced Features
Enable sharing and reuse across projects and teams.
FileOptionstoCompileFileOptionsfor intent clarity (breaking — target v0.5.0) #222 — Public TS: renameFileOptions→CompileFileOptions(with deprecated alias)v1.0.0 — Editor Experience (Deferred)
Full editor integration. Intentionally last — language features and production readiness come before distribution overhead. These items require significant DevOps, testing, and maintenance investment beyond the code itself.
Completed Milestones
v0.3.0 (2026-06-28) ✅
v0.2.0 (2026-06-06) ✅
v0.1.0 (2026-05-31) ✅
Notes
node scripts/bump-version.mjs 0.4.0→ land onmainvia PR →git tag -a v0.4.0 && git push origin v0.4.0. Theworkflow_dispatch -f version=path was deleted in chore: harden release machinery (5 independent fixes) #287; baregh workflow run release.ymlis now the dry-run.