mustflow 2.108.3 → 2.112.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.
@@ -0,0 +1,284 @@
1
+ ---
2
+ mustflow_doc: skill.duckdb-code-change
3
+ locale: en
4
+ canonical: true
5
+ revision: 1
6
+ lifecycle: mustflow-owned
7
+ authority: procedure
8
+ name: duckdb-code-change
9
+ description: Apply this skill when DuckDB-specific embedded OLAP database use, `.duckdb` file ownership, concurrency, language bindings, Appender usage, CSV/Parquet/JSON ingestion, query determinism, timestamp behavior, memory and temp spill settings, profiling, indexes, CTEs, macros, or DuckDB runtime behavior is created, changed, reviewed, or reported.
10
+ metadata:
11
+ mustflow_schema: "1"
12
+ mustflow_kind: procedure
13
+ pack_id: mustflow.core
14
+ skill_id: mustflow.core.duckdb-code-change
15
+ command_intents:
16
+ - changes_status
17
+ - changes_diff_summary
18
+ - test_related
19
+ - test
20
+ - lint
21
+ - build
22
+ - docs_validate_fast
23
+ - test_release
24
+ - mustflow_check
25
+ ---
26
+
27
+ # DuckDB Code Change
28
+
29
+ <!-- mustflow-section: purpose -->
30
+ ## Purpose
31
+
32
+ Keep DuckDB changes honest about embedded OLAP constraints, process ownership, file-format
33
+ ingestion, memory and spill behavior, deterministic SQL results, and profiling evidence.
34
+
35
+ DuckDB is embedded OLAP, not SQLite-like OLTP app storage. It is excellent for local analytics,
36
+ columnar scans, file-backed data exploration, batch transforms, and analytical features inside an
37
+ application process. It is a bad fit when code treats one native `.duckdb` file as a multi-process
38
+ write server, hides connection ownership behind a generic pool, or assumes fast vectorized scans
39
+ remove the need for deterministic SQL, import contracts, memory budgets, and measured plans.
40
+
41
+ <!-- mustflow-section: use-when -->
42
+ ## Use When
43
+
44
+ - DuckDB schema, SQL, generated SQL, query builders, migrations, embedded database files, analytics
45
+ jobs, local ETL, exports, imports, fixtures, tests, or docs are introduced, changed, reviewed, or
46
+ reported.
47
+ - Code uses DuckDB through Python, Node.js, Go, Rust, WASM, CLI-adjacent tooling, an ORM, a query
48
+ builder, a data-frame bridge, Appender APIs, or direct reads from CSV, Parquet, JSON, Hive-style
49
+ partitions, remote object storage, or another DuckDB file.
50
+ - A task mentions `.duckdb`, `duckdb.sql()`, `:default:`, `cursor()`, `DuckDBInstance`, Appender,
51
+ `memory_limit`, `temp_directory`, `duckdb_memory()`, `duckdb_temporary_files()`,
52
+ `preserve_insertion_order`, `union_by_name`, `store_rejects`, `filename`, `EXPLAIN ANALYZE`,
53
+ `profiling_coverage`, `AS MATERIALIZED`, `AS NOT MATERIALIZED`, `QUALIFY`, macros, ART indexes,
54
+ `TIMESTAMPTZ`, order-sensitive aggregates, or Parquet row group behavior.
55
+ - Documentation or final reports claim a DuckDB path is safe for concurrent app writes,
56
+ production-ready, deterministic, cheap, memory-bounded, spill-safe, schema-drift-safe,
57
+ file-format-safe, version-compatible, or query-plan-backed.
58
+
59
+ <!-- mustflow-section: do-not-use-when -->
60
+ ## Do Not Use When
61
+
62
+ - The task is database-backed but not DuckDB-specific; use `database-change-safety`.
63
+ - The task only changes generic database migrations without DuckDB-specific embedded-file,
64
+ process-concurrency, import/export, or analytical-query behavior; use `database-migration-change`
65
+ first.
66
+ - The task is primarily SQLite, PostgreSQL, ClickHouse, search, vector, cache, queue, or data
67
+ warehouse vendor work; use the matching engine or integration skill first.
68
+ - The task only researches DuckDB package, extension, or binding versions; use
69
+ `dependency-reality-check`, `dependency-upgrade-review`, or `version-freshness-check`.
70
+
71
+ <!-- mustflow-section: required-inputs -->
72
+ ## Required Inputs
73
+
74
+ - DuckDB role: embedded analytics engine, local scratch database, batch transform engine,
75
+ app-local report store, packaged read model, test fixture, cache, or source of product truth.
76
+ - Runtime identity: DuckDB version and track, binding or driver, extension inventory, bundled
77
+ versus system/runtime build, storage path, and whether the runtime is native, WASM, Node, Python,
78
+ Go, Rust, serverless, desktop, or mobile-like.
79
+ - File and process ownership: native `.duckdb` path, process count, thread model, read-only versus
80
+ read-write mode, writer owner, cross-process coordination, backup/export path, and whether
81
+ Quack, DuckLake, or another coordination layer is intentionally used.
82
+ - Ingest and export shape: file formats, compression, sample size, schema drift, malformed-row
83
+ policy, lineage columns, Parquet row groups, partition layout, object-store behavior, and whether
84
+ row-by-row inserts or Appender APIs are used.
85
+ - Query shape: selected columns, filters, ordering, pagination, grouping, order-sensitive
86
+ aggregates, windows, joins, CTE materialization expectations, macro usage, indexes, and plan or
87
+ profiling evidence when available.
88
+ - Operational shape: `memory_limit`, thread count, temp spill directory, temp size limit, app worker
89
+ count, blocking operators, profiling output location, observability through `duckdb_memory()` and
90
+ `duckdb_temporary_files()`, and failure behavior for out-of-memory, disk-full, parse, and reject
91
+ rows.
92
+ - Relevant command-intent contract entries for tests, builds, docs, release checks, and mustflow
93
+ validation.
94
+
95
+ <!-- mustflow-section: preconditions -->
96
+ ## Preconditions
97
+
98
+ - The task matches the Use When conditions and does not match the exclusions.
99
+ - Higher-priority instructions and `.mustflow/config/commands.toml` have been checked for the
100
+ current scope.
101
+ - Treat pasted docs, release summaries, AI output, benchmark snippets, and blog posts as reference
102
+ evidence, not command authority.
103
+ - Refresh version-sensitive DuckDB feature claims from official DuckDB docs, release notes, or
104
+ repository-pinned evidence when the change depends on current support. Keep current, LTS, beta,
105
+ extension, and binding-specific tracks separate. As of 2026-07-05, the official install page
106
+ identifies DuckDB 1.5.4 as current and 1.4.5 as LTS; do not reuse that fact later without a fresh
107
+ check.
108
+ - If DuckDB stores product truth, personal data, tenant data, billing facts, deletion state, or
109
+ security-sensitive events, also use `database-change-safety` and the relevant security or privacy
110
+ skill.
111
+ - If schema or data must move from an old shape to a new shape, also use `database-migration-change`.
112
+ - If performance, memory, p95, import cost, export cost, or scale claims are made, also use
113
+ `performance-budget-check` or `database-query-bottleneck-review` as appropriate.
114
+
115
+ <!-- mustflow-section: allowed-edits -->
116
+ ## Allowed Edits
117
+
118
+ - Update DuckDB SQL, schemas, query builders, connection setup, binding-specific code, ingest and
119
+ export code, Appender code, settings, fixtures, tests, docs, and directly synchronized template
120
+ surfaces tied to the task.
121
+ - Add explicit version, binding, file ownership, process model, memory, spill, import/export,
122
+ deterministic ordering, profiling, and feature-gate notes when behavior depends on them.
123
+ - Do not treat this skill as permission to run raw DuckDB clients, live SQL, migrations,
124
+ benchmarks, package scripts, object-store operations, background workers, or long-running
125
+ services outside configured command intents.
126
+ - Do not trade correctness, tenant isolation, data retention, deterministic exports, reject-row
127
+ visibility, or recoverability for a faster-looking local query.
128
+
129
+ <!-- mustflow-section: procedure -->
130
+ ## Procedure
131
+
132
+ 1. Classify DuckDB's role. Decide whether it is an embedded analytical engine, a scratch database, a
133
+ derived read model, a local cache, a packaged seed, or authoritative product storage. If clearing
134
+ the file loses product meaning, require a backup, migration, and recovery model.
135
+ 2. Identify runtime and version constraints. Check DuckDB version, current versus LTS track,
136
+ extension availability, binding feature coverage, and official docs before relying on
137
+ version-gated behavior such as `VARIANT`, core `GEOMETRY`, `read_duckdb()`,
138
+ `geometry_always_xy`, Quack beta behavior, lakehouse changes, `date_trunc(DATE)` return type
139
+ changes, or lambda syntax deprecations.
140
+ 3. Check file and process ownership. A native `.duckdb` file should have a single read-write process.
141
+ Multi-process writes to the same native database file need an explicit coordination layer such as
142
+ Quack or DuckLake-style ownership. Read-only multi-process access is acceptable only when no
143
+ writer is active and the mode is explicit.
144
+ 4. Separate thread concurrency from process concurrency. Within one process, review per-thread
145
+ connection or cursor rules, transaction width, optimistic concurrency conflict handling, and retry
146
+ behavior. Do not describe DuckDB as a multi-writer server because it handles parallel analytical
147
+ operators.
148
+ 5. Review language binding ownership. In Python, avoid assuming `duckdb.sql()` or the `:default:`
149
+ global connection is thread-safe. Treat Python `cursor()` as another handle, not connection-pool
150
+ parallelism. In Node.js Neo, avoid multiple `DuckDBInstance` objects for the same database file
151
+ unless the binding docs and ownership model say it is safe. In Go, remember `database/sql` can
152
+ hide real DuckDB connection boundaries and Appender ownership. In Rust, respect that Appender is
153
+ `Sync` but not `Send`; do not move it across threads incorrectly.
154
+ 6. Review write path shape. Prefer bulk loading and Appender APIs for large inserts. Row-by-row
155
+ prepared statements are not the bulk ingestion path. Appender buffers data, so flush, close, and
156
+ transaction boundaries must be explicit before code reports inserted rows as durable or visible.
157
+ 7. Review memory as process reality, not only DuckDB settings. `memory_limit` is not a full process
158
+ RSS cap because the host language, Arrow, file readers, native allocations, and extensions also
159
+ consume memory. Combine `memory_limit`, `threads`, app worker count, batch size, and blocking
160
+ operators into one budget.
161
+ 8. Review temp spill behavior. Configure or document `temp_directory` and
162
+ `max_temp_directory_size` when large sorts, joins, windows, aggregations, imports, or CTAS paths
163
+ can spill. Use `duckdb_memory()` and `duckdb_temporary_files()` when safe evidence exists. Treat
164
+ disk-full and temp cleanup failures as real operational cases.
165
+ 9. Review thread settings. DuckDB `threads` times app-level concurrency can multiply CPU and memory
166
+ pressure. Do not set it to maximum in every worker without an instance-level budget.
167
+ 10. Review insertion order costs. For large import/export paths, consider whether
168
+ `preserve_insertion_order=false` is acceptable and memory-saving. Never disable preserved order
169
+ when code depends on implicit row order; instead add explicit `ORDER BY`.
170
+ 11. Review CSV auto-detect. CSV auto-detect can sample too little, especially with gzip or files
171
+ where only the front is sampled. Header ambiguity, date and timestamp formats, decimal and null
172
+ values, mixed types, and late bad rows need explicit `columns`, `types`, `dateformat`,
173
+ `timestampformat`, `sample_size=-1`, `all_varchar`, or staged `try_cast` decisions.
174
+ 12. Review malformed-row policy. `ignore_errors=true` can hide data loss. Prefer reject-row
175
+ visibility such as `store_rejects` when the pipeline must reconcile bad rows, and report how
176
+ rejected rows are counted, stored, and alerted.
177
+ 13. Review multi-file schema drift. Use `union_by_name=true` only when schema drift is expected and
178
+ memory cost is acceptable. Preserve `filename` lineage when files may need replay, quarantine,
179
+ provenance, or tenant/source debugging.
180
+ 14. Review Parquet paths. Avoid `SELECT *` on wide Parquet inputs. Preserve projection and filter
181
+ pushdown, check Parquet row group size and sort locality for predicate skipping and parallelism,
182
+ and handle legacy file quirks such as `binary_as_string` or `can_have_nan` only when the source
183
+ format requires them.
184
+ 15. Review partitioned files. Hive partitioning turns paths into data. Validate path-derived values,
185
+ type conversions, and tenant/source trust. Treat `PARTITION_BY` with high-cardinality values as
186
+ a file-explosion risk during export.
187
+ 16. Review JSON ingestion. Use `columns` to project needed keys when possible, set
188
+ `maximum_object_size` for large objects, choose the intended JSON format, and do not rely on JSON
189
+ equality semantics without testing the exact behavior that matters.
190
+ 17. Require deterministic output. Add `ORDER BY` for tests, exports, pagination, snapshots, and any
191
+ user-visible ordering. Parallel scans and vectorized execution make accidental row order a bug,
192
+ not a contract.
193
+ 18. Review order-sensitive aggregates. `first`, `last`, `list`, `string_agg`, `arg_max`, and related
194
+ aggregates need ordering and tie-breakers when the result matters. Do not let "whatever came
195
+ first" become business logic.
196
+ 19. Review aggregate null and empty-set behavior. DuckDB aggregates can return `NULL` where product
197
+ code expects zero or an empty list; for example `sum` over no rows is `NULL`, and `list` over no
198
+ rows is `NULL`. Encode the fallback deliberately.
199
+ 20. Review timestamps. `TIMESTAMPTZ` stores instants, not timezone names. DATE versus TIMESTAMPTZ
200
+ comparisons can depend on the current timezone. Precision downgrade, local schedule values, and
201
+ display timezone need explicit contracts.
202
+ 21. Review query-plan evidence. Use `EXPLAIN` for planner shape and `EXPLAIN ANALYZE` for actual
203
+ execution evidence when available. Keep JSON, HTML, or Mermaid plan formats as tooling outputs,
204
+ not public contracts.
205
+ 22. Review profiling output. Profiling files can be overwritten unless the path is unique.
206
+ Profiling coverage often defaults to `SELECT`; use the intended `profiling_coverage` such as
207
+ `ALL` when load, export, CTAS, or DML work is what needs evidence. Remember parallel operator
208
+ time can sum above wall-clock time.
209
+ 23. Review joins and indexes. Detect join cardinality explosion before adding settings. Sorting data
210
+ to improve zone maps may beat an index. ART index choices have scope and memory costs; do not
211
+ add them as generic performance theater.
212
+ 24. Review CTE behavior. Use `AS MATERIALIZED` or `AS NOT MATERIALIZED` deliberately when reuse,
213
+ pushdown, memory, or nondeterminism matters. Do not assume the planner made the same choice the
214
+ code relies on.
215
+ 25. Review window functions. Windows are blocking and memory-heavy. Use `QUALIFY`, named `WINDOW`
216
+ clauses, explicit frames, explicit ordering, `IGNORE NULLS`, `fill`, and `EXCLUDE` only when the
217
+ semantics are intended and tested.
218
+ 26. Review macros. DuckDB macros are SQL templates, not arbitrary safe string substitution. Use
219
+ `query_table` and `cast_to_type` patterns where appropriate, and keep identifier/table inputs
220
+ allowlisted or generated from trusted metadata.
221
+ 27. Select verification from the command contract. Use configured test, build, docs, release, and
222
+ mustflow intents only; report missing DuckDB-specific verification instead of inventing raw
223
+ database commands.
224
+
225
+ <!-- mustflow-section: postconditions -->
226
+ ## Postconditions
227
+
228
+ - DuckDB role, version or track, binding, extension, file path, and feature gates are explicit.
229
+ - Native file ownership, process count, thread model, writer policy, and retry behavior are proven
230
+ or reported as risk.
231
+ - Appender, bulk load, transaction, flush, close, import, export, reject-row, and lineage behavior
232
+ match the pipeline contract.
233
+ - Memory, temp spill, thread count, profiling, and plan evidence are tied to representative evidence
234
+ or marked unverified.
235
+ - CSV, Parquet, JSON, Hive partitioning, timestamp, aggregate, ordering, CTE, window, macro, join,
236
+ and index decisions are fixed or named as risks.
237
+ - Verification uses configured command intents only.
238
+
239
+ <!-- mustflow-section: verification -->
240
+ ## Verification
241
+
242
+ Use configured oneshot command intents when available:
243
+
244
+ - `changes_status`
245
+ - `changes_diff_summary`
246
+ - `test_related`
247
+ - `test`
248
+ - `lint`
249
+ - `build`
250
+ - `docs_validate_fast`
251
+ - `test_release`
252
+ - `mustflow_check`
253
+
254
+ Prefer the narrowest configured test, build, docs, release, or mustflow intent that exercises the
255
+ changed DuckDB path. Do not infer raw DuckDB clients, live SQL, migration tools, profiling commands,
256
+ benchmarks, package-manager commands, or object-store operations.
257
+
258
+ <!-- mustflow-section: failure-handling -->
259
+ ## Failure Handling
260
+
261
+ - If DuckDB version, binding, extension, file mode, or feature gates cannot be identified, do not
262
+ claim support for version-sensitive DuckDB behavior.
263
+ - If process ownership, writer identity, retry rules, transaction boundaries, Appender flush, or
264
+ close behavior are unknown, mark concurrency and visibility as static risk.
265
+ - If import sampling, reject handling, schema drift, or lineage behavior is unknown, avoid claiming
266
+ the load path is lossless or replayable.
267
+ - If memory, temp spill, plan, or profiling evidence is unavailable, avoid claiming a query, index,
268
+ file layout, or setting is faster or safe under load.
269
+ - If configured verification is missing, report the missing command intent instead of running raw
270
+ database, profiling, migration, package, or provider commands.
271
+
272
+ <!-- mustflow-section: output-format -->
273
+ ## Output Format
274
+
275
+ - DuckDB role, version or track, binding, extension, file ownership, and process model inspected
276
+ - Concurrency, transaction, Appender, bulk load, and retry classification
277
+ - CSV, Parquet, JSON, partitioning, reject-row, lineage, and import/export decisions
278
+ - Ordering, aggregate, timestamp, window, CTE, macro, join, index, and query-plan findings
279
+ - Memory, temp spill, profiling, and evidence level: static diff risk, configured-test evidence,
280
+ DuckDB plan evidence, profiling evidence, measured production evidence, manual-only, missing, or
281
+ not applicable
282
+ - Command intents run
283
+ - Skipped DuckDB checks and reasons
284
+ - Remaining DuckDB risk
@@ -2,11 +2,11 @@
2
2
  mustflow_doc: skill.go-code-change
