fimo 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/assets/astro/components/DateTime.astro +22 -0
  2. package/assets/astro/components/index.d.ts +1 -0
  3. package/assets/astro/components/index.js +1 -0
  4. package/assets/content-templates/shared/types.eta +2 -0
  5. package/assets/skills/fimo-cli/SKILL.md +5 -2
  6. package/assets/skills/fimo-cli/references/content.md +2 -2
  7. package/assets/skills/fimo-cli/references/deploy.md +2 -0
  8. package/assets/skills/fimo-cli/references/init.md +11 -4
  9. package/assets/skills/fimo-cli/references/locales.md +38 -14
  10. package/assets/skills/fimo-cli/references/pages.md +70 -0
  11. package/assets/skills/fimo-cli/references/webhooks.md +1 -1
  12. package/assets/skills/fimo-code/SKILL.md +11 -0
  13. package/assets/skills/fimo-code/assets/react-router-locales/LocaleLayout.tsx +12 -0
  14. package/assets/skills/fimo-code/assets/react-router-locales/routes.ts +7 -6
  15. package/assets/skills/fimo-code/references/best-practices/astro.md +47 -0
  16. package/assets/skills/fimo-code/references/best-practices/next.md +42 -0
  17. package/assets/skills/fimo-code/references/best-practices/sveltekit.md +17 -0
  18. package/assets/skills/fimo-code/references/content/richtext.md +5 -0
  19. package/assets/skills/fimo-code/references/content/schema.md +4 -1
  20. package/assets/skills/fimo-code/references/frameworks/astro.md +5 -3
  21. package/assets/skills/fimo-code/references/frameworks/hosting.md +5 -2
  22. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +6 -0
  23. package/assets/skills/fimo-code/references/frameworks/next/locales.md +12 -2
  24. package/assets/skills/fimo-code/references/frameworks/next.md +7 -0
  25. package/assets/skills/fimo-code/references/frameworks/react-router.md +15 -7
  26. package/assets/skills/fimo-code/references/frameworks/sveltekit.md +15 -8
  27. package/assets/skills/fimo-code/references/labels.md +9 -1
  28. package/assets/skills/fimo-code/references/locales.md +8 -2
  29. package/assets/skills/fimo-code/references/migrations/react-router-route-ownership.md +93 -0
  30. package/assets/skills/fimo-code/references/ui.md +21 -2
  31. package/assets/skills/fimo-migration/SKILL.md +276 -51
  32. package/assets/skills/fimo-migration/references/content.md +119 -35
  33. package/assets/skills/fimo-migration/references/decision.md +72 -0
  34. package/assets/skills/fimo-migration/references/forms.md +38 -6
  35. package/assets/skills/fimo-migration/references/frameworks/nextjs.md +179 -23
  36. package/assets/skills/fimo-migration/references/import-contract.md +71 -19
  37. package/assets/skills/fimo-migration/references/manifest.md +11 -161
  38. package/assets/skills/fimo-migration/references/media.md +33 -1
  39. package/assets/skills/fimo-migration/references/platforms.md +26 -2
  40. package/assets/skills/fimo-migration/references/qa.md +167 -13
  41. package/assets/skills/fimo-migration/references/workers/content-execution.md +39 -0
  42. package/assets/skills/fimo-migration/references/workers/content-planner.md +64 -0
  43. package/assets/skills/fimo-migration/references/workers/framework.md +37 -0
  44. package/assets/skills/fimo-migration/references/workers/validator.md +25 -0
  45. package/assets/skills/fimo-migration/references/workers.md +82 -0
  46. package/assets/skills/fimo-migration/references/workflow.md +140 -192
  47. package/assets/skills/fimo-migration/scripts/apply-decision.mjs +534 -0
  48. package/assets/skills/fimo-migration/scripts/build-canonical-manifest.mjs +7 -4
  49. package/assets/skills/fimo-migration/scripts/write-migration-report.mjs +191 -4
  50. package/assets/skills/fimo-studio/references/cms.md +25 -7
  51. package/assets/skills/fimo-studio/references/webhooks.md +1 -1
  52. package/assets/sveltekit/components/DateTime.svelte +35 -0
  53. package/assets/sveltekit/components/FimoProvider.svelte +2 -2
  54. package/assets/sveltekit/components/index.d.ts +1 -0
  55. package/assets/sveltekit/components/index.js +1 -0
  56. package/dist/build/next/config.d.ts +4 -1
  57. package/dist/build/next/config.js +21 -5
  58. package/dist/build/sveltekit/vite.d.ts +3 -4
  59. package/dist/build/sveltekit/vite.js +3 -4
  60. package/dist/build/vite/plugins/runtime-env.d.ts +2 -1
  61. package/dist/build/vite/plugins/runtime-env.js +14 -10
  62. package/dist/cli/bundle.json +2 -2
  63. package/dist/cli/index.js +76 -78
  64. package/dist/runtime/app/FimoProviders.js +25 -14
  65. package/dist/runtime/app/prefetch.d.ts +3 -1
  66. package/dist/runtime/app/prefetch.js +11 -55
  67. package/dist/runtime/astro/preview.js +7 -9
  68. package/dist/runtime/content/client/internal.js +1 -0
  69. package/dist/runtime/i18n/locale.d.ts +4 -0
  70. package/dist/runtime/i18n/locale.js +14 -14
  71. package/dist/runtime/next/client-runtime.js +5 -1
  72. package/dist/runtime/next/client.d.ts +3 -2
  73. package/dist/runtime/next/client.js +2 -1
  74. package/dist/runtime/next/labels.d.ts +2 -2
  75. package/dist/runtime/next/labels.js +2 -2
  76. package/dist/runtime/next/preview.d.ts +13 -0
  77. package/dist/runtime/next/preview.js +34 -0
  78. package/dist/runtime/next/primitives/server.d.ts +2 -0
  79. package/dist/runtime/next/primitives/server.js +8 -0
  80. package/dist/runtime/next/provider.d.ts +5 -0
  81. package/dist/runtime/next/provider.js +17 -3
  82. package/dist/runtime/next/server-runtime.js +4 -1
  83. package/dist/runtime/next/server.d.ts +1 -1
  84. package/dist/runtime/next/server.js +1 -1
  85. package/dist/runtime/paths/get-fimo-paths.d.ts +6 -5
  86. package/dist/runtime/paths/get-fimo-paths.js +43 -42
  87. package/dist/runtime/preview/location.d.ts +19 -2
  88. package/dist/runtime/preview/location.js +16 -2
  89. package/dist/runtime/primitives/index.d.ts +1 -0
  90. package/dist/runtime/primitives/index.js +1 -0
  91. package/dist/runtime/react/primitives/editable/DateTime.d.ts +4 -0
  92. package/dist/runtime/react/primitives/editable/DateTime.js +13 -0
  93. package/dist/runtime/react/primitives/renderers/DateRenderer.d.ts +7 -1
  94. package/dist/runtime/react/primitives/renderers/DateRenderer.js +11 -8
  95. package/dist/runtime/react-router/{routes.d.ts → legacy/routes.d.ts} +6 -1
  96. package/dist/runtime/react-router/{routes.js → legacy/routes.js} +22 -7
  97. package/dist/runtime/routes/contract.d.ts +116 -0
  98. package/dist/runtime/routes/contract.js +377 -0
  99. package/dist/runtime/routes/index.d.ts +3 -0
  100. package/dist/runtime/routes/index.js +3 -0
  101. package/dist/runtime/routing/AppRoutesProvider.js +4 -3
  102. package/dist/runtime/seo/resolver.d.ts +5 -0
  103. package/dist/runtime/seo/resolver.js +10 -42
  104. package/dist/runtime/shared/fimo-config.types.d.ts +34 -8
  105. package/dist/runtime/shared/preview-location.d.ts +1 -22
  106. package/dist/runtime/shared/preview-location.js +5 -93
  107. package/dist/runtime/sveltekit/preview.d.ts +12 -3
  108. package/dist/runtime/sveltekit/preview.js +13 -8
  109. package/dist/scripts/sync-forms.js +1 -1
  110. package/dist/scripts/sync-schemas.js +1 -4
  111. package/dist/scripts/validate-fimo-config.js +5 -1
  112. package/dist/scripts/validate-page-registry.d.ts +2 -0
  113. package/dist/scripts/validate-page-registry.js +167 -0
  114. package/dist/scripts/validate-route-metadata.js +132 -41
  115. package/package.json +7 -3
  116. package/templates/astro/.fimo/config.json +13 -5
  117. package/templates/astro/AGENTS.md +5 -1
  118. package/templates/astro/astro.config.mjs +7 -0
  119. package/templates/astro/package.json +1 -1
  120. package/templates/astro/pnpm-workspace.yaml +0 -3
  121. package/templates/astro/src/components/ProjectOverview.astro +9 -6
  122. package/templates/astro/src/layouts/Base.astro +1 -1
  123. package/templates/astro/src/locales.ts +4 -0
  124. package/templates/astro/src/pages/[locale]/index.astro +19 -0
  125. package/templates/astro/src/pages/[locale]/projects/[slug].astro +35 -0
  126. package/templates/astro/src/pages/[locale]/projects/index.astro +19 -0
  127. package/templates/astro/src/pages/index.astro +5 -2
  128. package/templates/astro/src/pages/projects/[slug].astro +4 -2
  129. package/templates/astro/src/pages/projects/index.astro +5 -2
  130. package/templates/nextjs/.fimo/config.json +2 -1
  131. package/templates/nextjs/AGENTS.md +5 -0
  132. package/templates/nextjs/package.json +1 -1
  133. package/templates/nextjs/src/app/(default)/layout.tsx +10 -0
  134. package/templates/nextjs/src/app/[locale]/layout.tsx +22 -0
  135. package/templates/nextjs/src/app/[locale]/page.tsx +1 -0
  136. package/templates/nextjs/src/components/Document.tsx +26 -0
  137. package/templates/nextjs/src/components/FimoPreviewBridge.tsx +13 -0
  138. package/templates/nextjs/src/locales.ts +13 -0
  139. package/templates/react-router/.fimo/config.json +3 -6
  140. package/templates/react-router/AGENTS.md +4 -0
  141. package/templates/react-router/package.json +2 -2
  142. package/templates/react-router/pnpm-workspace.yaml +1 -3
  143. package/templates/react-router/react-router.config.ts +4 -10
  144. package/templates/react-router/src/pages/LocaleLayout.tsx +12 -0
  145. package/templates/react-router/src/root.tsx +2 -4
  146. package/templates/react-router/src/routes.ts +5 -3
  147. package/templates/sveltekit/.fimo/config.json +2 -1
  148. package/templates/sveltekit/AGENTS.md +5 -0
  149. package/templates/sveltekit/package.json +1 -1
  150. package/templates/sveltekit/src/app.html +1 -1
  151. package/templates/sveltekit/src/hooks.server.ts +11 -0
  152. package/templates/sveltekit/src/locales.ts +8 -0
  153. package/templates/sveltekit/src/params/locale.ts +5 -0
  154. package/templates/sveltekit/src/routes/+layout.server.ts +6 -1
  155. package/templates/sveltekit/src/routes/+layout.svelte +5 -0
  156. package/assets/skills/fimo-migration/references/inventory/coordinator.md +0 -40
  157. package/assets/skills/fimo-migration/references/inventory/locales/next-intl.md +0 -39
  158. package/assets/skills/fimo-migration/references/inventory/locales.md +0 -41
  159. package/assets/skills/fimo-migration/scripts/inventory/locales/next-intl.mjs +0 -459
  160. package/templates/nextjs/src/app/layout.tsx +0 -17
  161. /package/templates/nextjs/src/app/{page.tsx → (default)/page.tsx} +0 -0
  162. /package/templates/sveltekit/src/routes/{+page.svelte → [[locale=locale]]/+page.svelte} +0 -0
