mustflow 2.108.2 → 2.108.8

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 (34) hide show
  1. package/README.md +3 -0
  2. package/dist/cli/commands/script-pack.js +3 -0
  3. package/dist/cli/i18n/en.js +37 -0
  4. package/dist/cli/i18n/es.js +37 -0
  5. package/dist/cli/i18n/fr.js +37 -0
  6. package/dist/cli/i18n/hi.js +37 -0
  7. package/dist/cli/i18n/ko.js +37 -0
  8. package/dist/cli/i18n/zh.js +37 -0
  9. package/dist/cli/lib/command-registry.js +3 -0
  10. package/dist/cli/lib/script-pack-registry.js +84 -0
  11. package/dist/cli/script-packs/repo-automation-surface.js +88 -0
  12. package/dist/cli/script-packs/repo-dependency-surface.js +87 -0
  13. package/dist/cli/script-packs/repo-toolchain-provenance.js +90 -0
  14. package/dist/core/public-json-contracts.js +27 -0
  15. package/dist/core/repo-automation-surface.js +376 -0
  16. package/dist/core/repo-dependency-surface.js +282 -0
  17. package/dist/core/repo-toolchain-provenance.js +421 -0
  18. package/dist/core/script-pack-suggestions.js +33 -1
  19. package/package.json +1 -1
  20. package/schemas/README.md +10 -0
  21. package/schemas/repo-automation-surface-report.schema.json +148 -0
  22. package/schemas/repo-dependency-surface-report.schema.json +121 -0
  23. package/schemas/repo-toolchain-provenance-report.schema.json +124 -0
  24. package/templates/default/i18n.toml +18 -6
  25. package/templates/default/locales/en/.mustflow/skills/INDEX.md +15 -5
  26. package/templates/default/locales/en/.mustflow/skills/go-code-change/SKILL.md +98 -22
  27. package/templates/default/locales/en/.mustflow/skills/python-code-change/SKILL.md +86 -27
  28. package/templates/default/locales/en/.mustflow/skills/routes.toml +16 -4
  29. package/templates/default/locales/en/.mustflow/skills/rust-code-change/SKILL.md +51 -32
  30. package/templates/default/locales/en/.mustflow/skills/split-refactor-residual-path-review/SKILL.md +176 -0
  31. package/templates/default/locales/en/.mustflow/skills/typescript-code-change/SKILL.md +47 -29
  32. package/templates/default/locales/en/.mustflow/skills/ui-state-resurrection-review/SKILL.md +218 -0
  33. package/templates/default/locales/en/.mustflow/skills/version-freshness-check/SKILL.md +14 -13
  34. package/templates/default/manifest.toml +15 -1
@@ -2,11 +2,11 @@
2
2
  mustflow_doc: skill.go-code-change
3
3
  locale: en
4
4
  canonical: true
5
- revision: 4
5
+ revision: 7
6
6
  lifecycle: mustflow-owned
7
7
  authority: procedure
8
8
  name: go-code-change
9
- description: Apply this skill when Go source, modules, package APIs, interfaces, errors, goroutines, channels, context propagation, HTTP clients or servers, reverse proxies, JSON encoding, filesystem roots, network addresses, runtime limits, benchmarks, tests, tools, or generated code boundaries are created or changed.
9
+ description: Apply this skill when Go source, modules, workspaces, package APIs, package layout, internal boundaries, interfaces, structs, errors, goroutines, channels, context propagation, HTTP clients or servers, Gin engines, router groups, middleware chains, request binding, validation, recovery, access logging, CORS, cookies, trusted headers, graceful shutdown, reverse proxies, database/sql request integration, JSON encoding, filesystem roots, network addresses, runtime limits, profiling, benchmarks, tests, tools, or generated code boundaries 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 Go package, module, API, error, context, concurrency, runtime, HTTP, JSON, filesystem, and test boundaries without adding needless abstraction.
31
+ Preserve Go package, module, workspace, API, error, context, concurrency, runtime, HTTP, JSON, filesystem, performance, and test boundaries without adding needless abstraction.
32
32
 
33
33
  <!-- mustflow-section: use-when -->
34
34
  ## Use When
35
35
 
36
- - `.go`, `go.mod`, `go.sum`, `go.work`, build tags, generated code, public package API, tests, benchmarks, goroutines, channels, context propagation, HTTP clients or servers, reverse proxies, JSON encoding, filesystem access, network addresses, runtime tuning, tools, or module dependencies change.
37
- - The task touches interfaces, error wrapping, package structure, concurrency ownership, cancellation, timeout policy, memory limits, race-sensitive code, benchmark measurement, or module dependencies.
36
+ - `.go`, `go.mod`, `go.sum`, `go.work`, build tags, generated code, public package API, tests, benchmarks, goroutines, channels, context propagation, HTTP clients or servers, Gin engines, router groups, middleware chains, request binding, validation, recovery, access logging, CORS, cookies, trusted headers, graceful shutdown, reverse proxies, database/sql request integration, JSON encoding, filesystem access, network addresses, runtime tuning, profiling, tools, or module dependencies change.
37
+ - The task touches interfaces, structs, zero-value behavior, error wrapping, package structure, `internal` boundaries, import direction, concurrency ownership, cancellation, timeout policy, memory limits, race-sensitive code, benchmark measurement, or module dependencies.
38
38
  - Code or docs use Go-version-gated features such as expression operands to `new`, range-over-function iterators, generic type aliases, reflect iterators, `errors.AsType`, `sync.WaitGroup.Go`, `testing/synctest`, `testing.B.Loop`, `T.ArtifactDir`, `B.ArtifactDir`, `F.ArtifactDir`, `testing/cryptotest.SetGlobalRandom`, `os.Root` or `os.OpenInRoot`, `omitzero`, `go.mod` `tool`, `go fix` modernizers, `encoding/json/v2`, experimental `GOEXPERIMENT` features, or newer runtime defaults.
39
39
 
40
40
  <!-- mustflow-section: do-not-use-when -->
@@ -49,7 +49,9 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
49
49
  - `go.mod`, `go.sum`, `go.work`, build tooling, lint config, and CI hints.
50
50
  - All files in the changed package, including `_test.go`, build-tagged files, examples, and generated-file markers.
51
51
  - The public API surface when exported identifiers, errors, or package paths change.
52
+ - Package ownership, import direction, `internal` visibility, module path, major-version suffix, workspace usage, and whether the project is an importable library, self-contained server, tool, or monorepo.
52
53
  - Runtime and deployment context when the change touches HTTP, goroutines, timers, memory, `GOMAXPROCS`, cgroups, race detection, PGO, profiling, or container behavior.
54
+ - Gin or other Go HTTP framework context when relevant: framework version, minimum Go version, engine construction, route registration order, group creation order, middleware chain order, trusted proxy settings, recovery owner, logger query-string policy, route-pattern metric policy, CORS policy, cookie policy, trusted header boundary, context reuse boundaries, binding method, validator tags, body-size policy, upload limits, database call context, and response/error ownership.
53
55
  - Minimum supported Go version, `go` directive, `toolchain` directive, `GOEXPERIMENT`, and whether the feature is stable, experimental, or repository-pinned.