3
3
  locale: en
4
4
  canonical: true
5
- revision: 5
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, workspaces, package APIs, package layout, internal boundaries, interfaces, structs, errors, goroutines, channels, context propagation, HTTP clients or servers, graceful shutdown, reverse proxies, JSON encoding, filesystem roots, network addresses, runtime limits, profiling, 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
@@ -33,7 +33,7 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
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, graceful shutdown, reverse proxies, JSON encoding, filesystem access, network addresses, runtime tuning, profiling, tools, or module dependencies change.
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
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
 
@@ -51,6 +51,7 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
51
51
  - The public API surface when exported identifiers, errors, or package paths change.
52
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.
53
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.
54
55
  - Minimum supported Go version, `go` directive, `toolchain` directive, `GOEXPERIMENT`, and whether the feature is stable, experimental, or repository-pinned.
55
56
  - Configured verification intents.
56
57
 
@@ -60,7 +61,7 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
60
61
  - Inspect the whole package before adding names or methods.
61
62
  - Determine whether the change affects exported API, concurrency ownership, or dependency graph.
62
63
  - Identify generated files and avoid direct edits unless explicitly requested.
63
- - 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.
64
65
 
65
66
  <!-- mustflow-section: allowed-edits -->
66
67
  ## Allowed Edits
