@aotter/mantle 0.1.3 → 0.1.5-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +20 -20
  2. package/dist/cli/generate-cloudflare.d.ts +7 -0
  3. package/dist/cli/generate-cloudflare.d.ts.map +1 -0
  4. package/dist/cli/generate-cloudflare.js +123 -0
  5. package/dist/cli/generate-cloudflare.js.map +1 -0
  6. package/dist/cli/generate-project.d.ts +25 -0
  7. package/dist/cli/generate-project.d.ts.map +1 -0
  8. package/dist/cli/generate-project.js +282 -0
  9. package/dist/cli/generate-project.js.map +1 -0
  10. package/dist/cli/generate-sites.d.ts +8 -0
  11. package/dist/cli/generate-sites.d.ts.map +1 -0
  12. package/dist/cli/generate-sites.js +273 -0
  13. package/dist/cli/generate-sites.js.map +1 -0
  14. package/dist/cli/generate.d.ts.map +1 -1
  15. package/dist/cli/generate.js +121 -10
  16. package/dist/cli/generate.js.map +1 -1
  17. package/dist/cli/main.d.ts +1 -1
  18. package/dist/cli/main.d.ts.map +1 -1
  19. package/dist/cli/main.js +11 -11
  20. package/dist/cli/skills.js +1 -1
  21. package/dist/cli/skills.js.map +1 -1
  22. package/docs/adr/0001-four-atom-manifest-model.md +3 -2
  23. package/docs/adr/0013-agent-provisioned-consumer-projects.md +4 -4
  24. package/docs/adr/0016-site-semantic-layer.md +5 -4
  25. package/docs/adr/0018-core-starters-repository-boundary.md +1 -1
  26. package/docs/adr/0021-retire-starter-scaffolding.md +1 -1
  27. package/docs/adr/0026-progressive-generate.md +36 -0
  28. package/docs/adr/0027-scheduled-procedure-triggers.md +31 -0
  29. package/docs/adr/0028-schema-ttl-expiry.md +33 -0
  30. package/docs/adr/README.md +7 -4
  31. package/docs/agent-prompts.md +41 -78
  32. package/docs/assets/mantle-admin-developer.png +0 -0
  33. package/docs/examples/README.md +1 -1
  34. package/docs/examples/host-chatgpt-sites/README.md +29 -12
  35. package/docs/examples/host-chatgpt-sites/drizzle/0003_store_instance_id.sql +1 -0
  36. package/docs/examples/host-chatgpt-sites/drizzle/0004_mantle.sql +10 -0
  37. package/docs/examples/host-chatgpt-sites/drizzle/0005_mantle.sql +24 -0
  38. package/docs/examples/host-chatgpt-sites/drizzle/meta/_journal.json +1 -1
  39. package/docs/examples/host-chatgpt-sites/drizzle/meta/mantle-state.json +60 -0
  40. package/docs/examples/host-chatgpt-sites/package.json +1 -1
  41. package/docs/examples/host-chatgpt-sites/public/site.css +1 -1
  42. package/docs/examples/host-chatgpt-sites/scripts/build.mjs +2 -1
  43. package/docs/examples/host-chatgpt-sites/scripts/check.mjs +2 -0
  44. package/docs/examples/host-chatgpt-sites/scripts/migration.mjs +42 -8
  45. package/docs/examples/host-chatgpt-sites/src/chatgpt-auth.ts +9 -6
  46. package/docs/examples/host-chatgpt-sites/src/index.ts +1 -1
  47. package/docs/examples/host-chatgpt-sites/src/web.ts +1 -1
  48. package/docs/examples/host-local-admin-otp/package.json +2 -2
  49. package/docs/examples/host-minimal-worker/README.md +5 -5
  50. package/docs/examples/host-minimal-worker/package.json +2 -2
  51. package/docs/handbook/{sites → chatgpt-sites}/equipment-checkout.md +1 -1
  52. package/docs/handbook/chatgpt-sites/generated-app.md +84 -0
  53. package/docs/handbook/{sites → chatgpt-sites}/index.md +35 -13
  54. package/docs/handbook/cloudflare/authentication.md +19 -2
  55. package/docs/handbook/cloudflare/bindings.md +4 -11
  56. package/docs/handbook/cloudflare/chatgpt-sites.md +6 -6
  57. package/docs/handbook/cloudflare/conventional-worker.md +7 -3
  58. package/docs/handbook/cloudflare/deploy-and-operate.md +4 -3
  59. package/docs/handbook/cloudflare/media-r2.md +2 -2
  60. package/docs/handbook/concepts/four-atoms.md +1 -1
  61. package/docs/handbook/concepts/lifecycle-and-locales.md +1 -1
  62. package/docs/handbook/concepts/mcp-and-agents.md +24 -4
  63. package/docs/handbook/concepts/procedures-and-triggers.md +1 -1
  64. package/docs/handbook/concepts/runtime-and-adapters.md +8 -1
  65. package/docs/handbook/concepts/views.md +1 -1
  66. package/docs/handbook/guides/agent-setup.md +8 -7
  67. package/docs/handbook/navigation.json +7 -6
  68. package/docs/handbook/reference/diagnostics.md +5 -0
  69. package/docs/handbook/reference/procedure.md +52 -1
  70. package/docs/handbook/reference/schema.md +27 -1
  71. package/docs/handbook/reference/surface.md +3 -3
  72. package/docs/handbook/reference/trigger.md +21 -1
  73. package/docs/handbook/releases/index.md +81 -1
  74. package/docs/handbook/start/overview.md +6 -3
  75. package/docs/handbook/start/project-and-cli.md +103 -119
  76. package/docs/handbook/start/quickstart-admin.md +6 -4
  77. package/docs/handbook/start/quickstart-worker.md +17 -11
  78. package/docs/release-process.md +3 -2
  79. package/docs/sealed-pipeline-ownership.md +1 -1
  80. package/docs/skills/develop/SKILL.md +258 -0
  81. package/docs/skills/integrate/SKILL.md +60 -0
  82. package/docs/skills/media-gc/SKILL.md +85 -0
  83. package/docs/skills/plugin/SKILL.md +132 -0
  84. package/docs/skills/provision/SKILL.md +194 -0
  85. package/docs/skills/theme/SKILL.md +77 -0
  86. package/docs/skills/update/SKILL.md +51 -0
  87. package/docs/spec-only-host-adoption.md +1 -1
  88. package/package.json +19 -18
  89. package/skills/README.md +28 -21
  90. package/skills/develop/SKILL.md +16 -8
  91. package/skills/install/SKILL.md +103 -128
  92. package/skills/integrate/SKILL.md +60 -0
  93. package/skills/media-gc/SKILL.md +2 -2
  94. package/skills/plugin/SKILL.md +2 -2
  95. package/skills/provision/SKILL.md +3 -3
  96. package/skills/theme/SKILL.md +2 -2
  97. package/skills/update/SKILL.md +2 -2
  98. package/templates/chatgpt-sites/auth.ts +66 -0
  99. package/templates/chatgpt-sites/build.mjs +14 -0
  100. package/templates/chatgpt-sites/env.ts +1 -0
  101. package/templates/chatgpt-sites/mcp.ts +48 -0
  102. package/templates/chatgpt-sites/public-mcp.ts +29 -0
  103. package/templates/chatgpt-sites/smoke-local.mjs +20 -0
  104. package/skills/.keep +0 -0
  105. /package/docs/handbook/{sites → chatgpt-sites}/host-reference.md +0 -0
