mustflow 2.32.0 → 2.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/cli/commands/api/actions.js +55 -0
  2. package/dist/cli/commands/api/report-runner.js +62 -0
  3. package/dist/cli/commands/api/serve.js +149 -0
  4. package/dist/cli/commands/api/workspace-recommendations.js +13 -0
  5. package/dist/cli/commands/api.js +15 -275
  6. package/dist/cli/lib/local-index/search-read-model.js +44 -7
  7. package/dist/cli/lib/validation/frontmatter.js +75 -0
  8. package/dist/cli/lib/validation/index.js +4 -86
  9. package/dist/cli/lib/validation/safe-read.js +13 -0
  10. package/dist/core/active-run-locks.js +110 -10
  11. package/dist/core/run-performance-history.js +14 -1
  12. package/dist/core/validation-ratchet.js +1 -1
  13. package/package.json +1 -1
  14. package/templates/default/i18n.toml +61 -19
  15. package/templates/default/locales/en/.mustflow/docs/agent-workflow.md +15 -7
  16. package/templates/default/locales/en/.mustflow/skills/INDEX.md +21 -8
  17. package/templates/default/locales/en/.mustflow/skills/adapter-boundary/SKILL.md +9 -2
  18. package/templates/default/locales/en/.mustflow/skills/ai-generated-code-hardening/SKILL.md +249 -0
  19. package/templates/default/locales/en/.mustflow/skills/api-contract-change/SKILL.md +16 -11
  20. package/templates/default/locales/en/.mustflow/skills/auth-permission-change/SKILL.md +11 -4
  21. package/templates/default/locales/en/.mustflow/skills/backend-reliability-change/SKILL.md +289 -0
  22. package/templates/default/locales/en/.mustflow/skills/css-code-change/SKILL.md +24 -14
  23. package/templates/default/locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md +18 -7
  24. package/templates/default/locales/en/.mustflow/skills/frontend-render-stability/SKILL.md +144 -0
  25. package/templates/default/locales/en/.mustflow/skills/go-code-change/SKILL.md +70 -18
  26. package/templates/default/locales/en/.mustflow/skills/html-code-change/SKILL.md +20 -13
  27. package/templates/default/locales/en/.mustflow/skills/http-delivery-streaming/SKILL.md +205 -0
  28. package/templates/default/locales/en/.mustflow/skills/performance-budget-check/SKILL.md +9 -7
  29. package/templates/default/locales/en/.mustflow/skills/powershell-code-change/SKILL.md +158 -0
  30. package/templates/default/locales/en/.mustflow/skills/proactive-risk-surfacing/SKILL.md +198 -0
  31. package/templates/default/locales/en/.mustflow/skills/python-code-change/SKILL.md +27 -11
  32. package/templates/default/locales/en/.mustflow/skills/routes.toml +43 -1
  33. package/templates/default/locales/en/.mustflow/skills/rust-code-change/SKILL.md +41 -17
  34. package/templates/default/locales/en/.mustflow/skills/service-boundary-architecture/SKILL.md +167 -0
  35. package/templates/default/locales/en/.mustflow/skills/tailwind-code-change/SKILL.md +37 -23
  36. package/templates/default/locales/en/.mustflow/skills/tauri-code-change/SKILL.md +27 -10
  37. package/templates/default/locales/en/.mustflow/skills/typescript-code-change/SKILL.md +22 -4
  38. package/templates/default/locales/en/.mustflow/skills/unocss-code-change/SKILL.md +34 -15
  39. package/templates/default/locales/en/.mustflow/skills/version-freshness-check/SKILL.md +29 -5
  40. package/templates/default/locales/en/AGENTS.md +3 -2
  41. package/templates/default/locales/ko/.mustflow/docs/agent-workflow.md +13 -8
  42. package/templates/default/locales/ko/AGENTS.md +2 -2
  43. package/templates/default/manifest.toml +44 -1
@@ -2,11 +2,11 @@
2
2
  mustflow_doc: skill.python-code-change
3
3
  locale: en
4
4
  canonical: true
5
- revision: 2
5
+ revision: 3
6
6
  lifecycle: mustflow-owned
7
7
  authority: procedure
8
8
  name: python-code-change
9
- description: Apply this skill when Python source, packaging, runtime version, import layout, type checking, linting, tests, or CLI entry points are created or changed.
9
+ description: Apply this skill when Python source, standard-library API usage, packaging, runtime version, import layout, type checking, linting, tests, or CLI entry points are created or changed.
10
10
  metadata:
11
11
  mustflow_schema: "1"
12
12
  mustflow_kind: procedure
@@ -28,13 +28,13 @@ metadata:
28
28
  <!-- mustflow-section: purpose -->
29
29
  ## Purpose
30
30
 
31
- Preserve Python runtime, packaging, import, async resource, public API, typing, lint, and test boundaries while making a focused change.
31
+ Preserve Python runtime, standard-library, packaging, import, async resource, public API, typing, lint, and test boundaries while making a focused change.
32
32
 
33
33
  <!-- mustflow-section: use-when -->
34
34
  ## Use When
35
35
 
36
36
  - `.py`, `pyproject.toml`, `setup.py`, `setup.cfg`, requirements files, lockfiles, tox, nox, pytest, mypy, pyright, Ruff, or Python CI config changes.
37
- - The task touches package layout, CLI entry points, imports, type hints, dependency declarations, virtual environment assumptions, or tests.
37
+ - The task touches standard-library feature usage, package layout, CLI entry points, imports, type hints, dependency declarations, virtual environment assumptions, or tests.
38
38
 
39
39
  <!-- mustflow-section: do-not-use-when -->
40
40
  ## Do Not Use When
@@ -46,6 +46,7 @@ Preserve Python runtime, packaging, import, async resource, public API, typing,
46
46
  ## Required Inputs
47
47
 