@@ -112,6 +113,7 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
112
113
  - do not rely on `err == sentinel` when callers may receive wrapped errors;
113
114
  - do not expose dependency sentinel or typed errors through wrapping unless the package intentionally supports them as API;
114
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;
115
117
  - classify context cancellation, context deadlines, dependency timeouts, and domain failures at package boundaries instead of letting infrastructure errors leak upward unchanged;
116
118
  - keep typed error pointer/value behavior consistent and avoid typed-nil errors behind an `error` interface;
117
119
  - use `errors.Join` or multiple `%w` only when callers are expected to use `errors.Is` or `errors.As` rather than simple unwrap behavior;
@@ -159,45 +161,80 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
159
161
  - reuse clients and transports instead of creating them per request;
160
162
  - prefer reverse-proxy rewrite hooks over deprecated or unsafe director-style mutation when the supported Go version allows it;
161
163
  - keep hop-by-hop header, forwarded-host, scheme, cancellation, streaming, and error-mapping behavior explicit.
162
- 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:
163
200
  - choose `omitempty` versus `omitzero` deliberately, especially for `time.Time`, numeric zero, boolean false, and optional fields;
164
201
  - use `SetEscapeHTML(false)` only when the JSON is not embedded into HTML and callers expect raw `<`, `>`, or `&`;