@@ -29,6 +29,22 @@ Record what is available:
29
29
  - sha256 or another stable hash when possible
30
30
  - source references and target references
31
31
 
32
+ ## Alt Text Belongs To The Media
33
+
34
+ Alt text is media metadata, not a content field. An image that has alt text in
35
+ the source never justifies a standalone alt field in a collection or content
36
+ schema; the alt travels with the media value.
37
+
38
+ - Preserve the source alt on the media value alongside `source` and `url`, and
39
+ pass it through the asset upload metadata when the CLI exposes it. When the
40
+ upload command cannot carry it, keep it on the media value and record the
41
+ limitation as a note on the media item.
42
+ - Never use the filename as alt text.
43
+ - When the source has no alt, a meaningful generated alt is an explicit
44
+ fallback only: mark it with the media item's `altSource`
45
+ (`references/manifest.md`) so an editor can see which alt text the source did
46
+ not provide.
47
+
32
48
  ## Dedupe
33
49
 
34
50
  Deduplicate by hash when local bytes are available. If not, deduplicate by
@@ -45,7 +61,8 @@ failing. Either upload it (and record the Fimo target), or mark it `unresolved`
45
61
  with an owner action. "Bundled locally, upload later" is not an acceptable
46
62
  terminal state for referenced media.