48
48
  - Python version source: `requires-python`, `.python-version`, tool version files, CI matrix, or container base image.
49
+ - Standard-library feature and runtime-behavior assumptions, especially when using Python-version-gated APIs or changed security defaults.
49
50
  - Packaging and dependency files, test config, lint config, and type checker config.
50
51
  - Package layout: `src` layout, flat layout, namespace package, distribution name, import package name, package discovery settings, CLI entry points, plugin entry points, and nearby tests.
51
52
  - Async ownership and resource cleanup surface when coroutines, tasks, context managers, sessions, clients, pools, files, async generators, subprocesses, or logging change.
@@ -56,6 +57,7 @@ Preserve Python runtime, packaging, import, async resource, public API, typing,
56
57
  ## Preconditions
57
58
 
58
59
  - Determine the lowest supported Python version before choosing syntax or typing features.
60
+ - Determine the lowest supported Python version before choosing standard-library features, changed defaults, syntax, or typing features.
59
61
  - Read package layout and import style before editing imports.
60
62
  - Treat global machine Python state as irrelevant unless the project explicitly declares it.
61
63
 
@@ -85,7 +87,19 @@ Preserve Python runtime, packaging, import, async resource, public API, typing,
85
87
  - installed console scripts or plugin entry points should be smoke-tested through the installed entry point contract, not by directly running a source file.
86
88
  8. Verify import origin when packaging risk is present. The public package should resolve from the installed environment intended by the project, not from accidental repository-root files.
87
89
  9. Validate unknown external data before treating it as typed domain data.
88
- 10. Preserve async and resource ownership:
90
+ 10. Choose standard-library helpers by semantic contract and supported Python version:
91
+ - prefer cardinality-explicit iteration such as `zip(strict=True)`, `itertools.batched(..., strict=True)`, or Python 3.14+ `map(strict=True)` only when unequal lengths are a bug and the declared runtime supports the API;
92
+ - do not use `itertools.groupby` as a database-style grouping primitive unless input ordering and group materialization are intentional;
93
+ - avoid shared mutable defaults; use `default_factory` or an existing local construction pattern for per-instance mutable state;
94
+ - prefer `importlib.resources` for packaged data, `tomllib` for TOML reads, and `Path.walk()` only after checking version support, pruning behavior, symlink recursion, ordering, and cycle risks;
95
+ - use dataclass options such as `slots`, `frozen`, and `kw_only`, `StrEnum`, `TypedDict`, or `Protocol` only when they match the public shape and runtime/type-checker support;
96
+ - treat `functools.cache`, `lru_cache`, `cached_property`, `partial`, and Python 3.14+ `Placeholder` as state, memory, concurrency, and versioned-API choices rather than harmless terseness.
97
+ 11. Keep process, archive, and concurrency safety explicit:
98
+ - subprocess calls use argument lists, checked failure handling, timeouts, bounded captured output, and a narrow `shell=True` exception when the project already permits it;
99
+ - archive extraction, including `tarfile`, keeps untrusted archive inspection, extraction filters, partial-extract cleanup, and older-runtime defaults visible;
100
+ - `asyncio.TaskGroup`, `asyncio.timeout`, and `asyncio.to_thread` are used only when their cancellation, timeout, blocking-work, and Python-version semantics fit the surrounding lifecycle.
101
+ 12. Use runtime diagnostics as evidence, not as permanent workaround code. Interpreter or library diagnostics such as import timing, `tracemalloc`, `faulthandler`, profiling, and allocation tracing should go through configured diagnostic or verification intents when available, and missing intents should be reported instead of adding ad hoc command recipes to the skill.
102
+ 13. Preserve async and resource ownership:
89
103
  - every coroutine is awaited, returned by contract, or scheduled as an owned and tracked task;
90
104
  - raw background task creation is allowed only through the project's owner or spawn helper, a task group, or an equivalent lifecycle mechanism;
91
105
  - background tasks keep a strong reference, have a shutdown path, and retrieve failures instead of leaving never-retrieved exceptions;
@@ -94,20 +108,21 @@ Preserve Python runtime, packaging, import, async resource, public API, typing,
94
108
  - context managers and async context managers do not suppress exceptions unless suppression is the feature;
95
109
  - context-manager helpers that catch exceptions for logging re-raise after logging;
96
110
  - early-exit async generators have an explicit close path.
97
- 11. Preserve traceback evidence. Logging inside exception handlers should retain exception information instead of logging only the exception message.
98
- 12. Preserve public contracts:
111
+ 14. Preserve traceback evidence. Logging inside exception handlers should retain exception information instead of logging only the exception message.
112
+ 15. Preserve public contracts:
99
113
  - treat public imports, public signatures, exceptions, return shapes, CLI behavior, entry points, config keys, environment variables, dependency metadata, extras, Python version support, and typing stubs as compatibility-sensitive;
100
114
  - do not change sync functions into async functions, accepted input shapes, nullable behavior, documented exception types, tuple/dict/dataclass return shapes, config precedence, or environment variable semantics without a compatibility review;
101
115
  - typed packages should keep runtime and typing surfaces aligned, including `py.typed` and stubs when present.
102
- 13. Avoid mutable default arguments, broad `except Exception: pass`, broad `BaseException` catches outside process boundaries, global state hidden behind module imports, and path handling that ignores existing `pathlib` or OS conventions.
103
- 14. Use `# type: ignore[...]` only when tightly scoped, justified, and consistent with local policy.
104
- 15. If packaging, public API, CLI, config, or typing contracts change, synchronize README examples, entry point tests, build metadata, docs, fixtures, and downstream-style examples that describe installation or usage.
105
- 16. Choose configured verification intents that cover formatting, lint, type checking, tests, package build, installed-package smoke checks, and CLI smoke risk when available.
116
+ 16. Avoid mutable default arguments, broad `except Exception: pass`, broad `BaseException` catches outside process boundaries, global state hidden behind module imports, and path handling that ignores existing `pathlib` or OS conventions.
117
+ 17. Use `# type: ignore[...]` only when tightly scoped, justified, and consistent with local policy.
118
+ 18. If packaging, public API, CLI, config, or typing contracts change, synchronize README examples, entry point tests, build metadata, docs, fixtures, and downstream-style examples that describe installation or usage.
119
+ 19. Choose configured verification intents that cover formatting, lint, type checking, tests, package build, installed-package smoke checks, and CLI smoke risk when available.
106
120
 