54
56
  - Configured verification intents.
55
57
 
@@ -59,7 +61,7 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
59
61
  - Inspect the whole package before adding names or methods.
60
62
  - Determine whether the change affects exported API, concurrency ownership, or dependency graph.
61
63
  - Identify generated files and avoid direct edits unless explicitly requested.
62
- - If a Go release, "latest Go", standard-library feature, runtime default, experimental package, or toolchain claim is written durably, use `version-freshness-check` and official Go sources.
64
+ - If a Go release, "latest Go", standard-library feature, runtime default, experimental package, toolchain claim, or Go framework version claim such as Gin release or minimum-Go support is written durably, use `version-freshness-check` with official Go, package registry, or framework-owned sources.
63
65
 
64
66
  <!-- mustflow-section: allowed-edits -->
65
67
  ## Allowed Edits
@@ -67,6 +69,9 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
67
69
  - Keep interfaces small and preferably owned by the consuming side.
68
70
  - Return concrete provider types from provider packages unless the package intentionally hides multiple implementations as its public API.
69
71
  - Keep domain and use-case packages free of SQL, HTTP transport, queue, cloud SDK, ORM, and vendor persistence types unless those types are the explicit public API.
72
+ - Use `internal` to protect implementation freedom for server and tool packages that are not meant to be imported.
73
+ - Keep structs, constructors, and zero values aligned with invariants: make the zero value useful, harmless, or impossible to misuse.
74
+ - Split domain, storage, JSON, and transport DTO shapes when they have different owners, lifetimes, validation rules, or compatibility contracts.
70
75
  - Preserve context propagation across API and goroutine boundaries.
71
76
  - Return actionable errors and wrap causes when callers need `errors.Is` or `errors.As`.
72
77
  - Add table-driven tests when they clarify behavior.
@@ -76,43 +81,58 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
76
81
  ## Procedure
77
82
 
78
83
  1. Read module files, package files, tests, build tags, and generated-code markers.
79
- 2. Classify the change as package API, internal implementation, dependency, error behavior, context flow, concurrency, HTTP or proxy behavior, JSON encoding, filesystem safety, runtime or deployment behavior, benchmark, tooling, or test-only.
84
+ 2. Classify the change as module or workspace metadata, package API, package layout, internal implementation, dependency, error behavior, context flow, concurrency, HTTP or proxy behavior, JSON encoding, filesystem safety, runtime or deployment behavior, performance measurement, benchmark, tooling, or test-only.
80
85
  3. Check the Go version contract before using newer syntax or APIs:
81
86
  - treat the `go` directive as a language and module compatibility switch, not decoration;
82
87
  - do not use `new(expr)`, range-over-function iterators, generic type aliases, reflect iterator methods, `errors.AsType`, `sync.WaitGroup.Go`, `testing/synctest`, `testing.B.Loop`, `T.ArtifactDir`, `B.ArtifactDir`, `F.ArtifactDir`, `testing/cryptotest.SetGlobalRandom`, `os.Root`, `os.OpenInRoot`, `omitzero`, `go.mod` `tool`, `go fix` modernizers, `encoding/json/v2`, or any `GOEXPERIMENT` feature unless the repository's supported Go version and build path allow it;
83
88
  - distinguish stable standard-library APIs from experimental APIs that require `GOEXPERIMENT`;
84
- - when `go.mod` or `go.work` changes, report language-version, module-graph, toolchain, and downstream support impact.
89
+ - when `go.mod` or `go.work` changes, report language-version, module-graph, workspace, toolchain, and downstream support impact.
85
90
  4. Check package boundaries before adding a package or interface:
91
+ - treat a module as a release, version, and distribution boundary, not a folder-cleanup tool;
92
+ - treat `go.work` as a local multi-module development surface unless the repository explicitly supports committing and verifying workspace mode;
93
+ - keep module paths stable and use the required major-version suffix for v2+ modules;
94
+ - prefer `internal` for server implementation packages that are not intended as public imports;
95
+ - check import direction before function bodies: domain packages should not import HTTP status codes, ORM rows, SQL drivers, queues, cloud SDKs, or vendor transport shapes unless that dependency is the package's explicit contract;
86
96
  - reject shared bucket packages named `common`, `util`, `types`, `interfaces`, `api`, or `models` unless the repository already has a specific local convention with a narrower meaning;
87
97
  - put an interface in the package that consumes the methods, not in the package that merely implements them;
88
98
  - create an interface only after a real consumer needs that exact method set;
89
99
  - shrink an interface to the methods the immediate consumer calls;
90
100
  - reject provider-side interfaces that exist only for mocks;
91
101
  - reject provider constructors that return interfaces by default; prefer concrete exported types such as `*Client`, `*Store`, or `*Service`;
102
+ - use generics for reusable containers, algorithms, and type-safe plumbing, not as a substitute for clear domain boundaries;
92
103
  - verify that a package split reduces a real dependency direction problem or creates a coherent capability instead of hiding imports.
93
104
  5. If exported identifiers or package paths change, classify the public API impact:
94
105
  - treat exported functions, variables, constants, types, methods, struct fields, interfaces, interface method sets, sentinel errors, typed errors, module path, package import path, and minimum Go version as contracts;
95
106
  - assume exported symbols in a v1+ module are public API unless the package is internal or local evidence proves otherwise;
96
107
  - do not remove, rename, or change exported signatures, exported field types, exported interface methods, or observable error behavior without an explicit breaking-change plan;
97
- - adding a method to an exported interface is breaking for external implementations even when adding a method to a concrete type would be safe.
108
+ - adding a method to an exported interface is breaking for external implementations even when adding a method to a concrete type would be safe;
109
+ - changing exported struct fields or JSON tags can be an API change even when function signatures stay stable.
98
110
  6. Preserve error contracts:
99
111
  - use `errors.Is` and `errors.As` semantics as observable API when documented or already tested;
100
112
  - do not compare error strings;
113
+ - do not rely on `err == sentinel` when callers may receive wrapped errors;
101
114
  - do not expose dependency sentinel or typed errors through wrapping unless the package intentionally supports them as API;
102
115
  - treat a change between observable wrapping and non-observable formatting as API-sensitive;
116
+ - keep public response messages separate from internal error causes. Do not return `err.Error()` to clients when the error may contain SQL, file paths, URLs, tokens, dependency details, or stack context;
117
+ - classify context cancellation, context deadlines, dependency timeouts, and domain failures at package boundaries instead of letting infrastructure errors leak upward unchanged;
118
+ - keep typed error pointer/value behavior consistent and avoid typed-nil errors behind an `error` interface;
119
+ - use `errors.Join` or multiple `%w` only when callers are expected to use `errors.Is` or `errors.As` rather than simple unwrap behavior;
103
120
  - use `errors.AsType` only when the supported Go version allows it and the shorter form preserves the same typed-error contract;
104
121
  - add tests for documented sentinel or typed errors when the error behavior changes.