47
63
 
48
- After upload, update the manifest with the Fimo target asset ID/URL.
64
+ After upload, record the Fimo target asset ID/URL in the worker and migration
65
+ reports.
49
66
 
50
67
  When using downloaded files from a Fimo migration pack, copy the recorded
51
68
  `localPath` from the media map exactly. Do not reconstruct local filenames from
@@ -62,6 +79,11 @@ Replace source references in this order:
62
79
  Schema media should render through Fimo media primitives. Do not hardcode source
63
80
  URLs for editable media fields.
64
81
 
82
+ The library asset and the media value stored in an entry are distinct concerns:
83
+ the asset owns the uploaded bytes and their metadata, and the entry field holds
84
+ the media value `{ source, url, alt }` that points at it. Keep both carrying the
85
+ same alt text, and do not duplicate alt into a second schema field.
86
+
65
87
  ## Failure Handling
66
88
 
67
89
  If a media asset cannot be downloaded or uploaded:
@@ -71,3 +93,13 @@ If a media asset cannot be downloaded or uploaded:
71
93
  - list every page/entry that references it
72
94
  - include a suggested action such as re-exporting the asset folder or providing
73
95
  credentials
96
+
97
+ ## Planner obligations
98
+
99
+ The content planner enumerates every media obligation before fan-out: route and
100
+ SEO media, every schema media field, and every image node nested in richtext or
101
+ Tiptap JSON. Record its source location, consuming route/entry, and intended
102
+ target field or node. Give each obligation a stable identity that includes its
103
+ field or rich-text node path; a shared label or source URL is not unique. The
104
+ asset worker cannot report complete until every obligation has an uploaded or
105
+ duplicate Fimo mapping, or an explicit unresolved/unsupported disposition.
@@ -50,5 +50,29 @@ Use these notes to decide what is source of truth and what must be rebuilt.
50
50
 
51
51
  - Search for structured data before assuming static content: CSV, JSON, MD/MDX,
52
52
  frontmatter, CMS SDK calls, route loaders, API fixtures.