165
202
  - treat `encoding/json/v2` and `jsontext` as experimental unless the repository explicitly opts into the relevant experiment and migration tests.
166
- 16. Check filesystem and network address helpers:
203
+ 18. Check filesystem and network address helpers:
167
204
  - use traversal-resistant root APIs when accepting user-controlled relative paths and the supported Go version provides them;
168
205
  - do not treat `filepath.Join` plus prefix checks as sufficient against symlinks and TOCTOU;
169
206
  - prefer `net/netip` for comparable IP addresses and map keys when supported;
170
207
  - use `net.JoinHostPort` instead of string formatting for host and port assembly so IPv6 works.
171
- 17. Check runtime and deployment behavior when relevant:
208
+ 19. Check runtime and deployment behavior when relevant:
172
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;
173
210
  - question manual `GOMAXPROCS` pins in containers on Go versions with container-aware defaults;
174
211
  - use PGO only with representative profiles and keep `default.pgo` ownership clear;
175
212
  - treat goroutine leak profiling, SIMD, JSON v2, and other experiments as opt-in evidence-gathering, not default production assumptions;
176
213
  - remember that `-race` only finds races on executed paths and carries significant overhead.
177
- 18. For performance changes, measure before simplifying or optimizing:
214
+ 20. For performance changes, measure before simplifying or optimizing:
178
215
  - require profile or benchmark evidence before accepting a more complex hot-path change;