105
- 7. If goroutines or channels change, name the owner, stop condition, cancellation path, wait path, error path, close responsibility, and test synchronization.
122
+ 7. If goroutines or channels change, name the owner, stop condition, cancellation path, wait path, error path, panic policy, close responsibility, backpressure boundary, and test synchronization.
106
123
  8. Choose the right goroutine primitive:
107
124
  - use `sync.WaitGroup.Go` only for tasks that do not return errors and must not panic;
125
+ - call manual `WaitGroup.Add` before starting the goroutine and do not copy a `WaitGroup` after first use;
108
126
  - use an errgroup-style boundary when work needs error propagation, context cancellation, or concurrency limits;
109
127
  - do not hand-roll `WaitGroup` plus error channel plus cancellation plus semaphore unless the local code already owns that exact pattern and tests cover it;
110
128
  - treat buffered-channel semaphores as semantic backpressure, not just a performance knob; changing capacity can change ordering and pressure;
129
+ - do not treat a channel as a data-race shield for maps, slices, pointers, or structs still shared across goroutines;
111
130
  - treat `TryLock` as suspicious unless skipping the work is genuinely correct and observable.
112
131
  9. Reject fire-and-forget goroutines unless they are owned by a long-lived object with a shutdown path, joined before return, managed by a group with a wait path, or explicitly documented as safely detached.
113
132
  10. Preserve context propagation:
114
133
  - request-scoped functions accept `ctx` first and pass it down;
115
134
  - do not store request context in structs;
135
+ - do not use `context.Value` as dependency injection, optional parameters, or a hidden configuration bag;
116
136
  - do not pass nil context;
117
137
  - do not introduce `context.Background()` inside request or operation depth unless it is a true process root with a documented owner;
118
138
  - derived contexts must release their cancel function on every path;
@@ -124,41 +144,97 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
124
144
  - the sender that knows all sends are complete closes the channel;
125
145
  - receivers do not close borrowed input channels;
126
146
  - multiple senders require a coordinator that closes only after all senders finish;
127
- - cancellable pipelines must avoid permanently blocking upstream goroutines when downstream stops early.
147
+ - cancellable pipelines must avoid permanently blocking upstream goroutines when downstream stops early;
148
+ - buffered channels are not durable queues and must not hide unbounded producer or retry behavior;
149
+ - avoid busy-loop `select` statements with a `default` branch unless skipping work immediately is the intended behavior and CPU impact is bounded.
128
150
  12. Use iterator functions only for pull-style traversal, not hidden concurrency. Honor the `yield` return value immediately, call the `stop` function from pull iterators, keep resource ownership visible, and keep channels for actual concurrent communication or backpressure.
129
151
  13. Keep timeout policy at request, command, API, or operation boundaries. Do not hide arbitrary sleeps or timeouts in reusable helpers unless that helper explicitly owns the policy.
130
152
  14. Check HTTP and proxy defaults:
131
- - set deliberate `http.Client` and `http.Server` timeouts for network-facing code; zero timeout means no limit in important cases;
153
+ - use an explicit `http.Server` for production-facing servers rather than bare convenience helpers;
154
+ - set deliberate `ReadHeaderTimeout`, request/body read policy, `WriteTimeout`, `IdleTimeout`, `MaxHeaderBytes`, `BaseContext`, `ConnState`, and `ErrorLog` where the server owns those behaviors; zero timeout means no limit in important cases;
155
+ - protect request bodies separately from headers with size limits and route-appropriate read deadlines;
156
+ - treat `WriteTimeout` carefully for SSE, long polling, chunked streaming, and large downloads; streaming paths need heartbeat, flush, per-write deadline, and disconnect behavior instead of a single short global timeout;
157
+ - do not treat `http.TimeoutHandler` as cancellation of the underlying business work; pass `r.Context()` through database, RPC, cache, queue, and outbound HTTP calls;
158
+ - do not use `ResponseWriter` or request bodies after `ServeHTTP` returns; background work must copy the needed payload and use a lifecycle context that is not the finished request context;
159
+ - design graceful shutdown as a state transition: drain readiness, stop new traffic, wait for `Shutdown`, fall back to `Close` only after the shutdown budget, and keep the main goroutine alive until shutdown completes;
160
+ - track WebSocket, hijacked, upgraded, or long-lived connections separately because ordinary `Shutdown` does not wait for them;
132
161
  - reuse clients and transports instead of creating them per request;
133
162
  - prefer reverse-proxy rewrite hooks over deprecated or unsafe director-style mutation when the supported Go version allows it;
134
163
  - keep hop-by-hop header, forwarded-host, scheme, cancellation, streaming, and error-mapping behavior explicit.
