@aotter/mantle 0.2.1-alpha.2 → 0.2.1-alpha.3

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 (33) hide show
  1. package/README.md +16 -177
  2. package/dist/build/compiler.js +3 -3
  3. package/dist/infrastructure/help.js +1 -3
  4. package/dist/usecase/adminDescriptors.js +1 -1
  5. package/dist/usecase/generate.js +20 -4
  6. package/dist/usecase/rest.js +2 -4
  7. package/docs/examples/README.md +2 -2
  8. package/docs/examples/app-shell/README.md +1 -1
  9. package/docs/examples/app-shell/accept.mjs +12 -2
  10. package/docs/examples/app-shell/package.json +3 -3
  11. package/docs/handbook/cloudflare/authentication.md +1 -1
  12. package/docs/handbook/cloudflare/deploy-and-operate.md +20 -8
  13. package/docs/handbook/cloudflare/media-r2.md +31 -0
  14. package/docs/handbook/examples/hub.md +1 -1
  15. package/docs/handbook/guides/agent-setup.md +25 -67
  16. package/docs/handbook/guides/agent-workflow-acceptance.md +31 -4
  17. package/docs/handbook/guides/mcp-apps.md +3 -1
  18. package/docs/{skills/performance/SKILL.md → handbook/guides/performance.md} +53 -32
  19. package/docs/handbook/guides/size-and-startup.md +2 -2
  20. package/docs/handbook/guides/typed-queries.md +12 -0
  21. package/docs/handbook/navigation.json +4 -0
  22. package/docs/handbook/releases/index.md +54 -2
  23. package/docs/{upgrade-0.1-to-0.2.md → handbook/releases/upgrade-0.1-to-0.2.md} +13 -13
  24. package/docs/handbook/start/agents.md +25 -4
  25. package/docs/handbook/start/quickstart-worker.md +1 -1
  26. package/package.json +1 -1
  27. package/skills/README.md +7 -69
  28. package/skills/mantle/SKILL.md +15 -81
  29. package/docs/skills/develop/SKILL.md +0 -100
  30. package/docs/skills/integrate/SKILL.md +0 -51
  31. package/docs/skills/media-gc/SKILL.md +0 -109
  32. package/docs/skills/provision/SKILL.md +0 -44
  33. package/docs/skills/update/SKILL.md +0 -42
@@ -1,26 +1,21 @@
1
1
  ---
2
- name: performance
3
- description: Make an accepted Mantle 0.2 application fast — Lighthouse for app-authored pages, Worker cold start and first-load budgets, and backend reads and writes under realistic data volume with indexes and internal Views. Use right after independent acceptance converges, or when a user reports a slow page, first request or query.
4
- metadata:
5
- source: "@aotter/mantle"
6
- sourcePath: docs/skills/performance/SKILL.md
7
- applies_to: mantle 0.2
8
- projection: package
2
+ description: "After acceptance converges, or when something is slow: front end, cold start and backend load, each held to a target."
9
3
  ---
4
+ # Performance pass
10
5
 
11
- # Mantle Performance
12
-
13
- This skill sets direction: when to run, what to aim for, in what order and when
6
+ This page sets direction: when to run, what to aim for, in what order and when
14
7
  to stop. It names no tools or commands. Choose the measurement and repair
15
8
  methods that fit the application, its host and the tools available to you; the
16
9
  targets and rules below are what stay fixed.
17
10
 
18
11
  ## When to run
19
12
 
20
- - **After acceptance.** Once [independent acceptance](../../handbook/guides/agent-workflow-acceptance.md)
21
- reports CONVERGED for a new application or a feature, continue here before
22
- reporting done. Never optimize behavior that has not been accepted: after
23
- BLOCKED or UNVERIFIED, report that and stop.
13
+ - **After acceptance.** Run for every role and surface that
14
+ [independent acceptance](agent-workflow-acceptance.md)
15
+ reports CONVERGED for a new application or a feature, before reporting done.
16
+ Never optimize behavior that has not been accepted: report each BLOCKED or
17
+ UNVERIFIED role or surface as it is, with what it needs, and leave it out of
18
+ the pass. Stop without running only when no part is CONVERGED.
24
19
  - **On request.** When a user reports a slow page, slow first request or slow
25
20
  query, run only the part that covers it, then check the others it could affect.
26
21
 
@@ -40,6 +35,16 @@ skipped part with its reason.
40
35
  A change in one part can move another: an added index slows writes, a shared
41
36
  stylesheet or entry import affects every page. Re-measure what a repair can reach.
42
37
 
38
+ ## Propose the pass first
39
+
40
+ Before measuring, stop and give the user the plan, then wait for a go-ahead:
41
+
42
+ - the parts that run and the parts skipped, each with its reason (the table above);
43
+ - the test data for backend parts: rows per table (for example 1,000,000 RSVPs across 5,000 events and 20,000
44
+ members), its shape (owners, states, text length) and that it goes only into an isolated local database;
45
+ - the target for each part and the stop rule below;
46
+ - anything that needs the user, such as a deployment to measure real cold start.
47
+
43
48
  ## Front end
44
49
 
45
50
  **Target:** the highest Lighthouse performance score the page allows, with a
@@ -51,7 +56,7 @@ no regression in accessibility, SEO or best practices.
51
56
  (no compression or HTTP/2, a cold cache) and say which is which.
