@aotter/mantle 0.2.0 → 0.2.1-alpha.2
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.
- package/README.md +6 -2
- package/dist/build/compiler.d.ts +6 -6
- package/dist/build/compiler.js +6 -3
- package/dist/build/spec/domain/model/ManifestGrammar.d.ts +39 -1
- package/dist/build/spec/domain/model/RuntimePlan.d.ts +16 -3
- package/dist/build/spec/domain/model/SqlIr.d.ts +30 -0
- package/dist/build/spec/kernel/diagnostic.d.ts +1 -1
- package/dist/domain/describe/chunk-CW7X5Q5T.js +1 -0
- package/dist/domain/describe/index.d.ts +1 -0
- package/dist/domain/describe/index.js +1 -1
- package/dist/domain/describe/match.d.ts +19 -0
- package/dist/domain/describe/public.d.ts +3 -0
- package/dist/domain/describe/public.js +1 -0
- package/dist/infrastructure/adminEntries.js +19 -3
- package/dist/infrastructure/bundle.js +43 -8
- package/dist/infrastructure/cli.js +1 -1
- package/dist/infrastructure/generate.js +17 -3
- package/dist/kernel/binds.d.ts +18 -3
- package/dist/kernel/binds.js +1 -1
- package/dist/kernel/contracts.d.ts +7 -0
- package/dist/kernel/contracts.js +9 -0
- package/dist/kernel/driver/bun-sqlite.js +3 -3
- package/dist/kernel/driver/d1.d.ts +1 -1
- package/dist/kernel/driver/d1.js +6 -3
- package/dist/kernel/driver/postgres.d.ts +2 -1
- package/dist/kernel/driver/postgres.js +11 -6
- package/dist/kernel/mcp-apps.d.ts +3 -2
- package/dist/kernel/mcp-apps.js +7 -2
- package/dist/kernel/mcp-handler.js +22 -9
- package/dist/kernel/mcp.d.ts +18 -0
- package/dist/kernel/mcp.js +1 -0
- package/dist/kernel/rest-router.js +3 -5
- package/dist/kernel/rest.d.ts +2 -1
- package/dist/kernel/rest.js +1 -0
- package/dist/kernel/route-pattern.d.ts +26 -0
- package/dist/kernel/route-pattern.js +34 -0
- package/dist/kernel/store.d.ts +15 -1
- package/dist/kernel/store.js +51 -18
- package/dist/usecase/adminBindings.js +2 -2
- package/dist/usecase/adminClient.js +4 -1
- package/dist/usecase/generate.js +7 -5
- package/dist/usecase/handlers.js +1 -1
- package/dist/usecase/publishing.js +20 -7
- package/dist/usecase/rest.js +5 -5
- package/dist/usecase/stores.js +8 -3
- package/docs/examples/README.md +1 -1
- package/docs/examples/app-shell/README.md +58 -10
- package/docs/examples/app-shell/package.json +6 -6
- package/docs/examples/club-events/manifests/club-events.yaml +2 -0
- package/docs/examples/generated-web/seed.sql +5 -4
- package/docs/examples/purchasing/manifests/purchasing.yaml +3 -0
- package/docs/handbook/cloudflare/media-r2.md +6 -3
- package/docs/handbook/cloudflare/service-entry.md +2 -0
- package/docs/handbook/concepts/lifecycle-and-locales.md +21 -1
- package/docs/handbook/examples/hub.md +1 -1
- package/docs/handbook/guides/admin-ui.md +1 -1
- package/docs/handbook/guides/agent-setup.md +13 -8
- package/docs/handbook/guides/agent-workflow-acceptance.md +129 -19
- package/docs/handbook/guides/local-testing.md +50 -5
- package/docs/handbook/guides/mcp-apps.md +40 -0
- package/docs/handbook/guides/native-admin.md +218 -11
- package/docs/handbook/guides/native-execution.md +5 -4
- package/docs/handbook/guides/revisions.md +584 -0
- package/docs/handbook/guides/size-and-startup.md +140 -0
- package/docs/handbook/guides/sql-patterns.md +47 -1
- package/docs/handbook/guides/typed-queries.md +8 -3
- package/docs/handbook/navigation.json +4 -0
- package/docs/handbook/reference/authorization.md +2 -0
- package/docs/handbook/reference/describe.md +56 -4
- package/docs/handbook/reference/diagnostics.md +12 -3
- package/docs/handbook/reference/procedure.md +4 -4
- package/docs/handbook/reference/schema.md +71 -7
- package/docs/handbook/reference/sql.md +2 -1
- package/docs/handbook/reference/surface.md +13 -2
- package/docs/handbook/reference/trigger.md +12 -0
- package/docs/handbook/releases/index.md +75 -1
- package/docs/handbook/start/agents.md +6 -2
- package/docs/handbook/start/project-and-cli.md +4 -0
- package/docs/handbook/start/quickstart-worker.md +1 -1
- package/docs/skills/develop/SKILL.md +15 -3
- package/docs/skills/integrate/SKILL.md +3 -1
- package/docs/skills/performance/SKILL.md +169 -0
- package/docs/skills/update/SKILL.md +9 -5
- package/docs/upgrade-0.1-to-0.2.md +151 -39
- package/package.json +10 -11
- package/skills/README.md +6 -2
- package/skills/mantle/SKILL.md +19 -5
- package/dist/domain/describe/chunk-SGMRVDGE.js +0 -1
- package/dist/domain/describe/target-hash.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Every Mantle release line — what 0.2.
|
|
2
|
+
description: Every Mantle release line — what 0.2.x changes, and what each stable 0.1.x release contained.
|
|
3
3
|
---
|
|
4
4
|
# Releases
|
|
5
5
|
|
|
@@ -15,6 +15,80 @@ 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
|
+
## 0.2.1 — in preparation
|
|
19
|
+
|
|
20
|
+
0.2.1 adds Schema locks: a manifest rule that refuses a row's update or delete
|
|
21
|
+
for every caller path (REST, MCP, Admin and Procedures), with Admin showing the
|
|
22
|
+
lock before an edit. `spec.publishing.liveEdits` lets an application edit a
|
|
23
|
+
published row in place, and the [revisions guide](../guides/revisions.md) now
|
|
24
|
+
freezes the live revision with a lock and switches it atomically. It also brings
|
|
25
|
+
Admin form and refresh fixes, the media picker for custom inputs and pages
|
|
26
|
+
(`@aotter/mantle-admin/media`), `matchTarget` in `@aotter/mantle/describe`, and
|
|
27
|
+
dependency updates for current advisories.
|
|
28
|
+
|
|
29
|
+
Procedures gain `handler.steps`: a program written one statement per step, where
|
|
30
|
+
`onNoRows: conflict` makes a set-op write that writes nothing a `CONFLICT` and
|
|
31
|
+
rolls the whole program back ("create only if the parent exists"). Ref handlers
|
|
32
|
+
and interactive transactions can use `store.batch` for atomic multi-writes, and
|
|
33
|
+
`mantle bundle` under `wrangler dev` reports stale generated output in one line
|
|
34
|
+
instead of a failed build.
|
|
35
|
+
|
|
36
|
+
### Upgrading to 0.2.1-alpha.2
|
|
37
|
+
|
|
38
|
+
Pin the selected packages to `0.2.1-alpha.2` and regenerate. Breaking change:
|
|
39
|
+
|
|
40
|
+
- **`@aotter/mantle/describe`** keeps only `matchTarget` and the
|
|
41
|
+
`AppDescription`, `DescribeTarget` and `TargetRequest` types. `describeApp`,
|
|
42
|
+
`diffApp` and the `@aotter/mantle/target-hash` subpath are removed.
|
|
43
|
+
**`mantle describe` output is the supported way to get a description outside
|
|
44
|
+
the CLI:** run `mantle describe <target> manifests/*.yaml > describe.json` in
|
|
45
|
+
Node.js or Bun (for example in a deploy step) and give the JSON to
|
|
46
|
+
`matchTarget`. Do not import compiler files from `dist`; a Worker cannot
|
|
47
|
+
compile manifests that contain SQL ([describe](../reference/describe.md)).
|
|
48
|
+
Use `mantle describe --diff` instead of `diffApp`, and `_meta.targetHash`
|
|
49
|
+
instead of `targetHash()`.
|
|
50
|
+
|
|
51
|
+
Hand-built MCP tools gain three opt-in capabilities; without them the output
|
|
52
|
+
is unchanged ([MCP Apps](../guides/mcp-apps.md), [surface](../reference/surface.md)):
|
|
53
|
+
|
|
54
|
+
- `Tool.meta` merges into the tool's listed `_meta`. `ui.visibility: ["app"]`
|
|
55
|
+
can now hide a Procedure from clients without MCP Apps; it is a listing hint,
|
|
56
|
+
and calls are authorized as before.
|
|
57
|
+
- `withResultMeta(data, meta)` returns `meta` only in the result `_meta`, so a
|
|
58
|
+
value such as a signed upload URL stays out of `content`. `callTool` returns
|
|
59
|
+
`{ data, _meta }`; drop `_meta` before forwarding a result to a model.
|
|
60
|
+
- `toolsPageSize` pages `tools/list` with an opaque `nextCursor`.
|
|
61
|
+
|
|
62
|
+
Also: generation reports a SQL parser that cannot load in the current runtime
|
|
63
|
+
as such, instead of `SQL_SYNTAX`, and the handbook renders under Vue-based
|
|
64
|
+
site generators (bare `<placeholder>` text is now quoted, and `pnpm check`
|
|
65
|
+
fails on any that return).
|
|
66
|
+
|
|
67
|
+
### Upgrading to 0.2.1-alpha.1
|
|
68
|
+
|
|
69
|
+
Pin `@aotter/mantle`, and any selected `@aotter/mantle-ui` and
|
|
70
|
+
`@aotter/mantle-admin`, to `0.2.1-alpha.1`, refresh the lockfile, regenerate and
|
|
71
|
+
review owned output. No DDL changes are required. Breaking changes:
|
|
72
|
+
|
|
73
|
+
- **PostgreSQL `version`:** Store results return `version` as a number, as on
|
|
74
|
+
SQLite and D1. Procedure results stay driver-native.
|
|
75
|
+
- **Admin record form:** clearing an optional field sends `null`; generated
|
|
76
|
+
form types for optional fields are `T | null`.
|
|
77
|
+
- **REST route precedence** is fixed and most-specific-first. Only overlapping
|
|
78
|
+
same-method http Triggers with the same parameter count can change winner.
|
|
79
|
+
`TRIGGER_PATH_INVALID` and `TRIGGER_PATH_COLLISION` refuse ambiguous paths
|
|
80
|
+
at generation; see [route precedence](../reference/trigger.md#route-precedence).
|
|
81
|
+
- **Tooling:** the templates move to Wrangler 4.153.0 and
|
|
82
|
+
`@cloudflare/workers-types` 5.20261027.1.
|
|
83
|
+
- **PostgreSQL serialization failures:** SQLSTATE `40001` and `40P01` from a
|
|
84
|
+
definitive server refusal are now `CONFLICT` with `kind: "serialization"`
|
|
85
|
+
(409), instead of an unclassified driver error. Nothing is retried
|
|
86
|
+
automatically; read again before deciding to retry.
|
|
87
|
+
- **Revisions recipe:** an application that copied the guide's
|
|
88
|
+
`switch-revision` handler should adopt the new version. It requires
|
|
89
|
+
`expectedRevisionVersion` from the preview and seals and switches in one
|
|
90
|
+
`ctx.store.batch`.
|
|
91
|
+
|
|
18
92
|
## 0.2.0 (2026-10-19)
|
|
19
93
|
|
|
20
94
|
The first stable native 0.2 release compiles closed v2 manifests to SQL and
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The entry point `mantle help` prints first: choose a complete app or generation only, use examples as references, accept before done.
|
|
2
|
+
description: "The entry point `mantle help` prints first: choose a complete app or generation only, use examples as references, accept before done."
|
|
3
3
|
---
|
|
4
4
|
# Build with an agent
|
|
5
5
|
|
|
@@ -38,7 +38,11 @@ the app entry (`--entry`) never imports, it warns and names the topic that shows
|
|
|
38
38
|
4. `pnpm generate`, implement every handler it lists, `pnpm check`, then `pnpm smoke`.
|
|
39
39
|
5. Before reporting the app or a feature done, run [role-only acceptance](../guides/agent-workflow-acceptance.md)
|
|
40
40
|
(`mantle help agent-workflow-acceptance`). Scripted smoke is not acceptance. `pnpm accept` starts the app and hands
|
|
41
|
-
each role to a fresh evaluator as a URL that carries that role's session.
|
|
41
|
+
each role to a fresh evaluator as a URL that carries that role's session. After a repair, the guide's
|
|
42
|
+
[re-verification rule](../guides/agent-workflow-acceptance.md#re-verify-what-a-repair-touches) decides which roles
|
|
43
|
+
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.
|
|
42
46
|
|
|
43
47
|
The first verified sign-in with `ADMIN_EMAIL` becomes the admin. Further administrators are added in Admin:
|
|
44
48
|
**More → Administrators** invites by email, and **More → Members** grants Admin to an existing member.
|
|
@@ -59,6 +59,10 @@ Other handles may adapt to the same [structural driver contracts](../guides/adap
|
|
|
59
59
|
`--auth` and `--site` modules). `mantle bundle`, which Wrangler runs for `wrangler dev` and every
|
|
60
60
|
deploy, refuses to build when an input changed since, so stale generated code cannot run; regenerate and rebuild.
|
|
61
61
|
Commit it with the other generated files.
|
|
62
|
+
Under `wrangler dev` (Wrangler sets `WRANGLER_COMMAND=dev`) the refusal is one line per change instead of a failed
|
|
63
|
+
build: `mantle bundle` removes `<outdir>/worker` and exits 0, so Wrangler reports the entry missing and holds requests.
|
|
64
|
+
Writing `generated/` rebuilds. Other commands, other errors and a build by hand still fail with a nonzero exit.
|
|
65
|
+
To see that form while `wrangler dev` runs, run `pnpm build` (or `mantle bundle` by hand).
|
|
62
66
|
The bundle also prints notes, never errors, for SQL in the app's own code against Better Auth's tables (read users
|
|
63
67
|
through `userOf(caller)` or `readIdentity(auth)` instead) and for Better Auth roles beyond `admin` and `user`.
|
|
64
68
|
|
|
@@ -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
|
|
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.
|
|
7
7
|
|
|
8
8
|
Save `manifests/tickets.yaml`:
|
|
9
9
|
|
|
@@ -25,14 +25,23 @@ visibility, OCC and restart persistence, not just a 200 response.
|
|
|
25
25
|
Before reporting any new app or feature as done, follow the [independent
|
|
26
26
|
acceptance guide](../../handbook/guides/agent-workflow-acceptance.md): write a
|
|
27
27
|
private rubric, then give one fresh agent per role (`admin`, `user`) only its
|
|
28
|
-
role and entry points, across every surface it uses.
|
|
28
|
+
role and entry points, across every surface it uses. After a repair, re-run
|
|
29
|
+
the scope its [re-verification
|
|
30
|
+
rule](../../handbook/guides/agent-workflow-acceptance.md#re-verify-what-a-repair-touches)
|
|
31
|
+
names and state which evidence you reused. This is not limited to
|
|
29
32
|
MCP; if it was not run, say so explicitly and report the work as UNVERIFIED
|
|
30
|
-
rather than done.
|
|
31
|
-
|
|
33
|
+
rather than done. Hand off with the guide's [layered
|
|
34
|
+
report](../../handbook/guides/agent-workflow-acceptance.md#report-done-ness-in-layers):
|
|
35
|
+
an environment block is BLOCKED on its layer, never a product failure. For MCP workflows, also run the guide's design audit before implementing
|
|
36
|
+
tools. Once acceptance converges, follow the [performance skill](../performance/SKILL.md) before reporting done.
|
|
32
37
|
|
|
33
38
|
For native Admin, read the [current guide](../../handbook/guides/native-admin.md):
|
|
34
39
|
the app builds Admin with `mantle bundle`. To customise pages, slots, hooks or
|
|
35
40
|
MCP-host-safe components, follow [Customising Admin](../../handbook/guides/native-admin.md#customising-admin).
|
|
41
|
+
Custom structured inputs and browser pages can use the optional
|
|
42
|
+
`@aotter/mantle-admin/media` controlled `MediaPicker`: pass `readOnly` and an exact
|
|
43
|
+
`uploadPurpose` (omit for selection only), apply `onSelect` to the local draft,
|
|
44
|
+
and keep its import out of the MCP App entry. See the native Admin media example.
|
|
36
45
|
Keep matching SDK, Admin and UI versions. Ref handlers retain caller-bound
|
|
37
46
|
`ctx.store`; generic Admin reads use shared generated View templates and writes
|
|
38
47
|
use native Procedure fragments.
|
|
@@ -80,6 +89,9 @@ Destructive changes and type changes need explicit data migration. Mantle drops
|
|
|
80
89
|
|
|
81
90
|
Writes use Store `insert` / `update` / `delete`, `batch`, `transaction`, or declared Procedures. Never use raw SQL writes: they bypass scope, TTL, publishing and system-column rules. For reads beyond an id lookup or simple AND filter (joins, aggregates, OR, reuse), declare an internal View so the SQL is reviewable and typed. Store `findById`, `find` and `first` remain suitable for handler lookups and embedding in an existing app. Ref handlers receive `ctx.store` bound to the same Caller and transaction.
|
|
82
91
|
|
|
92
|
+
For published-content replacement with preview and rollback, follow `mantle help revisions`: Core supplies OCC, Schema locks and atomic `store.batch`; the recipe binds the previewed revision ID/version and atomically seals it while switching the parent. Applications own retention and review policy; Core does not mandate a preparation step. Keep the previewed version on submit and require another preview after a revision conflict.
|
|
93
|
+
Use its custom Native Admin preview/switch page: freeze the reviewed content and both row versions, then submit them through the authorized operation. Do not make editors copy version numbers or silently replace the reviewed snapshot after a refresh; conflicts require another explicit preview.
|
|
94
|
+
|
|
83
95
|
For simple creates/partial updates, prefer Store-backed ref Procedures; keep
|
|
84
96
|
Procedure `requires`/generated input checks, use only allowed patch fields and
|
|
85
97
|
return safe business fields with the actual returned ID/version. Preserve
|
|
@@ -22,7 +22,9 @@ data-preserving schema/auth/role migrations on a copy and retain rollback artifa
|
|
|
22
22
|
Initial schema.sql is for an empty database, not an in-place upgrade. Requests run
|
|
23
23
|
no DDL or storage checks; the only request-time write outside app operations is
|
|
24
24
|
the configured OAuth resource row (see [OAuth](../../handbook/guides/oauth.md)).
|
|
25
|
-
Verify cutover with actual app tests.
|
|
25
|
+
Verify cutover with actual app tests. Before reporting user-facing work done, run
|
|
26
|
+
[independent acceptance](../../handbook/guides/agent-workflow-acceptance.md), then the
|
|
27
|
+
[performance skill](../performance/SKILL.md).
|
|
26
28
|
|
|
27
29
|
Preserve the app router, verified identity and native resources. For selected
|
|
28
30
|
Admin, follow the [native guide](../../handbook/guides/native-admin.md) for its
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mantle Performance
|
|
12
|
+
|
|
13
|
+
This skill sets direction: when to run, what to aim for, in what order and when
|
|
14
|
+
to stop. It names no tools or commands. Choose the measurement and repair
|
|
15
|
+
methods that fit the application, its host and the tools available to you; the
|
|
16
|
+
targets and rules below are what stay fixed.
|
|
17
|
+
|
|
18
|
+
## When to run
|
|
19
|
+
|
|
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.
|
|
24
|
+
- **On request.** When a user reports a slow page, slow first request or slow
|
|
25
|
+
query, run only the part that covers it, then check the others it could affect.
|
|
26
|
+
|
|
27
|
+
## Choose what to run
|
|
28
|
+
|
|
29
|
+
Decide from the manifests, the service entry and the changed files, not from
|
|
30
|
+
guesses about future use. Run every part whose condition holds; record each
|
|
31
|
+
skipped part with its reason.
|
|
32
|
+
|
|
33
|
+
| Run | When the application or change has | Skip when |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| Front end | Pages a browser opens directly that the application authors: public pages, member pages, a custom frontend, Admin customisations | The only browser UI is SDK-built Admin, unchanged; MCP and REST alone have no page to measure |
|
|
36
|
+
| Cold start | A deployed Worker or service entry: always for a new application; for a change, any added or moved import in the entry, its startup graph, a page's or an MCP App entry's first-load code | The change touched no import, entry, page or MCP App bundle |
|
|
37
|
+
| Backend reads | Views, or Store reads in handlers, whose rows grow with data: lists, search, paging, joins, aggregates, totals, reports | Only id lookups and small, bounded configuration tables |
|
|
38
|
+
| Backend writes | Procedures or Store writes that run often or concurrently: stock, counters, approvals, checkout, imports | Rare single-row administrative writes |
|
|
39
|
+
|
|
40
|
+
A change in one part can move another: an added index slows writes, a shared
|
|
41
|
+
stylesheet or entry import affects every page. Re-measure what a repair can reach.
|
|
42
|
+
|
|
43
|
+
## Front end
|
|
44
|
+
|
|
45
|
+
**Target:** the highest Lighthouse performance score the page allows, with a
|
|
46
|
+
floor of 90 on mobile and 95 on desktop for every distinct page template, and
|
|
47
|
+
no regression in accessibility, SEO or best practices.
|
|
48
|
+
|
|
49
|
+
- Measure a production build, several runs on mobile and desktop, and report the
|
|
50
|
+
range. Separate what is real from what only the local environment causes
|
|
51
|
+
(no compression or HTTP/2, a cold cache) and say which is which.
|
|
52
|
+
- Measure pages behind sign-in (member pages, Admin) through the role's session
|
|
53
|
+
URL that `pnpm accept` prints
|
|
54
|
+
([hand each role](../../handbook/guides/agent-workflow-acceptance.md#hand-each-role-to-its-evaluator)),
|
|
55
|
+
never by weakening sign-in.
|
|
56
|
+
- Find the actual bottleneck before changing anything; a trace beats a guess.
|
|
57
|
+
- Repair in this order: what blocks the first paint (render-blocking styles and
|
|
58
|
+
font stylesheets, request chains, unused bytes), then main-thread work (heavy
|
|
59
|
+
scripts, animations, layout of off-screen content), then repeat visits
|
|
60
|
+
(content-hashed assets cached long, HTML revalidated).
|
|
61
|
+
- When a bottleneck appears only because the measuring environment lacks
|
|
62
|
+
something (a GPU, a fast CPU), fix it only in a way that also helps real users
|
|
63
|
+
without it. Never detect the measuring tool to serve it a different page.
|
|
64
|
+
- After every change, prove nothing else moved: the page looks the same, links,
|
|
65
|
+
forms and in-page anchors still work, and the
|
|
66
|
+
[public-page checks](../../handbook/guides/public-pages.md#check-before-you-report-done)
|
|
67
|
+
still pass without JavaScript.
|
|
68
|
+
|
|
69
|
+
## Cold start
|
|
70
|
+
|
|
71
|
+
**Target:** budgets that force code to load when it is needed, not before.
|
|
72
|
+
|
|
73
|
+
- **Worker:** its startup graph imports only what every request needs; auth, MCP,
|
|
74
|
+
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
|
|
76
|
+
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));
|
|
78
|
+
anything behind a dynamic import is outside it. Report its size locally as the
|
|
79
|
+
*Worker entry static graph*; measure the host's startup time only on
|
|
80
|
+
a deployment the user has authorized, and keep it well under the host's limit
|
|
81
|
+
(aim below 50 ms on Cloudflare).
|
|
82
|
+
- **Pages:** each page's *first-load JavaScript* is at most 100 KB, and only
|
|
83
|
+
what the first paint and first interaction need. Move the rest behind dynamic
|
|
84
|
+
imports, on use or when the browser is idle. An MCP App the application
|
|
85
|
+
authors holds its first-load JavaScript, the inline script text of its one
|
|
86
|
+
HTML file, to the same budget; it renders inside a host, so Lighthouse does
|
|
87
|
+
not measure it. Report the whole *MCP App HTML document* as its own number: it
|
|
88
|
+
also holds CSS and markup, so never compare it with this budget.
|
|
89
|
+
- Use the one definition of each metric in
|
|
90
|
+
[size metrics](../../handbook/guides/size-and-startup.md#size-metrics), with
|
|
91
|
+
its measurement. Where the SDK's own checks measure differently, that page says how.
|
|
92
|
+
- An overrun is a finding to repair by splitting, not a budget to raise. Raise a
|
|
93
|
+
budget only with the user's agreement and record why.
|
|
94
|
+
|
|
95
|
+
## Backend
|
|
96
|
+
|
|
97
|
+
**Target:** every read and write the application's surfaces actually make stays
|
|
98
|
+
fast at a realistic volume, and no hot path scans a table that grows.
|
|
99
|
+
|
|
100
|
+
- **Data:** seed an isolated local database, never a shared or production one,
|
|
101
|
+
with data shaped like real use: several owners and roles, every state, long
|
|
102
|
+
text where fields allow it, and more than one page of results everywhere. Size
|
|
103
|
+
the largest tables at 100,000 rows or 10 times the expected first-year volume,
|
|
104
|
+
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)
|
|
106
|
+
describes: it is test data, not an application write.
|
|
107
|
+
- **Load:** call every View and Procedure through the same callers and surfaces
|
|
108
|
+
the application uses, as each role. The app's local test harness already
|
|
109
|
+
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)).
|
|
111
|
+
Record typical and slow-tail latency and
|
|
112
|
+
rows read, then run concurrent writers wherever contention matters. A business
|
|
113
|
+
rule that breaks under concurrency (oversell, double approval, lost update) is
|
|
114
|
+
a correctness defect, not a performance finding: fix it first.
|
|
115
|
+
- **Aim:** hot reads stay in the tens of milliseconds locally at seeded volume,
|
|
116
|
+
and their cost does not grow with table size.
|
|
117
|
+
- **Repair in this order:**
|
|
118
|
+
1. Read the native query plan of each hot path, using the SQL in its generated
|
|
119
|
+
query module under `generated/` against the seeded database; a full scan of a
|
|
120
|
+
growing table is a finding.
|
|
121
|
+
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)).
|
|
124
|
+
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
|
|
126
|
+
already: generation refuses one no index serves.
|
|
127
|
+
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)).
|
|
131
|
+
4. Re-measure reads and writes after each repair.
|
|
132
|
+
|
|
133
|
+
## Rules
|
|
134
|
+
|
|
135
|
+
- Speed never buys a lower standard: scope, authorization, OCC, atomicity,
|
|
136
|
+
accessibility, the public-page requirements and every explicit user
|
|
137
|
+
requirement stay intact. The application's writes still go through Store and
|
|
138
|
+
Procedures; only seed data for the isolated test database is inserted directly.
|
|
139
|
+
- Do not lower a target, shrink the seeded data or drop a slow case to pass.
|
|
140
|
+
Report what is left instead.
|
|
141
|
+
- 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).
|
|
144
|
+
A repair that changes what a user sees or can do is no longer only a
|
|
145
|
+
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)
|
|
147
|
+
names. A changed View or Procedure widens it to every surface that reads or
|
|
148
|
+
writes that data, and so does a `uniqueIndexes` entry. A non-unique
|
|
149
|
+
`indexes` entry and its migration keep the business rules: run `pnpm check`,
|
|
150
|
+
the local HTTP checks and your focused regressions, not acceptance.
|
|
151
|
+
- 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)
|
|
153
|
+
per SDK version; while the installed version and Admin entry are unchanged,
|
|
154
|
+
reuse it instead of repeating that experiment each round. Built-in Admin's
|
|
155
|
+
page and MCP App both miss the first-load budget; that is SDK-existing cost,
|
|
156
|
+
not the application's. A target the SDK's cost misses is still PARTIAL, with
|
|
157
|
+
its owner named. Never relabel it PASS.
|
|
158
|
+
- Do not patch vendor or SDK code, remove native Admin features or build a
|
|
159
|
+
general benchmark framework to meet a target.
|
|
160
|
+
- Stop when every target is met, after three rounds, or when two rounds in a row
|
|
161
|
+
bring no measurable gain.
|
|
162
|
+
|
|
163
|
+
## Report
|
|
164
|
+
|
|
165
|
+
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
|
|
167
|
+
beside the acceptance verdict: **PASS** (every target that applies is met),
|
|
168
|
+
**PARTIAL** (improved, with the targets still missed and why) or **SKIPPED**
|
|
169
|
+
(nothing applied).
|
|
@@ -15,12 +15,16 @@ metadata:
|
|
|
15
15
|
Read the installed SDK README, then follow the version-matched [project and CLI
|
|
16
16
|
workflow](../../handbook/start/project-and-cli.md) before editing.
|
|
17
17
|
|
|
18
|
-
For 0.1.x, follow [Upgrade 0.1 to 0.2](../../upgrade-0.1-to-0.2.md)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
For 0.1.x, follow [Upgrade 0.1 to 0.2](../../upgrade-0.1-to-0.2.md). Mantle
|
|
19
|
+
ships no migration tool: plan the data move from
|
|
20
|
+
[Moving data from 0.1.x](../../upgrade-0.1-to-0.2.md#moving-data-from-01x),
|
|
21
|
+
verify each fact against the generated `schema.sql` and the 0.1.4 export, and
|
|
22
|
+
have the plan reviewed. Give the 0.2 service a new database, rehearse the load
|
|
23
|
+
on a copy, never boot 0.2 against a 0.1.x database, and keep exports out of the
|
|
24
|
+
repository. The guide's appendix is historical; do not follow it. Between 0.2
|
|
25
|
+
versions, apply reviewed migrations rehearsed on a copy.
|
|
22
26
|
|
|
23
|
-
For the stable 0.2 line, pin every selected Mantle package to `0.2.0`;
|
|
27
|
+
For the stable 0.2 line, pin every selected Mantle package to `0.2.0`; to try the 0.2.1 prerelease, pin all of them to `0.2.1-alpha.2` and read its release notes. Do not upgrade an existing application by following a moving dist-tag.
|
|
24
28
|
|
|
25
29
|
Pin exact target SDK/peer versions and read its release notes and Admin build
|
|
26
30
|
instructions. Core-to-native replaces app imports/wiring; it is not
|