135
- 15. Keep JSON contracts honest:
164
+ 15. Check Gin and Go HTTP framework boundaries when relevant:
165
+ - prefer explicit production server construction around the framework engine; do not treat `Run`, `RunTLS`, or convenience helpers as graceful shutdown, timeout, or lifecycle policy;
166
+ - treat `gin.Default()` as a demo convenience unless local production policy really accepts its logger and recovery defaults; production paths usually need explicit request id, trace id, structured logging, panic reporting, security headers, timeout, metrics, and recovery ownership;
167
+ - centralize error response, access log, and metrics ownership. Handlers may classify failures, but one final responder should map typed errors to status, code, safe message, log level, retryability, and exposed details;
168
+ - use `c.Error` only when a later middleware owns normalization. Do not mix scattered `c.JSON(500, ...)`, `AbortWithError`, and a separate logger that reads a different error source;
169
+ - preserve `errors.Is` and `errors.As` across service and transport boundaries so domain failures, context deadlines, client cancellations, dependency timeouts, and programmer bugs stay distinguishable;
170
+ - use custom recovery when production needs panic id, request id, route pattern, user or tenant id, stack capture, error tracking, and a safe generic response. Recovery middleware does not catch panics in goroutines started by the handler;
171
+ - log structured request fields from a fixed schema such as request id, trace id, method, route pattern, status, latency, client IP, user or tenant id, error code, error kind, panic marker, and body size. Use `c.FullPath()` or an equivalent route pattern for logs and metrics, not raw high-cardinality paths;
172
+ - treat 4xx, validation, auth denial, not found, timeout, client cancellation, 5xx, dependency failure, and panic as different observability classes instead of logging every non-2xx as the same error;
173
+ - register middleware before the routes and child groups that must receive it. `group.Use()` and parent middleware added after route or child-group creation must not be assumed to retrofit existing handlers;
174
+ - review middleware order around `c.Next()`: before-next code wraps inbound work, after-next code observes completed downstream work, and response writers or transactions must be finalized in the right phase;
175
+ - after `Abort` or `AbortWithStatusJSON`, return from the current middleware or handler unless the remaining local code is intentionally safe to run;
176
+ - do not pass the original `*gin.Context` into goroutines, store it in structs, or keep it after the request. Extract immutable values and use `c.Request.Context()` only for work that should die with the request;
177
+ - treat `c.Copy()` as a shallow request-context snapshot, not a deep copy of request data, cancellation semantics, pointers, maps, slices, body bytes, or framework writer state;
178
+ - keep response writes in the original handler flow. Background work should report through channels, queues, or owned result stores rather than calling `c.JSON`, `c.Error`, `c.Abort`, `c.Writer`, `c.Query`, `c.PostForm`, or multipart parsing from another goroutine;
179
+ - forward `c.Request.Context()` to database, cache, RPC, outbound HTTP, and long-running work that should respect disconnects or timeouts; for work that must outlive the request, use a queue or an explicit detached lifecycle context with its own timeout and wait or retry policy;
180
+ - configure trusted proxies before relying on `ClientIP()` for rate limits, admin allowlists, geo policy, audit, or abuse controls; do not trust client-supplied forwarding headers by default, and treat `ClientIP()` as an auxiliary signal rather than authentication;
181
+ - when using trusted platform headers, require an outer network boundary that prevents direct origin-server access. Strip client-supplied identity, scheme, host, and forwarding headers at the edge before reinjecting trusted values;
182
+ - review CORS as browser response exposure, not API authentication. Parse and compare Origin by scheme, host, and port; avoid substring checks, origin reflection with credentials, wildcard assumptions for credentialed requests, missing `Vary: Origin`, and exposure of internal request or response headers;
183
+ - keep cookie policy explicit: narrow domain, `Secure`, `HttpOnly`, `SameSite`, `Path`, and host-only behavior for session cookies. Do not derive cookie `Secure` from `c.Request.TLS` when TLS terminates before the Go process;
184
+ - treat logger query-string handling as a privacy boundary. Avoid logging tokens, emails, OAuth codes, magic links, redirect parameters, search terms, or payment callback data from query strings;
185
+ - make route wildcard, escaped-path, raw-path, unescape, trailing-slash redirect, fixed-path redirect, and method-not-allowed behavior explicit when identifiers, file paths, signed URLs, or reverse proxies can change path meaning;
186
+ - use `ShouldBind` variants instead of `Bind` or `MustBind` when the endpoint owns JSON error shape, status code, validation response, logging, or security behavior;
187
+ - pick the binding source deliberately: URI params, query, headers, form, multipart, and JSON body should not all feed one domain model or permission object through a vague auto-binding path;
188
+ - use request DTOs with explicit `json`, `form`, `uri`, and `header` tags and `binding` validator tags. Do not bind directly into database, ORM, or domain models that contain server-owned fields such as owner, role, status, plan, hash, or tenant ids;
189
+ - distinguish field presence from zero values for booleans, numbers, and optional strings. Use pointers, presence types, or custom validators when `false`, `0`, or empty string can be a valid submitted value;
190
+ - reject or explicitly account for unknown JSON fields, duplicate keys, large numeric identifiers, and `map[string]any` float conversion when the endpoint makes money, identity, permission, or audit decisions;
191
+ - if request bodies are read by logging, HMAC, audit, or multiple bind passes, set a route-appropriate size limit first and restore or share the bytes deliberately. Treat `ShouldBindBodyWith` as whole-body memory retention, not a free parser cache;
192
+ - treat `MaxMultipartMemory` as a memory buffering threshold, not a full upload size limit. Enforce total request size, verify content, discard client filenames, and use server-owned storage names.
193
+ 16. Check database integration from handlers when relevant:
194
+ - open `*sql.DB` once at process or application startup, inject the long-lived pool, and close it during shutdown, not per request;
195
+ - set `SetMaxOpenConns`, `SetMaxIdleConns`, `SetConnMaxLifetime`, and `SetConnMaxIdleTime` from database capacity, app instance count, and traffic shape instead of relying on unbounded defaults;
196
+ - pass request or operation context to `QueryContext`, `QueryRowContext`, `ExecContext`, `BeginTx`, and driver or ORM APIs that support it;
197
+ - close `Rows`, check `rows.Err()`, handle transaction commit and rollback paths explicitly, and keep query timeout, retry, and pool-wait observability visible;
198
+ - expose pool pressure through `DBStats` or local metrics when handler latency may be caused by connection waits rather than slow business code.
199
+ 17. Keep JSON contracts honest:
136
200
  - choose `omitempty` versus `omitzero` deliberately, especially for `time.Time`, numeric zero, boolean false, and optional fields;
137
201
  - use `SetEscapeHTML(false)` only when the JSON is not embedded into HTML and callers expect raw `<`, `>`, or `&`;
138
202
  - treat `encoding/json/v2` and `jsontext` as experimental unless the repository explicitly opts into the relevant experiment and migration tests.
139
- 16. Check filesystem and network address helpers:
203
+ 18. Check filesystem and network address helpers:
140
204
  - use traversal-resistant root APIs when accepting user-controlled relative paths and the supported Go version provides them;
141
205
  - do not treat `filepath.Join` plus prefix checks as sufficient against symlinks and TOCTOU;
142
206
  - prefer `net/netip` for comparable IP addresses and map keys when supported;
143
207
  - use `net.JoinHostPort` instead of string formatting for host and port assembly so IPv6 works.
144
- 17. Check runtime and deployment behavior when relevant:
208
+ 19. Check runtime and deployment behavior when relevant:
145
209
  - set `GOMEMLIMIT` or `debug.SetMemoryLimit` before tuning `GOGC` for container memory pressure, leaving headroom for non-Go memory such as cgo, mmap, and the kernel;
146
210
  - question manual `GOMAXPROCS` pins in containers on Go versions with container-aware defaults;
147
211
  - use PGO only with representative profiles and keep `default.pgo` ownership clear;
148
212
  - treat goroutine leak profiling, SIMD, JSON v2, and other experiments as opt-in evidence-gathering, not default production assumptions;
149
213
  - remember that `-race` only finds races on executed paths and carries significant overhead.
150
- 18. Keep tests and benchmarks deterministic:
214
+ 20. For performance changes, measure before simplifying or optimizing:
215
+ - require profile or benchmark evidence before accepting a more complex hot-path change;
216
+ - inspect CPU, heap, allocation, goroutine, block, and mutex evidence according to the symptom instead of assuming CPU is the bottleneck;
217
+ - treat allocation reduction as GC-pressure reduction only when benchmark or profile evidence supports it;
218
+ - use escape-analysis findings to explain heap movement instead of assuming pointers are faster than values;
219
+ - use `sync.Pool` only for disposable temporary objects that may vanish at any time, not as a durable cache or lifecycle owner.
220
+ 21. Keep tests and benchmarks deterministic:
151
221
  - do not use elapsed real time to wait for goroutine progress; use explicit synchronization, owned lifecycle waits, fake time, `testing/synctest` when supported, or the repository's established concurrency test helper;
152
222
  - prefer `testing.B.Loop` for new benchmarks when the supported Go version allows it, and keep setup, cleanup, allocation measurement, and compiler optimization boundaries honest;
223
+ - compare benchmark changes across repeated runs and include `B/op` and `allocs/op` when allocation behavior is part of the claim;
153
224
  - use test artifact directories for files that should survive a test run only when the supported Go version and test invocation preserve artifacts; otherwise use the repository's existing temporary-file or golden-output policy;