107
121
  <!-- mustflow-section: postconditions -->
108
122
  ## Postconditions
109
123
 
110
124
  - The code respects the declared Python version and packaging layout.
125
+ - Python-version-gated standard-library features and changed runtime defaults are accepted only when the declared support matrix allows them.
111
126
  - Imports work from the project-supported execution path.
112
127
  - Packaging changes distinguish development imports from release artifact imports.
113
128
  - Async tasks, context managers, files, clients, pools, subprocesses, and generators have visible ownership and cleanup.
@@ -136,6 +151,7 @@ Report missing package, type, or test intents rather than inventing raw tool com
136
151
  - If a test only passes because repository root, `src`, or `tests` is injected into import paths, reject the fix and repair packaging or test layout instead.
137
152
  - If packaging correctness matters but only repository-root tests can run, report that wheel or installed-artifact verification is missing.
138
153
  - If the supported Python version blocks a syntax choice, rewrite to the supported form.
154
+ - If the supported Python version blocks a standard-library feature, changed default, diagnostic flag, or helper API, use the supported equivalent or report the runtime-support decision instead of silently raising `requires-python`.
139
155
  - If third-party stubs or package metadata are wrong, document the local workaround and keep it narrow.
140
156
  - If a background task lacks owner, shutdown, strong reference, or exception retrieval, do not add it.
141
157
  - If cancellation or context-manager behavior is swallowed accidentally, restore propagation or document the intentional suppression contract.
@@ -12,6 +12,12 @@ route_type = "primary"
12
12
  priority = 70
13
13
  applies_to_reasons = ["code_change", "cross_cutting_code_change"]
14
14
 
15
+ [routes."service-boundary-architecture"]
16
+ category = "architecture_patterns"
17
+ route_type = "primary"
18
+ priority = 82
19
+ applies_to_reasons = ["code_change", "behavior_change", "data_change", "migration_change", "performance_change", "security_change", "privacy_change", "public_api_change"]
20
+
15
21
  [routes."code-review"]
16
22
  category = "general_code"
17
23
  route_type = "primary"
@@ -72,6 +78,12 @@ route_type = "adjunct"
72
78
  priority = 85
73
79
  applies_to_reasons = ["unknown_change", "code_change", "behavior_change", "public_api_change", "test_change", "docs_change", "mustflow_docs_change", "mustflow_config_change", "package_metadata_change", "release_risk"]
74
80
 
81
+ [routes."proactive-risk-surfacing"]
82
+ category = "workflow_contracts"
83
+ route_type = "event"
84
+ priority = 72
85
+ applies_to_reasons = ["unknown_change", "code_change", "behavior_change", "test_change", "docs_change", "mustflow_docs_change", "public_api_change", "security_change", "privacy_change", "data_change", "performance_change", "ui_change", "release_risk"]
86
+
75
87
  [routes."restricted-handoff-resume"]
76
88
  category = "workflow_contracts"
77
89
  route_type = "primary"
@@ -138,6 +150,12 @@ route_type = "primary"
138
150
  priority = 55
139
151
  applies_to_reasons = ["unknown_change", "code_change", "docs_change", "test_change", "behavior_change", "performance_change", "ui_change", "data_change"]
140
152
 
153
+ [routes."ai-generated-code-hardening"]
154
+ category = "general_code"
155
+ route_type = "adjunct"
156
+ priority = 74
157
+ applies_to_reasons = ["unknown_change", "code_change", "behavior_change", "test_change", "public_api_change", "performance_change"]
158
+
141
159
  [routes."clarifying-question-gate"]
142
160
  category = "general_code"
143
161
  route_type = "adjunct"
@@ -186,11 +204,23 @@ route_type = "primary"
186
204
  priority = 82
187
205
  applies_to_reasons = ["code_change", "public_api_change", "docs_change", "test_change"]
188
206
 
207
+ [routes."backend-reliability-change"]
208
+ category = "general_code"
209
+ route_type = "primary"
210
+ priority = 84
211
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "data_change", "migration_change", "performance_change", "security_change", "privacy_change", "docs_change", "test_change", "package_metadata_change", "release_risk"]
212
+
213
+ [routes."http-delivery-streaming"]
214
+ category = "general_code"
215
+ route_type = "primary"
216
+ priority = 84
217
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "performance_change", "security_change", "privacy_change", "docs_change", "test_change", "package_metadata_change", "release_risk"]
218
+
189
219
  [routes."typescript-code-change"]
190
220
  category = "general_code"
191
221
  route_type = "primary"
192
222
  priority = 85
193
- applies_to_reasons = ["code_change", "public_api_change", "test_change"]
223
+ applies_to_reasons = ["code_change", "public_api_change", "test_change", "package_metadata_change"]
194
224
 
195
225
  [routes."javascript-code-change"]
196
226
  category = "general_code"
@@ -204,6 +234,12 @@ route_type = "primary"
204
234
  priority = 85
205
235
  applies_to_reasons = ["code_change", "public_api_change", "test_change"]
206
236
 
237
+ [routes."powershell-code-change"]
238
+ category = "general_code"
239
+ route_type = "primary"
240
+ priority = 85
241
+ applies_to_reasons = ["code_change", "test_change", "docs_change", "package_metadata_change", "workflow_change"]
242
+
207
243
  [routes."go-code-change"]