53
- - Identify the current framework only to understand routing/data, not to copy
54
- implementation patterns into Fimo.
53
+ - Identify the current framework to understand routing and data. A source
54
+ repository keeps its framework, router, and runtime for the first migration.
55
+ If detection or hosting compatibility stays unclear, stop and ask. Do not
56
+ select Next.js as a fallback; a conversion happens only after the user's
57
+ explicit choice, through the framework conversion worker and gate in
58
+ `references/workers.md`.
59
+
60
+ ## Provider-specific hosting
61
+
62
+ - A provider file is evidence, not disposable scaffolding. Inventory its rules
63
+ and classify each one as preserved, replaced, safely unnecessary
64
+ implementation detail, or unresolved.
65
+ - Preserve the file until its externally observable behavior has an accepted,
66
+ verified replacement. Delete it only when redundancy is proven or the user
67
+ explicitly accepts the loss.
68
+ - Cloudflare cache storage, purge, and revalidation code may be safely
69
+ unnecessary when it has no external caller and no accepted freshness
70
+ contract depends on it. Do not copy provider mechanics merely to imitate the
71
+ implementation.
72
+ - Redirects, security headers, route and 404 behavior, Markdown negotiation,
73
+ feeds, sitemap, `llms.txt`, social metadata, and forms are public behavior.
74
+ Preserve them or replace them with an equivalent and verify the result.
75
+ - A React Router/Vite site can remain React Router/Vite even when Cloudflare-only
76
+ hosting features are conditional or unresolved. Hosting uncertainty is not
77
+ permission to convert the application; only the user's explicit choice
78
+ starts a conversion.
@@ -1,19 +1,117 @@
1
1
  # Migration QA Gate
2
2
 
3
- Run this gate before reporting completion.
3
+ Run this gate before reporting completion. The gate is read-only: it starts
4
+ only after every other worker has returned a terminal report, and it never
5
+ repairs what it finds — failures become bounded repair tasks or unresolved
6
+ items.
4
7
 
5
8
  ## Coverage
6
9
 
7
10
  - Every intended source route is implemented, ignored with a reason, or unresolved.
11
+ - The source route surface is preserved: routes were not restructured to
12
+ shrink the migration, and no group of source pages was replaced by a generic
13
+ static shell.
14
+ - Every imported schema, entry, single, and label has a consuming target route
15
+ or component. Content that exists in Fimo but is not rendered by the
16
+ application is unwired, not covered.
17
+ - Every source content item is represented in the target: a content type, a
18
+ field, a block, a reference, a label, or an explicit unresolved item.
19
+ - The editorial model is Fimo-native and not silently flattened. Structured or
20
+ repeatable editorial sections are blocks, rich bodies are richtext, and
21
+ categories, authors, related items, and repeated taxonomies are references -
22
+ not hardcoded strings, raw IDs, or opaque JSON. Every `json` field carries a
23
+ recorded reason that no Fimo-native model fits.
24
+ - Editable shared chrome (header, footer, navigation, site settings) has a
25
+ singleton or other content model an owner can edit, and labels are limited to
26
+ small UI copy and reusable translations.
27
+ - Content type, field, and block names are semantic and editor-facing: no markup
28
+ tags, HTML attributes, locale suffixes, or column indexes.
29
+ - Modeling did not redesign the site: the migrated routes render the same
30
+ content, order, and copy as the source, and the text plan records the
31
+ source-to-Fimo mapping.
32
+ - Media alt text is attached to the media (asset metadata and media value), with
33
+ no standalone alt field in a content schema. Alt is never the filename, and a
34
+ generated fallback is recorded as generated.
35
+ - Every planner `sourceFile`/`sourceKey` maps to its original consumer. Imported
36
+ labels or prose that are only appended elsewhere, including an additive
37
+ “Page content” section, are unwired gaps. Use existing literal-key extraction
38
+ for a bounded read-only comparison when it is sound; otherwise report every
39
+ unmapped key from the planner consumer map. Do not build a generic AST or
40
+ codemod system for this check.
8
41
  - Every CMS export file is mapped to a schema, ignored with a reason, or unresolved.
9
42
  - Source entry counts match imported counts (entries created in Fimo), excluding
10
43
  documented skips/unresolved. Generated seed JSON alone does not satisfy this.
11
44
  - Every media item referenced by routes, CMS entries, SEO, or forms is uploaded to
12
45
  the Fimo media library (Fimo asset id/URL) or has an unresolved item. A local
13
46
  `public/` copy is not an upload mapping.
14
- - Every visible form has a Fimo replacement, third-party plan, or unsupported note.
47
+ - Every planner media obligation, including schema media fields and nested
48
+ richtext/Tiptap image nodes, has a mapping or explicit disposition; the asset
49
+ worker's completion claim alone is not evidence.
50
+ - Every visible form has a Fimo replacement, a preserved third-party
51
+ integration, or an unsupported note. A form became Fimo-native only when the
52
+ Fimo form matches the source behavior 1:1.
53
+ - The detected source framework, router, runtime, and configuration are
54
+ preserved. React Router/Vite remains React Router/Vite; any Next.js conversion
55
+ has the user's explicit choice. Unsupported or unclear hosting is unresolved,
56
+ not hidden by a conversion or deleted configuration.
57
+ - In conversion mode, the framework gate passed before content code work: the
58
+ conversion worker's self-checks and the coordinator's independent rerun of
59
+ the build and representative route checks are both recorded. A gate failure
60
+ caps the status at draft-only or leaves the affected routes unresolved; no
61
+ route was replaced by a generic shell or another framework as a fallback.
62
+ - Every preserved third-party integration keeps its original wiring, and the
63
+ credential environment keys it needs are recorded by name. A missing secret
64
+ is an unresolved user follow-up, never silently removed behavior.
15
65
  - SEO title, description, canonical URL, share image, slugs, dates, authors,
