@aotter/mantle 0.2.1-alpha.3 → 0.2.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.
- package/dist/build/compiler.js +2 -2
- package/docs/examples/README.md +1 -1
- package/docs/examples/app-shell/README.md +2 -2
- package/docs/examples/app-shell/package.json +3 -3
- package/docs/handbook/concepts/runtime-and-adapters.md +1 -1
- package/docs/handbook/examples/hub.md +1 -1
- package/docs/handbook/guides/adapter-guide.md +1 -1
- package/docs/handbook/guides/agent-workflow-acceptance.md +6 -4
- package/docs/handbook/guides/native-admin.md +1 -1
- package/docs/handbook/guides/performance.md +4 -2
- package/docs/handbook/guides/size-and-startup.md +3 -3
- package/docs/handbook/guides/sql-patterns.md +1 -1
- package/docs/handbook/reference/features.md +1 -1
- package/docs/handbook/reference/sql.md +1 -1
- package/docs/handbook/reference/view.md +1 -2
- package/docs/handbook/releases/index.md +107 -105
- package/docs/handbook/start/agents.md +24 -8
- package/docs/handbook/start/overview.md +1 -1
- package/docs/handbook/start/project-and-cli.md +1 -1
- package/package.json +1 -1
- package/skills/mantle/SKILL.md +4 -3
package/docs/examples/README.md
CHANGED
|
@@ -39,5 +39,5 @@ shell's allow-all `src/signup.ts`, unless sign-up should be invite-only. Purchas
|
|
|
39
39
|
|
|
40
40
|
Every example uses two roles: `admin` (the admin layer) and `user`.
|
|
41
41
|
|
|
42
|
-
[Reference service](https://github.com/aotter/mantle/tree/v0.2.1
|
|
42
|
+
[Reference service](https://github.com/aotter/mantle/tree/v0.2.1/docs/examples/reference-service) is the release smoke test for packed packages, not a starting point. Its source lives in the tagged repository; it is not included in the npm docs.
|
|
43
43
|
Projects on 0.1.x move with [the upgrade guide](../handbook/releases/upgrade-0.1-to-0.2.md).
|
|
@@ -16,8 +16,8 @@ pnpm types && pnpm check # each builds once (see Which steps build)
|
|
|
16
16
|
cp .dev.vars.example .dev.vars
|
|
17
17
|
pnpm db:init # optional seed.sql for static reference data, then pnpm db:seed (see Seed data)
|
|
18
18
|
pnpm dev # builds, rebuilds on change; one-time codes print to this log
|
|
19
|
-
pnpm smoke # builds;
|
|
20
|
-
pnpm accept # builds;
|
|
19
|
+
pnpm smoke # builds; runs smoke.mjs, which you write on smoke-kit.mjs (init does not create it)
|
|
20
|
+
pnpm accept # builds; prints a signed-in URL per role for fresh evaluators (see Independent acceptance)
|
|
21
21
|
pnpm test # Admin MCP App check of the last build: needs Chrome (npx playwright-core install chromium, or MANTLE_TEST_CHROMIUM=<executable>)
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"accept": "node accept.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@aotter/mantle": "0.2.1
|
|
19
|
-
"@aotter/mantle-ui": "0.2.1
|
|
18
|
+
"@aotter/mantle": "0.2.1",
|
|
19
|
+
"@aotter/mantle-ui": "0.2.1",
|
|
20
20
|
"@better-auth/cimd": "1.7.7",
|
|
21
21
|
"@better-auth/core": "1.7.7",
|
|
22
22
|
"@better-auth/mcp": "1.7.7",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@modelcontextprotocol/ext-apps": "2.0.0",
|
|
26
26
|
"@modelcontextprotocol/server": "2.3.1",
|
|
27
27
|
"better-auth": "1.7.7",
|
|
28
|
-
"@aotter/mantle-admin": "0.2.1
|
|
28
|
+
"@aotter/mantle-admin": "0.2.1",
|
|
29
29
|
"react": "19.3.0",
|
|
30
30
|
"react-dom": "19.3.0"
|
|
31
31
|
},
|
|
@@ -21,7 +21,7 @@ The driver layer is open: handles are structural contracts, not a registration A
|
|
|
21
21
|
|
|
22
22
|
Users may supply anything that executes the emitted SQL, including WASM SQLite persisted to IndexedDB, at their own risk. Mantle promises behavior only on supported drivers: bun:sqlite, D1, Bun.SQL and postgres.js. A structural match alone does not prove transaction, result or error semantics.
|
|
23
23
|
|
|
24
|
-
The dialect layer is closed in 0.2
|
|
24
|
+
The dialect layer is closed in 0.2: exactly `postgres` and `sqlite`, selected by the generation target. SQL is rendered at generation time. A third engine requires forking the compiler and Store runtime; it is not a dialect plugin.
|
|
25
25
|
|
|
26
26
|
## Store and queries
|
|
27
27
|
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
Use the [Worker quickstart](../start/quickstart-worker.md) for a complete native manifest and entry, [typed queries](../guides/typed-queries.md) for embedding, and [service composition](../cloudflare/service-entry.md) for optional surfaces.
|
|
4
4
|
|
|
5
|
-
The runnable [reference service](https://github.com/aotter/mantle/tree/v0.2.1
|
|
5
|
+
The runnable [reference service](https://github.com/aotter/mantle/tree/v0.2.1/docs/examples/reference-service) exercises the native package integration. See the [generated public website](../../examples/generated-web/README.md) for a native Worker example.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Another host or database handle
|
|
2
2
|
|
|
3
|
-
Mantle has an open driver boundary and exactly two closed dialects in 0.2
|
|
3
|
+
Mantle has an open driver boundary and exactly two closed dialects in 0.2, postgres and sqlite. Choose the generation target whose emitted SQL and handle calls match your host. The app owns its router, resources, lifetime and scheduler.
|
|
4
4
|
|
|
5
5
|
PostgreSQL's `Postgres` in `kernel/contracts.ts` needs `unsafe(text, values)` and `begin(options, fn)`. Bun.SQL and postgres.js fit without wrappers. [The node-postgres example](postgres-adapters.md) shows the transaction and result-count contract. SQLite handle contracts are exported by `@aotter/mantle/driver/d1` and `/driver/bun-sqlite`: D1 prepare/bind/all/batch, or SQLite query/exec/transaction. Reads may need only the narrower reader shape.
|
|
6
6
|
|
|
@@ -85,15 +85,17 @@ rounds below before claiming the user-facing work is done. Keep the author's
|
|
|
85
85
|
capability map and worked call sequence out of the fresh agent's prompt: an MCP
|
|
86
86
|
evaluator must discover the workflow from public tool descriptions and results.
|
|
87
87
|
|
|
88
|
-
##
|
|
88
|
+
## Plan the run
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
The plan the user approves before the build ([Build from a product brief](../start/agents.md#build-from-a-product-brief))
|
|
91
|
+
says in plain words who tries the app and what they try to get done. Behind it, the run
|
|
92
|
+
fixes:
|
|
91
93
|
|
|
92
94
|
- each evaluator you will start: its role (`admin`, `user`, a visitor), the surfaces it uses (Admin, member pages,
|
|
93
95
|
REST, MCP, visitor pages) and the goals it is asked to finish, in the user's words;
|
|
94
96
|
- the round limit (at most three) and what triggers a re-run;
|
|
95
|
-
-
|
|
96
|
-
rather than reported as BLOCKED later.
|
|
97
|
+
- what the environment needs, such as a browser for a visitor or member page. Provide it yourself (install a headless
|
|
98
|
+
browser if none is there); only what you cannot provide goes to the user now, rather than reported as BLOCKED later.
|
|
97
99
|
|
|
98
100
|
Keep the rubric itself private: the plan names goals, never the checks an evaluator is graded on.
|
|
99
101
|
|
|
@@ -614,7 +614,7 @@ key's path. The `UI_EXTENSION_*` diagnostics no longer exist.
|
|
|
614
614
|
|
|
615
615
|
The compiler derives display/filter metadata from Schema `uiSchema`, searchable fields from `searchableFields`, and sortable fields from indexes plus required/non-null fields and selected system columns. It emits per-collection quoted fragments, row policies and bind recipes; Admin uses one shared `nativeEntryPage` implementation, not Store `find`, `search` or `count` for these lists.
|
|
616
616
|
|
|
617
|
-
Requests select only generated fields and append only supplied predicates. Absent filters are omitted, rather than expressed as `(? IS NULL OR …)`. Sorts and scalar values are checked before the route acquires its DB handle. In 0.2
|
|
617
|
+
Requests select only generated fields and append only supplied predicates. Absent filters are omitted, rather than expressed as `(? IS NULL OR …)`. Sorts and scalar values are checked before the route acquires its DB handle. In 0.2 there is no generated Cartesian set of filter variants or variant cap: runtime SQL shapes depend on selected filters, bounded IN lists, search, cursor and order. Only sortable fields are checked for indexes; there is no per-filter-combination index proof. Inspect EXPLAIN for the actual workload.
|
|
618
618
|
|
|
619
619
|
Store keeps `find({ search })`, `first({ search })` and `count(where?)`. See [Store search and count costs](typed-queries.md#store-reads-and-writes): Admin shares the dialect search, and a View does not make PostgreSQL ILIKE faster.
|
|
620
620
|
|
|
@@ -35,9 +35,11 @@ skipped part with its reason.
|
|
|
35
35
|
A change in one part can move another: an added index slows writes, a shared
|
|
36
36
|
stylesheet or entry import affects every page. Re-measure what a repair can reach.
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Plan the pass
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
The plan the user approves before the build ([Build from a product brief](../start/agents.md#build-from-a-product-brief))
|
|
41
|
+
says in plain words how much sample data there is and what "fast enough" means for each page.
|
|
42
|
+
Behind it, the pass fixes:
|
|
41
43
|
|
|
42
44
|
- the parts that run and the parts skipped, each with its reason (the table above);
|
|
43
45
|
- the test data for backend parts: rows per table (for example 1,000,000 RSVPs across 5,000 events and 20,000
|
|
@@ -23,7 +23,7 @@ report it.
|
|
|
23
23
|
|---|---|---|
|
|
24
24
|
| First-load JavaScript | Every script a page's HTML loads: `<script src>` files and inline `<script>` text, classic or `type="module"`, plus every file they import statically, recursively. A dynamic `import()` is not followed. CSS, fonts, images and scripts from another origin do not count. | gzip per file |
|
|
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
|
-
| Worker entry static graph | The Worker entry (Wrangler's `main`,
|
|
26
|
+
| Worker entry static graph | The Worker entry (Wrangler's `main`, `dist/worker/index.js` in an app from `mantle init`) plus every chunk it imports statically, recursively. A dynamic `import()` is not followed. | gzip per file; raw bytes beside it |
|
|
27
27
|
|
|
28
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
|
|
@@ -91,7 +91,7 @@ node first-load.mjs dist/client/admin/mcp-app.html
|
|
|
91
91
|
Worker entry static graph: pass Wrangler's `main`.
|
|
92
92
|
|
|
93
93
|
```sh
|
|
94
|
-
node first-load.mjs dist/worker/
|
|
94
|
+
node first-load.mjs dist/worker/index.js
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
MCP App HTML document:
|
|
@@ -128,7 +128,7 @@ dependencies, so they hold only for the version and commit named.
|
|
|
128
128
|
|
|
129
129
|
| SDK | Source | Admin page first-load JavaScript | MCP App first-load JavaScript | MCP App HTML document |
|
|
130
130
|
|---|---|---|---|---|
|
|
131
|
-
| 0.2.1 | `develop` at `
|
|
131
|
+
| 0.2.1 | `develop` at `1294c672` | 195,827 B gzip in 13 files (195,069 B without `theme.js`) | 167,516 B gzip, inline | 612,324 B raw / 174,501 B gzip |
|
|
132
132
|
|
|
133
133
|
Neither the built-in Admin page nor its MCP App meets the 100 KB first-load
|
|
134
134
|
budget. Both misses are SDK cost, not your application's: report them as
|
|
@@ -4,7 +4,7 @@ description: Eight SQL patterns most apps need, each a complete manifest that co
|
|
|
4
4
|
# SQL patterns
|
|
5
5
|
|
|
6
6
|
Each section is a business need, the manifest that meets it, and what the database refuses. Every block here is
|
|
7
|
-
generated by the docs check, and
|
|
7
|
+
generated by the docs check, and the SDK's tests run the same manifest on bun:sqlite,
|
|
8
8
|
local D1 and PostgreSQL through the generated REST boundary. The SQL is the SQLite and D1 spelling; where PostgreSQL
|
|
9
9
|
differs, the section says so. What each dialect accepts is listed in [the SQL reference](../reference/sql.md).
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Supported declarations
|
|
2
2
|
|
|
3
|
-
The native 0.2
|
|
3
|
+
The native 0.2 SDK compiles the closed v2 grammar for four targets. Generation diagnostics, rather than historical APIs or release plans, define the checked-out implementation. Existing integrations require explicit app wiring and data migration; initial schema.sql is for an empty database.
|
|
4
4
|
|
|
5
5
|
## Supported
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ worked examples see [SQL patterns](../guides/sql-patterns.md).
|
|
|
19
19
|
| Predicates | `=`, `<>`, `!=`, `<`, `>`, `<=`, `>=`, `AND`, `OR`, `NOT`, `IS [NOT] NULL`, `IS [NOT] DISTINCT FROM`, `[NOT] BETWEEN`, `IN (list)`, `IN (subquery)`, `LIKE`, `[NOT] EXISTS (subquery)` |
|
|
20
20
|
| Expressions | `+ - * / %`, `\|\|`, `->>` (JSON field), `CASE`, `COALESCE`, `NULLIF`, scalar subqueries, `CAST(… AS text \| int4 \| int8 \| float8 \| bool \| timestamptz \| date \| numeric \| interval)` |
|
|
21
21
|
| Aggregates | `count`, `sum`, `min`, `max`, `avg` |
|
|
22
|
-
| Windows | `row_number()`, `rank()`, `sum()`, `count()` with `OVER (PARTITION BY … ORDER BY …)` and the default frame |
|
|
22
|
+
| Windows (Views only) | `row_number()`, `rank()`, `sum()`, `count()` with `OVER (PARTITION BY … ORDER BY …)` and the default frame. A Procedure refuses them; rank there with a correlated `count(*)` subquery |
|
|
23
23
|
| Scalar functions | `lower`, `upper`, `length`, `abs`, `round`, `substr`, `replace`, `trim`, `ltrim`, `rtrim`, `instr` |
|
|
24
24
|
| Time | `now()`, `date_trunc('hour' \| 'day' \| 'week' \| 'month' \| 'year', …)`, `extract(year \| month \| day \| dow \| hour FROM …)` |
|
|
25
25
|
| Mantle | `auth.uid()`, `input.<name>`, `mantle.search`, `mantle.search_rank`, `mantle.near`, `mantle.distance` ([features](features.md)) |
|
|
@@ -21,8 +21,7 @@ OFFSET, arbitrary functions/relations, DDL and transaction control are not a rea
|
|
|
21
21
|
`mantle.search(<alias>, <text>)` matches the Schema's declared `searchableFields`, and `mantle.search_rank(<alias>)`
|
|
22
22
|
orders by relevance; qualify both with `mantle.`. An optional search reads
|
|
23
23
|
`WHERE p.active AND (input.q IS NULL OR mantle.search(p, input.q))`, and a ranked one
|
|
24
|
-
`WHERE mantle.search(p, input.q) ORDER BY mantle.search_rank(p), p.id
|
|
25
|
-
for cursor paging over the rank).
|
|
24
|
+
`WHERE mantle.search(p, input.q) ORDER BY mantle.search_rank(p), p.id`; page it with a cursor over the rank and the id.
|
|
26
25
|
|
|
27
26
|
Views using `mantle.search`, Store search and Admin list search share the dialect search: SQLite/D1 use FTS for queries of 3 or more characters (shorter queries use LIKE); PostgreSQL uses ILIKE over the declared fields and scans by default. A View does not make PostgreSQL search faster. For large PostgreSQL tables, the application's agent adds trigram indexes in a migration, which ILIKE then uses with no code change:
|
|
28
27
|
|
|
@@ -32,114 +32,116 @@ Pin every package you use to the same exact version and upgrade them together.
|
|
|
32
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
33
|
move, and never booting 0.2 against a 0.1.x database.
|
|
34
34
|
|
|
35
|
-
## 0.2.1
|
|
36
|
-
|
|
37
|
-
0.2.1 adds Schema locks
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
35
|
+
## 0.2.1 (2026-10-30)
|
|
36
|
+
|
|
37
|
+
0.2.1 adds **Schema locks**: a manifest rule that refuses a row's update or delete on every caller path (REST, MCP,
|
|
38
|
+
Admin and Procedures), and Admin shows the lock before an edit. `spec.publishing.liveEdits` lets an application edit a
|
|
39
|
+
published row in place. The [revisions guide](../guides/revisions.md) now freezes the live revision with a lock and
|
|
40
|
+
switches it atomically.
|
|
41
|
+
|
|
42
|
+
Procedures gain `handler.steps`, a program written one statement per step. With `onNoRows: conflict`, a set-op write
|
|
43
|
+
that writes nothing becomes a `CONFLICT` and rolls the whole program back ("create only if the parent exists"). Ref
|
|
44
|
+
handlers and interactive transactions can use `store.batch` for atomic multi-writes. Hand-built MCP tools can attach
|
|
45
|
+
listing and result metadata and page `tools/list`.
|
|
46
|
+
|
|
47
|
+
For agents and for the people working with them:
|
|
48
|
+
|
|
49
|
+
- `mantle help` is the single source of guidance, and the `mantle` skill no longer depends on the SDK version.
|
|
50
|
+
- An agent building from a brief first replies with one plan, written in business terms, and asks what the brief
|
|
51
|
+
leaves open. After one go-ahead, it builds, shows the Developer UI, runs acceptance and a performance pass, and
|
|
52
|
+
reports what each found and changed.
|
|
53
|
+
- The Developer UI draws a real ER diagram, a columned system wiring graph and one Procedure logic graph.
|
|
54
|
+
|
|
55
|
+
Generated Workers and the Admin start smaller.
|
|
56
|
+
|
|
57
|
+
[GitHub release](https://github.com/aotter/mantle/releases/tag/v0.2.1) is the complete change history. Known
|
|
58
|
+
follow-ups:
|
|
59
|
+
|
|
60
|
+
- mounting an adopter MCP server behind Mantle's caller gate ([#1843](https://github.com/aotter/mantle/issues/1843));
|
|
61
|
+
- tool-catalogue change notifications ([#1810](https://github.com/aotter/mantle/issues/1810));
|
|
62
|
+
- the Admin MCP App, which is still above its 480 KB size reference. About 40% of it is the official MCP SDK and zod,
|
|
63
|
+
which ADR-0029 requires.
|
|
64
|
+
|
|
65
|
+
### Upgrading from 0.2.0
|
|
66
|
+
|
|
67
|
+
Pin every selected `@aotter/mantle`, `@aotter/mantle-ui` and `@aotter/mantle-admin` dependency to `0.2.1`, refresh the
|
|
68
|
+
lockfile, regenerate, and review the owned output. No DDL changes are required.
|
|
69
|
+
|
|
70
|
+
Breaking changes:
|
|
71
|
+
|
|
72
|
+
- **`@aotter/mantle/describe`** keeps only `matchTarget` and the `AppDescription`, `DescribeTarget` and
|
|
73
|
+
`TargetRequest` types. `describeApp`, `diffApp` and the `@aotter/mantle/target-hash` subpath are removed.
|
|
74
|
+
- Get a description outside the CLI with `mantle describe <target> manifests/*.yaml > describe.json`, run in Node.js
|
|
75
|
+
or Bun (for example in a deploy step), and give the JSON to `matchTarget`. Do not import compiler files from
|
|
76
|
+
`dist`: a Worker cannot compile manifests that contain SQL ([describe](../reference/describe.md)).
|
|
77
|
+
- Use `mantle describe --diff` instead of `diffApp`, and `_meta.targetHash` instead of `targetHash()`.
|
|
78
|
+
- **PostgreSQL `version`:** Store results return `version` as a number, as on SQLite and D1. Procedure results stay
|
|
79
|
+
driver-native.
|
|
80
|
+
- **PostgreSQL serialization failures:** SQLSTATE `40001` and `40P01` from a definitive server refusal are now
|
|
81
|
+
`CONFLICT` with `kind: "serialization"` (409), instead of an unclassified driver error. Nothing is retried
|
|
82
|
+
automatically; read again before deciding to retry.
|
|
83
|
+
- **Admin record form:** clearing an optional field sends `null`, and generated form types for optional fields are
|
|
84
|
+
`T | null`.
|
|
85
|
+
- **REST route precedence** is fixed and most-specific-first. Only overlapping same-method http Triggers with the same
|
|
86
|
+
parameter count can change which one wins. `TRIGGER_PATH_INVALID` and `TRIGGER_PATH_COLLISION` refuse ambiguous
|
|
87
|
+
paths at generation; see [route precedence](../reference/trigger.md#route-precedence).
|
|
88
|
+
- **Agent guidance moved into the handbook.** The package no longer ships `docs/skills/`, so the `mantle help
|
|
89
|
+
skills/<name>` topics are gone. Their guidance now lives in these pages, and `mantle help` reaches all of them from
|
|
90
|
+
its entry page:
|
|
91
|
+
- [performance pass](../guides/performance.md);
|
|
92
|
+
- [deploy and operate](../cloudflare/deploy-and-operate.md);
|
|
93
|
+
- [cleaning up stale uploads](../cloudflare/media-r2.md#clean-up-stale-uploads);
|
|
94
|
+
- [upgrading an application](#upgrade-an-application);
|
|
95
|
+
- [adoption in an existing app](../guides/typed-queries.md#adopt-mantle-in-an-existing-application).
|
|
96
|
+
|
|
97
|
+
The 0.1 → 0.2 upgrade guide is the topic `mantle help upgrade-0.1-to-0.2`. A `mantle` skill installed from an
|
|
98
|
+
earlier tag still names `docs/skills/` paths; reinstall it with `npx skills add aotter/mantle@mantle`.
|
|
99
|
+
- **Revisions recipe:** an application that copied the guide's `switch-revision` handler should adopt the new version.
|
|
100
|
+
It requires `expectedRevisionVersion` from the preview, and seals and switches in one `ctx.store.batch`.
|
|
101
|
+
- **Tooling:** the templates move to Wrangler 4.153.0 and `@cloudflare/workers-types` 5.20261027.1.
|
|
102
|
+
|
|
103
|
+
New, opt-in:
|
|
104
|
+
|
|
105
|
+
- **Schema locks and live edits:** see [revisions](../guides/revisions.md).
|
|
106
|
+
- **`handler.steps` and `onNoRows: conflict`.** Ref handlers and interactive transactions can also use
|
|
107
|
+
`store.batch` for atomic multi-writes.
|
|
108
|
+
- **Hand-built MCP tools** ([MCP Apps](../guides/mcp-apps.md), [surface](../reference/surface.md)):
|
|
109
|
+
- `Tool.meta` merges into the tool's listed `_meta`. `ui.visibility: ["app"]` can hide a Procedure from clients
|
|
110
|
+
without MCP Apps; it is a listing hint, and calls are authorized as before.
|
|
111
|
+
- `withResultMeta(data, meta)` returns `meta` only in the result `_meta`, so a value such as a signed upload URL stays
|
|
112
|
+
out of `content`. `callTool` returns `{ data, _meta }`; drop `_meta` before forwarding a result to a model.
|
|
113
|
+
- `toolsPageSize` pages `tools/list` with an opaque `nextCursor`.
|
|
114
|
+
- **Admin media picker** for custom inputs and pages: `@aotter/mantle-admin/media`.
|
|
115
|
+
|
|
116
|
+
Picked up by regenerating, with no manifest or API change:
|
|
117
|
+
|
|
118
|
+
- **Agent workflow** ([Build from a product brief](../start/agents.md#build-from-a-product-brief)). The agent works
|
|
119
|
+
in four phases:
|
|
120
|
+
1. Before anything else, it replies with one plain-language plan: what each kind of user can do, the rules the app
|
|
121
|
+
enforces, who will try it, how much sample data, and what counts as fast enough. The plan ends with the open
|
|
122
|
+
questions, each with a default answer.
|
|
123
|
+
2. After one go-ahead, it builds and opens the Developer UI (`pnpm accept --open`) in the user's browser.
|
|
124
|
+
3. It runs role-only acceptance and the performance pass without stopping.
|
|
125
|
+
4. It ends with an acceptance summary and a before → after performance summary.
|
|
126
|
+
- **Developer UI diagrams:**
|
|
127
|
+
- The data model is an ER diagram with keys, types and crow's-foot cardinality, in three display modes, with a
|
|
128
|
+
minimap.
|
|
129
|
+
- System wiring is laid out in columns, also with a minimap.
|
|
78
130
|
- A Procedure's logic is one graph, the same in the wiring side panel and on the Procedure page: a transaction box,
|
|
79
131
|
CASE as ordered branch rows, and COMMIT and ROLLBACK ends. The SQL syntax trees stay available, folded, on the
|
|
80
132
|
Procedure page.
|
|
81
|
-
-
|
|
82
|
-
- **Smaller startup
|
|
83
|
-
- Generated Workers emit a repeated SQL statement once
|
|
84
|
-
|
|
85
|
-
- Admin loads sign-in, OAuth consent and the collection list on demand
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
`AppDescription`, `DescribeTarget` and `TargetRequest` types. `describeApp`,
|
|
94
|
-
`diffApp` and the `@aotter/mantle/target-hash` subpath are removed.
|
|
95
|
-
**`mantle describe` output is the supported way to get a description outside
|
|
96
|
-
the CLI:** run `mantle describe <target> manifests/*.yaml > describe.json` in
|
|
97
|
-
Node.js or Bun (for example in a deploy step) and give the JSON to
|
|
98
|
-
`matchTarget`. Do not import compiler files from `dist`; a Worker cannot
|
|
99
|
-
compile manifests that contain SQL ([describe](../reference/describe.md)).
|
|
100
|
-
Use `mantle describe --diff` instead of `diffApp`, and `_meta.targetHash`
|
|
101
|
-
instead of `targetHash()`.
|
|
102
|
-
|
|
103
|
-
Hand-built MCP tools gain three opt-in capabilities; without them the output
|
|
104
|
-
is unchanged ([MCP Apps](../guides/mcp-apps.md), [surface](../reference/surface.md)):
|
|
105
|
-
|
|
106
|
-
- `Tool.meta` merges into the tool's listed `_meta`. `ui.visibility: ["app"]`
|
|
107
|
-
can now hide a Procedure from clients without MCP Apps; it is a listing hint,
|
|
108
|
-
and calls are authorized as before.
|
|
109
|
-
- `withResultMeta(data, meta)` returns `meta` only in the result `_meta`, so a
|
|
110
|
-
value such as a signed upload URL stays out of `content`. `callTool` returns
|
|
111
|
-
`{ data, _meta }`; drop `_meta` before forwarding a result to a model.
|
|
112
|
-
- `toolsPageSize` pages `tools/list` with an opaque `nextCursor`.
|
|
113
|
-
|
|
114
|
-
Also: generation reports a SQL parser that cannot load in the current runtime
|
|
115
|
-
as such, instead of `SQL_SYNTAX`, and the handbook renders under Vue-based
|
|
116
|
-
site generators (bare `<placeholder>` text is now quoted, and `pnpm check`
|
|
117
|
-
fails on any that return).
|
|
118
|
-
|
|
119
|
-
### Upgrading to 0.2.1-alpha.1
|
|
120
|
-
|
|
121
|
-
Pin `@aotter/mantle`, and any selected `@aotter/mantle-ui` and
|
|
122
|
-
`@aotter/mantle-admin`, to `0.2.1-alpha.1`, refresh the lockfile, regenerate and
|
|
123
|
-
review owned output. No DDL changes are required. Breaking changes:
|
|
124
|
-
|
|
125
|
-
- **PostgreSQL `version`:** Store results return `version` as a number, as on
|
|
126
|
-
SQLite and D1. Procedure results stay driver-native.
|
|
127
|
-
- **Admin record form:** clearing an optional field sends `null`; generated
|
|
128
|
-
form types for optional fields are `T | null`.
|
|
129
|
-
- **REST route precedence** is fixed and most-specific-first. Only overlapping
|
|
130
|
-
same-method http Triggers with the same parameter count can change winner.
|
|
131
|
-
`TRIGGER_PATH_INVALID` and `TRIGGER_PATH_COLLISION` refuse ambiguous paths
|
|
132
|
-
at generation; see [route precedence](../reference/trigger.md#route-precedence).
|
|
133
|
-
- **Tooling:** the templates move to Wrangler 4.153.0 and
|
|
134
|
-
`@cloudflare/workers-types` 5.20261027.1.
|
|
135
|
-
- **PostgreSQL serialization failures:** SQLSTATE `40001` and `40P01` from a
|
|
136
|
-
definitive server refusal are now `CONFLICT` with `kind: "serialization"`
|
|
137
|
-
(409), instead of an unclassified driver error. Nothing is retried
|
|
138
|
-
automatically; read again before deciding to retry.
|
|
139
|
-
- **Revisions recipe:** an application that copied the guide's
|
|
140
|
-
`switch-revision` handler should adopt the new version. It requires
|
|
141
|
-
`expectedRevisionVersion` from the preview and seals and switches in one
|
|
142
|
-
`ctx.store.batch`.
|
|
133
|
+
- All of their wording is translated in every Admin language that has translations.
|
|
134
|
+
- **Smaller startup:**
|
|
135
|
+
- Generated Workers emit a repeated SQL statement once, and REST loads a Procedure on its first request. A generated
|
|
136
|
+
D1 Worker's startup is about 20% smaller.
|
|
137
|
+
- Admin loads sign-in, OAuth consent and the collection list on demand, and the Admin MCP App uses native select and
|
|
138
|
+
popover controls.
|
|
139
|
+
- **Fixes:**
|
|
140
|
+
- Admin forms and refresh;
|
|
141
|
+
- `mantle bundle` under `wrangler dev` reports stale generated output in one line, instead of a failed build;
|
|
142
|
+
- generation reports a SQL parser that cannot load in the current runtime as such, instead of `SQL_SYNTAX`;
|
|
143
|
+
- the handbook renders under Vue-based site generators;
|
|
144
|
+
- dependency updates for current advisories.
|
|
143
145
|
|
|
144
146
|
## 0.2.0 (2026-10-19)
|
|
145
147
|
|
|
@@ -25,6 +25,24 @@ the app entry (`--entry`) never imports, it warns and names the topic that shows
|
|
|
25
25
|
|
|
26
26
|
## Build from a product brief
|
|
27
27
|
|
|
28
|
+
**Plan once, then run to the end.** Before writing anything, reply with one plan and wait for the user's go-ahead.
|
|
29
|
+
Write it in the user's language and in business terms: no Schema, SQL, route, tool or package names.
|
|
30
|
+
|
|
31
|
+
- **What the app does:** what each kind of user can do, and the business rules it enforces. For example: "a full event
|
|
32
|
+
puts new sign-ups on a waiting list, and a cancellation moves the first person on it in".
|
|
33
|
+
- **How you will check it works:** who will try the app and what each of them tries to get done
|
|
34
|
+
([acceptance](../guides/agent-workflow-acceptance.md#plan-the-run)).
|
|
35
|
+
- **How you will check it is fast:** how much sample data, and what "fast enough" means for each page
|
|
36
|
+
([performance](../guides/performance.md#plan-the-pass)).
|
|
37
|
+
- **What you will do on the user's machine,** such as starting the app and opening the browser for them and for the
|
|
38
|
+
testers. Say it; do not ask. Ask only for what you cannot do yourself, such as a deployment or a credential.
|
|
39
|
+
- **Questions:** every rule the brief leaves open, such as limits, deadlines, who may see or change what, and what
|
|
40
|
+
happens on a cancellation. Give each one the answer you will assume if the user does not reply.
|
|
41
|
+
|
|
42
|
+
After the go-ahead, do every step below without stopping, and end with the report in the last step. Stop again only
|
|
43
|
+
for what the plan did not cover and needs the user: a credential, a deployment, a destructive action or a change of
|
|
44
|
+
scope.
|
|
45
|
+
|
|
28
46
|
1. `mantle init`, install, then read the app's `README.md` and search for `AGENT:`.
|
|
29
47
|
2. Map the brief to the [four atoms](../concepts/four-atoms.md): Schemas, Views, Procedures, Triggers.
|
|
30
48
|
Decide what each role (`admin`, `user`) does on each surface: Admin, MCP, REST and any visitor pages.
|
|
@@ -43,16 +61,14 @@ the app entry (`--entry`) never imports, it warns and names the topic that shows
|
|
|
43
61
|
the Schemas, Views, Procedures and Triggers and how they connect, with each surface's routes and tools. Tell the user
|
|
44
62
|
what they are looking at. Keep building while they look; the app rebuilds on every change. Without a browser on the
|
|
45
63
|
machine, give the user the admin URL it prints.
|
|
46
|
-
6. **
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
each role to a fresh evaluator as a URL that carries that role's session. After a repair, the guide's
|
|
64
|
+
6. **Run [role-only acceptance](../guides/agent-workflow-acceptance.md)** (`mantle help agent-workflow-acceptance`) as
|
|
65
|
+
planned. Scripted smoke is not acceptance. `pnpm accept` starts the app and prints, for each role, a URL that carries
|
|
66
|
+
that role's session; give each URL to a fresh evaluator. After a repair, the guide's
|
|
50
67
|
[re-verification rule](../guides/agent-workflow-acceptance.md#re-verify-what-a-repair-touches) decides which roles
|
|
51
68
|
and surfaces run again.
|
|
52
|
-
7. **
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
parts are reported as they are, never optimized. A declined step is reported as not run, never as done.
|
|
69
|
+
7. **Run the [performance pass](../guides/performance.md)** as planned, for every role and surface acceptance reports
|
|
70
|
+
CONVERGED. BLOCKED or UNVERIFIED parts are reported as they are, never optimized. A step the user declined in the
|
|
71
|
+
plan is reported as not run, never as done.
|
|
56
72
|
8. **Report what changed, not only that it passed:** the [acceptance summary](../guides/agent-workflow-acceptance.md#summarise-for-the-user)
|
|
57
73
|
and the [performance summary](../guides/performance.md#summarise-for-the-user), then the layered status.
|
|
58
74
|
|
|
@@ -40,7 +40,7 @@ module the entry never imports.
|
|
|
40
40
|
| `cloudflare-d1` | sqlite | D1 binding/session |
|
|
41
41
|
| `cloudflare-postgres` | postgres | postgres.js, usually with Hyperdrive |
|
|
42
42
|
|
|
43
|
-
Other handles may adapt to the same [structural driver contracts](../guides/adapter-guide.md). Dialects are exactly postgres and sqlite in 0.2.
|
|
43
|
+
Other handles may adapt to the same [structural driver contracts](../guides/adapter-guide.md). Dialects are exactly postgres and sqlite in 0.2.
|
|
44
44
|
|
|
45
45
|
| Option | Meaning |
|
|
46
46
|
| --- | --- |
|
package/package.json
CHANGED
package/skills/mantle/SKILL.md
CHANGED
|
@@ -18,7 +18,8 @@ its docs one topic at a time.
|
|
|
18
18
|
2. **Work in the user's application.** Read its `package.json` and lockfile for the exact Mantle version and keep using
|
|
19
19
|
that version's docs until the user asks to upgrade (`mantle help releases/index`). Preserve existing code, identity,
|
|
20
20
|
versions and resources.
|
|
21
|
-
3. **
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
3. **Plan once, then run to the end.** For a new app, first reply with the entry page's plan, in plain business terms
|
|
22
|
+
and with the questions the brief leaves open, and wait for one go-ahead. Then build, show the Developer UI, accept
|
|
23
|
+
and measure without stopping. Never report done without acceptance and performance; end with what each found and
|
|
24
|
+
changed, and each layer as CONVERGED, BLOCKED or UNVERIFIED.
|
|
24
25
|
4. **Deploy, delete remote data or publish nothing unless the user asks for that exact action.**
|