mustflow 2.39.1 → 2.58.1

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 (94) hide show
  1. package/dist/cli/commands/run/executor.js +16 -0
  2. package/dist/cli/commands/run/process-tree.js +6 -3
  3. package/dist/cli/commands/tech.js +60 -4
  4. package/dist/cli/commands/verify.js +3 -1
  5. package/dist/cli/lib/git-changes.js +11 -1
  6. package/dist/cli/lib/i18n.js +1 -1
  7. package/dist/cli/lib/local-index/index.js +8 -4
  8. package/dist/cli/lib/local-index/populate.js +17 -3
  9. package/dist/cli/lib/local-index/search-read-model.js +9 -7
  10. package/dist/cli/lib/local-index/search-text.js +2 -2
  11. package/dist/cli/lib/local-index/workflow-documents.js +17 -2
  12. package/dist/cli/lib/mustflow-read.js +14 -2
  13. package/dist/cli/lib/npm-version-check.js +36 -0
  14. package/dist/cli/lib/repo-map.js +16 -3
  15. package/dist/cli/lib/templates.js +8 -7
  16. package/dist/cli/lib/validation/constants.js +1 -1
  17. package/dist/core/active-run-locks.js +78 -20
  18. package/dist/core/change-classification.js +4 -0
  19. package/dist/core/command-contract-rules.js +1 -1
  20. package/dist/core/command-contract-validation.js +1 -1
  21. package/dist/core/command-cwd.js +13 -2
  22. package/dist/core/command-effects.js +22 -4
  23. package/dist/core/command-env.js +8 -6
  24. package/dist/core/command-preconditions.js +28 -2
  25. package/dist/core/completion-verdict.js +1 -1
  26. package/dist/core/line-endings.js +8 -4
  27. package/dist/core/safe-filesystem.js +9 -1
  28. package/dist/core/source-anchor-validation.js +7 -1
  29. package/dist/core/source-anchors.js +8 -2
  30. package/dist/core/verification-scheduler.js +8 -2
  31. package/package.json +1 -1
  32. package/templates/default/i18n.toml +330 -1
  33. package/templates/default/locales/en/.mustflow/skills/INDEX.md +302 -5
  34. package/templates/default/locales/en/.mustflow/skills/agent-eval-integrity-review/SKILL.md +160 -0
  35. package/templates/default/locales/en/.mustflow/skills/agent-execution-control-review/SKILL.md +163 -0
  36. package/templates/default/locales/en/.mustflow/skills/ai-generated-code-hardening/SKILL.md +49 -13
  37. package/templates/default/locales/en/.mustflow/skills/api-access-control-review/SKILL.md +298 -0
  38. package/templates/default/locales/en/.mustflow/skills/api-misuse-resistance-review/SKILL.md +297 -0
  39. package/templates/default/locales/en/.mustflow/skills/api-request-performance-review/SKILL.md +189 -0
  40. package/templates/default/locales/en/.mustflow/skills/app-startup-performance-review/SKILL.md +309 -0
  41. package/templates/default/locales/en/.mustflow/skills/backend-log-evidence-review/SKILL.md +213 -0
  42. package/templates/default/locales/en/.mustflow/skills/business-rule-leakage-review/SKILL.md +295 -0
  43. package/templates/default/locales/en/.mustflow/skills/cache-integrity-review/SKILL.md +291 -0
  44. package/templates/default/locales/en/.mustflow/skills/change-blast-radius-review/SKILL.md +297 -0
  45. package/templates/default/locales/en/.mustflow/skills/client-bundle-pruning-review/SKILL.md +160 -0
  46. package/templates/default/locales/en/.mustflow/skills/cloud-cost-guardrail-review/SKILL.md +321 -0
  47. package/templates/default/locales/en/.mustflow/skills/concurrency-invariant-review/SKILL.md +193 -0
  48. package/templates/default/locales/en/.mustflow/skills/core-web-vitals-field-review/SKILL.md +161 -0
  49. package/templates/default/locales/en/.mustflow/skills/credit-ledger-integrity-review/SKILL.md +156 -0
  50. package/templates/default/locales/en/.mustflow/skills/database-json-modeling-review/SKILL.md +171 -0
  51. package/templates/default/locales/en/.mustflow/skills/database-lock-contention-review/SKILL.md +192 -0
  52. package/templates/default/locales/en/.mustflow/skills/database-migration-change/SKILL.md +76 -34
  53. package/templates/default/locales/en/.mustflow/skills/database-query-bottleneck-review/SKILL.md +194 -0
  54. package/templates/default/locales/en/.mustflow/skills/deletion-lifecycle-review/SKILL.md +171 -0
  55. package/templates/default/locales/en/.mustflow/skills/deployment-rollout-safety-review/SKILL.md +321 -0
  56. package/templates/default/locales/en/.mustflow/skills/desktop-auto-update-safety-review/SKILL.md +265 -0
  57. package/templates/default/locales/en/.mustflow/skills/desktop-background-process-stability-review/SKILL.md +318 -0
  58. package/templates/default/locales/en/.mustflow/skills/desktop-memory-footprint-review/SKILL.md +318 -0
  59. package/templates/default/locales/en/.mustflow/skills/error-message-integrity-review/SKILL.md +283 -0
  60. package/templates/default/locales/en/.mustflow/skills/failure-integrity-review/SKILL.md +193 -0
  61. package/templates/default/locales/en/.mustflow/skills/file-upload-security-review/SKILL.md +305 -0
  62. package/templates/default/locales/en/.mustflow/skills/frame-render-performance-review/SKILL.md +159 -0
  63. package/templates/default/locales/en/.mustflow/skills/frontend-accessibility-tree-review/SKILL.md +202 -0
  64. package/templates/default/locales/en/.mustflow/skills/frontend-localization-review/SKILL.md +202 -0
  65. package/templates/default/locales/en/.mustflow/skills/frontend-state-ownership-review/SKILL.md +183 -0
  66. package/templates/default/locales/en/.mustflow/skills/frontend-stress-layout-review/SKILL.md +193 -0
  67. package/templates/default/locales/en/.mustflow/skills/hot-path-performance-review/SKILL.md +159 -0
  68. package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/SKILL.md +195 -0
  69. package/templates/default/locales/en/.mustflow/skills/image-delivery-performance-review/SKILL.md +161 -0
  70. package/templates/default/locales/en/.mustflow/skills/incident-triage-review/SKILL.md +185 -0
  71. package/templates/default/locales/en/.mustflow/skills/llm-hallucination-control-review/SKILL.md +155 -0
  72. package/templates/default/locales/en/.mustflow/skills/llm-response-latency-review/SKILL.md +155 -0
  73. package/templates/default/locales/en/.mustflow/skills/llm-service-ux-review/SKILL.md +2 -0
  74. package/templates/default/locales/en/.mustflow/skills/llm-token-cost-control-review/SKILL.md +155 -0
  75. package/templates/default/locales/en/.mustflow/skills/low-end-device-support-review/SKILL.md +340 -0
  76. package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/SKILL.md +169 -0
  77. package/templates/default/locales/en/.mustflow/skills/mobile-energy-efficiency-review/SKILL.md +329 -0
  78. package/templates/default/locales/en/.mustflow/skills/module-boundary-review/SKILL.md +278 -0
  79. package/templates/default/locales/en/.mustflow/skills/multi-agent-work-coordination/SKILL.md +1 -0
  80. package/templates/default/locales/en/.mustflow/skills/observability-debuggability-review/SKILL.md +208 -0
  81. package/templates/default/locales/en/.mustflow/skills/payment-integrity-review/SKILL.md +155 -0
  82. package/templates/default/locales/en/.mustflow/skills/prompt-contract-quality-review/SKILL.md +158 -0
  83. package/templates/default/locales/en/.mustflow/skills/quadratic-scan-review/SKILL.md +155 -0
  84. package/templates/default/locales/en/.mustflow/skills/queue-processing-integrity-review/SKILL.md +193 -0
  85. package/templates/default/locales/en/.mustflow/skills/race-condition-review/SKILL.md +188 -0
  86. package/templates/default/locales/en/.mustflow/skills/rate-limit-integrity-review/SKILL.md +344 -0
  87. package/templates/default/locales/en/.mustflow/skills/retry-policy-integrity-review/SKILL.md +195 -0
  88. package/templates/default/locales/en/.mustflow/skills/routes.toml +330 -0
  89. package/templates/default/locales/en/.mustflow/skills/security-flow-review/SKILL.md +279 -0
  90. package/templates/default/locales/en/.mustflow/skills/testability-boundary-review/SKILL.md +295 -0
  91. package/templates/default/locales/en/.mustflow/skills/transaction-boundary-integrity-review/SKILL.md +196 -0
  92. package/templates/default/locales/en/.mustflow/skills/type-state-modeling-review/SKILL.md +179 -0
  93. package/templates/default/locales/en/.mustflow/skills/web-render-performance-review/SKILL.md +164 -0
  94. package/templates/default/manifest.toml +386 -1