16
66
  categories, tags, redirects, and locales are preserved when present.
67
+ - Existing SEO, OG, and social behavior - including dynamic OG image routes -
68
+ is preserved or explicitly reported as a gap.
69
+ - When the source has no low-risk SEO or social value, safe defaults derived
70
+ from verified page/site data are present or the missing behavior is reported;
71
+ the migration must not invent marketing claims.
72
+ - Redirects and security headers stay in the source framework config when the
73
+ target keeps the source runtime and host, or are translated with a recorded
74
+ note in the text migration report when the target runtime or host requires
75
+ it.
76
+ - Every provider-specific rule is classified as preserved, replaced, safely
77
+ unnecessary implementation detail, or unresolved. A deletion has evidence of
78
+ redundancy or the user's accepted loss.
79
+ - Public behavior is verified independently: blog routes and 404s, Markdown
80
+ negotiation, RSS, sitemap, `llms.txt`, OG/social metadata, redirects,
81
+ security headers, and forms where present. Cloudflare cache storage, purge,
82
+ and revalidation internals need no copy when proven externally irrelevant.
83
+ - Each content/data lane records its source-access class. Local files/exports
84
+ and public APIs were read under their simple access rules; private sources
85
+ used a user export or narrowly scoped server-side credential. Missing access
86
+ is unresolved for that lane, and no content was guessed.
87
+
88
+ For linked Next.js targets, `withFimo` derives `FIMO_CONTENT_API_URL` and
89
+ `NEXT_PUBLIC_FIMO_API_URL` from `.fimo/project.json` during `next dev`,
90
+ `next build`, and `next start`. Both aliases resolve to the same tenant API,
91
+ while non-empty user overrides remain untouched; no committed env file is
92
+ required.
93
+
94
+ ## Hosting
95
+
96
+ Owned by the runtime lane; verified here read-only.
97
+
98
+ - The target starts locally: the dev server responds without startup errors.
99
+ - The target is embeddable in Fimo Preview, which frames the app in an iframe
100
+ and drives it over the postMessage preview bridge. Development/preview
101
+ responses carry no unconditional `X-Frame-Options` or CSP `frame-ancestors`
102
+ block; protective headers (nosniff, HSTS, referrer policy) stay. The
103
+ translation goes through `FIMO_PREVIEW_ALLOWED_ORIGINS`; `withFimo` alone
104
+ does not solve headers — it only extends `allowedDevOrigins` during
105
+ `next dev`.
106
+ - The runtime report covers local startup, preview embedding, build, derived
107
+ aliases, header translations, and integration env-key names, with every
108
+ claim backed by evidence.
109
+ - With a browser available, record `browserProof` (rendered route plus console
110
+ state) for startup and embedding. Without one, use deterministic HTTP
111
+ status/header/process/log checks and mark visual proof explicitly
112
+ unavailable in the report.
113
+ - Deployment smoke is explicit owner opt-in; never run deploy or publish as a
114
+ QA step.
17
115
 
18
116
  ## Behavior
19
117
 
@@ -21,13 +119,49 @@ Run this gate before reporting completion.
21
119
  - The project builds successfully.
22
120
  - Local dev starts without Vite loader/schema/form generation errors.
23
121
  - Primary routes render without console/runtime errors.
122
+ - In conversion mode, every route in the conversion worker's route map renders
123
+ locally with the expected status (including 404) and shows its source text
124
+ landmarks, and the target has exactly one app tree.
24
125
  - Collection listing/detail pages work with imported data, seed data, or explicit
25
126
  empty states.
127
+ - Every content-code batch exercised at least one non-empty imported item
128
+ through each Server-to-Client or plain-JSON boundary it introduced; build
129
+ success over an empty query result does not pass this check.
26
130
  - Navigation and footer links point to migrated routes or documented external URLs.
131
+ - Missing integration secrets do not block these checks: build, dev, and route
132
+ render run with the integration inert, and the missing key is a recorded
133
+ follow-up.
27
134
  - Unsupported app behavior is not hidden behind broken UI.
28
135
 
136
+ ## Browser smoke (required)
137
+
138
+ Build success and HTTP 200 responses are not sufficient evidence: a page can
139
+ build, return 200, and still render blank labels or an empty collection. Run
140
+ one bounded, scriptable browser pass (Playwright, agent-browser, or
141
+ equivalent):
142
+
143
+ 1. Start the app and wait for hydration, not just the HTTP response.
144
+ 2. Open a representative set of pages: home, one collection listing, one
145
+ collection detail, one static page.
146
+ 3. Exercise one representative interaction (open the nav menu, an accordion,
147
+ or a filter) and assert its visible result.
148
+ 4. Assert expected visible text on each opened page and at least one dynamic
149
+ collection item rendered from imported Fimo data.
150
+ 5. Assert globally rendered label/button text (header/footer nav, CTAs, cookie
151
+ banner) is non-empty; blank text usually means the component is mounted
152
+ outside the label provider.
153
+ 6. Inspect the browser console and server output for runtime errors.
154
+
155
+ Keep it bounded: representative pages and one interaction, not an interactive
156
+ walk of every route or a multi-hour visual audit. The Visual section below
157
+ remains a separate spot check.
158
+
29
159
  ## Visual
30
160
 