208
244
  category = "general_code"
209
245
  route_type = "primary"
@@ -468,6 +504,12 @@ route_type = "adjunct"
468
504
  priority = 60
469
505
  applies_to_reasons = ["migration_change"]
470
506
 
507
+ [routes."frontend-render-stability"]
508
+ category = "ui_assets"
509
+ route_type = "primary"
510
+ priority = 78
511
+ applies_to_reasons = ["ui_change", "performance_change", "behavior_change", "code_change"]
512
+
471
513
  [routes."ui-quality-gate"]
472
514
  category = "ui_assets"
473
515
  route_type = "primary"
@@ -2,11 +2,11 @@
2
2
  mustflow_doc: skill.rust-code-change
3
3
  locale: en
4
4
  canonical: true
5
- revision: 3
5
+ revision: 4
6
6
  lifecycle: mustflow-owned
7
7
  authority: procedure
8
8
  name: rust-code-change
9
- description: Apply this skill when Rust source, Cargo metadata, features, traits, errors, ownership, async runtime, unsafe code, tests, examples, or public crate APIs are created or changed.
9
+ description: Apply this skill when Rust source, Cargo metadata, features, traits, errors, ownership, async runtime, unsafe code, tests, examples, benchmarks, release profiles, MSRV, toolchain declarations, standard-library APIs, or public crate APIs are created or changed.
10
10
  metadata:
11
11
  mustflow_schema: "1"
12
12
  mustflow_kind: procedure
@@ -40,6 +40,7 @@ instead of treated as incidental.
40
40
 
41
41
  - `.rs`, `Cargo.toml`, `Cargo.lock`, workspace config, feature flags, public exports, traits, error types, tests, examples, benches, FFI, async runtime, or unsafe code change.
42
42
  - The task touches ownership, borrowing, lifetimes, `Clone`, `Arc`, `Mutex`, `unwrap`, or public crate compatibility.
43
+ - The task introduces or reviews Rust-version-gated APIs or language behavior such as `let else`, let chains, match `if let` guards, `cfg_select!`, `assert_matches!`, `core::range`, `Vec::push_mut`, `HashMap::get_disjoint_mut`, `Option::take_if`, `LazyLock`, `OnceLock`, `workspace.lints`, `rust-version`, Rust 2024 lints, or release-profile tuning.
43
44
 
44
45
  <!-- mustflow-section: do-not-use-when -->
45
46
  ## Do Not Use When
@@ -54,6 +55,7 @@ instead of treated as incidental.
54
55
  - Relevant `src/lib.rs`, `src/main.rs`, modules, public re-exports, tests, examples, and docs examples.
55
56
  - Existing error handling convention and async runtime.
56
57
  - Public crate status, minimum supported Rust version, feature support policy, and downstream compatibility expectations when available.
58
+ - `rust-version`, edition, `rust-toolchain.toml`, CI toolchain matrix, target triples, Cargo resolver, workspace inheritance policy, and whether newer standard-library APIs require a raised MSRV.
57
59
  - Host and build-loop constraints: OS, shell, native toolchain prerequisites, VM or remote-builder use, release profile, LTO, workspace size, disk budget, and configured smoke or focused-check intents.
58
60
  - Configured verification intents.
59
61
 
@@ -66,6 +68,7 @@ instead of treated as incidental.
66
68
  - Identify the intended edit-check-test loop before choosing a broad build. Treat whole-workspace
67
69
  checks, release builds, fat LTO, cross-compiles, and sanitizer-style runs as expensive evidence
68
70
  unless the command contract declares them as the normal focused path.
71
+ - If a Rust release, "latest stable Rust", standard-library feature, Cargo behavior, edition behavior, lint default, or toolchain-support claim is written durably, use `version-freshness-check` and official Rust sources before relying on memory or pasted notes.
69
72
 
70
73
  <!-- mustflow-section: allowed-edits -->
71
74
  ## Allowed Edits
@@ -93,20 +96,35 @@ instead of treated as incidental.
93
96
  MSVC, SDK, linker, or environment setup is required;
94
97
  - treat VM builds, remote builders, release profiles, fat LTO, and whole-workspace checks as
95
98
  environment and verification choices that must be reported when they dominate iteration cost.