154
225
  - for deterministic crypto tests, prefer the standard cryptographic test hook when the supported Go version provides it instead of overriding global readers in production code paths.
155
- 19. Keep Go tools and modernization explicit:
226
+ 22. Keep Go tools and modernization explicit:
156
227
  - prefer the `tool` directive over `tools.go` pinning only when the repository's supported Go version allows it;
157
228
  - use `go fix` modernizers as reviewed migrations, not silent drive-by rewrites;
158
229
  - update code generators, schema generators, lint helpers, and reflection-heavy tooling for generic aliases, alias node behavior, and reflect iterator methods only with fixture coverage;
159
230
  - prefer standard-library helpers such as `min`, `max`, `clear`, `slices`, `maps`, and `cmp` over new local utility packages when the supported Go version allows them.
160
- 20. If dependency metadata changes, keep module files and dependent tests synchronized. Do not raise the `go` directive, add toolchain requirements, change module path, or introduce direct dependencies unless the task requires it and the final report calls out the support impact.
161
- 21. Choose configured verification intents that cover formatting, tests, race-sensitive behavior, lint, API drift, module drift, docs, and release metadata when available.
231
+ 23. If dependency metadata changes, keep module files and dependent tests synchronized:
232
+ - do not raise the `go` directive, add toolchain requirements, change module path, or introduce direct dependencies unless the task requires it and the final report calls out the support impact;
233
+ - treat `go.sum` as checksum evidence, not a package lockfile and not disposable noise;
234
+ - treat `replace`, especially local-path `replace`, as temporary main-module or workspace-only wiring unless the repository documents a release plan for it;
235
+ - verify vendor output is regenerated by a configured intent when vendoring is part of the repository contract;
236
+ - check private module settings before adding private import paths so module names do not leak through public proxy or checksum lookups.
237
+ 24. Choose configured verification intents that cover formatting, tests, race-sensitive behavior, lint, API drift, module drift, docs, and release metadata when available.
162
238
 
163
239
  <!-- mustflow-section: postconditions -->
164
240
  ## Postconditions
@@ -166,7 +242,7 @@ Preserve Go package, module, API, error, context, concurrency, runtime, HTTP, JS
166
242
  - Package ownership and exported API impact are clear.
167
243
  - Context, goroutine, channel, and error ownership are explicit.
168
244
  - Go-version-gated syntax, standard-library APIs, runtime defaults, experiments, and module metadata are compatible with the repository's supported Go version.
169
- - HTTP timeout, proxy, JSON, filesystem, network address, runtime, test-time, benchmark, and tool decisions are explicit where touched.
245
+ - HTTP timeout, graceful shutdown, proxy, Gin route and middleware order, error response ownership, recovery, access logging, CORS, cookie, trusted header, Gin context lifetime, binding, validation, database integration, JSON, filesystem, network address, runtime, profiling, test-time, benchmark, and tool decisions are explicit where touched.
170
246
  - Tests cover the changed behavior without sleeps as synchronization.
171
247
  - Module drift is reported when dependency verification cannot run.
172
248
 
@@ -194,7 +270,7 @@ For concurrency-sensitive changes, report whether a configured race or equivalen
194
270
  - If an iterator function ignores `yield` returning false, a pull iterator omits `stop`, or a channel is replaced by an iterator while concurrency or backpressure remains required, restore the ownership contract before accepting the change.
195
271
  - If a goroutine has no owner, stop condition, wait path, cancellation path, or error path, do not add it.
196
272
  - If a newer Go feature is useful but the repository's `go` directive or CI matrix is lower, keep a fallback, defer the change, or report the required version bump instead of sneaking in the feature.
197
- - If HTTP clients, servers, or proxies have no timeout or cancellation boundary, stop and make the missing policy explicit before calling the path production-ready.
273
+ - If HTTP clients, servers, proxies, or Gin handlers have no timeout, cancellation, trusted-proxy, error response owner, recovery owner, log schema, CORS, cookie, trusted-header, context-lifetime, binding-source, body-size, database context, or middleware-order boundary, stop and make the missing policy explicit before calling the path production-ready.
198
274
  - If JSON tag changes alter omitted fields, zero values, HTML escaping, or experimental JSON behavior, treat the change as an API contract risk.
199
275
  - If a public error stops satisfying documented `errors.Is` or `errors.As` checks, restore the contract or report the breaking-change requirement.
200
276
  - If wrapping would expose a dependency error as public API, keep the dependency error internal or document the intentional contract.
@@ -206,7 +282,7 @@ For concurrency-sensitive changes, report whether a configured race or equivalen
206
282
  - Boundary checked
207
283
  - Package and API impact
208
284
  - Context/concurrency/error notes
209
- - Go version, runtime, HTTP, JSON, filesystem, benchmark, and tool notes when relevant
285
+ - Go version, module/workspace, runtime, HTTP/shutdown, Gin route/middleware/error/recovery/logging/CORS/cookie/context/binding, database, JSON, filesystem, profiling, benchmark, and tool notes when relevant
210
286
  - Files changed
211
287
  - Command intents run
212
288
  - Skipped checks and reasons
@@ -2,11 +2,11 @@
2
2
  mustflow_doc: skill.python-code-change
3
3
  locale: en
4
4
  canonical: true
5
- revision: 4
5
+ revision: 5
6
6
  lifecycle: mustflow-owned
7
7
  authority: procedure
8
8
  name: python-code-change
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.
9
+ description: Apply this skill when Python source, standard-library API usage, packaging, runtime version, import layout, architecture boundaries, type checking, async tasks, exception/logging/retry behavior, performance-sensitive collection usage, pytest fixtures/mocks, 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, standard-library, packaging, import, async resource, public API, typing, lint, and test boundaries while making a focused change.
31
+ Preserve Python runtime, standard-library, packaging, import, architecture, async resource, failure, performance, 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 standard-library feature usage, 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, async task lifecycles, exceptions, logging, retry, fallback, collection performance, or tests.
38
38
 
39
39
  <!-- mustflow-section: do-not-use-when -->
40
40
  ## Do Not Use When
@@ -47,10 +47,13 @@ Preserve Python runtime, standard-library, packaging, import, async resource, pu
47
47
 
48
48
  - Python version source: `requires-python`, `.python-version`, tool version files, CI matrix, or container base image.
49
49
  - Standard-library feature and runtime-behavior assumptions, especially when using Python-version-gated APIs or changed security defaults.
50
- - Packaging and dependency files, test config, lint config, and type checker config.
50
+ - Packaging and dependency files, build backend, package manager, lockfile owner, test config, lint config, and type checker config.
51
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.
52
+ - Architecture boundary: external adapters, framework request/response objects, ORM models, environment input, DTOs, domain value objects, import direction, and shared utility ownership.
52
53
  - Async ownership and resource cleanup surface when coroutines, tasks, context managers, sessions, clients, pools, files, async generators, subprocesses, or logging change.
54
+ - Failure surface when exceptions, logging config, retry, timeout, fallback, degraded responses, or observability fields change.
53
55
  - Public contract surface when imports, signatures, exceptions, return shapes, CLI behavior, config, environment variables, extras, Python version support, or typing stubs change.
