Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .devflow/features/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Feature Knowledge Index

- **bundler-plugins** — packages/bundler-utils/, packages/vite-plugin/, packages/rollup-plugin/, packages/webpack-loader/, packages/rspack-loader/ — Use when adding a new bundler integration, modifying the emitted-module contract, debugging HMR behavior, working on the CJS compatibility shim, updating the transformer/loader factory, registering a new package in the release pipeline, or investigating why a .mds file emits unexpected output. Keywords: createMdsTransformer, createMdsLoader, bundler-utils, vite-plugin, rollup-plugin, webpack-loader, rspack-loader, addWatchFile, addDependency, handleHotUpdate, emitted module contract, export default string, export default Message[], safeJsonForJs, escapeForJs, metadata, kind, markdown, messages, discriminated union, mds.d.ts, MdsMessage, string | MdsMessage[].
- **mds-cli** — crates/mds-cli/ — Use when adding new subcommands, changing output-path resolution logic, modifying the watch architecture, adding new compile paths, updating mds.json config handling, debugging stdout/stderr stream separation, investigating exit codes, adding directory-mode build/check support, or working on stale-output cleanup. Keywords: mds build, mds check, mds watch, mds init, OutputKind, run_build, run_watch, build.rs, output.rs, watch.rs, mds.json, output_dir, resolve_output_base, OutputBase, output_path_for, compile_and_write, compile_to_content, intrinsic extension, run_build_directory, run_check_directory, is_partial, collect_mds_files, probe_and_remove_stale, canonicalize_out_dir, output_base_no_ext, continue-on-error, subtree mirror, symlink guard, 10 MiB cap.
- **mds-compiler** — crates/mds-core/ — Use when working on the MDS compilation pipeline, adding directives, modifying scope/variable handling, extending the module system, debugging output rendering, working with @message blocks, the intrinsic output format, CompiledOutput, CompileResult, or mixed-content errors. Keywords: lexer, parser, evaluator, resolver, validator, scope, frontmatter, interpolation, directive, import, include, define, for, if, message, @message, CompiledOutput, CompileResult, into_markdown, into_messages, intrinsic, mixed_content, MixedContent, has_message_block, process_module_intrinsic, collect_messages_strict, evaluate_messages_intrinsic, TextNode.offset.
- **mds-fmt** — crates/mds-core/src, crates/mds-cli/src — Use when modifying the mds fmt formatter engine (crates/mds-core/src/formatter.rs), the mds fmt CLI subcommand (crates/mds-cli/src/fmt.rs), any change to mds-core's output model (clean_output, evaluate_nodes, @message/@define body evaluation, the lexer's fence recognition) that could silently break the formatter's compile-equivalence guarantee, or changes to the shared directory walker (output.rs). Keywords: mds fmt, format_str, format_str_with, format_str_named, FormatterInvariant, clean_output, compile-equivalence, idempotent, assert_equivalent, structural_equivalent, strip_trailing_insignificant_text, in_raw_content, raw_content_spans, protected_spans, R1 R2 R3 R4, safety gate, token lossiness, @message body, @define body, @block body, FmtConfig, FmtFlags, interior-verbatim contract, try_scan_fence_at, FenceMatch, deep_merge_yaml, RESERVED_MERGE_KEYS, is_default_excluded_dir, is_within_default_excluded_dir, walker exclusions, node_modules, hidden dirs, effective_parent, bare filename, atomic_write_file.
- **mds-lint** — crates/mds-core/src/lint, crates/mds-cli/src, crates/mds-wasm/src, crates/mds-napi/src, crates/mds-python/src, packages/mds/src — Use when adding or modifying lint rules, extending the --fix pipeline, changing the JSON wire format, wiring lint into a binding layer, debugging unexpected exit codes and reverify gate refusals, or working on the ESC/bidi/newline injection defences. Keywords: mds lint, LintDiagnostic, fix_removals, fix_edits, TextEdit, FixLineSpan, diag_to_edits, LintResult, LintConfig, to_canonical_json, fix tier, reverify gate, FixOutcome, PartiallyFixed, apply_fixes_incremental, preview_fixes, PreviewOutcome, set_diag_display_path, AnalysisContext, ElseifBranch, end_offset, DefineFact, assertKnownKeys, CheckOptions, unreachable-branch, unused-variable, duplicate-import, empty-block, legacy-interpolation, is_output_neutral, all_output_neutral, Tier A Tier B Tier C, structural-standalone, compile-clean, is_standalone, sanitize_control_chars, sanitize_control_chars_wire, named_source_for_render, neutralize_source_for_render, SanitizedReport, SanitizedNode, MAX_AUX_DEPTH, EscapeMode, HUMAN WIRE, eprint_warning, safe_path, safe_inline, safe_file_display, preview_text_for, print_discipline, reverify_failure_reason, LintDirCtx, config_cache, dedup_contained_or_identical, EXIT 0 1 2 3, render_error_sanitized, eprint_error, display_sanitized, MdsError::display_sanitized, ESC-injection, CWE-150, CWE-117, bidi, Trojan-Source, CVE-2021-42574, U+061C, U+202E, U+FEFF, U+2028, U+2029, PF-014, PF-005, construction-time sanitization, per-field rule, Cow, #176, ADR-008, ResultSink, from_rules_checked, relative_display, write_bytes, PF-020, #309, emit-ordering.
- **source-map-security** — crates/mds-core/src, crates/mds-cli/src, packages/mds/src — Use when working with Source Map v3 generation, sources[] path relativization, the relativize_source choke-point, FileSystem::source_root(), CompileOptions.source_map_base, cross-surface source-map parity tests, or the Windows verbatim UNC path fix. Keywords: source map, sources[], relativize_source, source_map_base, source_root, path containment, basename fallback, PF-005, ADR-005, SEC-3, Windows verbatim UNC, path_to_unified, compute_source_map_base, apply_source_map_file_label, CF-SM2, V-SM1, differential test, two-level anchoring, map-relative, root-relative.
- **mds-js** — packages/mds/src, packages/mds/__test__ — Use when modifying the JS/TS public API surface, adding backend methods, changing option types, debugging basePath rejection behaviour, changing result types, updating the backend contract, working on WASM/native backend validation, or debugging why a backend result is rejected. Keywords: compileFile, compile, check, checkFile, lint, lintFile, lintVirtual, CompileResult, MarkdownResult, MessagesResult, CheckResult, LintResult, LintDiagnostic, LintFileOptions, CompileFileOptions, FileOptions, assertResultShape, validateBackendMethods, METHOD_KEYS, forwardOpts, assertKnownKeys, getBasePathError, BASEPATH_REJECTORS, BASE_METHODS, NODE_METHODS, WASM_EXPORTS, discriminated union, kind, mds::invalid_backend_result, mds::invalid_options, basePath, synchronous throw, native.ts, wasm.ts, contract.ts, types.ts, node.ts, browser.ts, options.ts.
- **mds-lint** — crates/mds-core/src/lint, crates/mds-cli/src, crates/mds-wasm/src, crates/mds-napi/src, crates/mds-python/src, packages/mds/src — Use when adding or modifying lint rules, extending the --fix pipeline, changing the JSON wire format, wiring lint into a binding layer, debugging unexpected exit codes and reverify gate refusals, or working on the ESC/bidi/newline injection defences. Keywords: mds lint, LintDiagnostic, fix_removals, fix_edits, TextEdit, FixLineSpan, diag_to_edits, LintResult, LintConfig, to_canonical_json, fix tier, reverify gate, FixOutcome, PartiallyFixed, apply_fixes_incremental, preview_fixes, PreviewOutcome, set_diag_display_path, AnalysisContext, ElseifBranch, end_offset, DefineFact, assertKnownKeys, CheckOptions, unreachable-branch, unused-variable, duplicate-import, empty-block, legacy-interpolation, is_output_neutral, all_output_neutral, Tier A Tier B Tier C, structural-standalone, compile-clean, is_standalone, sanitize_control_chars, sanitize_control_chars_wire, named_source_for_render, neutralize_source_for_render, SanitizedReport, SanitizedNode, MAX_AUX_DEPTH, EscapeMode, HUMAN WIRE, eprint_warning, safe_path, safe_inline, safe_file_display, preview_text_for, print_discipline, reverify_failure_reason, LintDirCtx, config_cache, dedup_contained_or_identical, EXIT 0 1 2 3, render_error_sanitized, eprint_error, display_sanitized, MdsError::display_sanitized, ESC-injection, CWE-150, CWE-117, bidi, Trojan-Source, CVE-2021-42574, U+061C, U+202E, U+FEFF, U+2028, U+2029, PF-014, PF-005, construction-time sanitization, per-field rule, Cow, #176, ADR-008, ResultSink, from_rules_checked, relative_display, write_bytes, PF-020, #309, emit-ordering.
- **mds-napi** — crates/mds-napi/ — Use when modifying the native addon API surface, adding new napi exports, debugging FFI marshaling, working on error serialization, understanding the discriminated-union wire format, or investigating why a JS caller gets unexpected result shapes. Keywords: mds-napi, napi-rs, compile, compileFile, check, checkFile, build_canonical_result, CheckResult, serde_json::Value, ToNapiValue, discriminated union, kind, output, messages, absent field, mds::mixed_content, mds::internal, mds::invalid_options, mds::resource_limit, throw_mds_error, run_catching, catch_unwind.
- **release-pipeline** — .github/workflows, .github/actions, scripts, scripts/__test__ — Use when modifying release.yml, adding CI jobs, updating TIER_B_EXPECTED_SKIPPED, adjusting the pull_request surface trigger, debugging a publish failure, running the pre-merge verifier, or reasoning about the publish job ordering. Keywords: release, release.yml, verify-pr-checks, TIER_B_EXPECTED_SKIPPED, RELEASE_SURFACE, rehearse-publish-python, tag-push, TestPyPI, publish-crates, publish-npm, publish-python, github-release, version-gate, stage-and-verify-napi, ADR-013, PF-040.
- **source-map-security** — crates/mds-core/src, crates/mds-cli/src, packages/mds/src — Use when working with Source Map v3 generation, sources[] path relativization, the relativize_source choke-point, FileSystem::source_root(), CompileOptions.source_map_base, cross-surface source-map parity tests, or the Windows verbatim UNC path fix. Keywords: source map, sources[], relativize_source, source_map_base, source_root, path containment, basename fallback, PF-005, ADR-005, SEC-3, Windows verbatim UNC, path_to_unified, compute_source_map_base, apply_source_map_file_label, CF-SM2, V-SM1, differential test, two-level anchoring, map-relative, root-relative.
6 changes: 4 additions & 2 deletions .devflow/features/mds-cli/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ referencedFiles:
- crates/mds-cli/tests/intrinsic_output.rs
- crates/mds-cli/Cargo.toml
created: 2026-06-26
updated: 2026-09-15
updated: 2026-09-16
---