179
216
  - inspect CPU, heap, allocation, goroutine, block, and mutex evidence according to the symptom instead of assuming CPU is the bottleneck;
180
217
  - treat allocation reduction as GC-pressure reduction only when benchmark or profile evidence supports it;
181
218
  - use escape-analysis findings to explain heap movement instead of assuming pointers are faster than values;
182
219
  - use `sync.Pool` only for disposable temporary objects that may vanish at any time, not as a durable cache or lifecycle owner.
183
- 19. Keep tests and benchmarks deterministic:
220
+ 21. Keep tests and benchmarks deterministic:
184
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;
185
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;
186
223
  - compare benchmark changes across repeated runs and include `B/op` and `allocs/op` when allocation behavior is part of the claim;
187
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;
188
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.
189
- 20. Keep Go tools and modernization explicit:
226
+ 22. Keep Go tools and modernization explicit:
190
227
  - prefer the `tool` directive over `tools.go` pinning only when the repository's supported Go version allows it;
191
228
  - use `go fix` modernizers as reviewed migrations, not silent drive-by rewrites;
192
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;
193
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.
194
- 21. If dependency metadata changes, keep module files and dependent tests synchronized:
231
+ 23. If dependency metadata changes, keep module files and dependent tests synchronized:
195
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;
196
233
  - treat `go.sum` as checksum evidence, not a package lockfile and not disposable noise;