56
+ - Runtime truth boundary for type hints: external input validation, `Any`, casts, ignores, protocols, guards, stubs, and `py.typed` when present.
54
57
  - Configured verification intents.
55
58
 
56
59
  <!-- mustflow-section: preconditions -->
@@ -59,6 +62,7 @@ Preserve Python runtime, standard-library, packaging, import, async resource, pu
59
62
  - Determine the lowest supported Python version before choosing syntax or typing features.
60
63
  - Determine the lowest supported Python version before choosing standard-library features, changed defaults, syntax, or typing features.
61
64
  - Read package layout and import style before editing imports.
65
+ - Read framework, adapter, or entry-point boundaries before moving data shapes across layers.
62
66
  - Treat global machine Python state as irrelevant unless the project explicitly declares it.
63
67
 
64
68
  <!-- mustflow-section: allowed-edits -->
@@ -70,61 +74,107 @@ Preserve Python runtime, standard-library, packaging, import, async resource, pu
70
74
  - Do not lower Ruff, mypy, pyright, pytest, or packaging strictness to hide a failure.
71
75
  - Keep import fixes in package metadata, package discovery, entry points, or test invocation contracts instead of path hacks.
72
76
  - Make resource ownership explicit: code closes only the resources it creates.
77
+ - Translate external data and third-party failures at boundaries instead of leaking framework, SDK, ORM, raw JSON, or environment shapes into domain logic.
73
78
 
74
79
  <!-- mustflow-section: procedure -->
75
80
  ## Procedure
76
81
 
77
82
  1. Read project metadata, Python version constraints, dependency files, and test/lint/type configs.
78
- 2. Identify the boundary touched: runtime version, package API, import root, packaging metadata, CLI entry, test fixture, async resource ownership, external input, or dependency contract.
83
+ 2. Identify the boundary touched: runtime version, package API, import root, packaging metadata, architecture layer, CLI entry, test fixture, async resource ownership, external input, exception/logging/retry path, performance-sensitive collection path, or dependency contract.
79
84
  3. For packaging and import changes, separate the distribution name from the import package name. Check package directory mapping, package discovery settings, namespace package behavior, package data, entry points, optional dependencies, and `requires-python` before touching imports.
80
- 4. Treat `src` layout as an installation contract. Importable code under `src/` should be tested through the supported installed-package path, not by making repository files accidentally importable from the working directory.
81
- 5. Match existing package layout and import conventions. Do not add `sys.path`, `site.addsitedir`, `PYTHONPATH`, pytest `pythonpath`, ad hoc import loading, or test `conftest.py` import hacks to make package imports pass.
82
- 6. Do not add `__init__.py` to tests as a blind fix. Add it only when tests are intentionally a package and the import-mode behavior remains explicit.
83
- 7. For packaging changes, distinguish development and release contracts:
85
+ 4. For `pyproject.toml`, keep build metadata, package metadata, and tool settings separate:
86
+ - `[build-system]` names the build backend and build requirements;
87
+ - `[project]` names distribution metadata, runtime dependencies, Python support, scripts, optional dependencies, and package typing signals;
88
+ - `[tool.*]`, dependency groups, uv or Poetry settings, and lockfiles are tool or environment contracts, not a substitute for wheel metadata.
89
+ 5. Treat `src` layout as an installation contract. Importable code under `src/` should be tested through the supported installed-package path, not by making repository files accidentally importable from the working directory.
90
+ 6. Match existing package layout and import conventions. Do not add `sys.path`, `site.addsitedir`, `PYTHONPATH`, pytest `pythonpath`, ad hoc import loading, or test `conftest.py` import hacks to make package imports pass.
91
+ 7. Do not add `__init__.py` to tests as a blind fix. Add it only when tests are intentionally a package and the import-mode behavior remains explicit.
92
+ 8. For packaging changes, distinguish development and release contracts:
84
93
  - editable installs prove the local development path;
85
94
  - wheel installs or equivalent built artifacts prove the release path;
95
+ - editable installs may not reflect entry point, dependency, package metadata, C extension, or package data changes until reinstall or rebuild;
96
+ - build dependencies, runtime dependencies, optional dependencies, and dependency groups are different contracts;
97
+ - apps should pin or lock environments; libraries should publish compatible dependency ranges instead of over-pinning downstream users;
98
+ - uv, Poetry, pip, and build backends each own different parts of the workflow; do not mix their metadata as competing sources of truth;
86
99
  - entry point, dependency, optional dependency, metadata, and package data changes require reinstall-oriented verification when a configured intent exists;
87
100
  - installed console scripts or plugin entry points should be smoke-tested through the installed entry point contract, not by directly running a source file.
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.
89
- 9. Validate unknown external data before treating it as typed domain data.
90
- 10. Choose standard-library helpers by semantic contract and supported Python version:
101
+ 9. 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.
102
+ 10. Preserve architecture boundaries:
103
+ - keep framework request objects, ORM models, SDK clients, raw JSON, environment variables, and CLI parser output in adapter layers;
104
+ - convert external input into explicit DTOs, dataclasses, value objects, or validated models before domain logic uses it;
105
+ - name modules by responsibility instead of dumping shared behavior into `utils.py`, `helpers.py`, or `common.py`;
106
+ - keep import direction one-way and treat circular imports as architecture evidence, not only a runtime nuisance;
107
+ - prefer protocols or narrow callable/data contracts over inheritance when callers only need behavior shape.
108
+ 11. Validate unknown external data before treating it as typed domain data. Type hints do not enforce runtime values; boundary validation owns JSON, form, CSV, queue, environment, and third-party API input.
109
+ 12. Keep type-checking honest:
110
+ - treat `Any`, bare generics, untyped imports, `cast`, broad `type: ignore`, false `TypeGuard` or `TypeIs`, and runtime `Protocol` checks as trust-boundary risks;
111
+ - prefer `object` plus narrowing over `Any` when a value is unknown but operations must be checked;
112
+ - require scoped `# type: ignore[...]` with a local reason when the project policy allows ignores;
113
+ - do not use `cast()` as conversion; add parsing, validation, or a checked adapter when runtime shape is uncertain;
114
+ - keep `None` explicit in signatures and return shapes instead of returning `None` from non-optional contracts;
115
+ - when publishing typed packages, keep `py.typed`, stubs, and public exports aligned.
116
+ 13. Choose standard-library helpers by semantic contract and supported Python version:
91
117
  - 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
118
  - do not use `itertools.groupby` as a database-style grouping primitive unless input ordering and group materialization are intentional;
93
119
  - avoid shared mutable defaults; use `default_factory` or an existing local construction pattern for per-instance mutable state;
94
120
  - 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
121
  - 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
122
  - 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. Treat newer syntax and typing features as semantic tools, not style trophies:
123
+ 14. Review collection and iterator performance when code can scale with input size:
124
+ - avoid list membership inside large loops, `pop(0)`, repeated list concatenation, large loop slices, and hot-path `deepcopy`;
125
+ - use `set`, `dict`, `deque`, `Counter`, `heapq`, `join`, comprehensions, or `itertools` when they match the data contract;
126
+ - treat generators as one-shot streams; do not add hidden `list()`, `sorted()`, `len()`, `tee()`, or `cycle()` materialization without memory reasoning;
127
+ - rebuild large dicts after bulk deletion when long-lived memory and iteration cost matter;
128
+ - avoid eager default factories hidden in `dict.get(key, expensive())` or `setdefault(key, expensive())`.
129
+ 15. Treat newer syntax and typing features as semantic tools, not style trophies:
98
130
  - use template string literals only when a handler needs the static and interpolated parts separately, such as SQL builders, shell command objects, logging templates, or markup renderers; do not replace ordinary f-strings when the result is just a string;
99
131
  - when runtime code reads annotations, use the supported annotation inspection API and choose the intended format explicitly instead of assuming `__annotations__` already contains runtime values;
100
132
  - use sentinel values to distinguish "argument omitted" from `None`, but compare sentinels by identity and keep public signatures readable;
101
133
  - prefer `Mapping` or narrower read-only protocols for read-only inputs so immutable mapping implementations are not rejected accidentally;
102
134
  - use closed or extra-key `TypedDict` forms only when the supported Python and type-checker versions agree with that shape.
103
- 12. Keep `finally` as cleanup, not outcome selection. Do not add `return`, `break`, or `continue` inside `finally` blocks because they can mask exceptions and cancellation; move result decisions outside cleanup or make suppression an explicit documented contract.
104
- 13. Use explicit lazy imports only for startup-sensitive module-scope dependencies after checking version support and import-time side effects. Do not lazily import plugins, registries, monkey patches, model definitions, ORM mappings, or observability setup whose import side effects are part of startup correctness.
105
- 14. Keep process, archive, and concurrency safety explicit:
135
+ 16. Keep `finally` as cleanup, not outcome selection. Do not add `return`, `break`, or `continue` inside `finally` blocks because they can mask exceptions and cancellation; move result decisions outside cleanup or make suppression an explicit documented contract.
136
+ 17. Use explicit lazy imports only for startup-sensitive module-scope dependencies after checking version support and import-time side effects. Do not lazily import plugins, registries, monkey patches, model definitions, ORM mappings, or observability setup whose import side effects are part of startup correctness.
137
+ 18. Keep process, archive, and concurrency safety explicit:
106
138
  - subprocess calls use argument lists, checked failure handling, timeouts, bounded captured output, and a narrow `shell=True` exception when the project already permits it;
107
139
  - archive extraction, including `tarfile`, keeps untrusted archive inspection, extraction filters, partial-extract cleanup, and older-runtime defaults visible;
108
140
  - `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.
109
- 15. 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.
110
- 16. Preserve async and resource ownership:
141
+ 19. 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.
142
+ 20. Preserve async and resource ownership:
111
143
  - every coroutine is awaited, returned by contract, or scheduled as an owned and tracked task;
112
144
  - raw background task creation is allowed only through the project's owner or spawn helper, a task group, or an equivalent lifecycle mechanism;
113
145
  - background tasks keep a strong reference, have a shutdown path, and retrieve failures instead of leaving never-retrieved exceptions;
114
146
  - cancellation is control flow, so cleanup uses `finally` and cancellation is re-raised after cleanup unless suppression is the documented behavior;
147
+ - choose `TaskGroup` over `gather()` when sibling task failure must cancel the rest;
148
+ - bound fan-out with semaphores, queues, worker pools, or an existing local concurrency primitive;
149
+ - propagate absolute deadlines or remaining budgets through nested calls instead of resetting relative timeouts at every layer;
150
+ - cancel and await pending tasks after `asyncio.wait()` timeouts;
115
151
  - async functions do not call blocking I/O, blocking sleeps, long CPU work, or blocking subprocess waits directly unless the project has an explicit executor or isolation pattern;
116
152
  - context managers and async context managers do not suppress exceptions unless suppression is the feature;
117
153
  - context-manager helpers that catch exceptions for logging re-raise after logging;
118
154
  - early-exit async generators have an explicit close path.
119
- 17. Preserve traceback evidence. Logging inside exception handlers should retain exception information instead of logging only the exception message.
120
- 18. Preserve public contracts:
155
+ 21. Preserve failure evidence:
156
+ - translate external exceptions into domain exceptions at boundaries with `raise ... from exc`;
157
+ - do not use `except Exception: pass`, broad `BaseException` catches, or fallback returns that hide failures;
158
+ - use `logger.exception()` only inside exception handlers or preserve exception info explicitly;
159
+ - configure logging so module loggers propagate through a deliberate root or parent handler, existing loggers are not disabled accidentally, and slow handlers are isolated when request latency matters;
160
+ - keep retry finite, jittered or backed off where appropriate, idempotent, and owned by one layer;
161
+ - make fallback a visible degraded path with logs, metrics, or response metadata rather than silent success.
162
+ 22. Preserve public contracts:
121
163
  - 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;
122
164
  - 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;
123
165
  - typed packages should keep runtime and typing surfaces aligned, including `py.typed` and stubs when present.
124
- 19. Avoid mutable default arguments, broad `except Exception: pass`, broad `BaseException` catches outside process boundaries, global state hidden behind module imports, `finally` masking, and path handling that ignores existing `pathlib` or OS conventions.
125
- 20. Use `# type: ignore[...]` only when tightly scoped, justified, and consistent with local policy.
126
- 21. 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.
127
- 22. Choose configured verification intents that cover formatting, lint, type checking, tests, package build, installed-package smoke checks, and CLI smoke risk when available.
166
+ 23. Preserve test truth:
167
+ - keep pytest fixtures small, with one state-changing responsibility and cleanup coupled to that state;
168
+ - treat fixture scope and autouse as isolation decisions, not speed knobs;
169
+ - avoid mutable `parametrize` values unless each case receives a fresh object;
170
+ - use `tmp_path`, scoped `monkeypatch`, and patch the namespace where code looks up the object;
171
+ - prefer mock `autospec`, `spec_set`, and `AsyncMock` await assertions so tests cannot lie about signatures or async execution;
172
+ - use log assertions to check operational signals, not only message text;
173
+ - use property-based tests when behavior is an invariant over an input space and existing project dependencies support it.
174
+ 24. Avoid mutable default arguments, broad `except Exception: pass`, broad `BaseException` catches outside process boundaries, global state hidden behind module imports, `finally` masking, and path handling that ignores existing `pathlib` or OS conventions.
175
+ 25. Use `# type: ignore[...]` only when tightly scoped, justified, and consistent with local policy.
176
+ 26. If packaging, public API, CLI, config, typing, async, retry, logging, or test contracts change, synchronize README examples, entry point tests, build metadata, docs, fixtures, and downstream-style examples that describe installation or usage.
177
+ 27. Choose configured verification intents that cover formatting, lint, type checking, tests, package build, installed-package smoke checks, and CLI smoke risk when available.
128
178
 
129
179
  <!-- mustflow-section: postconditions -->