@@ -0,0 +1,295 @@
1
+ ---
2
+ mustflow_doc: skill.testability-boundary-review
3
+ locale: en
4
+ canonical: true
5
+ revision: 1
6
+ lifecycle: mustflow-owned
7
+ authority: procedure
8
+ name: testability-boundary-review
9
+ description: Apply this skill when code is created, changed, reviewed, or reported and testability needs review for hidden decision inputs, direct time or randomness, direct I/O, constructor side effects, static or singleton state, oversized private logic, branch policy sprawl, boolean mode flags, broad option objects, implicit environment or request context, void side effects, swallowed errors, log-only outcomes, cache order dependence, ORM lazy loading, transaction and external-call coupling, hidden event publication, fire-and-forget async work, real-time retry waits, nondeterministic collection order, hidden defaults, mixed validation and policy, scattered authorization, framework magic, smart controllers, conditional DTO mapping, mock-heavy classes, call-order assertions, inheritance coupling, or reflection-only tests.
10
+ metadata:
11
+ mustflow_schema: "1"
12
+ mustflow_kind: procedure
13
+ pack_id: mustflow.core
14
+ skill_id: mustflow.core.testability-boundary-review
15
+ command_intents:
16
+ - changes_status
17
+ - changes_diff_summary
18
+ - lint
19
+ - build
20
+ - test_related
21
+ - test
22
+ - test_audit
23
+ - docs_validate_fast
24
+ - test_release
25
+ - mustflow_check
26
+ ---
27
+
28
+ # Testability Boundary Review
29
+
30
+ <!-- mustflow-section: purpose -->
31
+ ## Purpose
32
+
33
+ Review whether code can be forced into the important conditions needed for deterministic tests.
34
+
35
+ The review question is not only "is the logic correct?" It is "can a test stop time, force failure,
36
+ replace the external world, fix random output, run the core decision without a database, and observe
37
+ the result without peeking through private seams?"
38
+
39
+ <!-- mustflow-section: use-when -->
40
+ ## Use When
41
+
42
+ - Code review, implementation, or refactor work touches business decisions, validators, services,
43
+ handlers, repositories, entities, jobs, workers, events, retries, caches, controllers, DTO mappers,
44
+ framework hooks, constructors, global state, static helpers, or tests.
45
+ - A test would need real time, random values, UUIDs, database sessions, external APIs, files, queues,
46
+ mail, logs, sleeps, framework containers, reflection, broad mocks, or internal call-order assertions.
47
+ - A class or function looks simple but hides decision inputs in environment variables, current user,
48
+ locale, timezone, config files, global caches, default values, static singletons, or framework
49
+ context.
50
+ - A review needs to decide whether to use `dependency-injection`, `pure-core-imperative-shell`,
51
+ `state-machine-pattern`, `strategy-pattern`, `result-option`, `auth-permission-change`,
52
+ `failure-integrity-review`, `cache-integrity-review`, or `test-design-guard`.
53
+
54
+ <!-- mustflow-section: do-not-use-when -->
55
+ ## Do Not Use When
56
+
57
+ - The task is only designing test cases or classifying RED evidence; use `test-design-guard`.
58
+ - The task is only updating stale, duplicated, flaky, or obsolete tests; use `test-maintenance`.
59
+ - The only issue is hidden construction of a direct external dependency; use `dependency-injection`
60
+ as the primary skill and this skill only for the broader testability review.
61
+ - The main work is separating deterministic business decisions from side effects; use
62
+ `pure-core-imperative-shell` as the primary skill.
63
+ - The code is a trivial pure helper with explicit inputs, deterministic output, no hidden state, and
64
+ no meaningful branch or side effect.
65
+
66
+ <!-- mustflow-section: required-inputs -->
67
+ ## Required Inputs
68
+
69
+ - User goal, current diff or target files, and the behavior or decision that should be testable.
70
+ - Decision-input ledger: explicit parameters, hidden reads, time, randomness, identifiers, config,
71
+ environment, locale, timezone, current actor, permissions, feature flags, cache, and defaults.
72
+ - Side-effect ledger: database, ORM lazy loading, network, filesystem, queue, mail, logs, metrics,
73
+ events, transactions, retries, timers, background work, and external providers.
74
+ - Observability ledger: returned value, typed error, emitted event, state change, persisted record,
75
+ outbox message, public response, log-only outcome, or private reflection-only state.
76
+ - Test friction evidence: mocks required, sleeps, framework container setup, reflection, call-order
77
+ assertions, real infrastructure, test ordering dependence, shared state cleanup, and existing tests.
78
+ - Relevant command-intent contract entries for tests, lint, build, docs, release, and mustflow checks.
79
+
80
+ <!-- mustflow-section: preconditions -->
81
+ ## Preconditions
82
+
83
+ - The task matches the Use When conditions and does not match the Do Not Use When exclusions.
84
+ - Higher-priority instructions and `.mustflow/config/commands.toml` have been checked for the
85
+ current scope.
86
+ - Required inputs are available, or missing hidden-input, side-effect, observability, or test-friction
87
+ evidence can be reported without guessing.
88
+ - If the review finds a concrete dependency, pure-core, failure, cache, concurrency, authorization,
89
+ state-machine, strategy, or test-design issue, use the narrower skill before editing that part.
90
+
91
+ <!-- mustflow-section: allowed-edits -->
92
+ ## Allowed Edits
93
+
94
+ - Make decision inputs explicit through parameters, narrow context values, fixed clocks, fixed
95
+ identifier or random providers, policy objects, strategy objects, state tables, or small value
96
+ objects.
97
+ - Move I/O, framework objects, caches, logs, metrics, event publication, timers, retries,
98
+ transactions, and background execution into shell or adapter boundaries when directly tied to
99
+ testability.
100
+ - Return observable results such as values, typed errors, state transitions, domain events, effect
101
+ descriptions, outbox messages, or command results instead of requiring tests to inspect logs,
102
+ private fields, or collaborator call order.
103
+ - Add or adjust focused tests only when they prove the reviewed testability boundary and follow
104
+ `test-design-guard`.
105
+ - Do not add broad dependency bags, speculative abstractions, global test hooks, sleeps, reflection
106
+ helpers, or mock-only tests just to make one test pass.
107
+
108
+ <!-- mustflow-section: procedure -->
109
+ ## Procedure
110
+
111
+ 1. Ask what the test must be able to control.
112
+ - Name the conditions a test should force: current time, timezone, random value, UUID, external
113
+ failure, retry timing, DB result, permission, locale, feature flag, cache state, event output,
114
+ ordering, or provider response.
115
+ - If those conditions cannot be controlled without real infrastructure or sleeps, testability is
116
+ already leaking.
117
+ 2. Find hidden decision inputs.
118
+ - Flag direct `new Date()`, `Date.now()`, `LocalDateTime.now()`, `System.currentTimeMillis()`,
119
+ `Math.random()`, UUID generation, environment reads, config reads, current-user lookups, locale,
120
+ timezone, global cache reads, and framework request context inside business decisions.
121
+ - Prefer passing captured values, a narrow time context, a fixed generator, or an explicit policy
122
+ input from the boundary.
123
+ 3. Split decision from contact with the outside world.
124
+ - A function that decides and also queries a database, calls an API, reads a file, sends mail,
125
+ writes a queue, or logs the only outcome forces unit tests into mini integration tests.
126
+ - Use `pure-core-imperative-shell` when business decisions and side effects are mixed.
127
+ 4. Inspect constructors.
128
+ - Constructors should accept ingredients, not start cooking.
129
+ - Treat constructors that connect to databases, read files, read environment, fill caches, spawn
130
+ threads, start timers, or perform network setup as testability hazards.
131
+ 5. Inspect static, singleton, and global state.
132
+ - Shared mutable state makes test order part of behavior.
133
+ - Look for global registries, mutable singletons, module-level caches, static config, process-wide
134
+ current user, and global loggers that hold test-specific state.
135
+ 6. Treat large private methods as trapped responsibility.
136
+ - Do not test private methods through reflection.
137
+ - If private logic has meaningful policy, calculation, parsing, validation, or branching, extract
138
+ the responsibility behind a small public or module-local boundary with explicit inputs.
139
+ 7. Count policy branches, not just branch count.
140
+ - Nested `if`, `switch`, `when`, or pattern matching may mean different policies are welded into
141
+ one function.
142
+ - Use strategy, rule table, state machine, or named policy object when each branch represents a
143
+ different reason to change or a different test matrix.
144
+ 8. Replace boolean mode flags with named concepts.
145
+ - Flag signatures like `process(user, true, false)`.
146
+ - Two or more boolean inputs create hidden modes. Use named variants, explicit option types, or
147
+ separate functions when modes have different behavior contracts.
148
+ 9. Shrink trash-can option and context objects.
149
+ - Broad `RequestOptions`, `Config`, `Context`, or dependency bags hide which fields affect the
150
+ result.
151
+ - Keep only the facts required for the decision, and give test fixtures small builders or explicit
152
+ values instead of giant fake objects.
153
+ 10. Make outputs observable.
154
+ - Void functions that update DB rows, publish events, delete caches, send logs, and call providers
155
+ force tests to spy on internals.
156
+ - Prefer returning decision results, typed errors, domain events, effect descriptions, state
157
+ changes, or command outcomes that shell code can execute.
158
+ 11. Do not swallow failures into logs.
159
+ - `catch { log.warn(...) }` with no returned failure makes tests assert log text instead of
160
+ behavior.
161
+ - Use `failure-integrity-review` or `result-option` when expected failures need to be visible as
162
+ values or errors.
163
+ 12. Keep cache outside the policy.
164
+ - If first call and second call differ because a hidden cache changed, tests become order
165
+ dependent.
166
+ - Core decisions should return the same output for the same input whether cache is present or
167
+ not; cache belongs in the shell or adapter.
168
+ 13. Keep ORM behavior out of unit decisions.
169
+ - Lazy loading, entity hooks, DB sessions, generated row types, and active-record saves can pull
170
+ real persistence into tests.
171
+ - Entities may own state and invariants, but query composition and external dependencies belong
172
+ at repository or service boundaries.
173
+ 14. Check transaction and external-call coupling.
174
+ - External API calls inside DB transactions create test and production uncertainty.
175
+ - Prefer local state plus outbox or effect descriptions, then execute external effects after
176
+ commit with idempotency.
177
+ 15. Make events visible at one boundary.
178
+ - Hidden event publication in the middle of a function makes tests verify every side channel.
179
+ - Prefer returning domain events or publishing once at a clear shell boundary.
180
+ 16. Remove fire-and-forget timing from core logic.
181
+ - `setTimeout`, background job launch, coroutine launch, thread start, unawaited promises, and
182
+ detached tasks make tests sleep.
183
+ - Inject a scheduler or executor, or return work descriptions so tests can run them
184
+ synchronously.
185
+ 17. Decouple retry, backoff, timeout, and expiration from real time.
186
+ - Waiting 30 seconds to prove a retry is not a useful test.
187
+ - Model retry policy as data or a deterministic calculator, and advance fake time in tests.
188
+ 18. Stabilize collection ordering.
189
+ - If order matters, code should sort with a named key.
190
+ - If order does not matter, tests should assert as a set or multiset rather than relying on DB,
191
+ map, set, or parallel iteration order.
192
+ 19. Make defaults explicit.
193
+ - Hidden defaults such as server timezone, default admin, default shipping, default permission,
194
+ default locale, default currency, and default cache policy multiply test cases silently.
195
+ - Put defaults at the boundary, name them, and test the fallback path deliberately.
196
+ 20. Separate input shape validation from business judgment.
197
+ - Email format, JSON shape, file size, or required field checks are not the same as eligibility,
198
+ permission, balance, quota, status, or domain invariants.
199
+ - Separate structural validation, authorization, and policy decisions so failure reasons can be
200
+ tested directly.
201
+ 21. Centralize authorization evidence.
202
+ - Scattered controller, service, and repository permission checks create test holes.
203
+ - Use `auth-permission-change` when protected actions need one policy source, denial cases, or
204
+ consistent server/database enforcement.
205
+ 22. Keep framework magic at the edge.
206
+ - Annotations, decorators, AOP, interceptors, middleware, dependency containers, ORM hooks, and
207
+ lifecycle callbacks should not be required to run core decision tests.
208
+ - A useful testability check is whether the decision can run without the framework container.
209
+ 23. Keep controllers as translators.
210
+ - Controllers should parse requests, call an application boundary, and map results to responses.
211
+ - If they own business decisions, permissions, error mapping, response formatting, and external
212
+ calls, tests have to fake a web server to prove a rule.
213
+ 24. Treat conditional DTO mapping as policy.
214
+ - Mapping code that hides fields by status, role, flag, or permission is no longer simple
215
+ mapping.
216
+ - Move the policy to a named owner and keep DTO mapping mechanical where possible.
217
+ 25. Use mocks as a design sensor.
218
+ - If a unit test needs more than three mocks, inspect responsibility boundaries.
219
+ - If it needs five or more mocks, the class is probably talking to too many collaborators.
220
+ - Prefer fewer, narrower ports and pure decision tests over broad mock choreography.
221
+ 26. Prefer outcome assertions over call-order assertions.
222
+ - Some protocols require order tests. Most business logic should be tested by result, final
223
+ state, emitted event, persisted command, or rejected effect.
224
+ - Frequent `A before B` assertions usually mean the responsibility boundary is too procedural.
225
+ 27. Prefer composition over deep inheritance for test setup.
226
+ - Parent constructors, protected state, template methods, and partial overrides create hidden
227
+ dependencies.
228
+ - Use composition when tests need to swap behavior or observe a small collaborator.
229
+ 28. Treat reflection-only tests as a design failure.
230
+ - Tests that set private fields, call private methods, or mutate hidden state through reflection
231
+ are using a back door.
232
+ - Create a real boundary for the behavior or report that the current design cannot be tested
233
+ naturally.
234
+ 29. Pick the smallest response.
235
+ - If one hidden input blocks testing, inject that one value instead of reshaping the whole module.
236
+ - If several smells point to the same root, name the root boundary and fix there.
237
+ - If changing structure is too risky now, report the exact condition that remains hard to force
238
+ in tests.
239
+
240
+ <!-- mustflow-section: postconditions -->
241
+ ## Postconditions
242
+
243
+ - Important test conditions can be forced without real time, real randomness, live infrastructure,
244
+ sleeps, reflection, broad framework containers, or hidden global state.
245
+ - Decision inputs are explicit or the remaining hidden inputs are named.
246
+ - Core decision behavior has observable values, typed failures, events, effects, or state changes.
247
+ - External I/O, transactions, retries, caches, logging, metrics, scheduling, and framework magic are
248
+ kept at boundary code or explicitly reported as remaining testability risk.
249
+ - Any new or changed tests assert observable behavior rather than only mock choreography.
250
+
251
+ <!-- mustflow-section: verification -->
252
+ ## Verification
253
+
254
+ Use configured oneshot command intents when available:
255
+
256
+ - `changes_status`
257
+ - `changes_diff_summary`
258
+ - `lint`
259
+ - `build`
260
+ - `test_related`
261
+ - `test`
262
+ - `test_audit`
263
+ - `docs_validate_fast`
264
+ - `test_release`
265
+ - `mustflow_check`
266
+
267
+ Prefer focused tests that prove the newly controllable condition and observable outcome. Use
268
+ `test-design-guard` before adding or reshaping tests.
269
+
270
+ <!-- mustflow-section: failure-handling -->
271
+ ## Failure Handling
272
+
273
+ - If the behavior cannot be tested without reflection, sleeps, broad mocks, or live infrastructure,
274
+ report the exact hidden decision input or side effect instead of claiming the testability issue is
275
+ solved.
276
+ - If extracting a boundary changes behavior, stop and use `behavior-preserving-refactor` or
277
+ `repro-first-debug` before continuing.
278
+ - If tests still require the framework container, report which framework dependency remains inside
279
+ the decision.
280
+ - If a command fails, use `failure-triage` before further edits.
281
+
282
+ <!-- mustflow-section: output-format -->
283
+ ## Output Format
284
+
285
+ - Testability boundary reviewed
286
+ - Conditions tests must control
287
+ - Hidden decision inputs found
288
+ - Side effects and framework dependencies found
289
+ - Observability gaps found
290
+ - Mocks, sleeps, reflection, call-order, or global-state risks
291
+ - Fixes made or recommendation
292
+ - Tests or behavior evidence
293
+ - Command intents run
294
+ - Skipped checks and reasons
295
+ - Remaining testability risk
@@ -0,0 +1,196 @@
1
+ ---
2
+ mustflow_doc: skill.transaction-boundary-integrity-review
3
+ locale: en
4
+ canonical: true
5
+ revision: 1
6
+ lifecycle: mustflow-owned
7
+ authority: procedure
8
+ name: transaction-boundary-integrity-review
9
+ description: Apply this skill when code is created, changed, reviewed, or reported and transaction boundaries, database write paths, ORM atomic blocks, unit-of-work code, lock usage, isolation levels, retry handling, rollback behavior, after-commit side effects, outbox patterns, framework transaction annotations, or transactional tests can break business invariants despite a transaction existing.
10
+ metadata:
11
+ mustflow_schema: "1"
12
+ mustflow_kind: procedure
13
+ pack_id: mustflow.core
14
+ skill_id: mustflow.core.transaction-boundary-integrity-review
15
+ command_intents:
16
+ - changes_status
17
+ - changes_diff_summary
18
+ - lint
19
+ - build
20
+ - test_related
21
+ - test
22
+ - docs_validate_fast
23
+ - test_release
24
+ - mustflow_check
25
+ ---
26
+
27
+ # Transaction Boundary Integrity Review
28
+
29
+ <!-- mustflow-section: purpose -->
30
+ ## Purpose
31
+
32
+ Review transactions by asking whether the whole business action stays true under failure, concurrency, retries, framework behavior, and external side effects.
33
+
34
+ The review question is not "is there a transaction?" It is "does the read -> decision -> write sequence, plus every side effect and retry, still preserve the invariant when another request, worker, or failure changes the timing?"
35
+
36
+ <!-- mustflow-section: use-when -->
37
+ ## Use When
38
+
39
+ - Code creates, changes, reviews, or reports a database transaction, ORM transaction, unit of work, repository write path, service write workflow, command handler, webhook processor, queue consumer, checkout, credit, inventory, booking, entitlement, permission, approval, status transition, or multi-step business action.
40
+ - The risk is read -> decision -> write integrity, check-then-insert, count-before-add, row lock scope, missing durable constraints, isolation-level assumptions, retry behavior, deadlock handling, rollback behavior, transaction propagation, nested transaction semantics, savepoints, after-commit side effects, outbox or inbox boundaries, external API calls inside transactions, or tests that hide commit behavior.
41
+ - Code or docs claim a path is atomic, transactional, serialized, locked, retry-safe, rollback-safe, isolated, idempotent, durable, committed, or protected from concurrent requests.
42
+ - A transaction-related review needs a focused integrity pass before deeper database-engine, race-condition, backend-reliability, payment, credit-ledger, or state-machine review.
43
+
44
+ <!-- mustflow-section: do-not-use-when -->
45
+ ## Do Not Use When
46
+
47
+ - The task is only query latency, index fit, plan shape, projection, pagination, or N+1 behavior; use `database-query-bottleneck-review`.
48
+ - The task is only general stale shared state or lock ordering outside a database or unit-of-work boundary; use `race-condition-review` or `concurrency-invariant-review`.
49
+ - The task is primarily exception honesty, swallowed errors, false success, fallback defaults, or public error shape; use `failure-integrity-review`.
50
+ - The task is primarily retries, queue reliability, provider deadlines, health checks, outbox processing, or operational failure handling; use `backend-reliability-change`.
51
+ - The task is payment, credit, wallet, or ledger specific and the transaction issue is only one part of money-event integrity; use `payment-integrity-review` or `credit-ledger-integrity-review` first.
52
+ - The transaction is a tiny single-row write with no prior decision, no concurrency-sensitive invariant, no external side effect, no retry, and no framework propagation risk.
53
+
54
+ <!-- mustflow-section: required-inputs -->
55
+ ## Required Inputs
56
+
57
+ - Business invariant: balance cannot go negative, member count cannot exceed a limit, email must be unique, one coupon can be redeemed once, one order can be fulfilled once, status transitions must be legal, or equivalent rule.
58
+ - Transaction boundary: where the transaction starts and ends, which repository, ORM session, connection, data source, transaction manager, isolation level, propagation mode, savepoint, and lock scope are active.
59
+ - Decision ledger: reads, existence checks, counts, predicate checks, business validations, authorization checks, state reads, and the writes or side effects that depend on them.
60
+ - Durable guard evidence: unique constraints, exclusion constraints, conditional updates, version columns, row locks, parent-row locks, predicate locking, atomic upsert, idempotency records, outbox or inbox records, and affected-row checks.
61
+ - Framework behavior: Spring `@Transactional`, `rollbackFor`, self-invocation, `readOnly`, `REQUIRES_NEW`, `NESTED`, rollback-only, `UnexpectedRollbackException`, Django `atomic()`, `transaction.on_commit()`, SQLAlchemy `Session`, Hibernate flush and `@Version`, or local equivalents.
62
+ - Side-effect ledger: email, cache invalidation, queue publish, message ack, HTTP API call, payment provider call, object storage, file upload, search indexing, notification, analytics, and any after-commit callback.
63
+ - Failure and retry evidence: `serialization_failure`, `deadlock_detected`, optimistic-lock failure, timeout, unknown external outcome, retry budget, idempotency key, compensation, reconciliation, and manual recovery.
64
+ - Test evidence: concurrency tests, transactional tests, commit-time constraint tests, after-commit callback tests, query-count tests, framework integration tests, and configured command intents.
65
+
66
+ <!-- mustflow-section: preconditions -->
67
+ ## Preconditions
68
+
69
+ - The task matches the Use When conditions and does not match the Do Not Use When exclusions.
70
+ - Higher-priority instructions and `.mustflow/config/commands.toml` have been checked for the current scope.
71
+ - Required inputs are available, or missing invariant, isolation, lock, propagation, side-effect, retry, or test evidence can be reported without guessing.
72
+ - Existing local patterns for transactions, unit of work, idempotency, outbox, locks, optimistic locking, retry classification, and transactional tests have been searched before adding new shapes.
73
+ - If the transaction crosses money, authorization, personal data, multi-tenant data, or durable events, also apply the relevant payment, credit, security, database, backend, API, state-machine, or failure skill.
74
+
75
+ <!-- mustflow-section: allowed-edits -->
76
+ ## Allowed Edits
77
+
78
+ - Move the whole read -> decision -> write sequence into the correct transaction, replace app-only checks with durable constraints, add atomic upsert or conditional updates, check affected row counts, add version checks, lock the right row before the decision, narrow transaction scope, and move external side effects to after-commit or outbox patterns when local style supports it.
79
+ - Add retry classification for serialization failures, deadlocks, optimistic-lock failures, and unknown external outcomes only when the full transaction or command can be retried idempotently.
80
+ - Add focused tests for duplicate concurrent inserts, count-limit races, rollback behavior, after-commit behavior, commit-time constraints, transaction propagation, savepoint behavior, optimistic locking, and external side-effect ordering when configured tests can exercise them.
81
+ - Do not add broad SERIALIZABLE, distributed locks, `SELECT ... FOR UPDATE`, `SKIP LOCKED`, `REQUIRES_NEW`, retries, or after-commit callbacks as magic fixes without naming the invariant, lock target, failure behavior, and side-effect ordering.
82
+ - Do not trade correctness, authorization, tenant isolation, idempotency, auditability, or user-visible truth for shorter code or a narrower transaction.
83
+
84
+ <!-- mustflow-section: procedure -->
85
+ ## Procedure
86
+
87
+ 1. Name the business invariant before judging the transaction. If the invariant cannot be stated, the transaction cannot be reviewed.
88
+ 2. Draw the decision ledger.
89
+ - Mark every read, `exists()`, `count`, `findBy`, status check, balance check, permission check, uniqueness check, and validation.
90
+ - Mark the write, insert, update, delete, publish, send, cache change, and response that depends on each decision.
91
+ - The true boundary is read -> decision -> write, not only the final `UPDATE`.
92
+ 3. Reject app-only check-then-act for durable facts.
93
+ - `exists()` then `insert()` needs a unique constraint, atomic upsert, insert-or-ignore, or equivalent durable guard.
94
+ - `count < limit` then add may need a parent row lock, counter row, conditional update, exclusion constraint, SERIALIZABLE with retry, or another durable single-writer authority.
95
+ - "No row found" is not locked by `SELECT ... FOR UPDATE`; absent future rows need constraints, parent locks, predicate protection, or atomic create.
96
+ 4. Check lock target and lock timing.
97
+ - Pessimistic locks are most useful when acquired before the business decision.
98
+ - A lock after reading and validating can protect the write while leaving the decision stale.
99
+ - PostgreSQL row locks do not block ordinary reads. Do not assume `FOR UPDATE` makes the row invisible.
100
+ - `SKIP LOCKED` intentionally skips locked rows and can produce an incomplete view; use it for queue claiming, not ordinary consistency checks.
101
+ 5. Check isolation-level assumptions by engine and framework.
102
+ - READ COMMITTED does not mean one stable world for the whole transaction.
103
+ - PostgreSQL and MySQL InnoDB REPEATABLE READ differ, especially when locking reads or writes mix with ordinary reads.
104
+ - SERIALIZABLE is not a global mutex. It can abort the transaction and require a full retry.
105
+ - Report engine-specific uncertainty instead of claiming isolation behavior from memory.
106
+ 6. Review full-transaction retry semantics.
107
+ - Retry the full transaction or command decision, not only the last failed statement.
108
+ - Treat `serialization_failure`, `deadlock_detected`, optimistic-lock failure, lock timeout, and unknown provider outcome as separate categories.
109
+ - Retrying without idempotency can duplicate side effects; not retrying serialization failures can surface false 500s for normal concurrency.
110
+ 7. Review rollback triggers and swallowed exceptions.
111
+ - Frameworks often decide rollback from whether an exception escapes the transactional boundary.
112
+ - Catching inside the transaction and returning success can commit partial failure.
113
+ - Spring defaults roll back on runtime exceptions and errors, not every checked exception; review `rollbackFor` and local rules.
114
+ 8. Review transaction proxy and propagation behavior.
115
+ - Spring self-invocation can bypass `@Transactional` proxy behavior.
116
+ - `readOnly` is usually a hint, not a guaranteed write blocker.
117
+ - Isolation declarations usually apply only when a new transaction starts.
118
+ - Inner rollback-only markers can make an outer `REQUIRED` commit fail with `UnexpectedRollbackException`.
119
+ - `REQUIRES_NEW` commits independently and consumes another connection while the outer transaction may still hold resources.
120
+ - `NESTED` is typically a savepoint, not an independent commit.
121
+ 9. Review Django, SQLAlchemy, and Hibernate lifecycle traps when relevant.
122
+ - Nested Django `atomic()` blocks do not make inner work durable if an outer block rolls back; `transaction.on_commit()` runs only after a successful outer commit.
123
+ - SQLAlchemy `Session` can begin transactions implicitly; absence of an explicit `begin` is not proof there is no transaction.
124
+ - Hibernate flush is not commit. Flush can occur before commit and before queries, so constraint failures or SQL effects may appear earlier than code order suggests.
125
+ - Hibernate `@Version` or equivalent optimistic lock checks are needed for long user think-time updates where last writer would otherwise win.
126
+ 10. Move external side effects out of the transaction boundary.
127
+ - Email, cache eviction, queue publish, HTTP API calls, payment provider calls, object storage writes, file uploads, and search indexing do not roll back with the database.
128
+ - Prefer after-commit hooks for non-critical callbacks and outbox records for durable side effects that must eventually happen.
129
+ - Remember that an after-commit callback failure does not roll back an already committed database transaction.
130
+ 11. Review transaction width and resource pressure.
131
+ - Do not hold locks or connections across HTTP API calls, file uploads, sleeps, large loops, slow calculations, logging sinks, JSON serialization, queue waits, or user-controlled waits.
132
+ - Timeouts do not undo already-sent external effects.
133
+ - `REQUIRES_NEW`, nested service calls, and transaction-per-item loops can exhaust connection pools.
134
+ 12. Review multi-database and transaction-manager scope.
135
+ - A transaction annotation or helper may cover only one data source, ORM session, connection, or transaction manager.
136
+ - Cross-database updates, external services, caches, search indexes, queues, and object storage need outbox, saga, compensation, reconciliation, or manual recovery rather than pretend single-transaction atomicity.
137
+ 13. Review advisory and distributed locks.
138
+ - PostgreSQL session-level advisory locks can survive rollback and require release or session end.
139
+ - Transaction-level advisory locks release at transaction end and are usually safer for short critical sections.
140
+ - Distributed locks need durable backstops such as fencing tokens, idempotency keys, conditional writes, unique constraints, or state transitions.
141
+ 14. Review transaction tests with suspicion.
142
+ - Spring transactional tests commonly roll back after each test.
143
+ - Django `TestCase` wraps tests in transactions and may not run real commit behavior or `on_commit()` callbacks.
144
+ - Tests that never commit can miss commit-time constraints, after-commit callbacks, lock behavior, deadlocks, serialization failures, and pool pressure.
145
+ 15. Check grep bait near the transaction.
146
+ - Review code around `exists`, `count`, `findBy`, `save`, `flush`, `catch`, `rollbackFor`, `REQUIRES_NEW`, `NESTED`, `readOnly`, `FOR UPDATE`, `SKIP LOCKED`, `on_commit`, `afterCommit`, `@Async`, `Executor`, `RestTemplate`, `WebClient`, `send`, `publish`, and `cache.evict`.
147
+ - These terms are not bugs by themselves. They are anchors for read-decision-write, propagation, external side-effect, and rollback review.
148
+ 16. Label evidence honestly.
149
+ - Static review can identify transaction boundary risk but cannot prove concurrency safety.
150
+ - Engine docs, framework docs, plan output, integration tests, and production traces are stronger evidence only when they match the repository version and workload.
151
+
152
+ <!-- mustflow-section: postconditions -->
153
+ ## Postconditions
154
+
155
+ - The business invariant, transaction boundary, decision ledger, durable guard, side-effect ledger, retry rule, and test evidence are explicit.
156
+ - App-only `exists()`/`count` checks, stale read -> decision -> write sequences, row-lock gaps, isolation assumptions, swallowed rollback triggers, propagation surprises, premature side effects, wide transactions, connection-pool pressure, multi-database drift, advisory-lock scope, and transactional-test blind spots are fixed or reported.
157
+ - External side effects are after commit, outbox-backed, idempotent, compensatable, or explicitly marked as manual recovery risk.
158
+ - Correctness, authorization, tenant isolation, idempotency, ordering, auditability, and user-visible truth remain intact or are reported as tradeoffs.
159
+ - Transaction safety claims are backed by configured evidence, representative framework or database evidence, or labeled as static review risk.
160
+
161
+ <!-- mustflow-section: verification -->
162
+ ## Verification
163
+
164
+ Use configured oneshot command intents when available:
165
+
166
+ - `changes_status`
167
+ - `changes_diff_summary`
168
+ - `lint`
169
+ - `build`
170
+ - `test_related`
171
+ - `test`
172
+ - `docs_validate_fast`
173
+ - `test_release`
174
+ - `mustflow_check`
175
+
176
+ Use the narrowest configured test, build, docs, release, or mustflow intent that covers the changed transaction boundary and synchronized template surfaces. Do not infer raw database shells, live lock tests, load tests, chaos tests, provider calls, server processes, watcher processes, or package-manager commands outside the command contract.
177
+
178
+ <!-- mustflow-section: failure-handling -->
179
+ ## Failure Handling
180
+
181
+ - If a configured command fails, preserve the failing intent, failing assertion or output tail, and the transaction invariant it exercised before editing again.
182
+ - If the invariant, transaction manager, isolation level, propagation mode, or durable guard is unknown, report static risk instead of claiming the transaction is safe.
183
+ - If a safe fix requires a schema constraint, engine-specific isolation change, outbox worker, idempotency store, saga, compensation path, or provider reconciliation outside the current scope, report the missing durable boundary.
184
+ - If deterministic concurrency or commit-time proof is not configured, report the missing manual evidence and complete the configured checks that are available.
185
+
186
+ <!-- mustflow-section: output-format -->
187
+ ## Output Format
188
+
189
+ - Transaction boundary reviewed
190
+ - Business invariant and decision ledger
191
+ - Durable guard, lock target, isolation, retry, rollback, propagation, savepoint, framework lifecycle, external side-effect, transaction width, multi-database, advisory or distributed lock, and transactional-test findings
192
+ - Transaction-boundary fix made or recommended
193
+ - Evidence level: configured-test evidence, framework evidence, database evidence, static review risk, manual-only, missing, or not applicable
194
+ - Command intents run
195
+ - Skipped transaction diagnostics and reasons
196
+ - Remaining transaction-boundary integrity risk