96
- 4. Resolve ownership problems in this order: identify the real owner, shrink borrow scopes, fix function signatures to accept references or slices when ownership is unnecessary, distinguish transfer from sharing, then consider clone or shared ownership only when the semantics require it.
97
- 5. Before adding `clone`, verify it is a cheap handle clone such as `Arc`, `Rc`, or `Bytes`, a small intentional value clone, or a true independent ownership split. Reject large collection clones, loop clones, clone-then-borrow code, and whole-state clones made only to satisfy `spawn`.
98
- 6. Before adding `Arc<Mutex<_>>`, verify multiple owners truly need shared mutable state. Keep critical sections short, document lock order when relevant, and do not hold a lock guard across `.await`, I/O, callbacks, or user code.
99
- 7. Use explicit lifetimes only to describe real borrow relationships. Do not add `'static` or `T: 'static` to public APIs merely because an internal task boundary requires it.
100
- 8. Use concrete error enums for library APIs when callers need to classify failures. Keep `Box<dyn Error>` mostly to binaries, examples, tests, prototypes, or explicitly opaque error policies.
101
- 9. Avoid `unwrap`, vague `expect`, and unbounded `panic!` in production paths. They are allowed only for tests, examples, startup policy, panic-boundary adapters, or invariants already proven by nearby code.
102
- 10. If feature flags change, treat default features, no-default builds, all-features builds, optional dependency implicit features, public re-exports, docs examples, and feature-gated trait impls as compatibility surfaces. Features should be additive.
103
- 11. Treat public re-exports, public dependency types, generic bounds, trait item sets, error enum variants, `#[non_exhaustive]`, and MSRV as public API. Tightened bounds, added required trait methods, removed re-exports, or changed error variants require compatibility review.
104
- 12. Do not mix async runtimes. A Tokio crate should not casually gain `async-std` or runtime-specific APIs in library core. Do not call blocking I/O or CPU-heavy work in async paths without an established boundary such as async-native APIs, a blocking pool, or a dedicated worker.
105
- 13. For async spawning, avoid leaking internal `Send + Sync + 'static` requirements into public APIs. Prefer owned task state, smaller spawn boundaries, local task structures, or caller-owned runtime decisions.
106
- 14. Touch `unsafe` only when a safe design cannot express the required behavior. Every unsafe block needs a nearby `SAFETY:` explanation; every public `unsafe fn` needs `# Safety` docs. Keep unsafe scopes small and wrap them in safe abstractions only when callers have no hidden safety obligations.
107
- 15. For FFI, keep Rust ABI types out of C boundaries. Use explicit ownership, `#[repr(C)]` where required, raw pointer plus length pairs, `CStr`/`CString`, RAII wrappers, null handling, panic boundaries, and documented thread-safety evidence before manual `Send` or `Sync`.
108
- 16. Calibrate performance claims. Do not claim Rust made a system faster from compile success, empty-database timings, warm-cache microbenchmarks, local-only runs, or debug versus release confusion. Require representative data size, concurrency, target hardware, profile, and measurement method before reporting speed claims.
109
- 17. Choose configured verification intents that cover format, lint, build, tests, feature combinations, docs, public API, unsafe, FFI, smoke targets, package artifact, and release-profile risk when available.
99
+ 4. Determine the Rust version contract before using newer syntax or standard-library APIs:
100
+ - treat `rust-version`, edition, `rust-toolchain.toml`, CI matrix, docs.rs metadata, and downstream compatibility notes as the MSRV evidence ledger;
101
+ - do not use 1.95+ APIs such as `cfg_select!`, match `if let` guards, or `Vec::push_mut`, or 1.96+ APIs such as `assert_matches!` and `core::range`, unless the declared MSRV and toolchain path support them;
102
+ - keep experimental, nightly-only, target-specific, or edition-specific behavior behind explicit gates or fallbacks instead of calling it general Rust advice.
103
+ 5. Prefer flatter control flow when the MSRV supports it: use `let else` for early validation, let chains for related optional/result guards, and match `if let` guards for state-machine refinements. Remember that guard patterns do not satisfy match exhaustiveness; keep the fallback arm meaningful.
104
+ 6. In tests, prefer `assert_matches!` over `assert!(matches!(...))` when the MSRV supports it and the failed value has useful `Debug` output. Import it explicitly from `std` or `core`; do not assume it is in the prelude.
105
+ 7. Resolve ownership problems in this order: identify the real owner, shrink borrow scopes, fix function signatures to accept references or slices when ownership is unnecessary, distinguish transfer from sharing, then consider clone or shared ownership only when the semantics require it.
106
+ 8. Before adding `clone`, verify it is a cheap handle clone such as `Arc`, `Rc`, or `Bytes`, a small intentional value clone, or a true independent ownership split. Reject large collection clones, loop clones, clone-then-borrow code, and whole-state clones made only to satisfy `spawn`.
107
+ 9. Before adding `Arc<Mutex<_>>`, verify multiple owners truly need shared mutable state. For read-mostly snapshots, prefer ownership-preserving choices such as `Arc::make_mut`, immutable swaps, or explicit reload boundaries. Keep critical sections short, document lock order when relevant, and do not hold a lock guard across `.await`, I/O, callbacks, or user code.
108
+ 10. Choose initialization primitives by input and failure semantics: use `LazyLock` for no-argument static lazy values that may poison permanently on panic, and `OnceLock` when boot-time or test-time code supplies the value or panic poisoning must not become the recovery policy.
109
+ 11. Avoid hidden allocation when cheaper type contracts fit: use `Cow<'_, str>` or borrowed slices for mostly-borrowed results, query `HashMap<String, V>` with `&str` when `Borrow` supports it, use `Option::take`, `take_if`, or `as_slice` for state transitions and 0-or-1 iteration, and use `ControlFlow`, `try_for_each`, or `try_fold` when visitor or iterator APIs need explicit short-circuiting.
110
+ 12. Treat collection and string capacity as part of performance correctness. Use `with_capacity`, `reserve`, `spare_capacity_mut`, or `push_mut` only when the safety and MSRV contract are clear; keep `set_len` inside a small proven unsafe boundary; avoid repeated `String::insert` or front insertion loops that create quadratic movement.
111
+ 13. Use explicit lifetimes only to describe real borrow relationships. Do not add `'static` or `T: 'static` to public APIs merely because an internal task boundary requires it.
112
+ 14. Use concrete error enums for library APIs when callers need to classify failures. Keep `Box<dyn Error>` mostly to binaries, examples, tests, prototypes, or explicitly opaque error policies.
113
+ 15. Avoid `unwrap`, vague `expect`, and unbounded `panic!` in production paths. They are allowed only for tests, examples, startup policy, panic-boundary adapters, or invariants already proven by nearby code.
114
+ 16. Review public API shape before adding `impl Trait`, `Deref`, or trait/lifetime machinery:
115
+ - argument-position `impl Trait` removes caller turbofish control and can be a public breaking change when converted from named generics;
116
+ - return-position `impl Trait` hides one concrete type, so divergent iterator or future branches need an enum, boxed trait object, or different API boundary;
117
+ - implement `Deref` only for pointer-like wrappers, not domain inheritance or method forwarding;
118
+ - use GATs for borrowing iterator/view traits when they remove a real allocation or boxed lifetime escape, not as decorative complexity.
119
+ 17. If feature flags or Cargo workspace metadata change, treat default features, no-default builds, all-features builds, optional dependency implicit features, resolver behavior, target-specific dependencies, `workspace.package`, `workspace.dependencies`, `workspace.lints`, public re-exports, docs examples, and feature-gated trait impls as compatibility surfaces. Features should be additive, and `resolver = "2"` or a newer resolver decision must match the crate's edition/MSRV policy.
120
+ 18. Treat public re-exports, public dependency types, generic bounds, trait item sets, error enum variants, `#[non_exhaustive]`, and MSRV as public API. Tightened bounds, added required trait methods, removed re-exports, changed error variants, or raised `rust-version` require compatibility review.
121
+ 19. Do not mix async runtimes. A Tokio crate should not casually gain `async-std` or runtime-specific APIs in library core. Do not call blocking I/O or CPU-heavy work in async paths without an established boundary such as async-native APIs, a blocking pool, or a dedicated worker.
122
+ 20. For async spawning, avoid leaking internal `Send + Sync + 'static` requirements into public APIs. Prefer owned task state, smaller spawn boundaries, local task structures, or caller-owned runtime decisions.
123
+ 21. Touch `unsafe` only when a safe design cannot express the required behavior. Every unsafe block needs a nearby `SAFETY:` explanation; every public `unsafe fn` needs `# Safety` docs. In Rust 2024 or when `unsafe_op_in_unsafe_fn` is enabled, unsafe operations inside `unsafe fn` still need explicit unsafe blocks. Keep unsafe scopes small and wrap them in safe abstractions only when callers have no hidden safety obligations.
124
+ 22. For FFI, keep Rust ABI types out of C boundaries. Use explicit ownership, `#[repr(C)]` where required, raw pointer plus length pairs, `CStr`/`CString`, RAII wrappers, null handling, panic boundaries, and documented thread-safety evidence before manual `Send` or `Sync`.
125
+ 23. Review release profiles when the task changes binary delivery, CLI startup, embedded, wasm, or performance behavior. Treat `opt-level`, LTO, `panic`, `codegen-units`, and `strip` as product tradeoffs that must be measured or reported, not decorative Cargo knobs.
126
+ 24. Calibrate performance claims. Do not claim Rust made a system faster from compile success, empty-database timings, warm-cache microbenchmarks, local-only runs, or debug versus release confusion. Require representative data size, concurrency, target hardware, profile, and measurement method before reporting speed claims.
127
+ 25. Choose configured verification intents that cover format, lint, build, tests, feature combinations, docs, public API, unsafe, FFI, smoke targets, package artifact, and release-profile risk when available.
110
128
 