# MDS CLI (mds-cli)

## Overview

`crates/mds-cli/` implements the `mds` binary with four subcommands: `build`, `check`, `watch`, and `init`. The CLI delegates all compilation to `mds-core`; its job is input resolution, output routing, config loading, and process lifecycle. After the intrinsic-output refactor, **the output extension is derived from the compiled result's kind** — there is no `--format` flag. Markdown templates produce `.md` files; messages templates produce `.json` files.
`crates/mds-cli/` implements the `mds` binary with six subcommands: `build`, `check`, `fmt`, `lint`, `watch`, and `init`. The CLI delegates all compilation to `mds-core`; its job is input resolution, output routing, config loading, and process lifecycle. After the intrinsic-output refactor, **the output extension is derived from the compiled result's kind** — there is no `--format` flag. Markdown templates produce `.md` files; messages templates produce `.json` files.

The CLI now supports both single-file and directory modes for `build` and `check`. Directory mode (`mds build <dir>` / `mds check <dir>`) recursively compiles all non-partial `.mds` files under the given root, mirrors the subtree into an optional `--out-dir`, and continues on error with a final summary.

Expand Down Expand Up @@ -205,6 +205,8 @@ Exit codes:
- Watch mode derives the extension from `compiled.kind.extension()` after each compile. On deletion it must probe both `.md` and `.json` since the kind is not known.
- The `CompileOutput` struct in `build.rs` is a local CLI struct (content + kind + deps) — not the same as `mds::CompiledOutput` (the Rust enum). The naming is similar but they are different types.
- `mds.json build.output_dir` rejects `..` components at parse time to prevent path traversal. This check runs in both single-file and directory mode.
- Debounce is a quiet period, not a fixed window (#379, `watch.rs`): the first relevant content event opens a `--debounce` window and every further content event restarts it (`Access` events and watch errors do not restart it); the window is bounded by `debounce_cap = max(10 × window, 1s)` and `--debounce` itself is clamped to `MAX_DEBOUNCE_MS = 60_000` (60s), with an additional `MAX_DEBOUNCE_MESSAGES = 10_000` drained-message cap; a window's exit reason is one of `DebounceEnd::{Quiet, Cap, MessageLimit, Disabled, Interrupted, Disconnected}`.
- Every write the CLI performs funnels through `atomic_write_file` (`output.rs`, #227): temp-file + rename, refusing a symlink at the target; `Durability::Fsync` is used for source rewrites (`fmt`, `lint --fix`) and `Durability::RenameOnly` for reproducible derived artifacts (`build`/`watch`/`init`, #386). `crates/mds-cli/tests/write_funnel.rs` is a lexical guard that fails if a new raw `fs::write`/`File::create` site appears in `crates/mds-cli/src/**` outside its allow-list. An empty directory is now a hard failure (not silent success) for `build`/`check`/`fmt`/`lint` (#204), and a directory whose only `.mds` files are partials is the same "nothing to do" failure (#387).

## Key Files

Expand Down
Loading
Loading