161
+ Visual checks need a browser. When none is available, run the deterministic
162
+ Hosting checks instead and mark visual proof explicitly unavailable in the
163
+ report; never claim a visual check that did not run.
164
+
31
165
  - Compare source and migrated site at desktop and mobile sizes.
32
166
  - Prioritize layout, typography, content hierarchy, media, and brand tokens.
33
167
  - Remove generated placeholder copy from visible UI.
@@ -42,8 +176,11 @@ Record:
42
176
  - media uploaded/failed
43
177
  - forms pushed
44
178
  - redirects/locales imported or unresolved
179
+ - the exact CLI used for the run, recorded in the report's Source section (see
180
+ "CLI provenance" in `SKILL.md`)
45
181
 
46
- Counts must be written into `.fimo/migration/manifest.json`.
182
+ Counts belong in `.fimo/migration/migration-report.md` and the relevant worker
183
+ reports. Do not create a JSON QA registry just to store them.
47
184
 
48
185
  Media, entries, and forms are blocking checks. Entries generated as seed JSON but
49
186
  not created in Fimo, and media bundled under `public/` but not uploaded to the
@@ -66,15 +203,25 @@ complete | complete-with-unresolved | draft-only
66
203
 
67
204
  ## Source
68
205
 
206
+ ## Coverage by dimension
207
+
69
208
  ## Routes
70
209
 
71
- ## CMS
210
+ ## Content
72
211
 
73
212
  ## Media
74
213
 
75
214
  ## Forms
76
215
 
77
- ## SEO, Redirects, Locales
216
+ ## SEO and OG
217
+
218
+ ## Redirects and Headers
219
+
220
+ ## Integrations
221
+
222
+ ## Hosting
223
+
224
+ ## Timing
78
225
 
79
226
  ## Checks
80
227
 
@@ -83,15 +230,22 @@ complete | complete-with-unresolved | draft-only
83
230
  ## Next Actions