@@ -3,7 +3,7 @@ description: Enable staff media uploads on R2 — presigned PUT flow through Sta
3
3
  ---
4
4
  # Media uploads with R2
5
5
 
6
- R2-backed media is an optional post-launch capability for Workers whose staff or agents need to upload images and files. This page covers the native Cloudflare direct-to-R2 flow, the configuration it needs, how a Schema references an asset, what a commit costs, and how to clean up. For ChatGPT Sites with an R2 binding but no S3 credentials, use [the same-origin Worker flow](../sites/host-reference.md#media-with-only-an-r2-binding).
6
+ R2-backed media is an optional post-launch capability for Workers whose staff or agents need to upload images and files. This page covers the native Cloudflare direct-to-R2 flow, the configuration it needs, how a Schema references an asset, what a commit costs, and how to clean up. For ChatGPT Sites with an R2 binding but no S3 credentials, use [the same-origin Worker flow](../chatgpt-sites/host-reference.md#media-with-only-an-r2-binding).
7
7
 
8
8
  ## When to enable it
9
9
 
@@ -213,4 +213,4 @@ The full catalog is in [Diagnostic codes](../reference/diagnostics.md).
213
213
  - [`packages/mantle-spec/src/domain/service/SiteDefaultsValidator.ts`](../../../packages/mantle-spec/src/domain/service/SiteDefaultsValidator.ts)
214
214
  - [`packages/mantle-spec/src/kernel/diagnostic.ts`](../../../packages/mantle-spec/src/kernel/diagnostic.ts)
215
215
  - [`packages/adapters/cloudflare/README.md`](../../../packages/adapters/cloudflare/README.md)
216
- - [`skills/media-gc/SKILL.md`](../../../skills/media-gc/SKILL.md)
216
+ - [`docs/skills/media-gc/SKILL.md`](../../skills/media-gc/SKILL.md)
@@ -170,4 +170,4 @@ Postgres exposes roughly twenty-five object kinds; an application developer writ
170
170
  - [`docs/adr/0012-views-as-public-rest.md`](../../../docs/adr/0012-views-as-public-rest.md)
171
171
  - [`packages/mantle-spec/src/domain/model/ManifestGrammar.ts`](../../../packages/mantle-spec/src/domain/model/ManifestGrammar.ts)
172
172
  - [`packages/mantle-spec/src/domain/service/ManifestParser.ts`](../../../packages/mantle-spec/src/domain/service/ManifestParser.ts)
173
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
173
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -139,4 +139,4 @@ The full worked version of this pattern, with a locale-parameterized public View
139
139
  - [`packages/mantle-spec/src/domain/model/SiteConfig.ts`](../../../packages/mantle-spec/src/domain/model/SiteConfig.ts)
140
140
  - [`packages/mantle-runtime/src/domain/service/io/EntryWriteGuard.ts`](../../../packages/mantle-runtime/src/domain/service/io/EntryWriteGuard.ts)
141
141
  - [`packages/mantle-runtime/src/infrastructure/mcp/McpToolCatalog.ts`](../../../packages/mantle-runtime/src/infrastructure/mcp/McpToolCatalog.ts)
142
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
142
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -68,6 +68,25 @@ Only `status: published` entries appear anywhere in that set. Details are in [Pu
68
68
 
69
69
  ## WebMCP in the browser
70
70
 
71
+ ### Admin: tools for the signed-in staff member
72
+
73
+ Admin UI registers staff tools in browsers supporting `document.modelContext`.
74
+ The catalog comes from `GET /admin/api/webmcp`; calls use
75
+ `POST /admin/api/mcp` with the current staff session. Server-side role checks,
76
+ Procedure authorization, and optimistic concurrency remain in force.
77
+ `admin_get_context` and `admin_navigate` add page context and navigation.
78
+ The WebMCP control appears after registration succeeds; unsupported browsers
79
+ can continue using the regular Admin UI.
80
+
81
+ Owners can explore application API documentation in Developer UI:
82
+ `/admin/dev/docs/api` for HTTP, `/admin/dev/docs/mcp` for remote MCP, and
83
+ `/admin/dev/docs/webmcp` for the Admin catalog and public-page capabilities.
84
+ These pages show projected definitions. Remote clients connect to the host's
85
+ advertised MCP endpoints using the authentication described above.
86
+ See the [Admin API guide](../../../packages/mantle-admin/README.md#admin-webmcp).
87
+
88
+ ### Public pages: opt-in registration
89
+
71
90
  `@aotter/mantle-web/webmcp` exposes public capabilities as tools inside a page, for browsers implementing the draft imperative WebMCP API. Importing the subpath has no side effect; registration starts only when `bindWebMcp()` is called.
72
91
 
73
92
  ```ts
@@ -78,7 +97,7 @@ const binding = await bindWebMcp();
78
97
  binding.dispose();
79
98
  ```
80
99
 
81
- It feature-detects `document.modelContext` and returns `{ supported: false }` on browsers without it. Only public capabilities are registered — staff capabilities never leave the server. Existing host tool names are inspected and skipped, never replaced. A server-backed page discovers the safe descriptors published at `GET /api/views` and calls the same-origin `GET /api/views/<name>` routes; a browser-local SPA passes `projectCallableCapabilities(plan, { surface: "public" })` and its own invoker. Procedure tools must still originate from an explicit public MCP Trigger, and invocation enters the runtime through that Trigger, so browser tools cannot bypass validation or authorization. See [Runtime pipeline and adapters](./runtime-and-adapters.md).
100
+ It feature-detects `document.modelContext` and returns `{ supported: false }` on browsers without it. This public-page binding registers only public capabilities. Staff tools use the separate authenticated Admin integration above. Existing host tool names are inspected and skipped, never replaced. A server-backed page discovers the safe descriptors published at `GET /api/views` and calls the same-origin `GET /api/views/<name>` routes; a browser-local SPA passes `projectCallableCapabilities(plan, { surface: "public" })` and its own invoker. Procedure tools must still originate from an explicit public MCP Trigger, and invocation enters the runtime through that Trigger, so browser tools cannot bypass validation or authorization. See [Runtime pipeline and adapters](./runtime-and-adapters.md).
82
101
 
83
102
  ## Skills for your coding agent
84
103
 
@@ -91,11 +110,12 @@ pnpm exec mantle skills --check
91
110
 
92
111
  This copies every skill the installed package marks `projection: project` — the develop skill among them — into matching `.agents/skills/mantle-*` and `.claude/skills/mantle-*` paths. Both layouts receive identical bytes; `--check` detects drift without writing. Skills that act destructively or target one platform stay out of that set and are opt-in. Manifest generation never rewrites agent instructions.
93
112
 
94
- The same bundle is installable from the plugin marketplace:
113
+ The bootstrap `mantle` skill is also available from the plugin marketplace.
114
+ The ongoing workflows come from the installed SDK through `mantle skills`:
95
115
 
96
116
  ```sh
97
117
  # Canonical
98
- npx skills add aotter/mantle --skill install
118
+ npx skills add aotter/mantle
99
119
 
100
120
  # Claude Code — two separate prompts
101
121
  /plugin marketplace add aotter/mantle
@@ -111,4 +131,4 @@ Never point a versioned project at a mutable branch. See [Project layout and the
111
131
  - [`packages/mantle-web/README.md`](../../../packages/mantle-web/README.md)
112
132
  - [`packages/mantle/README.md`](../../../packages/mantle/README.md)
113
133
  - [`packages/adapters/cloudflare/README.md`](../../../packages/adapters/cloudflare/README.md)
114
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
134
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -218,4 +218,4 @@ Register the two `ref` keys in the project's handlers map, then run the check lo
218
218
  - [`packages/mantle-spec/src/domain/model/ManifestGrammar.ts`](../../../packages/mantle-spec/src/domain/model/ManifestGrammar.ts)
219
219
  - [`packages/mantle-runtime/src/domain/service/BuiltinProjector.ts`](../../../packages/mantle-runtime/src/domain/service/BuiltinProjector.ts)
220
220
  - [`packages/mantle-runtime/src/infrastructure/http/createMantleRequestHandler.ts`](../../../packages/mantle-runtime/src/infrastructure/http/createMantleRequestHandler.ts)
221
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
221
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -95,6 +95,13 @@ A storage adapter prepares one `RuntimePlan` into semantic ports. Three are requ
95
95
 
96
96
  Two are optional and only when a feature needs them: `MediaStorage` for upload flows, and `DeferredHookDispatcher` for at-least-once `after_*` delivery. `DatabaseDriver` is not a portability contract — it is the reusable SQLite/D1 seam. A PostgreSQL, MongoDB or application-owned-table adapter implements the semantic ports directly rather than emulating D1.
97
97
 
98
+ `PreparedMantleStorage.atomicEntries` is an optional semantic write capability.
99
+ An adapter exposes it only when it can commit an ordered group of entry
100
+ mutations all-or-nothing, including zero-row version/status failures. The
101
+ SQLite implementation covers Cloudflare D1 and Bun; IndexedDB and custom
102
+ adapters without that guarantee leave it absent. Ref Procedures use
103
+ `ctx.writeAtomically` as described in [Procedure](../reference/procedure.md#atomic-entry-writes-in-a-ref-handler).
104
+
98
105
  Declarative Views compile to logical plans once, and preparation lowers those plans to native queries. `View.spec.sql` is the exception: it is explicitly SQLite-only in v0.1. Storage that does not declare that dialect rejects such a View at preparation with `VIEW_DIALECT_UNSUPPORTED`, before mutating any state. Mantle does not guess a translation and ships no universal query driver. A View that must run everywhere uses `from` with a filter AST; see [View](../reference/view.md).
99
106
 
100
107
  ## Embedding each adapter
@@ -174,4 +181,4 @@ If a normal feature cannot be expressed through a purpose-shaped surface, treat
174
181
  - [`packages/adapters/bun/README.md`](../../../packages/adapters/bun/README.md)
175
182
  - [`packages/adapters/vercel/README.md`](../../../packages/adapters/vercel/README.md)
176
183
  - [`packages/adapters/indexeddb/README.md`](../../../packages/adapters/indexeddb/README.md)
177
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
184
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -189,4 +189,4 @@ spec:
189
189
  - [`packages/mantle-runtime/src/infrastructure/storage/SqliteViewCompiler.ts`](../../../packages/mantle-runtime/src/infrastructure/storage/SqliteViewCompiler.ts)
190
190
  - [`packages/mantle-runtime/src/infrastructure/http/createMantleRequestHandler.ts`](../../../packages/mantle-runtime/src/infrastructure/http/createMantleRequestHandler.ts)
191
191
  - [`packages/adapters/cloudflare/src/mount/mountRuntimeEndpoints.ts`](../../../packages/adapters/cloudflare/src/mount/mountRuntimeEndpoints.ts)
192
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
192
+ - [`docs/skills/develop/SKILL.md`](../../skills/develop/SKILL.md)
@@ -9,12 +9,12 @@ application's SDK. Installing one does not install the other.
9
9
  ## 1. Install the bootstrap skill
10
10
 
11
11
  ```sh
12
- npx skills add aotter/mantle --skill install
12
+ npx skills add aotter/mantle
13
13
  ```
14
14
 
15
- The installer selects the repository's `install` skill. Read its printed
15
+ The installer selects the repository's `mantle` skill. Read its printed
16
16
  installation path. In a project-local Codex installation that is
17
- `.agents/skills/install/SKILL.md`, not `skills/install/SKILL.md` (the latter is
17
+ `.agents/skills/mantle/SKILL.md`, not `skills/install/SKILL.md` (the latter is
18
18
  its source-repository path). Other agent selections and global installation
19
19
  can use different locations.
20
20
 
@@ -32,6 +32,7 @@ version. `latest` and `alpha` can describe different capabilities. Resolve only
32
32
  requirements the user has not provided: host, storage, public API/HTML, and
33
33
  whether staff need Admin. Follow the bootstrap skill to install the selected
34
34
  packages locally.
35
+ No matching `mantle-starters` tag or bundle is needed to create a project.
35
36
 
36
37
  Then read:
37
38
 
@@ -44,7 +45,7 @@ node_modules/@aotter/mantle/docs/handbook/reference/features.md
44
45
  These files are in the npm tarball. They are the version-matched authority,
45
46
  including when the bootstrap skill came from a different Git ref. Every
46
47
  `docs/...` path in the skill resolves under the installed package, not under
47
- `.agents/skills/install/`. Keep using that SDK's docs for host examples and CLI
48
+ `.agents/skills/mantle/`. Keep using that SDK's docs for host examples and CLI
48
49
  behavior. No local `mantle` binary is available before package installation.
49
50
 
50
51
  ## 3. Project the ongoing workflows
@@ -61,7 +62,7 @@ pnpm exec mantle skills --check
61
62
  |---|---|
62
63
  | `.agents/skills/mantle-{develop,plugin,theme,update}/SKILL.md` | The installed package's four project-scoped workflows. |
63
64
  | `.claude/skills/mantle-{develop,plugin,theme,update}/SKILL.md` | Identical bytes for Claude compatibility. |
64
- | `node_modules/@aotter/mantle/skills/` | All seven shipped skills, including opt-in `install`, `provision` and `media-gc`. |
65
+ | `node_modules/@aotter/mantle/skills/` | All eight shipped skills, including opt-in `mantle`, `integrate`, `provision` and `media-gc`. |
65
66
  | `node_modules/@aotter/mantle/docs/` | Handbook and examples matched to the package. |
66
67
 
67
68
  `mantle skills` overwrites these four generated projections. Keep project-specific
@@ -83,9 +84,9 @@ It does not prove a server, login, Admin assets or MCP connection works.
83
84
  | `skills/install/SKILL.md` is missing | That is source provenance. Read the installer's destination instead. |
84
85
  | `docs/...` is missing after `skills add` | The skill does not carry the handbook. Install the pinned SDK and read its embedded docs. |
85
86
  | `mantle` is missing | Install local `@aotter/mantle`; run its binary through the project package manager. |
86
- | `MANIFEST_ROOT_NOT_FOUND` | Author manifests in the configured directory; `generate` is not a scaffold command. |
87
+ | `MANIFEST_ROOT_NOT_FOUND` | Check the installed CLI and saved project selection. New generated projects may start with an empty manifest set; legacy compile mode still needs the configured source. |
87
88
  | `mantle skills --check` exits 1 | Run `mantle skills`, then read the refreshed project skill. |
88
- | No projected provision/media-gc skill | These are intentionally opt-in. Read their installed package files when the task calls for them. |
89
+ | No projected integrate/provision/media-gc skill | These are intentionally opt-in. Read their installed package files when the task calls for them. |
89
90
  | A documented feature fails on an older release | Use that release's docs or explicitly upgrade; changing a skill does not change Runtime. |
90
91
 
91
92
  ## Source
@@ -5,10 +5,10 @@
5
5
  "text": "Start here",
6
6
  "items": [
7
7
  { "text": "Handbook overview", "link": "/start/overview" },
8
- { "text": "Project layout and the CLI loop", "link": "/start/project-and-cli" },
8
+ { "text": "Generate a project and use the CLI", "link": "/start/project-and-cli" },
9
9
  { "text": "Quickstart: a minimal Worker", "link": "/start/quickstart-worker" },
10
- { "text": "Quickstart: local Admin (opt-in)", "link": "/start/quickstart-admin" },
11
- { "text": "When the host is ChatGPT Sites", "link": "/sites/index" }
10
+ { "text": "Quickstart: authored Worker Admin", "link": "/start/quickstart-admin" },
11
+ { "text": "When the host is ChatGPT Sites", "link": "/chatgpt-sites/index" }
12
12
  ]
13
13
  },
14
14
  {
@@ -49,9 +49,10 @@
49
49
  {
50
50
  "text": "ChatGPT Sites",
51
51
  "items": [
52
- { "text": "Get started", "link": "/sites/index" },
53
- { "text": "Host reference", "link": "/sites/host-reference" },
54
- { "text": "Equipment checkout and external APIs", "link": "/sites/equipment-checkout" },
52
+ { "text": "Get started", "link": "/chatgpt-sites/index" },
53
+ { "text": "Generate a blank app", "link": "/chatgpt-sites/generated-app" },
54
+ { "text": "Host reference", "link": "/chatgpt-sites/host-reference" },
55
+ { "text": "Equipment checkout and external APIs", "link": "/chatgpt-sites/equipment-checkout" },
55
56
  { "text": "Earlier guide URL", "link": "/cloudflare/chatgpt-sites" }
56
57
  ]
57
58
  },
@@ -81,11 +81,16 @@ Raised by the parser, the graph validator and the code generator. `mantle valida
81
81
  | `UNIQUE_INDEX_FIELD_UNKNOWN` | A `uniqueIndexes` field is not a top-level Schema property. | — |
82
82
  | `SCHEMA_SEARCH_INVALID` | `searchableFields` repeats an entry or names a non-string property. | — |
83
83
  | `SCHEMA_SEARCH_FIELD_UNKNOWN` | A `searchableFields` entry is not a Schema property. | — |
84
+ | `SCHEMA_TTL_INVALID` | TTL must name a top-level date-time field and a finite nonnegative duration. | — |
85
+ | `SCHEMA_TTL_TRANSLATION_UNSUPPORTED` | TTL on either side of a translation join cannot guarantee the joined content's expiry. | — |
86
+ | `VIEW_TTL_NATIVE_UNSAFE` | A native SQL View cannot guarantee logical expiry while a Schema has TTL. | — |
84
87
  | `SCHEMA_UI_INVALID` | A Schema or Procedure `uiSchema` rule is broken, including unknown roots, invalid `nav.standalone`, or a Schema declaring `uiSchema.collectionAction`. | — |
85
88
  | `HANDLER_BUILTIN_NOT_IN_V010` | A builtin Procedure was invoked on a runtime assembled without the builtin collaborator. | — |
86
89
  | `MANIFEST_ROOT_NOT_FOUND` | The manifests directory is missing, unreadable, or contains no `.yaml` or `.yml` file. | — |
87
90
  | `MANIFEST_READ_FAILED` | A manifest source could not be read. | — |
88
91
  | `CODEGEN_IDENTIFIER_COLLISION` | Two names in one group collapse to the same generated lower-camel identifier. | — |
92
+ | `SCHEDULE_INPUT_INVALID` | A scheduled Procedure cannot accept the empty object supplied by its system Trigger. | — |
93
+ | `SCHEDULE_AUTH_INVALID` | A scheduled Procedure requires user or staff authority that the system caller never has. | — |
89
94
  | `FIXTURE_SCHEMA_VIOLATION` | Reserved for consumer-authored test diagnostics on the `test` phase. Core emits purpose-shaped harness reports instead. | — |
90
95
 
91
96
  ## Cross-phase
@@ -207,7 +207,7 @@ An HTTP Trigger wraps a success as `{ "ok": true, "data": <EntryRow> }` with sta
207
207
 
208
208
  ## Conflicts and idempotency
209
209
 
210
- A unique-index preflight runs before every write, and the database's own constraints catch the races the preflight misses. Both surface as `CONFLICT` (409), as do a stale `expectedVersion` and an illegal lifecycle transition. **There is no automatic retry** — the caller decides whether to re-read and try again.
210
+ A unique-index preflight runs before individual writes, and the database's own constraints catch the races the preflight misses. Atomic groups rely on the transaction's database constraints so an earlier operation may free a unique value for a later one. Both paths surface collisions as `CONFLICT` (409), as do a stale `expectedVersion` and an illegal lifecycle transition. **There is no automatic retry** — the caller decides whether to re-read and try again.
211
211
 
212
212
  Idempotency has no grammar key. The convention is an `input` property marked `x-mcp-hint: idempotency-key`: Admin generates and hides one UUID per form submission, and other callers generate one and reuse it across retries of the same logical request. The handler is responsible for acting on it.
213
213
 
@@ -215,6 +215,57 @@ Optimistic concurrency uses the reserved input name `expectedVersion` — the ve
215
215
 
216
216
  Deferred lifecycle hooks have a stronger guarantee to work with: delivery is at-least-once, and handlers key on `${ctx.event.id}:${ctx.event.trigger}` — stable across enqueue fallback, queue retries and replay. See [Deferred hooks on Queues](../cloudflare/deferred-hooks-queues.md).
217
217
 
218
+ ## Atomic entry writes in a ref handler
219
+
220
+ When one request must change several Schemas together, a `ref` handler can call
221
+ `ctx.writeAtomically(operations)`. Cloudflare D1 and Bun SQLite support it; an
222
+ adapter without the optional `atomicEntries` capability returns
223
+ `RESOURCE_UNAVAILABLE` (503)
224
+ instead of committing part of the group. Operations use the `createDraft`,
225
+ `updateDraft`, or `deleteEntry` request shape; atomic deletes additionally
226
+ require `expectedVersion`. Operational Schemas become live on create;
227
+ publishing Schemas create drafts. Updates and deletes require the version the
228
+ caller read.
229
+
230
+ ```ts
231
+ const sessionId = crypto.randomUUID();
232
+ const rows = await ctx.writeAtomically!([
233
+ { kind: "create", id: sessionId, request: {
234
+ collection: "sessions", data: { name: input.name }, authorId: ctx.user?.id ?? null, ctx,
235
+ } },
236
+ { kind: "create", request: {
237
+ collection: "exercise-blocks", data: { sessionId, exercise: input.exercise },
238
+ authorId: ctx.user?.id ?? null, ctx,
239
+ } },
240
+ { kind: "create", request: {
241
+ collection: "receipts", data: { token: input.requestId }, authorId: ctx.user?.id ?? null, ctx,
242
+ } },
243
+ ]);
244
+ return { sessionId: rows[0]!.id };
245
+ ```
246
+
247
+ Declare `receipts.token` as a Schema `uniqueIndexes: [[token]]`. A duplicate
248
+ receipt rejects the whole group, including the session and block. The handler
249
+ can then read the existing receipt **after** the failed transaction to answer
250
+ an idempotent retry. A stale update or delete rejects the whole group even
251
+ when it is the final operation. The group may touch each entry only once;
252
+ read and authorization decisions happen before the batch, and the expected
253
+ version/status is checked again by the conditional database write.
254
+
255
+ All Schema projection, stamping, validation, uniqueness, and lifecycle rules
256
+ still apply. `before_*` hooks run in operation order before the batch and can
257
+ veto it; their external effects cannot be rolled back. `after_*` hooks run
258
+ only after commit, in operation order. Publishing-content invalidation runs
259
+ once for the group. Deferred Queue delivery is separate from the database
260
+ transaction. Application-owned tables can use their host's transaction
261
+ facility inside a ref handler, but that does not give those tables Mantle
262
+ entry semantics. Direct SQL writes to Mantle Schema tables are unsupported.
263
+ Authorization guard Procedures do not receive `ctx.writeAtomically`.
264
+
265
+ ## TTL sweep in a ref handler
266
+
267
+ `ctx.sweepExpired({ collection, limit })` previews a bounded page of expired rows; `delete: true` explicitly removes it. The result contains `scanned`, `removed` and an optional `nextCursor`. Continue with that cursor until absent. D1 and Bun SQLite implement this semantic capability; unsupported storage returns `RESOURCE_UNAVAILABLE`. Authorization guard Procedures do not receive the sweep function. For a scheduled cleanup, declare a [schedule Trigger](./trigger.md#schedule-source) targeting a no-input ref Procedure. No sweep is scheduled automatically. See [Schema TTL](./schema.md#ttl).
268
+
218
269
  ## `uiSchema`
219
270
 
220
271
  Admin presentation only. It never affects input validation, the MCP tool schema or the OpenAPI document. Roots are closed: `collectionAction` and `fields`.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Schema field reference — JSON Schema subset, extension keywords, uiSchema, indexes, searchable fields, translates and lifecycle rules.
2
+ description: Schema field reference — JSON Schema subset, uiSchema, indexes, translates, lifecycle and TTL rules.
3
3
  ---
4
4
  # Schema
5
5
 
@@ -19,6 +19,7 @@ A Schema declares one collection: the JSON Schema for each entry's `data`, its i
19
19
  | `localized` | boolean | no | `false` | When `false`, a `locale` property is rejected. Must be a boolean. |
20
20
  | `translates` | `{ parent, on }` | no | — | Marks a translation child. Requires `localized: true`. |
21
21
  | `lifecycle` | `publishing` \| `operational` | no | `publishing` | Selects the [state machine](#lifecycle). |
22
+ | `ttl` | `{ field, expireAfterSeconds }` | no | — | Logical expiry over one top-level date-time property. See [TTL](#ttl). |
22
23
 
23
24
  ### Reserved entry columns
24
25
 
@@ -242,6 +243,31 @@ Every authoring path (Admin, Staff MCP, builtin Procedures) runs the same guard
242
243
 
243
244
  Site locales are configured in [Site config](./site-config.md).
244
245
 
246
+ ## TTL
247
+
248
+ ```yaml
249
+ spec:
250
+ ttl: { field: expiresAt, expireAfterSeconds: 0 }
251
+ schema:
252
+ type: object
253
+ properties:
254
+ expiresAt: { type: string, format: date-time, nullable: true }
255
+ ```
256
+
257
+ `field` must name one top-level `date-time` string property; `expireAfterSeconds` is finite and nonnegative. An entry expires when its timestamp plus the duration is **at or before** the current instant. Missing or null dates never expire. `SCHEMA_TTL_INVALID` rejects invalid policies.
258
+
259
+ Legacy values that SQLite cannot parse as dates also remain visible and are not swept; correct those rows before relying on TTL. New writes must pass the Schema's date-time validation.
260
+
261
+ Expiry is logical first: Entry, declarative View, Admin, MCP and Web reads stop returning the row at the boundary, even before a sweep deletes it. A native SQL View cannot guarantee that filter and is rejected (`VIEW_TTL_NATIVE_UNSAFE`) while any Schema has TTL. A View over a TTL Schema cannot use shared caching (`VIEW_CACHE_INVALID`). Bun and D1 use the same SQLite predicate; other storage adapters must supply equivalent read filtering or reject the plan.
262
+
263
+ TTL is currently rejected on either side of a `translates` relationship (`SCHEMA_TTL_TRANSLATION_UNSUPPORTED`), because a translation child could otherwise remain visible after its parent expires.
264
+
265
+ Physical cleanup is **explicit**. `runtime.sweepExpired({ collection: "events", limit: 50 })` previews one page; add `delete: true` to remove it. Follow `nextCursor` until absent. The limit is 1–100, `scanned` counts expired candidates and `removed` counts successful deletes. A failure throws and the previous cursor is safe to retry. Ref Procedures can call `ctx.sweepExpired`; a Cloudflare schedule may invoke such a Procedure. The sweep does not fire entry lifecycle hooks: expiration already changed logical visibility, and the sweep only reclaims storage (ADR-0028).
266
+
267
+ The Developer Console shows declared TTL policies. It does not infer sweep history from a policy; a scheduled Procedure can return `scanned` and `removed` counts to include them in its run observation.
268
+
269
+ Adding or shortening TTL on an existing Schema immediately changes **read visibility**, but never starts a deletion job. Preview a sweep and review its counts before requesting `delete: true`. Keep a backup when changing the policy on populated data. Physical unique constraints still see expired rows until cleanup, so a reused unique value may conflict before the sweep.
270
+
245
271
  ## Source
246
272
 
247
273
  - [`packages/mantle-spec/src/domain/model/ManifestGrammar.ts`](../../../packages/mantle-spec/src/domain/model/ManifestGrammar.ts)
@@ -116,14 +116,14 @@ The `@aotter/mantle` package installs two binaries, `mantle` and `mantle-harness
116
116
 
117
117
  | Command | Flags |
118
118
  |---|---|
119
- | `mantle generate` | `--manifests <dir>` (default `./manifests`), `-o, --output <dir>` (default `.mantle/generated`), `--namespace <name>` (default `Mantle`), `--check`, `-h, --help` |
119
+ | `mantle generate` | `--manifests <dir>` (default `./manifests`), `-o, --output <dir>` (default `.mantle/generated`), `--namespace <name>` (default `Mantle`), `--host cf\|chatgpt-sites`, `--features <list>`, `--review-unique-indexes` (managed Sites only), `--check`, `-h, --help` |
120
120
  | `mantle skills` | `--check`, `-h, --help` |
121
121
  | `mantle validate` | `--manifests <dir>` (default `./manifests`), `--source <dir>` (default `./src`), `--no-source`, `--phase preview\|deploy` (default `preview`), `--format json\|text` (default by TTY), `--json`, `-h, --help` |
122
122
  | `mantle emit-openapi` | `--manifests <dir>`, `--title <str>` (default `mantle`), `--version <str>` (default `0.1.0`), `--session-cookie-name <str>`, `-o, --output <file>`, `-h, --help` |
123
123
  | `mantle-harness indexes` | `--manifests <dir>`, `--rows <n>`, `--require <view>` (repeatable), `--require-public`, `--format json\|text`, `-h, --help` |
124
124
  | `mantle-harness http` | `--route <name=url>` (repeatable, required), `--base-url <url>`, `--rounds <n>`, `--warmup <n>`, `--format json\|text`, `-h, --help` |
125
125
 
126
- `generate` validates and compiles the manifest directory, writes the typed module, and — when `@aotter/mantle-admin-ui` is installed — syncs the Admin SPA into `public/_mantle/admin/`, excluding `server.*` files. `--check` fails without writing when either output is stale. `skills` copies every skill the installed package marks `projection: project` into `.agents/skills/mantle-*` and `.claude/skills/mantle-*`; both layouts receive identical bytes. `validate --phase deploy` adds the pre-deploy-only gates on top of the grammar and cross-Schema checks. `emit-openapi` covers HTTP Triggers and View REST routes; MCP is out of scope. `mantle-harness indexes` executes compiled Views against crowded SQLite and inspects query plans; `http` samples a running Worker for p50 and p95. Day-to-day use is in [Project and CLI](../start/project-and-cli.md).
126
+ `generate` assembles new hosted projects with full Spec/Runtime/API/MCP/Admin/Web by default, or a smaller positive `--features` selection, then validates and compiles manifests into a typed module. Saved selections rerun safely; legacy authored projects keep compile mode. Selected Admin syncs its prebuilt SPA into `public/_mantle/admin/`. `--check` fails without writing on drift. `skills` copies project-scoped skills into `.agents/skills/mantle-*` and `.claude/skills/mantle-*`. `validate --phase deploy` adds pre-deploy checks; `emit-openapi` covers HTTP Triggers and View REST routes. `mantle-harness indexes` checks SQLite plans, while `http` samples a running Worker. [Project and CLI](../start/project-and-cli.md) has the install and ownership sequence.
127
127
 
128
128
  ## The generated module
129
129
 
@@ -182,7 +182,7 @@ This handbook describes the snapshot in this source tree. Pin every `@aotter/man
182
182
 
183
183
  The documentation site pins its handbook commit in `docs/handbook.json` and records its vendored SDK source in `vendor/mantle/SOURCE.txt`. Those commits may differ when the intervening changes are behavior-neutral; the site verifies that condition during the build.
184
184
 
185
- Projects are authored directly: write the manifests, run `generate`, `skills`, `validate` and `emit-openapi`, and wire the Worker. There is no project generator. Prerelease packages take their exact version from their own `package.json`; APIs may change between prereleases until a stable line ships.
185
+ New projects can use `generate` to assemble a blank hosted app. Existing authored Workers can keep their own entry and use the same CLI for typed compilation. Pin all selected packages to one exact SDK version; prerelease APIs can change until stable publication.
186
186
 
187
187
  ## Source
188
188
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Trigger field reference — http, mcp and lifecycle sources, path and tool-name rules, the eight lifecycle hooks and their timing and error policy.
2
+ description: Trigger field reference — http, mcp, lifecycle and schedule sources, routing rules, and delivery semantics.
3
3
  ---
4
4
  # Trigger
5
5
 
@@ -19,9 +19,29 @@ A Trigger binds one source to one [Procedure](./procedure.md). Every external su
19
19
  | `http` | `method`, `path` | One REST endpoint under `/api/`. |
20
20
  | `mcp` | `surface` | One tool on `/mcp` or `/mcp/staff`. |
21
21
  | `lifecycle` | `schema`, `on`, `errorPolicy` | Entry-writer hooks on one Schema. |
22
+ | `schedule` | `cron`, optional `enabled` | A Cloudflare Cron Trigger calling one Procedure. |
22
23
 
23
24
  An unknown `kind`, a missing `kind`, or a key that does not belong to the chosen kind is `INVALID_MANIFEST_ENVELOPE`. One Procedure may carry several Triggers — that is how the same handler becomes an HTTP endpoint and an MCP tool without duplicating logic.
24
25
 
26
+ ## `schedule` source
27
+
28
+ ```yaml
29
+ apiVersion: cms.mantle.aotter.net/v1
30
+ kind: Trigger
31
+ metadata: { name: nightly-cleanup }
32
+ spec:
33
+ source: { kind: schedule, cron: "0 2 * * *" }
34
+ target: { procedure: clean-expired-records }
35
+ ```
36
+
37
+ `cron` is a five-field Cloudflare UTC expression (minute, hour, day, month, weekday). Each field accepts `*`, a number, a range, comma-separated values, or `*/step` / `start-end/step`. Weekdays are **1 = Sunday through 7 = Saturday**; use `2-6` for Monday–Friday. Month and weekday names and provider-specific extensions are outside this subset. `enabled` defaults to `true`; a disabled schedule remains in the compiled plan but never invokes its Procedure. The target Procedure must accept `{}` as input (`SCHEDULE_INPUT_INVALID`) and have no user/staff authorization requirements (`SCHEDULE_AUTH_INVALID`). The schedule creates no public HTTP or MCP route.
38
+
39
+ On Cloudflare, add each enabled expression to `wrangler.jsonc` under `triggers.crons` and export the `scheduled` method returned by `createMantleWorker`. Mantle does not provision the provider trigger. A disabled expression still registered in Wrangler is ignored; an expression absent from the Mantle plan fails visibly. If the Worker also owns unrelated cron tasks, route those expressions in the application's `scheduled` export. Multiple Mantle Triggers may share one expression and run in Trigger-name order; all run even if an earlier one fails, then the event reports failure.
40
+
41
+ Handlers receive `ctx.schedule` with `id`, `trigger`, `cron`, and `scheduledTime` (Unix milliseconds). The stable ID is `${trigger}:${scheduledTime}`. The caller is always `user: null`, `staff: null`, with no credential metadata; normal Procedure guards still apply. Cloudflare executes cron events in UTC, but its Cron Trigger documentation does not promise automatic retries. Duplicate/manual replay is still possible, so use `ctx.schedule.id` as an idempotency key for writes. A failure rejects the scheduled event; exactly-once execution is not promised. Bun, Vercel, and ChatGPT Sites do not register schedules and reject enabled schedules at boot or generation.
42
+
43
+ Cloudflare's default D1 composition records each attempt under that stable run ID. The owner-only Developer Console shows declared schedules even before the first run, separately from recent observations; Wrangler registration is **not observed** by Core. Records include scheduled/start/finish times, status, attempt, duration, a diagnostic code or generic handler-error summary, and optional sweep counts. A started attempt with no finish record says **Completion not observed**, not success. Inputs, outputs, exception text, credentials and secrets are not stored. The default history retains 30 days, hides older rows on reads, and prunes them during later runs (at most once per day per runtime instance). If observation start fails, the Procedure is skipped and the scheduled event rejects; if recording completion fails, the event also rejects. Use the stable ID to make replay safe. If the host supplies custom storage without a durable observation store, the Console says **Unavailable**; it never reports a missing record as success.
44
+
25
45
  ## `http` source
26
46
 
27
47
  ```yaml
@@ -21,6 +21,86 @@ All eleven packages share a single version and are published together, so mixed
21
21
  versions across `@aotter/mantle*` are never a supported combination. Pin the
22
22
  version you install and upgrade the whole set at once.
23
23
 
24
+ ## 0.1.5 — in preparation
25
+
26
+ `mantle generate` now assembles a blank, editable full site by default for
27
+ Cloudflare Workers or ChatGPT Sites. `--features` positively selects a smaller
28
+ composition; Spec-only needs no host. The first run declares exact matching
29
+ dependencies, and a second run after installation completes the project.
30
+ Existing directly authored applications retain their compile path. Saved
31
+ choices and user-owned files survive reruns, while `--check` reports drift
32
+ without writing. On Sites, review and apply append-only D1 migrations before
33
+ running code that expects the new Schema. The new Sites worker trusts identity
34
+ only behind the Sites dispatcher and does not expose a separate `workers.dev`
35
+ URL.
36
+
37
+ Reviewed Sites unique-index tuple replacement can now generate an immutable
38
+ SQL migration with source/target fingerprints, checksum and an explicit report.
39
+ Local D1 duplicate preflight fails before writing files; production D1 still
40
+ enforces the new constraint when the reviewed migration is applied. Runtime-
41
+ managed CF boot continues to reject uniqueness changes without a reviewed
42
+ artifact path.
43
+
44
+ The owner-only Developer Console can inspect live Schema entries and run
45
+ declared Views on demand through guarded Admin routes. Its HTTP and MCP lists
46
+ link to the owning declarations. UI action placement is no longer shown as a
47
+ Procedure-to-Schema execution path; custom handlers and native SQL Views state
48
+ when their data relationships cannot be inferred from the Manifest.
49
+
50
+ Ref Procedures can now group create, update and delete operations across
51
+ Schemas with `ctx.writeAtomically`. D1 and Bun commit the group or roll it
52
+ back, including when the last conditional write finds a stale version. Other
53
+ adapters must explicitly implement the optional capability before using it.
54
+
55
+ Cloudflare Cron Triggers now target ordinary Procedures through `source.kind:
56
+ schedule`. The generated runtime plan records each schedule, while Wrangler
57
+ registration remains application-owned. Scheduled calls have no user or staff
58
+ authority, carry a stable retry key, and pass through Procedure validation and
59
+ authorization. D1-backed Workers retain owner-only run observations
60
+ for 30 days; the Console distinguishes a declaration from registration and
61
+ observed executions. Managed SQLite hosts must apply the append-only
62
+ `0007-schedule-run-observations` migration before boot. Other hosts do not
63
+ register schedules.
64
+
65
+ Schemas may declare a `ttl` date-time policy. D1 and Bun hide expired entries
66
+ from semantic reads and declarative Views before any deletion. Physical cleanup
67
+ is an explicit bounded sweep, previewed by default and resumable by cursor;
68
+ there is no automatic bulk deletion when a policy is introduced or shortened.
69
+ Native SQL Views and shared View caches are rejected for TTL Schemas because
70
+ they cannot guarantee the expiry boundary. Cloudflare public routes that can
71
+ include TTL content use `no-store` so a cached page cannot outlive its entries.
72
+
73
+ Agents installed through `npx skills add aotter/mantle` must still inspect the
74
+ target project's actual SDK version. Published 0.1.4 packages do **not**
75
+ support the new project flags; 0.1.5-alpha.1 does. Use the installed docs and
76
+ upgrade all selected packages together. The bootstrap skill remains a small directory,
77
+ not a repository clone.
78
+
79
+ ## 0.1.4 — 2026-09-24
80
+
81
+ 0.1.4 repairs the published consumer path without changing the Manifest
82
+ grammar. Pin every selected `@aotter/mantle*` package to `0.1.4`, refresh the
83
+ lockfile, then rerun `mantle generate` and `mantle skills` with their `--check`
84
+ commands. Read the handbook and skills from that installed version.
85
+
86
+ **ChatGPT Sites reference.** The 0.1.3 reference omitted the
87
+ `_mantle_boot_state.store_instance_id` column required by the runtime, which
88
+ could make deployed runtime routes return 500. The reference now adds the
89
+ append-only `drizzle/0003_store_instance_id.sql` migration. If your project
90
+ was copied from that reference, carry the new migration forward and apply
91
+ pending D1 migrations **before** deploying updated code; do not edit a
92
+ migration already applied. Repeated builds now clear `dist` so removed SQL
93
+ files cannot remain in the deployment artifact. The Sites guide also shows
94
+ how to mount an HTTP Trigger, identifies the browser and MCP owner workflows,
95
+ and names its integration chapter `docs/handbook/chatgpt-sites/`.
96
+
97
+ **Agent installation.** `npx skills add aotter/mantle` installs the small
98
+ `mantle` bootstrap skill; the installed npm package supplies version-matched
99
+ instructions and docs. The skill now checks the application's installed
100
+ version before reading them. Superseded Starter decisions are marked as
101
+ history: no `mantle-starters/v0.1.4` tag or `mantle create` command is needed
102
+ to author a new application.
103
+
24
104
  ## 0.1.3 — 2026-09-23
25
105
 
26
106
  0.1.3 tightens the contract between Manifests, generated TypeScript, agent
@@ -98,7 +178,7 @@ See [HTTP, MCP, CLI and packages](../reference/surface.md) for the full list.
98
178
  D1 and assets bindings, Better Auth 1.7 (social providers, email OTP, magic
99
179
  link, passkey), Admin, MCP, Web and R2 media uploads. The Bun and Vercel
100
180
  adapters are experimental, cover public Views and HTTP Triggers only, and leave
101
- authentication and CSRF to the host. [ChatGPT Sites](../sites/index.md) is a
181
+ authentication and CSRF to the host. [ChatGPT Sites](../chatgpt-sites/index.md) is a
102
182
  first-class integration with a runnable reference.
103
183
 
104
184
  **Agents.** `mantle skills` projects the installed package's skills into
@@ -21,15 +21,18 @@ current npm `latest` contains it.
21
21
  |---|---|---|
22
22
  | Understand what manifests can express | [Manifest feature reference](../reference/features.md) | A capability-to-field map across the four atoms. |
23
23
  | Validate manifests in an existing tool | [Spec-only adoption](../../spec-only-host-adoption.md) | Parse and link without Runtime, storage or a UI. |
24
+ | Bring Mantle into an existing application | [Integration skill](../../skills/integrate/SKILL.md) | Inspect the app and choose embedding, incremental replacement or rebuilding with data migration. |
24
25
  | Embed Runtime in an existing host | [Runtime and adapters](../concepts/runtime-and-adapters.md), then [typed queries](../guides/typed-queries.md) | Bind your storage and call the generated API. |
25
26
  | Build a local Cloudflare API | [Minimal Worker tutorial](./quickstart-worker.md) | A running public View and a verified HTTP response. |
26
27
  | Add a staff console | [Local Admin tutorial](./quickstart-admin.md) | Email OTP, Admin assets and a local human workflow. |
27
- | Build on ChatGPT Sites | [Sites integration](../sites/index.md) | Host-owned sign-in and deployment with Mantle content. |
28
+ | Build on ChatGPT Sites | [Sites integration](../chatgpt-sites/index.md) | Host-owned sign-in and deployment with Mantle content. |
28
29
  | Work through a coding agent | [Skill installation and handoff](../guides/agent-setup.md) | Bootstrap skill, pinned package, then project-local instructions. |
29
30
 
30
31
  Human authors can follow these pages directly; installing an agent skill is
31
- optional. Do not start with `mantle generate` in an empty directory: author the
32
- manifests and host first, then generate and validate.
32
+ optional. For a new app, install an exact SDK version and run
33
+ `mantle generate --host cf` or `--host chatgpt-sites`. The CLI assembles a blank
34
+ site by default; add your own Manifests after generation. Use explicit
35
+ `--features` for a smaller composition, including host-free Spec-only.
33
36
 
34
37
  ## Find the right kind of documentation
35
38