130
180
  ## Postconditions
@@ -133,10 +183,14 @@ Preserve Python runtime, standard-library, packaging, import, async resource, pu
133
183
  - Python-version-gated standard-library features and changed runtime defaults are accepted only when the declared support matrix allows them.
134
184
  - Imports work from the project-supported execution path.
135
185
  - Packaging changes distinguish development imports from release artifact imports.
186
+ - Framework, ORM, SDK, raw input, and environment data stay outside the domain core unless intentionally adapted.
187
+ - Runtime validation, type hints, and published typing metadata agree at public and external-input boundaries.
136
188
  - Async tasks, context managers, files, clients, pools, subprocesses, and generators have visible ownership and cleanup.
189
+ - Exceptions, logs, retries, timeouts, and fallback paths preserve cause, deadline, idempotency, and degraded-state evidence.
190
+ - Collection and iterator changes have size, copy, and materialization behavior reviewed when relevant.
137
191
  - Public API, CLI, config, environment, dependency metadata, and typing contract changes are called out.
138
192
  - Type and lint strictness are not weakened.
139
- - Tests or skipped verification are tied to the changed behavior.
193
+ - Tests or skipped verification are tied to the changed behavior, with fixture/mock/async/logging risks named when relevant.
140
194
 
141
195
  <!-- mustflow-section: verification -->
142
196
  ## Verification
@@ -158,13 +212,18 @@ Report missing package, type, or test intents rather than inventing raw tool com
158
212
  - If import resolution fails, inspect package metadata and test invocation before adding path hacks.
159
213
  - 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.
160
214
  - If packaging correctness matters but only repository-root tests can run, report that wheel or installed-artifact verification is missing.
215
+ - If build backend, package manager, lockfile, dependency group, optional dependency, or editable-install behavior is ambiguous, keep the existing owner and report the missing packaging contract instead of migrating tools.
161
216
  - If the supported Python version blocks a syntax choice, rewrite to the supported form.
162
217
  - 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`.
163
218
  - If template strings, annotation runtime access, lazy imports, sentinels, immutable mappings, or typed extra keys are useful but version-gated, keep a fallback or report the required support bump instead of smuggling the newer feature into a lower-runtime project.
164
219
  - If third-party stubs or package metadata are wrong, document the local workaround and keep it narrow.
220
+ - If `Any`, `cast`, `type: ignore`, runtime `Protocol`, or type guard behavior is needed, keep it local, justified, and backed by runtime validation or tests where the type claim can lie.
221
+ - If performance risk appears in collections, generators, copies, or caches, report the input-size assumption or use an existing benchmark/profile intent when configured.
165
222
  - If a background task lacks owner, shutdown, strong reference, or exception retrieval, do not add it.
166
223
  - If cancellation or context-manager behavior is swallowed accidentally, restore propagation or document the intentional suppression contract.
224
+ - If retry, timeout, or fallback lacks idempotency, deadline, owner layer, or degraded-state evidence, keep the failure explicit instead of adding hidden recovery.
167
225
  - If resource cleanup cannot be proven, use the project's context manager, exit stack, fixture, or lifecycle pattern before broadening tests.
226
+ - If tests require broad fixtures, autouse state, unscoped monkeypatching, bare mocks, or mutable parametrization, narrow the test seam before trusting the result.
168
227
  - If public contracts change without compatibility evidence, stop and report the breaking-change or deprecation requirement.
169
228
 
170
229
  <!-- mustflow-section: output-format -->
@@ -173,7 +232,7 @@ Report missing package, type, or test intents rather than inventing raw tool com
173
232
  - Boundary checked
174
233
  - Runtime and packaging assumptions
175
234
  - Files changed
176
- - Type, lint, and import notes
235
+ - Architecture, type, lint, import, async, failure, performance, and test notes
177
236
  - Command intents run
178
237
  - Skipped checks and reasons
179
238
  - Remaining Python risk
@@ -36,6 +36,12 @@ route_type = "primary"
36
36
  priority = 40
37
37
  applies_to_reasons = ["code_change", "behavior_change"]
38
38
 
39
+ [routes."split-refactor-residual-path-review"]
40
+ category = "architecture_patterns"
41
+ route_type = "adjunct"
42
+ priority = 79
43
+ applies_to_reasons = ["unknown_change", "code_change", "behavior_change", "test_change", "public_api_change", "performance_change", "ui_change", "data_change"]
44
+
39
45
  [routes."composition-over-inheritance"]
40
46
  category = "architecture_patterns"
41
47
  route_type = "primary"
@@ -526,7 +532,7 @@ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "pe
526
532
  category = "general_code"
527
533
  route_type = "primary"
528
534
  priority = 85
529
- applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "data_change", "migration_change", "ui_change", "package_metadata_change"]
535
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "data_change", "migration_change", "ui_change", "performance_change", "package_metadata_change", "release_risk"]
530
536
 
531
537
  [routes."javascript-code-change"]
532
538
  category = "general_code"
@@ -538,7 +544,7 @@ applies_to_reasons = ["code_change", "public_api_change", "test_change"]
538
544
  category = "general_code"
539
545
  route_type = "primary"
540
546
  priority = 85
541
- applies_to_reasons = ["code_change", "public_api_change", "test_change"]
547
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "data_change", "migration_change", "performance_change", "security_change", "privacy_change", "package_metadata_change", "release_risk"]
542
548
 
543
549
  [routes."powershell-code-change"]
544
550
  category = "general_code"
@@ -550,13 +556,13 @@ applies_to_reasons = ["code_change", "test_change", "docs_change", "package_meta
550
556
  category = "general_code"
551
557
  route_type = "primary"
552
558
  priority = 85
553
- applies_to_reasons = ["code_change", "public_api_change", "test_change"]
559
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "docs_change", "data_change", "performance_change", "package_metadata_change", "release_risk"]
554
560
 
555
561
  [routes."rust-code-change"]
556
562
  category = "general_code"
557
563
  route_type = "primary"
558
564
  priority = 85
559
- applies_to_reasons = ["code_change", "public_api_change", "test_change"]
565
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "docs_change", "data_change", "performance_change", "security_change", "privacy_change", "package_metadata_change", "release_risk"]
560
566
 
561
567
  [routes."axum-code-change"]
562
568
  category = "general_code"
@@ -990,6 +996,12 @@ route_type = "adjunct"
990
996
  priority = 80
991
997
  applies_to_reasons = ["ui_change", "behavior_change", "code_change", "performance_change", "data_change", "test_change", "public_api_change"]
992
998
 
999
+ [routes."ui-state-resurrection-review"]
1000
+ category = "ui_assets"
1001
+ route_type = "adjunct"
1002
+ priority = 83
1003
+ applies_to_reasons = ["unknown_change", "ui_change", "behavior_change", "code_change", "performance_change", "data_change", "test_change", "public_api_change", "docs_change", "package_metadata_change", "release_risk"]
1004
+
993
1005
  [routes."frontend-stress-layout-review"]
994
1006
  category = "ui_assets"
995
1007
  route_type = "adjunct"