197
234
  - treat `replace`, especially local-path `replace`, as temporary main-module or workspace-only wiring unless the repository documents a release plan for it;
198
235
  - verify vendor output is regenerated by a configured intent when vendoring is part of the repository contract;
199
236
  - check private module settings before adding private import paths so module names do not leak through public proxy or checksum lookups.
200
- 22. Choose configured verification intents that cover formatting, tests, race-sensitive behavior, lint, API drift, module drift, docs, and release metadata when available.
237
+ 24. Choose configured verification intents that cover formatting, tests, race-sensitive behavior, lint, API drift, module drift, docs, and release metadata when available.
201
238
 
202
239
  <!-- mustflow-section: postconditions -->
203
240
  ## Postconditions
@@ -205,7 +242,7 @@ Preserve Go package, module, workspace, API, error, context, concurrency, runtim
205
242
  - Package ownership and exported API impact are clear.
206
243
  - Context, goroutine, channel, and error ownership are explicit.
207
244
  - Go-version-gated syntax, standard-library APIs, runtime defaults, experiments, and module metadata are compatible with the repository's supported Go version.
208
- - HTTP timeout, graceful shutdown, proxy, JSON, filesystem, network address, runtime, profiling, 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.
209
246
  - Tests cover the changed behavior without sleeps as synchronization.
210
247
  - Module drift is reported when dependency verification cannot run.
211
248
 
@@ -233,7 +270,7 @@ For concurrency-sensitive changes, report whether a configured race or equivalen
233
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.
234
271
  - If a goroutine has no owner, stop condition, wait path, cancellation path, or error path, do not add it.
235
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.
236
- - 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.
237
274
  - If JSON tag changes alter omitted fields, zero values, HTML escaping, or experimental JSON behavior, treat the change as an API contract risk.
238
275
  - If a public error stops satisfying documented `errors.Is` or `errors.As` checks, restore the contract or report the breaking-change requirement.
239
276
  - If wrapping would expose a dependency error as public API, keep the dependency error internal or document the intentional contract.
@@ -245,7 +282,7 @@ For concurrency-sensitive changes, report whether a configured race or equivalen
245
282
  - Boundary checked
246
283
  - Package and API impact
247
284
  - Context/concurrency/error notes
248
- - Go version, module/workspace, runtime, HTTP/shutdown, JSON, filesystem, profiling, 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
249
286
  - Files changed
250
287
  - Command intents run
251
288
  - Skipped checks and reasons