111
129
  <!-- mustflow-section: rejection-criteria -->
112
130
  ## Review Rejection Criteria
@@ -115,6 +133,10 @@ Reject or revise the patch when any of these appear without strong local justifi
115
133
 
116
134
  - New large `clone()` calls, clone-then-borrow code, loop clones, or state clones used only to appease ownership errors.
117
135
  - New `Arc<Mutex<AppState>>`-style shared bags, locks held across `.await`, or async I/O resources shared mainly by mutex.
136
+ - New Rust 1.95+ or 1.96+ API usage without MSRV, `rust-version`, edition, toolchain, CI, or fallback evidence.
137
+ - New `LazyLock` initialization for recoverable runtime configuration where permanent panic poisoning would be the wrong failure policy.
138
+ - New `spare_capacity_mut` plus `set_len` without a narrow, proven initialization invariant.
139
+ - New public `impl Trait`, `Deref`, GAT, workspace resolver, feature, or `rust-version` change without public API and compatibility review.
118
140
  - New public `'static`, `Send`, or `Sync` bounds that exist only because an internal task was spawned.
119
141
  - New public `Box<dyn Error>` in a library where callers need typed failures.
120
142
  - New production `unwrap` or vague `expect` on I/O, parse, environment, network, FFI, lock, or user input paths.
@@ -130,9 +152,11 @@ Reject or revise the patch when any of these appear without strong local justifi
130
152
  ## Postconditions
131
153
 
132
154
  - Ownership changes are intentional, not compiler appeasement.
155
+ - Rust-version-gated syntax, standard-library APIs, Cargo behavior, and lint assumptions match the declared MSRV or have explicit fallbacks.
133
156
  - Public API, features, optional dependencies, and error contracts are synchronized.
134
157
  - Async runtime ownership is preserved and blocking work is isolated.
135
- - Unsafe and FFI invariants are preserved or no unsafe code was touched.
158
+ - Unsafe, `unsafe_op_in_unsafe_fn`, and FFI invariants are preserved or no unsafe code was touched.
159
+ - Allocation, initialization, Cargo workspace, and release-profile choices are intentional and reported when they affect public or delivery behavior.
136
160
  - Build-loop cost, target/cache impact, smoke-target coverage, and native toolchain prerequisites
137
161
  are handled or reported.
138
162
  - Missing feature, semver, docs, unsafe, FFI, smoke, package, or performance verification is reported.