52
57
  - Measure pages behind sign-in (member pages, Admin) through the role's session
53
58
  URL that `pnpm accept` prints
54
- ([hand each role](../../handbook/guides/agent-workflow-acceptance.md#hand-each-role-to-its-evaluator)),
59
+ ([hand each role](agent-workflow-acceptance.md#hand-each-role-to-its-evaluator)),
55
60
  never by weakening sign-in.
56
61
  - Find the actual bottleneck before changing anything; a trace beats a guess.
57
62
  - Repair in this order: what blocks the first paint (render-blocking styles and
@@ -63,7 +68,7 @@ no regression in accessibility, SEO or best practices.
63
68
  without it. Never detect the measuring tool to serve it a different page.
64
69
  - After every change, prove nothing else moved: the page looks the same, links,
65
70
  forms and in-page anchors still work, and the
66
- [public-page checks](../../handbook/guides/public-pages.md#check-before-you-report-done)
71
+ [public-page checks](public-pages.md#check-before-you-report-done)
67
72
  still pass without JavaScript.
68
73
 
69
74
  ## Cold start
@@ -72,9 +77,9 @@ no regression in accessibility, SEO or best practices.
72
77
 
73
78
  - **Worker:** its startup graph imports only what every request needs; auth, MCP,
74
79
  Admin and rarely used routes load on the request that uses them
75
- ([size and startup](../../handbook/guides/size-and-startup.md)). On Workers the
80
+ ([size and startup](size-and-startup.md)). On Workers the
76
81
  startup graph is the entry chunk `mantle bundle` writes under `<outdir>/worker`
77
- plus the chunks it imports statically ([outputs](../../handbook/start/project-and-cli.md#outputs));
82
+ plus the chunks it imports statically ([outputs](../start/project-and-cli.md#outputs));
78
83
  anything behind a dynamic import is outside it. Report its size locally as the
79
84
  *Worker entry static graph*; measure the host's startup time only on
80
85
  a deployment the user has authorized, and keep it well under the host's limit
@@ -87,7 +92,7 @@ no regression in accessibility, SEO or best practices.
87
92
  not measure it. Report the whole *MCP App HTML document* as its own number: it
88
93
  also holds CSS and markup, so never compare it with this budget.
89
94
  - Use the one definition of each metric in
90
- [size metrics](../../handbook/guides/size-and-startup.md#size-metrics), with
95
+ [size metrics](size-and-startup.md#size-metrics), with
91
96
  its measurement. Where the SDK's own checks measure differently, that page says how.
92
97
  - An overrun is a finding to repair by splitting, not a budget to raise. Raise a
93
98
  budget only with the user's agreement and record why.
@@ -102,12 +107,12 @@ fast at a realistic volume, and no hot path scans a table that grows.
102
107
  text where fields allow it, and more than one page of results everywhere. Size
103
108
  the largest tables at 100,000 rows or 10 times the expected first-year volume,
104
109
  whichever is larger. Seed with SQL straight into that database, setting the
105
- native columns as [reserved entry columns](../../handbook/reference/schema.md#reserved-entry-columns)
110
+ native columns as [reserved entry columns](../reference/schema.md#reserved-entry-columns)
106
111
  describes: it is test data, not an application write.
107
112
  - **Load:** call every View and Procedure through the same callers and surfaces
108
113
  the application uses, as each role. The app's local test harness already
109
114
  starts it on a fresh database, signs each role in and calls routes and MCP
110
- tools as that role ([local HTTP checks](../../handbook/guides/local-testing.md#what-smoke-covers)).
115
+ tools as that role ([local HTTP checks](local-testing.md#what-smoke-covers)).
111
116
  Record typical and slow-tail latency and
112
117
  rows read, then run concurrent writers wherever contention matters. A business
113
118
  rule that breaks under concurrency (oversell, double approval, lost update) is
@@ -119,15 +124,15 @@ fast at a realistic volume, and no hot path scans a table that grows.
119
124
  query module under `generated/` against the seeded database; a full scan of a
120
125
  growing table is a finding.
121
126
  2. Add the index that serves it in the Schema's `indexes`
122
- ([indexes](../../handbook/reference/schema.md#indexes-checks-and-search))
123
- together with a native migration ([database changes](../develop/SKILL.md#database-changes)).
127
+ ([indexes](../reference/schema.md#indexes-checks-and-search))
128
+ together with a native migration ([database changes](../cloudflare/deploy-and-operate.md#install-and-change-schemas)).
124
129
  Index only what a measured query uses; every index costs writes. Paged Views
125
- and [Schema locks](../../handbook/reference/schema.md#locks) are index-proven
130
+ and [Schema locks](../reference/schema.md#locks) are index-proven
126
131
  already: generation refuses one no index serves.
127
132
  3. Move complex reads (joins, aggregates, OR, reuse) into an
128
- [internal View](../../handbook/guides/typed-queries.md#declare-an-internal-view),
129
- page with keysets ([results and paging](../../handbook/reference/view.md#results-and-paging)),
130
- and replace exact totals on hot paths ([search and totals](../../handbook/reference/view.md#search-and-totals)).
133
+ [internal View](typed-queries.md#declare-an-internal-view),
134
+ page with keysets ([results and paging](../reference/view.md#results-and-paging)),
135
+ and replace exact totals on hot paths ([search and totals](../reference/view.md#search-and-totals)).
131
136
  4. Re-measure reads and writes after each repair.
132
137
 
133
138
  ## Rules
@@ -139,17 +144,17 @@ fast at a realistic volume, and no hot path scans a table that grows.
139
144
  - Do not lower a target, shrink the seeded data or drop a slow case to pass.
140
145
  Report what is left instead.
141
146
  - Work locally. Deploying or measuring a deployment follows the
142
- [provision skill](../provision/SKILL.md) and needs the user's authorization.
143
- - After any repair, rerun the [local HTTP checks](../../handbook/guides/local-testing.md).
147
+ [deploy guide](../cloudflare/deploy-and-operate.md) and needs the user's authorization.
148
+ - After any repair, rerun the [local HTTP checks](local-testing.md).
144
149
  A repair that changes what a user sees or can do is no longer only a
145
150
  performance change: re-run acceptance for the scope the
146
- [re-verification rule](../../handbook/guides/agent-workflow-acceptance.md#re-verify-what-a-repair-touches)
151
+ [re-verification rule](agent-workflow-acceptance.md#re-verify-what-a-repair-touches)
147
152
  names. A changed View or Procedure widens it to every surface that reads or
148
153
  writes that data, and so does a `uniqueIndexes` entry. A non-unique
149
154
  `indexes` entry and its migration keep the business rules: run `pnpm check`,
150
155
  the local HTTP checks and your focused regressions, not acceptance.
151
156
  - Report app-added cost and SDK-existing cost separately. Built-in Admin has a
152
- recorded [baseline](../../handbook/guides/size-and-startup.md#native-admin-baselines)
157
+ recorded [baseline](size-and-startup.md#native-admin-baselines)
153
158
  per SDK version; while the installed version and Admin entry are unchanged,
154
159
  reuse it instead of repeating that experiment each round. Built-in Admin's
155
160
  page and MCP App both miss the first-load budget; that is SDK-existing cost,
@@ -160,10 +165,26 @@ fast at a realistic volume, and no hot path scans a table that grows.
160
165
  - Stop when every target is met, after three rounds, or when two rounds in a row
161
166
  bring no measurable gain.
162
167
 
168
+ ## Summarise for the user
169
+
170
+ Report each change with the number it moved, so the gain is visible:
171
+
172
+ ```markdown
173
+ | Part | Change | Before | After |
174
+ | --- | --- | --- | --- |
175
+ | Backend read: `event-roster`, 1,000,000 RSVPs | index `[eventId, created_at]` + keyset paging | p95 1,840 ms | p95 38 ms |
176
+ | Front end: `/events/{slug}` (mobile) | inline critical CSS, sized images | Lighthouse 71 | 94 |
177
+ | Cold start: Worker entry | auth and Admin behind dynamic imports | 212 KB gzip startup graph | 61 KB |
178
+ ```
179
+
180
+ Give the data volume beside every backend number, the device and throttling beside every Lighthouse score, and say
181
+ where a target is still missed and why.
182
+
163
183
  ## Report
164
184
 
165
185
  For each part: run or skipped (with the reason), the environment, before and
166
- after numbers as ranges, what changed and what is left. Close with one verdict
186
+ after numbers as ranges, what changed and what is left. Name the roles and
187
+ surfaces left out because acceptance did not converge on them. Close with one verdict
167
188
  beside the acceptance verdict: **PASS** (every target that applies is met),
168
189
  **PARTIAL** (improved, with the targets still missed and why) or **SKIPPED**
169
190
  (nothing applied).
@@ -10,7 +10,7 @@ Cloudflare startup_time_ms needs an actual upload/deployment; offline dry runs d
10
10
 
11
11
  ## Size metrics
12
12
 
13
- Three metrics, one definition each. The [performance skill](../../skills/performance/SKILL.md)
13
+ Three metrics, one definition each. The [performance pass](performance.md)
14
14
  and the SDK's own checks use these names. Measure the production build that
15
15
  `mantle bundle` writes, never a dev server.
16
16
 
@@ -25,7 +25,7 @@ report it.
25
25
  | MCP App HTML document | The whole built App document as served: its inline JavaScript, CSS and markup in one file. | raw bytes and gzip of the file |
26
26
  | Worker entry static graph | The Worker entry (Wrangler's `main`, such as `dist/worker/worker.js`) plus every chunk it imports statically, recursively. A dynamic `import()` is not followed. | gzip per file; raw bytes beside it |
27
27
 
28
- The 100 KB budget in the performance skill is first-load JavaScript. It applies to
28
+ The 100 KB budget in the [performance pass](performance.md) is first-load JavaScript. It applies to
29
29
  an MCP App too: `mantle bundle` builds the App as one HTML file with its
30
30
  JavaScript inline, so its first-load JavaScript is its inline script text. The
31
31
  MCP App HTML document also holds CSS and markup, so do not compare the document
@@ -11,6 +11,18 @@ description: Choose Store for writes and simple lookups; declare internal Views
11
11
 
12
12
  Never write raw SQL to Mantle collections: it bypasses scope, TTL, publishing and system-column rules. The Store applies row rules but does not check a View's or Procedure's `requires`; authorize your handler before using it.
13
13
 
14
+ ## Adopt Mantle in an existing application
15
+
16
+ Keep the application's router, database handle, identity and frontend; declare only the Schemas and operations you
17
+ adopt and import their `views/<encoded-name>.ts` or `procedures/<encoded-name>.ts`. Bun.SQL and postgres.js fit
18
+ directly; node-postgres needs an [adapter](postgres-adapters.md). Resolve one verified Caller per request, with the
19
+ shared cookie-session origin check on writes ([authentication](../cloudflare/authentication.md)). No Admin, auth or
20
+ surface module is required for direct queries.
21
+
22
+ Existing tables need an explicit migration into the declared storage shape, including system columns and constraints;
23
+ never apply the initial `schema.sql` over an occupied database. Rehearse the migration on a copy, keep a rollback, and
24
+ test scope, TTL, publication, OCC and persisted state with the application's own identity and tests.
25
+
14
26
  ## Declare an internal View
15
27
 
16
28
  Save this as `manifests/tickets.yaml`:
@@ -84,6 +84,10 @@
84
84
  {
85
85
  "text": "Size and startup",
86
86
  "link": "/guides/size-and-startup"
87
+ },
88
+ {
89
+ "text": "Performance pass",
90
+ "link": "/guides/performance"
87
91
  }
88
92
  ]
89
93
  },
@@ -15,6 +15,23 @@ From 0.2.0-alpha.7, Mantle publishes three packages together at one version:
15
15
  and `@aotter/mantle-admin` (optional Admin server, SPA and MCP App).
16
16
  Pin every package you use to the same exact version and upgrade them together.
17
17
 
18
+ ## Upgrade an application
19
+
20
+ 1. Pin every Mantle package to the same exact published version; never follow a dist-tag. Read every release section
21
+ between your version and the target, including its breaking changes.
22
+ 2. Regenerate with the project's own command and review the emitted TypeScript, SQL and policy diffs. A schema change
23
+ needs a data-preserving migration written with the host's tool and rehearsed on a copy
24
+ ([Install and change schemas](../cloudflare/deploy-and-operate.md#install-and-change-schemas)); the initial
25
+ `schema.sql` never rebuilds production tables.
26
+ 3. Keep users, sessions, content and application code. Follow [Customising Admin](../guides/native-admin.md#customising-admin)
27
+ for the application-built Admin; old UI subpaths have no aliases.
28
+ 4. Re-run the project's checks, member and Admin OTP, affected REST/MCP/Admin routes, private-field visibility, OCC and
29
+ unknown outcomes, then [acceptance](../guides/agent-workflow-acceptance.md) before an authorized cutover. Updating a
30
+ dependency never publishes a package.
31
+
32
+ From 0.1.x, follow [Upgrade 0.1 to 0.2](upgrade-0.1-to-0.2.md) instead: a new database, a reviewed and rehearsed data
33
+ move, and never booting 0.2 against a 0.1.x database.
34
+
18
35
  ## 0.2.1 — in preparation
19
36
 
20
37
  0.2.1 adds Schema locks: a manifest rule that refuses a row's update or delete
@@ -33,6 +50,41 @@ and interactive transactions can use `store.batch` for atomic multi-writes, and
33
50
  `mantle bundle` under `wrangler dev` reports stale generated output in one line
34
51
  instead of a failed build.
35
52
 
53
+ ### Upgrading to 0.2.1-alpha.3
54
+
55
+ - **Agent guidance has one home, the handbook.** The package no longer ships `docs/skills/`, so the `mantle help
56
+ skills/<name>` topics are gone. Their guidance is now in handbook pages:
57
+ [performance pass](../guides/performance.md),
58
+ [deploy and operate](../cloudflare/deploy-and-operate.md),
59
+ [cleaning up stale uploads](../cloudflare/media-r2.md#clean-up-stale-uploads),
60
+ [upgrading an application](#upgrade-an-application) and
61
+ [adoption in an existing app](../guides/typed-queries.md#adopt-mantle-in-an-existing-application).
62
+ `mantle help` reaches all of them from the entry page.
63
+ - **The `mantle` skill no longer depends on the SDK version.** It routes to `mantle help`, so
64
+ `npx skills add aotter/mantle@mantle` no longer needs a release tag. A skill installed from an earlier tag still
65
+ names `docs/skills/` paths; reinstall it.
66
+ - **Docs moves.** The 0.1 → 0.2 upgrade guide is now the topic `mantle help upgrade-0.1-to-0.2`. The package README is
67
+ an index of topics.
68
+ - **The agent workflow checks in with the user.** Once the manifests generate, `pnpm accept --open` opens the Developer
69
+ UI (`/admin/dev`) so the user can see the wiring. The agent then stops twice with a plan: before acceptance and
70
+ before the performance pass. It finishes with an acceptance summary and a before → after performance summary
71
+ ([agents](../start/agents.md)).
72
+
73
+ Regenerate to pick up the rest of this release. No manifest or API changes:
74
+
75
+ - **Developer UI diagrams.**
76
+ - The data model is a real ER diagram: keys, types and crow's-foot cardinality, with three display modes.
77
+ - System wiring is laid out in columns, with a minimap.
78
+ - A Procedure's logic is one graph, the same in the wiring side panel and on the Procedure page: a transaction box,
79
+ CASE as ordered branch rows, and COMMIT and ROLLBACK ends. The SQL syntax trees stay available, folded, on the
80
+ Procedure page.
81
+ - Their wording is translated in every Admin language that has translations.
82
+ - **Smaller startup.**
83
+ - Generated Workers emit a repeated SQL statement once. REST loads a Procedure on its first request, the way views and
84
+ MCP already did. The reference D1 Worker's startup is about 20% smaller.
85
+ - Admin loads sign-in, OAuth consent and the collection list on demand.
86
+ - The Admin MCP App uses native select and popover controls.
87
+
36
88
  ### Upgrading to 0.2.1-alpha.2
37
89
 
38
90
  Pin the selected packages to `0.2.1-alpha.2` and regenerate. Breaking change:
@@ -99,7 +151,7 @@ and deployment; selected REST, MCP, public pages, publishing, translations and
99
151
  media compose around the generated operations.
100
152
 
101
153
  This is a breaking upgrade from 0.1.x: follow the [0.1-to-0.2 migration
102
- guide](../../upgrade-0.1-to-0.2.md), use a new 0.2 database and explicitly move
154
+ guide](upgrade-0.1-to-0.2.md), use a new 0.2 database and explicitly move
103
155
  data. From alpha.11, pin the three selected packages to 0.2.0, regenerate and
104
156
  review owned output; the stable version commit changes release metadata and
105
157
  documentation rather than adding another runtime API.
@@ -216,7 +268,7 @@ the native migration above supersede their runtime and CLI instructions.
216
268
 
217
269
  0.2.0 replaces 0.1.x's grammar and composition; no stable 0.1.5 was released
218
270
  (`0.1.5-alpha.1` was a prerelease). It breaks every consumer, and
219
- `docs/upgrade-0.1-to-0.2.md` in the package is the guide for moving a project
271
+ `mantle help upgrade-0.1-to-0.2` is the guide for moving a project
220
272
  by hand.
221
273
 
222
274
  - **Manifests are `cms.mantle.aotter.net/v2`.** Views are one SQL `SELECT` and
@@ -5,11 +5,11 @@ migration tool and no in-place upgrade of a 0.1.x database: a coding agent
5
5
  rebuilds the project on 0.2.0 and plans a reviewed data move for it.
6
6
 
7
7
  1. **Rebuild the project on 0.2.0** with the current handbook: the
8
- [0.2.0 release notes](handbook/releases/index.md#upgrading-to-020) and the
9
- [native SDK migration](handbook/releases/index.md#native-sdk-migration-alpha7),
10
- the [CLI and generated ownership](handbook/start/project-and-cli.md), the
11
- [app shell](examples/app-shell/) and the [Schema](handbook/reference/schema.md),
12
- [View](handbook/reference/view.md) and [Procedure](handbook/reference/procedure.md)
8
+ [0.2.0 release notes](index.md#upgrading-to-020) and the
9
+ [native SDK migration](index.md#native-sdk-migration-alpha7),
10
+ the [CLI and generated ownership](../start/project-and-cli.md), the
11
+ [app shell](../../examples/app-shell/) and the [Schema](../reference/schema.md),
12
+ [View](../reference/view.md) and [Procedure](../reference/procedure.md)
13
13
  references. The application owns routing, Auth, native handles and database
14
14
  migrations. Install the same exact version of `@aotter/mantle`,
15
15
  `@aotter/mantle-ui` and, when selecting Admin, `@aotter/mantle-admin`.
@@ -44,18 +44,18 @@ for human review before it touches production data.
44
44
 
45
45
  - **Through the SDK.** The generated `store(db, caller)`, or `ctx.store` in a
46
46
  `ref` handler, with a trusted caller such as `{ kind: "system", reason }`
47
- ([authorization](handbook/concepts/authorization.md)). It accepts no value
47
+ ([authorization](../concepts/authorization.md)). It accepts no value
48
48
  for `id`, `version`, `created_at`, `updated_at`, `author_id`, `status`,
49
49
  `published_at` or the scope column, for any caller: it sets them itself, so new IDs, versions,
50
50
  timestamps and authors replace the old ones. Publishing goes through the
51
51
  generated `<schema>.publish` Procedure, which sets `published_at` to now
52
- ([lifecycle](handbook/concepts/lifecycle-and-locales.md)). With new IDs,
52
+ ([lifecycle](../concepts/lifecycle-and-locales.md)). With new IDs,
53
53
  remap every `x-mantle-ref`, every `translates.on` key and any ID embedded
54
54
  in JSON; `x-mantle-ref` is not a foreign key, so a missed one dangles
55
55
  quietly.
56
56
  - **Through SQL**, to keep IDs, history and authors: `INSERT` the rows with
57
57
  every native column set, as
58
- [reserved entry columns](handbook/reference/schema.md#reserved-entry-columns)
58
+ [reserved entry columns](../reference/schema.md#reserved-entry-columns)
59
59
  lists. This bypasses row policy, so review it like a migration.
60
60
 
61
61
  ### Entry columns on D1
@@ -86,7 +86,7 @@ for human review before it touches production data.
86
86
 
87
87
  0.1.4 used Better Auth 1.7.2 with hand-written DDL; 0.2.0 uses 1.7.7, with the
88
88
  tables `mantle generate --auth src/auth.ts` adds to `schema.sql`
89
- ([auth](handbook/cloudflare/authentication.md)).
89
+ ([auth](../cloudflare/authentication.md)).
90
90
 
91
91
  - The 0.2 caller subject is the Better Auth `user.id`. Keep user IDs, so that
92
92
  `author_id` and owner scopes still name the right people.
@@ -97,13 +97,13 @@ tables `mantle generate --auth src/auth.ts` adds to `schema.sql`
97
97
  - 0.1.4 roles `owner`, `editor` and `contributor` have no 0.2 meaning. The
98
98
  admin layer is Better Auth's admin plugin `adminRoles` (default
99
99
  `["admin"]`) and `adminUserIds`
100
- ([authorization](handbook/reference/authorization.md)); decide each mapping
100
+ ([authorization](../reference/authorization.md)); decide each mapping
101
101
  deliberately.
102
102
  - A 0.1.4 `githubLogin` column must be declared in `user.additionalFields`
103
103
  to keep it.
104
104
  - Leave sessions, verification rows and OAuth tokens behind; users sign in
105
105
  again. Mantle re-creates its OAuth resource rows from configuration
106
- ([OAuth](handbook/guides/oauth.md)). Check `jwks`, OAuth clients and
106
+ ([OAuth](../guides/oauth.md)). Check `jwks`, OAuth clients and
107
107
  consents against Better Auth 1.7.7 and your secrets and URLs before copying
108
108
  any.
109
109
  - The admin MCP endpoint moved from `/mcp/staff` to `/mcp/admin`; update MCP
@@ -115,7 +115,7 @@ tables `mantle generate --auth src/auth.ts` adds to `schema.sql`
115
115
  epoch **milliseconds**. Copy the rows as they are.
116
116
  - Each variant keeps its stored `storageKey` and `publicUrl`, so 0.1.x objects
117
117
  in the same bucket keep working while their prefixes stay served
118
- ([media](handbook/cloudflare/media-r2.md)).
118
+ ([media](../cloudflare/media-r2.md)).
119
119
  - Do not carry over `pending_media_uploads`; an upload expires after 15
120
120
  minutes.
121
121
  - `site_config` keeps its `key`/`value` columns; compare its keys with the
@@ -256,7 +256,7 @@ Schema reference; do not repeat them.
256
256
  | 0.1.x | 0.2.0 |
257
257
  |---|---|
258
258
  | builtin `create` | `handler: { sql: "INSERT INTO s (a, b) VALUES (input.a, input.b) RETURNING id" }` (on a `publishing` Schema the row starts as a draft, as before) |
259
- | builtin `update` (always version-checked, merges over the stored row) | `UPDATE s SET a = COALESCE(input.a, a), … WHERE id = input.id AND version = input.expectedVersion`. Keep both: without the version the lock is lost; without `COALESCE` an omitted optional field is cleared. `COALESCE` also means `null` cannot clear a field; give clearing its own flag input ([clear flag](handbook/guides/sql-patterns.md#change-only-the-fields-given-coalesce), [leave out, replace or clear](handbook/guides/native-admin.md#leave-out-replace-or-clear)) |
259
+ | builtin `update` (always version-checked, merges over the stored row) | `UPDATE s SET a = COALESCE(input.a, a), … WHERE id = input.id AND version = input.expectedVersion`. Keep both: without the version the lock is lost; without `COALESCE` an omitted optional field is cleared. `COALESCE` also means `null` cannot clear a field; give clearing its own flag input ([clear flag](../guides/sql-patterns.md#change-only-the-fields-given-coalesce), [leave out, replace or clear](../guides/native-admin.md#leave-out-replace-or-clear)) |
260
260
  | builtin `upsert` with `match` | `INSERT … ON CONFLICT (<match columns>) DO UPDATE SET x = EXCLUDED.x`; the conflict columns are a unique index; on a scoped Schema the scope field may be named or left out, Store adds it |
261
261
  | builtin `delete` | `DELETE FROM s WHERE id = input.id AND version = input.expectedVersion` |
262
262
  | builtin `archive` | a `ref` handler: `ctx.store.write([{ update: "s", set: { status: "archived" }, where: { id }, lock: expectedVersion }])` (SQL cannot set `status`) |
@@ -7,12 +7,14 @@ description: "The entry point `mantle help` prints first: choose a complete app
7
7
  Topics are the handbook paths below (for example `guides/native-admin`) or their last segment when unique (`native-admin`).
8
8
  The installed package's `docs/` is the source of every topic, so the text always matches the installed version.
9
9
 
10
+ Node 22.22 or newer. Pin every `@aotter/mantle*` package to one exact version.
11
+
10
12
  ## Choose how much Mantle owns
11
13
 
12
14
  | You want | Do |
13
15
  | --- | --- |
14
16
  | A complete application | `mantle init [directory]`, then follow its `README.md`. It writes the app shell once: Better Auth email OTP with `admin` and `user`, the Admin console, MCP for both roles, REST, and a member `/sign-in` page. Existing files stop it; `--dry-run` lists what it would write. |
15
- | Only typed SQL and bindings inside an app you already have | Skip `init`. Write manifests and run `mantle generate <target> <output-directory> <manifest>...`; see `mantle help project-and-cli` and `mantle help typed-queries`. |
17
+ | Only typed SQL and bindings inside an app you already have | Skip `init`. Write manifests and run `mantle generate <target> <output-directory> <manifest>...`; see `mantle help project-and-cli` and [adopting Mantle in an existing app](../guides/typed-queries.md#adopt-mantle-in-an-existing-application). |
16
18
 
17
19
  `init` writes the `cloudflare-d1` shell, the default target. `bun-sqlite`, `bun-postgres` and `cloudflare-postgres`
18
20
  generate the same bindings; their app entry is yours (`mantle help service-entry`).
@@ -36,14 +38,33 @@ the app entry (`--entry`) never imports, it warns and names the topic that shows
36
38
  canonical and Open Graph tags, JSON-LD and an answer block on detail pages, Markdown alternates, `/sitemap.xml`,
37
39
  `/robots.txt` and `/llms.txt`. A brief that names a site, shop or catalogue for visitors includes all of them.
38
40
  4. `pnpm generate`, implement every handler it lists, `pnpm check`, then `pnpm smoke`.
39
- 5. Before reporting the app or a feature done, run [role-only acceptance](../guides/agent-workflow-acceptance.md)
41
+ 5. **Show the user the wiring.** As soon as the manifests generate, run `pnpm accept --open`: it starts the app,
42
+ signs the admin in without a one-time code and opens the Developer UI (`/admin/dev`) in the user's browser, showing
43
+ the Schemas, Views, Procedures and Triggers and how they connect, with each surface's routes and tools. Tell the user
44
+ what they are looking at. Keep building while they look; the app rebuilds on every change. Without a browser on the
45
+ machine, give the user the admin URL it prints.
46
+ 6. **Stop and ask before acceptance.** Propose the [acceptance plan](../guides/agent-workflow-acceptance.md#propose-the-run-first)
47
+ and wait for the user's go-ahead. Then run [role-only acceptance](../guides/agent-workflow-acceptance.md)
40
48
  (`mantle help agent-workflow-acceptance`). Scripted smoke is not acceptance. `pnpm accept` starts the app and hands
41
49
  each role to a fresh evaluator as a URL that carries that role's session. After a repair, the guide's
42
50
  [re-verification rule](../guides/agent-workflow-acceptance.md#re-verify-what-a-repair-touches) decides which roles
43
51
  and surfaces run again.
44
- 6. Once acceptance converges, follow the [performance skill](../../skills/performance/SKILL.md): it decides which of
45
- front end (Lighthouse), cold start and backend load apply, and holds each to a target before you report done.
52
+ 7. **Stop and ask before the performance pass.** For every role and surface acceptance reports CONVERGED, propose the
53
+ [performance plan](../guides/performance.md#propose-the-pass-first) (which parts run, how much test data, which
54
+ targets) and wait for the go-ahead; then run the [performance pass](../guides/performance.md). BLOCKED or UNVERIFIED
55
+ parts are reported as they are, never optimized. A declined step is reported as not run, never as done.
56
+ 8. **Report what changed, not only that it passed:** the [acceptance summary](../guides/agent-workflow-acceptance.md#summarise-for-the-user)
57
+ and the [performance summary](../guides/performance.md#summarise-for-the-user), then the layered status.
46
58
 
47
59
  The first verified sign-in with `ADMIN_EMAIL` becomes the admin. Further administrators are added in Admin:
48
60
  **More → Administrators** invites by email, and **More → Members** grants Admin to an existing member.
49
61
  [Authentication](../cloudflare/authentication.md#identity-helpers) documents the same operations as an API.
62
+
63
+ ## Other tasks
64
+
65
+ | Task | Read |
66
+ | --- | --- |
67
+ | Upgrade Mantle | [Upgrade an application](../releases/index.md#upgrade-an-application) |
68
+ | Deploy, only when the user asks | [Deploy and operate](../cloudflare/deploy-and-operate.md) |
69
+ | A slow page, first request or query | [Performance pass](../guides/performance.md) |
70
+ | Stale media uploads, only when the user asks | [Clean up stale uploads](../cloudflare/media-r2.md#clean-up-stale-uploads) |
@@ -3,7 +3,7 @@ description: Generate a small native D1 service and mount an application-owned W
3
3
  ---
4
4
  # Quickstart: a service on Workers
5
5
 
6
- Create an application outside the SDK checkout. Install `@aotter/mantle@0.2.1-alpha.2` exactly (a prerelease; stable 0.2.0 has its own tagged handbook), TypeScript, Wrangler and Cloudflare Worker types; `node_modules/@aotter/mantle/docs/examples/app-shell/package.json` lists the versions this release is tested with. Read that installed version's handbook; this page describes the native 0.2 contract.
6
+ Create an application outside the SDK checkout. Install one exact `@aotter/mantle` version ([Releases](../releases/index.md)), TypeScript, Wrangler and Cloudflare Worker types; `node_modules/@aotter/mantle/docs/examples/app-shell/package.json` lists the versions this release is tested with. Read that installed version's handbook; this page describes the native 0.2 contract.
7
7
 
8
8
  Save `manifests/tickets.yaml`:
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aotter/mantle",
3
- "version": "0.2.1-alpha.2",
3
+ "version": "0.2.1-alpha.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "engines": {
package/skills/README.md CHANGED
@@ -1,71 +1,9 @@
1
- # SKILL.md briefs (mantle)
1
+ # Mantle agent skill
2
2
 
3
- Agent-readable skills for consumers of `@aotter/mantle` 0.2. There are two
4
- distributions (ADR-0032 decision 13):
3
+ [`mantle`](mantle/SKILL.md) is the one consumer skill, shipped by the plugins and by `npx skills add aotter/mantle@mantle`.
4
+ Installation: [agent setup](../docs/handbook/guides/agent-setup.md).
5
5
 
6
- - **The plugin** ships one OSS authoring skill, [`mantle`](mantle/SKILL.md),
7
- without a hosted-service MCP connection or transport.
8
- - **The npm package** ships the workflow skills under `docs/skills/`. An agent
9
- reads them from `node_modules/@aotter/mantle/docs/skills/`, matched to the
10
- installed version. Nothing copies them into a project; 0.2 has no
11
- `mantle skills` command.
12
-
13
- | Skill | When to invoke |
14
- |---|---|
15
- | [`mantle`](mantle/SKILL.md) | Create or continue a Mantle application and deploy to a user-owned host. |
16
- | [`develop`](../docs/skills/develop/SKILL.md) | Change manifests, SQL, handlers, the service entry or surfaces of an existing project. |
17
- | [`integrate`](../docs/skills/integrate/SKILL.md) | Add Mantle to an application that has its own code, users or data, or rebuild one and migrate. |
18
- | [`update`](../docs/skills/update/SKILL.md) | Upgrade `@aotter/mantle`, including from 0.1.x. |
19
- | [`provision`](../docs/skills/provision/SKILL.md) | Ship to Cloudflare Workers or ChatGPT Sites with production sign-in. |
20
- | [`media-gc`](../docs/skills/media-gc/SKILL.md) | Audit or remove stale, uncommitted R2 uploads. |
21
- | [`performance`](../docs/skills/performance/SKILL.md) | Make an accepted app fast: Lighthouse, cold start, backend load, indexes and Views. Runs after acceptance converges. |
22
-
23
- ## Install
24
-
25
- Use the [agent setup guide](../docs/handbook/guides/agent-setup.md) for Codex,
26
- Claude Code, Cursor and GitHub Copilot. Pin the plugin checkout to the same
27
- release tag as the application's SDK; alpha releases on `develop` can be newer
28
- than the default `main` branch. For a skill-only installation:
29
-
30
- ```sh
31
- npx skills add aotter/mantle@mantle
32
- ```
33
-
34
- Without a version it follows `main`, the latest stable release; pin the SDK's
35
- release tag with `npx skills add aotter/mantle#v0.2.1-alpha.2@mantle`.
36
- The explicit skill name (`@mantle`) excludes repository maintainer skills. The manifests
37
- are generated by `scripts/sync-plugin-manifests.mjs` and checked with `--check`.
38
- When upgrading, update the marketplace ref or local tagged checkout and refresh
39
- the plugin. Verify the loaded manifest version; Claude Code's plugin version
40
- is Core's, so packaged skill changes reach users through the next Core release.
41
-
42
- ## Disclosure audit
43
-
44
- Every skill is one `SKILL.md`; the plugin skill carries local acceptance references.
45
- `scripts/check-skills.mjs` holds this table, the front matter and the links to
46
- each other: `metadata.projection` is `plugin` for `skills/mantle` and
47
- `package` for `docs/skills/*`, a reason in the last column must equal
48
- `metadata.projectionReason`, and a relative link must stay inside what ships
49
- (the skill's own directory for the plugin, `docs/` for the package).
50
-
51
- | Skill | Routes on | Entry constraints | Distribution | Restricted because |
52
- |---|---|---|---|---|
53
- | `mantle` | new project, existing project, self-host deployment | the installed package's docs win; never use the SDK checkout as the application; no deploy during a cold start | plugin | The plugin's authoring entry skill is installed from the repository; workflow documentation comes from the installed SDK package. |
54
- | `develop` | manifest, SQL, handler, service or surface work | read the installed version first; never edit generated files; writes through Store/Procedures, richer reads through internal Views | package | — |
55
- | `integrate` | an application with its own code, users or data | inspect before choosing; the application keeps its users; one writer per table | package | — |
56
- | `update` | an SDK upgrade | never overwrite application files; 0.1.x moves by the upgrade guide to a new database | package | — |
57
- | `provision` | ship to production | secrets never in source, chat or logs; a new database for 0.2; self-hosting is always an option | package | Creates remote resources and handles production secrets; opt-in only. |
58
- | `media-gc` | stale R2 uploads | audit by default; exact keys only, never a prefix delete; re-audit before applying | package | Destructive remote object deletion and Cloudflare-specific; opt-in only. |
59
- | `performance` | converged acceptance, a slow page, first request or query | accepted behavior only; never trade scope, authorization, OCC or atomicity for speed; local unless deployment is authorized | package | — |
60
-
61
- ## Audience
62
-
63
- These are for **AI agents acting for consumers of Mantle**, not for
64
- contributors to the SDK, who read the repository's `CONTRIBUTING.md`.
65
-
66
- ## Conventions
67
-
68
- Each SKILL.md has front matter (`name`, a trigger-complete `description`,
69
- `metadata.source`, `sourcePath`, `applies_to`, `projection`), the reads to do
70
- first, concrete commands, the rules an agent must not break, and what to report
71
- when done. Commands and prose match the package version that carries the skill.
6
+ The skill only routes to `mantle help`, which prints the installed package's handbook. It holds no contract, version
7
+ number or workflow detail of its own, so it never drifts from the SDK an application pins: put any rule an agent must
8
+ follow in the handbook instead. `scripts/check-skills.mjs` enforces that this is the only skill, its front matter, a
9
+ line budget, no version strings, and that every `mantle help <topic>` it names exists.