@decocms/start 2.14.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -168,16 +168,116 @@ one imported symbol is a real silent stub (returns `null` / `{}` / `[]`
168
168
  alongside stubs (e.g. a `parseCookie` cookie parser, a `fetchSafe`
169
169
  wrapper) no longer create noise.
170
170
 
171
- The audit's finding names the exact stub symbols, e.g.
171
+ The audit's finding names the exact stub symbols **and emits per-symbol
172
+ fix guidance**, e.g.
172
173
 
173
174
  ```
174
175
  [WARNING] src/loaders/search/x.ts — Imports stub-only symbols from
175
176
  vtex-transform (toProduct); vtex-segment (getSegmentFromBag) —
176
177
  runtime is silently stubbed
177
- fix: Repoint imports to '@decocms/apps/vtex/...' or
178
- 'apps/commerce/utils/...'
178
+ fix: toProduct @decocms/apps/vtex/utils/transform (1:1 import swap)
179
+ — canonical signature is `toProduct(product, sku, level, options)`;
180
+ 1-arg call sites need to expand args first | getSegmentFromBag →
181
+ call-site refactor: read cookies via `request.headers.get('cookie')`
182
+ then call `buildSegmentFromCookies()` from
183
+ '@decocms/apps/vtex/utils/segment'.
179
184
  ```
180
185
 
186
+ JSON consumers can read structured guidance from `meta.fixHints`:
187
+
188
+ ```json
189
+ {
190
+ "rule": "vtex-shim-regression",
191
+ "meta": {
192
+ "stubsBySim": { "vtex-transform": ["toProduct"], "vtex-segment": ["getSegmentFromBag"] },
193
+ "fixHints": {
194
+ "toProduct": { "kind": "swap", "canonical": "@decocms/apps/vtex/utils/transform", "note": "..." },
195
+ "getSegmentFromBag": { "kind": "refactor", "note": "..." }
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Canonical replacement table
202
+
203
+ | Stub symbol | Kind | Canonical / fix |
204
+ |---|---|---|
205
+ | `toProduct` | swap | `@decocms/apps/vtex/utils/transform.toProduct` — note canonical signature is `(product, sku, level, options)`; 1-arg call sites need to expand args |
206
+ | `withSegmentCookie` | swap | `@decocms/apps/vtex/utils/segment.withSegmentCookie` — note canonical signature is `(segment, headers?)` |
207
+ | `getSegmentFromBag` | refactor | read cookies via `request.headers.get('cookie')`, then `buildSegmentFromCookies()` from `@decocms/apps/vtex/utils/segment` |
208
+ | `getISCookiesFromBag` | refactor | extract IS cookies from `request.headers.get('cookie')` directly — no canonical helper, the bag-based mechanism doesn't exist on TanStack Start |
209
+
210
+ Symbols not in the table get the generic guidance ("repoint to
211
+ `@decocms/apps/vtex/...` or `apps/commerce/utils/...`") — when you find
212
+ a new one worth pinning down, add it to `STUB_FIX_HINTS` in
213
+ [`scripts/migrate/post-cleanup/rules.ts`](https://github.com/decocms/deco-start/blob/main/scripts/migrate/post-cleanup/rules.ts).
214
+
215
+ ### Recipe: expanding 1-arg `toProduct(p)` call sites
216
+
217
+ Two real-world patterns surface, requiring different fixes:
218
+
219
+ **Pattern A — call site already passes 4 args under `as any`** (e.g.
220
+ `smartShelfForYou.ts` on casaevideo): the dev wrote the call for
221
+ canonical, the import pointed at the stub. Fix is **import-only**:
222
+
223
+ ```diff
224
+ -import { toProduct } from "~/lib/vtex-transform";
225
+ +import { toProduct } from "@decocms/apps/vtex/utils/transform";
226
+
227
+ const normalizedProducts = rawProducts.data.map((p: VTEXProduct) =>
228
+ (toProduct as any)(p, p.items?.[0], 0, {
229
+ baseUrl: baseURL,
230
+ priceCurrency: "BRL",
231
+ }),
232
+ );
233
+ ```
234
+
235
+ The `as any` cast may stay if local `~/types/vtex.Product` and
236
+ canonical `LegacyProductVTEX | ProductVTEX` differ structurally — that's
237
+ a separate refactor.
238
+
239
+ **Pattern B — call site uses true 1-arg form** (e.g.
240
+ `intelligenseSearch.ts` on casaevideo): the dev relied on the stub's
241
+ identity-cast behaviour. Fix is to **expand the call** mirroring the
242
+ canonical pattern in
243
+ [`apps-start/vtex/loaders/autocomplete.ts`](https://github.com/decocms/apps-start/blob/main/vtex/loaders/autocomplete.ts):
244
+
245
+ ```diff
246
+ -import { toProduct } from "~/lib/vtex-transform";
247
+ +import { pickSku, toProduct } from "@decocms/apps/vtex/utils/transform";
248
+
249
+ const baseURL = new URL(req.url).origin;
250
+ return {
251
+ searches,
252
+ - products: (products ?? []).map((p) => toProduct(p)).slice(0, count),
253
+ + products: (products ?? []).slice(0, count).map((p: any) => {
254
+ + const sku = pickSku(p);
255
+ + return toProduct(p, sku, 0, { baseUrl: baseURL, priceCurrency: "BRL" });
256
+ + }),
257
+ };
258
+ ```
259
+
260
+ `pickSku` handles the IS-shape SKU selection; without it, downstream
261
+ fields like `productID`, `gtin`, `additionalProperty[]` come back
262
+ empty.
263
+
264
+ **Pattern C — keep the stub deliberately**: rare, but valid when the
265
+ upstream API already returns canonical `Product[]` shape and the call
266
+ is purely a type-narrowing cast. Replace with a typed cast at the
267
+ boundary instead of importing a stub:
268
+
269
+ ```diff
270
+ -import { toProduct } from "~/lib/vtex-transform";
271
+ +import type { Product } from "@decocms/apps/commerce/types";
272
+
273
+ -products: (products ?? []).map((p) => toProduct(p)).slice(0, count),
274
+ +products: ((products ?? []) as Product[]).slice(0, count),
275
+ ```
276
+
277
+ This silences the audit (the stub import is gone) without changing
278
+ behaviour. Only do this if you've **verified** the upstream payload is
279
+ already schema.org-shaped.
280
+
181
281
  Manual sweep (still useful if you don't have the audit handy):
182
282
 
183
283
  ```bash
@@ -0,0 +1,111 @@
1
+ ---
2
+ description: Constitutional decisions for the deco-start migration-tooling effort (D1–D5, priorities, process). Always loaded.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Migration Tooling Policy
7
+
8
+ Decisions for `@decocms/start` + `@decocms/apps` + migration scripts/skills.
9
+ Authority: `MIGRATION_TOOLING_PLAN.md` in this repo. This rule is a quick-load
10
+ summary; always defer to the plan when they conflict.
11
+
12
+ ## Constitutional principles
13
+
14
+ 1. **Design for 100 sites, not 3.** When the surface of an abstraction is
15
+ well-understood, ship it. Don't defer waiting for "more signal" — design
16
+ for the projection. When the surface is *not* understood, *decide*
17
+ explicitly (write a D-record like D1–D5), don't ship fast.
18
+ 2. **Strict over flexible.** No support layers, no soft drift, no
19
+ fork-runtime adapters. Every fork divergence becomes either a PR back to
20
+ canonical or visible local debt.
21
+ 3. **Audit is the safety net.** Anything we can't auto-fix becomes a flagged
22
+ finding. The gap between "detect" and "fix" is the next thing to close,
23
+ not a permanent state.
24
+ 4. **PR-only, no direct main, no deploys.** Every change goes through
25
+ review. Even policy/plan changes (this rule).
26
+
27
+ ## Decisions (signed off 2026-05-01)
28
+
29
+ ### D1 — Apps forks: force convergence
30
+ All sites consume `@decocms/apps` from canonical. Site-specific
31
+ customizations live in `src/apps/local/`. Forking is **not supported** by
32
+ the framework — sites that need framework-level changes either PR to
33
+ canonical, or fork independently and own the consequence.
34
+
35
+ **Agent behavior**: never write a "fork support layer". When auditing a
36
+ site, treat any non-canonical apps import as a finding; recommend
37
+ PR-to-canonical or move-to-`src/apps/local/`.
38
+
39
+ ### D2 — HTMX: rewrite on migration
40
+ HTMX is fully rewritten to React idioms (state, effects, server functions,
41
+ mutations) during migration. There is **no HTMX runtime** in
42
+ `@decocms/start`. The migration ships codemods for the common patterns
43
+ and skill recipes for the long tail.
44
+
45
+ **Agent behavior**: never propose an HTMX adapter or `@decocms/start/htmx`
46
+ package. When facing HTMX patterns, reach for codemods first, skill
47
+ recipes second, pattern catalog third.
48
+
49
+ ### D3 — Stub generation: throw at runtime
50
+ Migration-time stubs (`src/lib/vtex-*`, `src/lib/http-utils.ts`, etc.) must
51
+ **throw at runtime** with a clear message pointing at the canonical
52
+ replacement, not return identity casts or empty objects. This forces:
53
+
54
+ - The audit's `--fix` to cover swap cases (no permanent detect-only state).
55
+ - Skill recipes to keep up with stub generation.
56
+
57
+ **Agent behavior**: when adding or modifying a generated stub template,
58
+ the body must throw with a message including (a) what the stub stands in
59
+ for, (b) the canonical replacement, (c) a pointer to the relevant skill
60
+ section. Silent stubs are a regression.
61
+
62
+ ### D4 — Site-local apps: local by default, promote at 3
63
+ Site-specific apps (extensions, custom commerce integrations) live in
64
+ `src/apps/local/` by default. Promotion to `@decocms/apps` happens when
65
+ **3 or more sites** use the same extension.
66
+
67
+ **Agent behavior**: don't preemptively promote single-consumer code.
68
+ Conversely, don't accept "wait for more signal" as a dodge — when you see
69
+ the third consumer, promote.
70
+
71
+ ### D5 — Failed migrations: rm -rf and re-run
72
+ There is **no `--restart` mode**. A half-migrated site repo is a throwaway:
73
+ delete it and re-run `deco-migrate` from scratch on the latest tooling.
74
+ Failure modes get documented in skills, not encoded as escape hatches.
75
+
76
+ **Agent behavior**: when a migration goes sideways, propose deletion +
77
+ re-run, not in-place repair. Add the failure mode to the skill.
78
+
79
+ ## Priority order
80
+
81
+ Work proceeds in this order. Higher priorities don't block on lower ones,
82
+ but lower ones don't ship before the higher ones are at least scoped:
83
+
84
+ 1. **Framework changes** (`@decocms/start` + `@decocms/apps`) — fix the
85
+ foundation first. New factories, new audit rules, new framework
86
+ primitives. Without these, scripts have nothing to migrate *to*.
87
+ 2. **Migration scripts + skills** — make migration to the latest
88
+ `@decocms/start` + `@decocms/apps` automated. Codemods, audit `--fix`
89
+ rules, skill recipes.
90
+ 3. **Migrate als** — first real htmx-heavy site. Validates the htmx
91
+ sub-track end-to-end.
92
+ 4. **Update existing TanStack sites to latest** — open PRs against
93
+ casaevideo, baggagio, future sites bumping `@decocms/start` and
94
+ `@decocms/apps`, applying audit `--fix`, cleaning up to reflect
95
+ current best practices.
96
+
97
+ Out-of-band work (incident response, urgent prod fixes) bypasses this
98
+ order — but only if explicitly identified as urgent.
99
+
100
+ ## Process directives
101
+
102
+ - All work goes through PR review on a feature branch (`feat/`, `fix/`,
103
+ `chore/`, `docs/`). No exceptions.
104
+ - Conventional Commits in English for `decocms/*` repos; PT-BR for
105
+ storefront site repos.
106
+ - Plan updates (`MIGRATION_TOOLING_PLAN.md`) ship with the work they
107
+ describe, in the same PR or a follow-up. The plan is the single source
108
+ of truth; this rule is its boot loader.
109
+ - When reading a section of the plan or a skill, prefer the plan or skill
110
+ over your memory of past conversations.
111
+ - Do not run `deco-deploy` or any deploy command from agent flows.
package/CLAUDE.md CHANGED
@@ -8,6 +8,10 @@ Guidance for AI assistants working with `@decocms/start`.
8
8
 
9
9
  **Not a storefront itself** — this is the npm package that storefronts depend on.
10
10
 
11
+ ## Migration tooling policy (constitutional)
12
+
13
+ This repo also hosts the migration scripts + skills that move Deco storefronts from Fresh/Deno to TanStack Start. The work is governed by signed-off architectural decisions (D1–D5) and a strict priority order — see [`.cursor/rules/migration-tooling-policy.mdc`](./.cursor/rules/migration-tooling-policy.mdc) (always-loaded) and [`MIGRATION_TOOLING_PLAN.md`](./MIGRATION_TOOLING_PLAN.md) (full record). Defer to the plan when in doubt.
14
+
11
15
  ## Tech Stack
12
16
 
13
17
  - Runtime: Cloudflare Workers (Node compat)