@@ -0,0 +1,167 @@
1
+ ---
2
+ mustflow_doc: skill.service-boundary-architecture
3
+ locale: en
4
+ canonical: true
5
+ revision: 1
6
+ lifecycle: mustflow-owned
7
+ authority: procedure
8
+ name: service-boundary-architecture
9
+ description: Apply this skill when service boundaries, modular-monolith boundaries, data ownership, queue/event boundaries, multi-tenant isolation, failure flow, operational recovery, or large-scale architecture split decisions are designed, reviewed, or changed.
10
+ metadata:
11
+ mustflow_schema: "1"
12
+ mustflow_kind: procedure
13
+ pack_id: mustflow.core
14
+ skill_id: mustflow.core.service-boundary-architecture
15
+ command_intents:
16
+ - changes_status
17
+ - changes_diff_summary
18
+ - test_related
19
+ - test
20
+ - lint
21
+ - build
22
+ - docs_validate_fast
23
+ - test_release
24
+ - mustflow_check
25
+ ---
26
+
27
+ # Service Boundary Architecture
28
+
29
+ <!-- mustflow-section: purpose -->
30
+ ## Purpose
31
+
32
+ Design or review large-system boundaries by starting with ownership, failure, data coupling, and operations. Treat service splits, queues, caches, events, and deployment topology as consequences of the boundary model, not as architecture decorations.
33
+
34
+ This skill protects against the common failure mode where a system is split by nouns, shares data anyway, retries blindly, emits ambiguous events, lacks tenant isolation, and then discovers during an incident that no team owns the truth.
35
+
36
+ <!-- mustflow-section: use-when -->
37
+ ## Use When
38
+
39
+ - A task designs, reviews, documents, or changes service boundaries, modular-monolith boundaries, bounded contexts, team ownership, API ownership, event ownership, queue ownership, or data ownership.
40
+ - A monolith is being prepared for future split, a microservice split is proposed, or a service/module boundary is causing deploy, data, incident, or team coordination pain.
41
+ - The task touches cross-service transactions, outbox/inbox patterns, idempotency, retries, timeouts, caches, read models, search models, shared databases, operational tools, manual correction, observability, tenancy, hot keys, or failure recovery.
42
+ - Architecture docs, decision records, onboarding docs, or skills need durable guidance for large-system design and operational readiness.
43
+
44
+ <!-- mustflow-section: do-not-use-when -->
45
+ ## Do Not Use When
46
+
47
+ - The task is a small local refactor with no ownership, data, deployment, or operational boundary decision; use `architecture-deepening-review` or `behavior-preserving-refactor`.
48
+ - The task only changes a single API shape; use `api-contract-change`.
49
+ - The task only changes database schema or persistence safety inside one owner; use `database-change-safety` or `database-migration-change`.
50
+ - The task only changes one external provider adapter; use `adapter-boundary`.
51
+ - The task only models one lifecycle state machine; use `state-machine-pattern`.
52
+
53
+ <!-- mustflow-section: required-inputs -->
54
+ ## Required Inputs
55
+
56
+ - Candidate domains, capabilities, teams, modules, services, and the reason each boundary may need to exist.
57
+ - Data ownership map: which module or service is the source of truth for each core fact, identifier, status, ledger, permission, tenant record, event, and read projection.
58
+ - Current or proposed communication paths: direct calls, APIs, events, queues, shared databases, shared caches, batch jobs, search indexes, analytics stores, files, and admin tools.
59
+ - Failure flows: duplicate requests, partial success, timeout, retry, consumer crash, queue backlog, dead-letter handling, external provider uncertainty, reconciliation, and manual correction.
60
+ - Consistency expectations: strong consistency, eventual consistency, tolerated delay, stale reads, cache invalidation, read/write split, search delay, and deletion or retention rules.
61
+ - Tenant, authorization, observability, deployment, migration, and operations requirements.
62
+ - Configured verification intents and any existing architecture decision records or context files.
63
+
64
+ <!-- mustflow-section: preconditions -->
65
+ ## Preconditions
66
+
67
+ - Do not start by choosing microservices, Kafka, Kubernetes, service mesh, CQRS, or event sourcing. Start by identifying ownership and failure pressure.
68
+ - Do not split by nouns alone. Check which rules and data change together, which teams own them, and which failures must be isolated.
69
+ - Treat shared databases, shared caches, and table reads across owners as coupling evidence even when code appears separated.
70
+ - Treat architecture diagrams as secondary evidence. Decision records, ownership maps, failure behavior, and recovery tools are the durable contract.
71
+
72
+ <!-- mustflow-section: allowed-edits -->
73
+ ## Allowed Edits
74
+
75
+ - Architecture docs, decision records, context files, workflow skills, tests, fixtures, schema notes, operational runbook notes, and directly related source changes.
76
+ - Boundary diagrams only when they are backed by ownership, data, failure, and operations text.
77
+ - Module, service, API, event, queue, cache, read-model, or operations-tool boundaries when the repository scope and command contract support that edit.
78
+ - Do not introduce new infrastructure, service topology, queue systems, brokers, databases, orchestration platforms, or deployment tools unless the user explicitly requests that implementation and the repository already has an approved path.
79
+
80
+ <!-- mustflow-section: procedure -->
81
+ ## Procedure
82
+
83
+ 1. Name the business capabilities and the facts each capability owns. For every core fact, identify exactly one source of truth and the owner responsible for correcting it.
84
+ 2. Split first by reason to change, not by noun. Keep code together when it changes together; split only when ownership, release cadence, scale, compliance, failure isolation, or team autonomy makes the boundary useful.
85
+ 3. Prefer a modular monolith with hard internal boundaries when the team is still discovering the domain. Draw future split lines early, but do not pay distributed-system costs before the boundary pressure is real.
86
+ 4. Reject shared database ownership. If another service or module needs data, choose an API, event, read projection, export, or explicitly owned query surface instead of direct table coupling.
87
+ 5. Design failure flows before the happy path. Cover partial success, duplicated requests, timeout, unknown external outcome, consumer crash, queue backlog, dead-letter handling, replay, reconciliation, and manual recovery.
88
+ 6. Require idempotency for commands that create, charge, reserve, approve, issue, grant, cancel, refund, redeem, or mutate durable state. Use stable request keys and return the previous result for duplicate keys.
89
+ 7. Treat queues as storage and backpressure, not magic. Define retry policy, exponential backoff or jitter, max attempts, retention, dead-letter ownership, consumer scaling, ordering expectations, replay safety, and loss tolerance.
90
+ 8. Every network call across the boundary needs a timeout, bounded retry policy, fallback or failure result, duplicate-safety story, and observability identifiers.
91
+ 9. Treat caches as a consistency tradeoff. Declare which stale values are acceptable, max staleness, invalidation owner, tenant and permission visibility, and whether the cache is allowed to become authority.
92
+ 10. Model authorization, tenant isolation, audit, and data visibility at the boundary. Tenant ID must travel through APIs, queues, caches, logs, files, reports, and admin tools when the system is multi-tenant.
93
+ 11. For event-driven boundaries, use past-tense fact events such as `OrderCreated` or `PaymentApproved`. Do not disguise commands as events. Include event ID, version, occurred time, publisher, subject, causation or request ID, correlation or trace ID, and compatible schema evolution rules.
94
+ 12. Separate transaction data from search, reporting, analytics, and screen-shaped read projections when their consistency, indexing, query, or retention needs diverge.
95
+ 13. Define tolerated delay with numbers. Replace vague "real-time" claims with accepted latency or freshness windows such as seconds, minutes, or batch cadence.
96
+ 14. Check hot keys and noisy neighbors. Define per-tenant, per-customer, per-room, per-campaign, or per-product limits, queue separation, worker pool separation, connection caps, and external API call caps when one key can dominate load.
97
+ 15. Keep domain rules in the owning domain layer. Do not scatter refund windows, cancellation rules, entitlement checks, inventory reservations, or admin overrides across controllers, UI, workers, and jobs.
98
+ 16. Plan migrations with expand, dual-write or compatibility, backfill, read switch, verification, and contract removal. Do not rename or remove shared fields in one deployment step.
99
+ 17. Plan deletion and retention before data is created. Identify legal retention, anonymization, log masking, backup retention, search/read-model cleanup, and audit exceptions.
100
+ 18. Make observability a product feature. Connect API, queue, worker, external provider, database, and admin operations with trace, request, correlation, causation, job, and tenant identifiers. Prefer p95, p99, error rate, queue age, backlog, dependency failure rate, and business success rate over averages.
101
+ 19. Make deployment and rollback a boundary decision. Use feature flags, canaries, partial exposure, compatibility windows, and kill switches for risky boundary changes.
102
+ 20. Provide operational tools for reality: reconcile external state, retry or quarantine failed messages, correct user/account/order state, revoke permissions, inspect provider responses, and undo manual changes with audit and approval when required.
103
+ 21. Record the decision: selected boundary, rejected alternatives, reason, assumptions, failure modes, data owner, operational owner, verification, and revisit triggers.
104
+
105
+ <!-- mustflow-section: review-rejection-criteria -->
106
+ ## Review Rejection Criteria
107
+
108
+ Reject or revise the design when:
109
+
110
+ - A service or module boundary has no named data owner.
111
+ - Two owners write the same core fact without a conflict rule.
112
+ - A service reads another service's tables or cache as normal behavior.
113
+ - The design shows only the happy path.
114
+ - Retries lack timeout, backoff, jitter, max attempts, idempotency, or failure ownership.
115
+ - A queue has no dead-letter, retention, replay, ordering, or backlog policy.
116
+ - Cache behavior does not state acceptable staleness and invalidation ownership.
117
+ - Events are imperative commands instead of past-tense facts.
118
+ - Event schemas lack version, event ID, occurred time, publisher, and correlation or causation identifiers.
119
+ - Tenant, permission, audit, or data-retention boundaries are added after the fact.
120
+ - Architecture choice is justified by tooling fashion instead of ownership, failure, scale, compliance, or team autonomy.
121
+ - Manual operations can mutate critical state without audit, approval, and reversal or reconciliation path.
122
+
123
+ <!-- mustflow-section: postconditions -->
124
+ ## Postconditions
125
+
126
+ - Data ownership and source-of-truth boundaries are explicit.
127
+ - Boundary split is justified by change reason, ownership, scale, compliance, failure isolation, or team autonomy.
128
+ - Failure handling, idempotency, retry, queue, cache, event, and observability contracts are defined or explicitly deferred.
129
+ - Tenant, authorization, deletion, retention, migration, deployment, and operational recovery risks are checked or reported.
130
+ - Decision records explain why this boundary was chosen, what alternatives were rejected, and when to revisit.
131
+
132
+ <!-- mustflow-section: verification -->
133
+ ## Verification
134
+
135
+ Use configured oneshot command intents when available:
136
+
137
+ - `changes_status`
138
+ - `changes_diff_summary`
139
+ - `test_related`
140
+ - `test`
141
+ - `lint`
142
+ - `build`
143
+ - `docs_validate_fast`
144
+ - `test_release`
145
+ - `mustflow_check`
146
+
147
+ Use broader configured checks when the boundary change affects templates, public docs, package behavior, or cross-module contracts. Report missing architecture, integration, load, or operational verification instead of claiming the design is production-ready.
148
+
149
+ <!-- mustflow-section: failure-handling -->
150
+ ## Failure Handling
151
+
152
+ - If ownership cannot be assigned, stop at a decision record or open question instead of drawing a false boundary.
153
+ - If shared database coupling is unavoidable for now, document it as temporary coupling with the exit path, owner, read/write limits, and revisit trigger.
154
+ - If the user asks for a new service but failure, data ownership, or operational tooling is missing, recommend the smallest boundary-preserving modular step first.
155
+ - If verification is unavailable, report which boundary risks remain untested: duplicate command, stale read, queue replay, provider timeout, tenant isolation, migration, deletion, or manual recovery.
156
+
157
+ <!-- mustflow-section: output-format -->
158
+ ## Output Format
159
+
160
+ - Boundary checked
161
+ - Data owners and source-of-truth notes
162
+ - Failure, idempotency, queue, cache, and event notes
163
+ - Tenant, auth, retention, observability, deployment, and operations notes
164
+ - Files changed
165
+ - Command intents run
166
+ - Skipped checks and reasons
167
+ - Remaining service-boundary risk