84
231
  ```
85
232
 
233
+ `Coverage by dimension` is one row per migration surface (routes, content,
234
+ forms, SEO/OG, redirects/headers, integrations, hosting, media, labels, and
235
+ locales) with `gate`,
236
+ `discovered`, `migrated`, `verified`, `unresolved`, `unsupported`,
237
+ `denominator`, and `coverage`. Never collapse it into a single score: full route
238
+ coverage must not average away a missing entry or an unuploaded asset. Timing is
239
+ a separate section copied from the worker reports, so it never dilutes coverage.
240
+
241
+ Cache freshness is a report check only when the source or user made freshness an
242
+ accepted observable requirement; do not fail a migration for omitted provider
243
+ cache mechanics alone.
244
+
86
245
  Use `complete` only when all required checks pass. Use
87
246
  `complete-with-unresolved` when the migrated site is usable and all gaps are
88
247
  owner-visible. Use `draft-only` when import or verification has not happened.
89
248
 
90
- The bundled script can update `qa.status` and write the report:
91
-
92
- ```bash
93
- node <this-skill>/scripts/write-migration-report.mjs <project-root>
94
- ```
95
-
96
- If it fails, read the generated report and either complete the missing work or
97
- add precise unresolved items with owner-friendly suggested actions.
249
+ Write the report directly as text. A later evaluator may calculate the table
250
+ from it, but the migration does not need a manifest or report-generation
251
+ registry to run.
@@ -0,0 +1,39 @@
1
+ # Content execution workers
2
+
3
+ Execute the content planner's text handoff. Do not rediscover the source,
4
+ reclassify values, redesign schemas, or edit files outside the assigned batch.
5
+ If the handoff is incomplete, report the missing item to the coordinator so the
6
+ planner can repair it.
7
+
8
+ ## Data worker
9
+
10
+ Own one bounded schema/locale payload. Start only after every referenced asset
11
+ has a confirmed Fimo mapping and, during conversion, the framework gate passes.
12
+ Perform create-or-update writes and read the batch back before returning.
13
+
14
+ For entry batches, use
15
+ `fimo entries bulk-create <Uid> --file <payload> --upsert-by slug` and report
16
+ per-chunk created, updated, reconciled, and conflict counts. Do not leave a
17
+ payload as evidence of an import. An unavailable dependency blocks promptly;
18
+ do not poll indefinitely.
19
+
20
+ ## Code worker
21
+
22
+ Start only after this batch's real records read back as non-empty. Own exactly
23
+ the consumer files assigned by the planner.
24
+
25
+ 1. Load the active framework's `fimo-code` reference.
26
+ 2. Establish the generated Fimo client/adapter needed by the batch.
27
+ 3. Replace every planned `sourceFile`/`sourceKey` at its existing consumer in
28
+ place. Appending a disconnected duplicate section is not wiring.
29
+ 4. Preserve executable React/MDX children in order around editable prose.
30
+ 5. Render at least one real imported item through every Server-to-Client or
31
+ plain-JSON boundary in the batch. Use the framework's generated
32
+ serialization/hydration contract; do not partially unwrap tracked values.
33
+ 6. Confirm each original literal or data source is gone only where its Fimo
34
+ replacement now renders once.
35
+
36
+ A loader that reads Fimo while the consuming markup is missing, an imported
37
+ entry no route consumes, or a successful build over empty data is incomplete.
38
+ Return source items wired, files changed, read-back/render evidence, and any
39
+ unresolved item in plain text.
@@ -0,0 +1,64 @@
1
+ # Content planning worker
2
+
3
+ Own semantic discovery, schema authoring, payload preparation, and the text
4
+ handoff. Do not import entries or rewrite application consumers.
5
+
6
+ 1. Inspect every content-bearing source and consumer: Markdown/MDX bodies and
7
+ frontmatter, JSX/TSX modules, hardcoded arrays and objects, imports, data
8
+ clients, and call sites. Read local exports and public APIs directly. A
9
+ private API requires a user-provided export or narrowly scoped server-side
10
+ credential; never recover or copy secret values.
11
+ 2. Classify each value as collection content, single content, an
12
+ editor-visible label, or application-owned code. Repetition is evidence,
13
+ not an automatic collection rule. Assistive text, identifiers, and values
14
+ that drive behavior are not labels.
15
+ 3. Define complete schemas from source evidence: types, requiredness, defaults,
16
+ uniqueness, locale behavior, media constraints, references, and
17
+ cardinalities. Do not invent constraints. Load `references/decision.md` and
18
+ the target project's Fimo schema guidance.
19
+ 4. Trace every item to the route, component, loader, query, or render module
20
+ that consumes it. Record its `sourceFile`, `sourceKey`, target files, payload
21
+ file, and worker batch. Finding data without consumers is incomplete.
22
+ 5. Enumerate every media field and rich-text image node as an asset obligation.
23
+ 6. Write and push `src/schemas/*.json`, generate required clients/types, and
24
+ write self-contained JSON payloads for the data workers.
25
+ 7. Write `.fimo/migration/content-plan.md` before any entry, label, single, or
26
+ content-driven code rewrite begins.
27
+
28
+ The text plan has one source item per independently migrated construct and
29
+ groups them into non-overlapping data and code batches. Every object in a
30
+ hardcoded content array is an item. MDX prose and executable imports/components
31
+ are separate items when needed; executable JSX cannot disappear inside a
32
+ rich-text conversion.
33
+
34
+ Keep the handoff short:
35
+
36
+ ```md
37
+ ## BlogPost
38
+
39
+ - Source: `content/blog/post.mdx`
40
+ - Schema: `src/schemas/BlogPost.json` (pushed)
41
+ - Payload: `.fimo/migration/content/BlogPost.en.json`
42
+ - Items: title, body, cover, `CoverageChart` behavior
43
+ - Consumers: `src/app/blog/[slug]/page.tsx`
44
+ - Data worker: `BlogPost/en`
45
+ - Code worker: `blog-rendering`, owns the consumer above
46
+
47
+ ## Unresolved
48
+
49
+ - `content/blog/post.mdx:11`: `CoverageChart` implementation is absent; owner
50
+ must restore it. Do not remove the node silently.
51
+ ```
52
+
53
+ A construct is unresolved only when it genuinely cannot be migrated. Include
54
+ its exact source, user-visible impact, reason, and owner action; "custom" is not
55
+ a reason.
56
+
57
+ ## Optional extraction helpers
58
+
59
+ Start with `rg` and targeted reads. A bounded read-only helper under
60
+ `.fimo/migration/tmp/` may parse repeated frontmatter, JSON/YAML exports, or
61
+ literal structures while preserving source locations. Spot-check its output.
62
+ The agent still owns classification, schema design, and consumer tracing. Do
63
+ not build a generic codemod system or let the helper write Fimo data or app
64
+ code.
@@ -0,0 +1,37 @@
1
+ # Framework conversion worker
2
+
3
+ Use this worker only after the user explicitly chose a framework conversion.
4
+ Preserve mode never uses it.
5
+
6
+ `fimo migrate init` creates the target first. Inspect the initialized template
7
+ and its real paths before writing. Own all structural target code: dependencies,
8
+ framework config, root layout and providers, app tree, route modules, 404,
9
+ redirects, headers, middleware, sitemap/robots/OG structure, and locale-routing
10
+ structure. There is no separate runtime or route writer during conversion.
11
+
12
+ Port the source APIs, loaders, hardcoded content, integrations, and visible
13
+ behavior into the new framework unchanged. Do not migrate those values to Fimo
14
+ in this pass; schemas, data, and Fimo consumer wiring belong to later content
15
+ workers. The content planner may inspect the source in parallel but must not
16
+ edit structural target code.
17
+
18
+ Load the target framework's `fimo-code` and hosting references. For Next.js,
19
+ also load `references/frameworks/nextjs.md` and translate portable hosting
20
+ behavior before declaring provider-specific behavior unresolved.
21
+
22
+ ## Framework gate
23
+
24
+ Before returning, self-check and report:
25
+
26
+ - dependencies install cleanly;
27
+ - the framework build succeeds;
28
+ - every source route maps to a target route and renders locally with its
29
+ expected status, including 404 behavior;
30
+ - representative source text landmarks appear;
31
+ - exactly one app tree and one root layout exist; and
32
+ - primary routes have no runtime or console errors.
33
+
34
+ Return a plain-text route map, files changed, check results, preserved behavior,
35
+ and unresolved behavior. The coordinator independently reruns the build and
36
+ representative route checks. Content data cannot start until this gate and the
37
+ asset gate pass.
@@ -0,0 +1,25 @@
1
+ # Migration validator
2
+
3
+ The validator is an independent read-only worker. It did not author the
4
+ migration and starts only after all writers return.
5
+
6
+ Compare the source, content plan, actual `git diff`, real Fimo state, and local
7
+ application behavior. A worker report is a claim, not evidence.
8
+
9
+ Verify:
10
+
11
+ - every source route renders with expected status and representative content;
12
+ - schemas, entries, singles, labels, media, forms, and locales exist through
13
+ CLI read-back;
14
+ - every planned source item is consumed at its original behavior path, not in
15
+ an appended duplicate section;
16
+ - media URLs load as their expected media type;
17
+ - native Fimo APIs are used without migration-only wrappers;
18
+ - imports are safe to rerun;
19
+ - build and representative browser interactions pass; and
20
+ - every unsupported item names its impact and owner action.
21
+
22
+ Return a plain-text report with status, duration, checks run, counts, failing
23
+ source items, and suggested bounded repair surface. The coordinator may run one
24
+ repair for that surface and rerun validation. It does not restart every worker
25
+ or loop indefinitely.
@@ -0,0 +1,82 @@
1
+ # Migration workers
2
+
3
+ The root coding agent is the coordinator. It inspects the initialized target,
4
+ writes a short text plan, starts independent workers through its native
5
+ subagent mechanism, and fans their results back in. If subagents are
6
+ unavailable, run the same lanes sequentially; never skip a surface silently.
7
+
8
+ The CLI does not start language models. JSON is reserved for Fimo schemas and
9
+ content payloads. Worker ownership, dependencies, reports, and unresolved work
10
+ stay in `.fimo/migration/*.md` or the agents' plain-text responses.
11
+
12
+ ## Schedule
13
+
14
+ Plan a lane only when the source proves that surface exists:
15
+
16
+ | worker | owns | starts when |
17
+ | --------------- | ----------------------------------------------- | ------------------------ |
18
+ | runtime | framework/runtime files and provider config | immediately |
19
+ | routes | route modules, redirects, SEO and host behavior | immediately |
20
+ | content planner | schemas, content payloads, and content handoff | immediately |
21
+ | locales | locale setup and translated UI copy | immediately |
22
+ | assets/forms | media uploads and form behavior | after content planner |
23
+ | content data | one schema/locale import | after assets |
24
+ | content code | listed consuming files | after its data read-back |
25
+ | validator | read-only final checks | after all writers |
26
+
27
+ This is preserve mode, the default. When the user explicitly chose a framework
28
+ conversion, one framework worker replaces runtime and routes and owns all
29
+ structural target code. The content planner may run beside it. Data then waits
30
+ for both the asset and framework gates, and code waits for real imported-data
31
+ read-back.
32
+
33
+ ## Ownership
34
+
35
+ - **runtime** preserves the detected framework, router, runtime, dependencies,
36
+ provider setup, environment wiring, and provider-specific configuration. An
37
+ unclear or unsupported setup produces a question, not a silent conversion.
38
+ - **routes** preserves every route, redirect, 404, SEO/OG/social output,
39
+ sitemap, robots, feeds, headers, and other observable host behavior. A file
40
+ that consumes migrated content belongs to its later content-code worker.
41
+ - **content planner** discovers and models all editable content, labels,
42
+ consumers, schemas, payloads, media obligations, and execution batches. It
43
+ never imports entries or rewrites consumers. Read
44
+ `references/workers/content-planner.md`.
45
+ - **assets/forms** uploads every planner media obligation and patches payload
46
+ references. It replaces a form or integration only when Fimo preserves its
47
+ behavior end to end; otherwise it preserves or reports it.
48
+ - **content data and code** execute the planner handoff without rediscovering
49
+ or redesigning it. Read `references/workers/content-execution.md`.
50
+ - **locales** owns locale configuration, locale routing, and translated
51
+ visitor-visible labels.
52
+ - **framework conversion** is used only after explicit user choice. Read
53
+ `references/workers/framework.md`.
54
+ - **validator** authors nothing. Read `references/workers/validator.md`.
55
+
56
+ If two lanes need one file, name one owner in the text plan and sequence the
57
+ other after it. Do not add a metadata format for a small overlap.
58
+
59
+ ## Coordinator gates
60
+
61
+ 1. Run `fimo migrate init` and inspect the real target paths before workers
62
+ write.
63
+ 2. Start runtime/routes/content-planner/locales together, or the framework
64
+ worker plus content planner/locales in conversion mode.
65
+ 3. After the content plan, upload every planned asset and patch payloads.
66
+ 4. Start data workers only after the asset gate and, in conversion mode, the
67
+ framework gate.
68
+ 5. Start each code worker only after its own imported records read back as
69
+ non-empty. A build over empty data proves nothing.
70
+ 6. Start the independent validator only after every writer has returned.
71
+
72
+ Each prompt names the worker's source paths, exact target ownership, applicable
73
+ reference above, and dependencies. Each report states status, duration, source
74
+ evidence, files changed, Fimo writes, source items handled, unresolved work,
75
+ and the next action. The coordinator verifies those claims against `git diff`,
76
+ CLI read-back, and rendered routes.
77
+
78
+ A source item is covered only when its target value exists and the application
79
+ consumes it at the original behavior path, or when an explicit unresolved item
80
+ names the impact and owner action. If validation fails, create one bounded
81
+ repair task for that surface and rerun the validator; do not restart every
82
+ worker.