6.7 KiB
6.7 KiB
Modular Development Workflow and Traceability
Goal
- Enable incremental implementation without re-reading the entire codebase each time.
- Make module changes discoverable via grep and predictable locations.
- Keep a single source of truth for the API surface, invariants, and extension points.
Core Principles
-
Contract-first per module
- API signatures and responsibilities are documented in docs/API-SKELETONS.md and mirrored by crate modules:
- src/types.rs
- fn load_and_merge(), fn validate()
- fn from_args()
- struct LogOptions, fn init_logging()
- fn discover()
- fn plan_partitions(), fn apply_partitions()
- fn plan_filesystems(), fn make_filesystems()
- fn plan_mounts(), fn apply_mounts(), fn maybe_write_fstab()
- const REPORT_VERSION, fn build_report(), fn write_report()
- struct Context, fn run()
- fn detect_existing_state(), fn is_empty_disk()
- struct CmdOutput, fn which_tool(), fn run_cmd(), fn run_cmd_capture(), fn udev_settle()
- API signatures and responsibilities are documented in docs/API-SKELETONS.md and mirrored by crate modules:
-
Grep-able region markers in code
- Every module contains the following optional annotated regions:
- // REGION: API
- // REGION: EXTENSION_POINTS
- // REGION: SAFETY
- // REGION: ERROR_MAPPING
- // REGION: TODO
- Example snippet to add near top of a module: // REGION: API // api: device::discover(filter: &DeviceFilter) -> Result<Vec> // api: device::DeviceProvider // REGION: API-END
- These must be kept concise, one-liners per function/trait/struct; they act as a quick index for search.
- Every module contains the following optional annotated regions:
-
Stable identifiers for cross-references
- Use short identifiers in comments to reference public items:
- api: module::item
- ext: module::hook_or_trait
- safety: module::invariant_name
- errmap: module::error_path
- This allows quick discovery via regex: grep -R "api: device::" src/
- Use short identifiers in comments to reference public items:
-
Single source of truth for API surface
- Keep high-level API in docs/API-SKELETONS.md as canonical index. After adding/removing a public function or type, update this file.
- Add a short note in docs/SPECS.md if behavior or invariants change.
-
Architectural decisions recorded as ADRs
- Use docs/adr/NNNN-title.md to document decisions (context, decision, consequences).
- Start with docs/adr/0001-modular-workflow.md (added alongside this doc).
- Link ADRs from docs/ARCHITECTURE.md when they supersede or refine prior guidance.
-
Module ownership and boundaries
- Add a “Module Responsibilities” section in each module’s header doc comment summarizing scope and non-goals.
- Example references:
-
Invariants and safety notes
- For code that must uphold safety or idempotency invariants, annotate with: // SAFETY: explanation // IDEMPOTENCY: explanation
- Example locations:
- fn apply_partitions() must enforce empty-disks rule when configured.
- fn make_filesystems() must not run if partitioning failed.
-
Error mapping consistency
- Centralize conversions to enum Error. When calling external tools, wrap failures into Error::Tool with stderr captured.
- Annotate mapping areas with: // ERROR: mapping external failure to Error::Tool
-
Module-local CHANGELOG entries
- Keep a single CHANGELOG in the repo root, plus module-local “Changes” sections appended on each module top comment (short bullets).
- Cross-link to the ADR when relevant.
-
Task-level breadcrumbs
- For multi-step features, add a short progress marker at top of relevant modules: // TODO(KILO): feature-X step 2/4 – parsing args done; next implement validation
- Summary of active tasks can also live in docs/SPECS.md under “In-Progress Work”.
- Example configs and fixtures
- Keep comprehensive examples in:
- Add minimal example variants if needed for tests (future):
- examples/config/minimal.yaml
- examples/config/dual-btrfs.yaml
- examples/config/ssd-hdd-bcachefs.yaml
- “Golden paths” for resuming work
- If resuming work later:
- Read module headers for responsibilities
- Grep for REGION markers: API / TODO / SAFETY / ERROR_MAPPING
- Check docs/API-SKELETONS.md for contract changes
- Check latest ADRs in docs/adr/
- Check docs/SPECS.md and the “In-Progress Work” section (if used)
Checklist for adding a new feature
- Update contracts:
- Add or modify function/type signatures in code and reflect in docs/API-SKELETONS.md
- Add REGION: API one-liners for the new items
- Update invariants:
- Add REGION: SAFETY notes if needed
- Update specs:
- Document behavior in docs/SPECS.md
- If it is a long-term decision, add an ADR under docs/adr/
- Add examples if config or output formats change
- Update config/zosstorage.example.yaml or add a new example file
- Keep error mapping and logging consistent:
- Ensure any external tool calls map errors to enum Error
- Run cargo build and update any broken references
Optional automation (future)
- A simple “index check” script (cargo xtask) could validate:
- All public items referenced under REGION: API appear in docs/API-SKELETONS.md
- No broken module references
- REGION markers are well-formed
By following these conventions, changes stay localized and discoverable. A contributor (human or assistant) can quickly locate relevant areas by scanning module headers, REGION markers, and the centralized API/docs without re-reading the entire tree.