@aotter/mantle 0.1.3 → 0.1.5-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +20 -20
  2. package/dist/cli/generate-cloudflare.d.ts +7 -0
  3. package/dist/cli/generate-cloudflare.d.ts.map +1 -0
  4. package/dist/cli/generate-cloudflare.js +123 -0
  5. package/dist/cli/generate-cloudflare.js.map +1 -0
  6. package/dist/cli/generate-project.d.ts +25 -0
  7. package/dist/cli/generate-project.d.ts.map +1 -0
  8. package/dist/cli/generate-project.js +282 -0
  9. package/dist/cli/generate-project.js.map +1 -0
  10. package/dist/cli/generate-sites.d.ts +8 -0
  11. package/dist/cli/generate-sites.d.ts.map +1 -0
  12. package/dist/cli/generate-sites.js +273 -0
  13. package/dist/cli/generate-sites.js.map +1 -0
  14. package/dist/cli/generate.d.ts.map +1 -1
  15. package/dist/cli/generate.js +121 -10
  16. package/dist/cli/generate.js.map +1 -1
  17. package/dist/cli/main.d.ts +1 -1
  18. package/dist/cli/main.d.ts.map +1 -1
  19. package/dist/cli/main.js +11 -11
  20. package/dist/cli/skills.js +1 -1
  21. package/dist/cli/skills.js.map +1 -1
  22. package/docs/adr/0001-four-atom-manifest-model.md +3 -2
  23. package/docs/adr/0013-agent-provisioned-consumer-projects.md +4 -4
  24. package/docs/adr/0016-site-semantic-layer.md +5 -4
  25. package/docs/adr/0018-core-starters-repository-boundary.md +1 -1
  26. package/docs/adr/0021-retire-starter-scaffolding.md +1 -1
  27. package/docs/adr/0026-progressive-generate.md +36 -0
  28. package/docs/adr/0027-scheduled-procedure-triggers.md +31 -0
  29. package/docs/adr/0028-schema-ttl-expiry.md +33 -0
  30. package/docs/adr/README.md +7 -4
  31. package/docs/agent-prompts.md +41 -78
  32. package/docs/assets/mantle-admin-developer.png +0 -0
  33. package/docs/examples/README.md +1 -1
  34. package/docs/examples/host-chatgpt-sites/README.md +29 -12
  35. package/docs/examples/host-chatgpt-sites/drizzle/0003_store_instance_id.sql +1 -0
  36. package/docs/examples/host-chatgpt-sites/drizzle/0004_mantle.sql +10 -0
  37. package/docs/examples/host-chatgpt-sites/drizzle/0005_mantle.sql +24 -0
  38. package/docs/examples/host-chatgpt-sites/drizzle/meta/_journal.json +1 -1
  39. package/docs/examples/host-chatgpt-sites/drizzle/meta/mantle-state.json +60 -0
  40. package/docs/examples/host-chatgpt-sites/package.json +1 -1
  41. package/docs/examples/host-chatgpt-sites/public/site.css +1 -1
  42. package/docs/examples/host-chatgpt-sites/scripts/build.mjs +2 -1
  43. package/docs/examples/host-chatgpt-sites/scripts/check.mjs +2 -0
  44. package/docs/examples/host-chatgpt-sites/scripts/migration.mjs +42 -8
  45. package/docs/examples/host-chatgpt-sites/src/chatgpt-auth.ts +9 -6
  46. package/docs/examples/host-chatgpt-sites/src/index.ts +1 -1
  47. package/docs/examples/host-chatgpt-sites/src/web.ts +1 -1
  48. package/docs/examples/host-local-admin-otp/package.json +2 -2
  49. package/docs/examples/host-minimal-worker/README.md +5 -5
  50. package/docs/examples/host-minimal-worker/package.json +2 -2
  51. package/docs/handbook/{sites → chatgpt-sites}/equipment-checkout.md +1 -1
  52. package/docs/handbook/chatgpt-sites/generated-app.md +84 -0
  53. package/docs/handbook/{sites → chatgpt-sites}/index.md +35 -13
  54. package/docs/handbook/cloudflare/authentication.md +19 -2
  55. package/docs/handbook/cloudflare/bindings.md +4 -11
  56. package/docs/handbook/cloudflare/chatgpt-sites.md +6 -6
  57. package/docs/handbook/cloudflare/conventional-worker.md +7 -3
  58. package/docs/handbook/cloudflare/deploy-and-operate.md +4 -3
  59. package/docs/handbook/cloudflare/media-r2.md +2 -2
  60. package/docs/handbook/concepts/four-atoms.md +1 -1
  61. package/docs/handbook/concepts/lifecycle-and-locales.md +1 -1
  62. package/docs/handbook/concepts/mcp-and-agents.md +24 -4
  63. package/docs/handbook/concepts/procedures-and-triggers.md +1 -1
  64. package/docs/handbook/concepts/runtime-and-adapters.md +8 -1
  65. package/docs/handbook/concepts/views.md +1 -1
  66. package/docs/handbook/guides/agent-setup.md +8 -7
  67. package/docs/handbook/navigation.json +7 -6
  68. package/docs/handbook/reference/diagnostics.md +5 -0
  69. package/docs/handbook/reference/procedure.md +52 -1
  70. package/docs/handbook/reference/schema.md +27 -1
  71. package/docs/handbook/reference/surface.md +3 -3
  72. package/docs/handbook/reference/trigger.md +21 -1
  73. package/docs/handbook/releases/index.md +81 -1
  74. package/docs/handbook/start/overview.md +6 -3
  75. package/docs/handbook/start/project-and-cli.md +103 -119
  76. package/docs/handbook/start/quickstart-admin.md +6 -4
  77. package/docs/handbook/start/quickstart-worker.md +17 -11
  78. package/docs/release-process.md +3 -2
  79. package/docs/sealed-pipeline-ownership.md +1 -1
  80. package/docs/skills/develop/SKILL.md +258 -0
  81. package/docs/skills/integrate/SKILL.md +60 -0
  82. package/docs/skills/media-gc/SKILL.md +85 -0
  83. package/docs/skills/plugin/SKILL.md +132 -0
  84. package/docs/skills/provision/SKILL.md +194 -0
  85. package/docs/skills/theme/SKILL.md +77 -0
  86. package/docs/skills/update/SKILL.md +51 -0
  87. package/docs/spec-only-host-adoption.md +1 -1
  88. package/package.json +19 -18
  89. package/skills/README.md +28 -21
  90. package/skills/develop/SKILL.md +16 -8
  91. package/skills/install/SKILL.md +103 -128
  92. package/skills/integrate/SKILL.md +60 -0
  93. package/skills/media-gc/SKILL.md +2 -2
  94. package/skills/plugin/SKILL.md +2 -2
  95. package/skills/provision/SKILL.md +3 -3
  96. package/skills/theme/SKILL.md +2 -2
  97. package/skills/update/SKILL.md +2 -2
  98. package/templates/chatgpt-sites/auth.ts +66 -0
  99. package/templates/chatgpt-sites/build.mjs +14 -0
  100. package/templates/chatgpt-sites/env.ts +1 -0
  101. package/templates/chatgpt-sites/mcp.ts +48 -0
  102. package/templates/chatgpt-sites/public-mcp.ts +29 -0
  103. package/templates/chatgpt-sites/smoke-local.mjs +20 -0
  104. package/skills/.keep +0 -0
  105. /package/docs/handbook/{sites → chatgpt-sites}/host-reference.md +0 -0
@@ -1,140 +1,124 @@
1
1
  ---
2
- description: The files you own in a Mantle project, every mantle and mantle-harness command with its flags, the generated module, the daily check loop, and version pins.
2
+ description: Generate a full Mantle app or select smaller modules, then safely rerun the CLI as your manifests evolve.
3
3
  ---
4
- # Project layout and the CLI loop
4
+ # Project layout and CLI
5
5
 
6
- This page describes a directly authored Mantle project: which files are yours, what the installed CLI does to them, and the loop you run before every commit. Surfaces are optional — take only what you need. [The minimal Worker](./quickstart-worker.md) is Spec + adapter without Admin. [Local Admin](./quickstart-admin.md) is the opt-in Dev UI path when humans need a console.
6
+ `mantle generate` can assemble a new application or compile manifests in an
7
+ existing one. A new hosted app defaults to Spec, Runtime, API, MCP, Admin and
8
+ an editable blank home. You can select a smaller set explicitly. It never
9
+ invents a business Schema or publishes a deployment.
7
10
 
8
- Agents can bootstrap with the install skill; human authors can follow this guide directly. For installation paths and the pinned-package handoff, see [Agent setup](../guides/agent-setup.md):
11
+ ## Start a new app
9
12
 
10
- ```sh
11
- npx skills add aotter/mantle --skill install
12
- ```
13
-
14
- ## You own the project
15
-
16
- Core is a manifest compiler and a runtime, not a project generator. You write `package.json`, the manifests, the Worker entry, handlers, TypeScript and provider configuration. `mantle generate` compiles what exists; it never initializes a missing project or invents a default Schema, frontend or home route.
17
-
18
- ```txt
19
- my-service/
20
- ├── package.json exact-pinned @aotter/mantle* + peers, scripts
21
- ├── tsconfig.json includes src/ and .mantle/generated/
22
- ├── wrangler.jsonc Worker name, flags, vars, bindings
23
- ├── .dev.vars local secrets for wrangler dev; never committed
24
- ├── manifests/
25
- │ └── site.yaml immediate .yaml/.yml files; multi-document with ---
26
- ├── src/
27
- │ ├── index.ts createMantleWorker({ plan, extend })
28
- │ └── mantle/handlers/ handler refs (a convention; any path under src/)
29
- ├── public/ required ASSETS root when Admin is installed; generate writes public/_mantle/admin/
30
- ├── .mantle/generated/
31
- │ └── mantle.ts written by mantle generate
32
- ├── .agents/skills/mantle-*/ written by mantle skills
33
- └── .claude/skills/mantle-*/ same bytes, for Claude compatibility
34
- ```
35
-
36
- The minimal Worker reference keeps `.mantle/`, `.agents/`, `.claude/`, `.wrangler/`, `.dev.vars*` and `.env*` out of git and regenerates the first three in its `check` script. Committing the generated files is also workable, because `generate --check` and `skills --check` detect drift either way. Commit the lockfile in a real application and install with `--frozen-lockfile` afterwards.
37
-
38
- `mantle validate` greps `./src` for the names of `handler.kind: ref` Procedures; a handler that is not found anywhere under `src/` produces a `HANDLER_NOT_REGISTERED` warning, so keep handlers under that root or pass `--source`.
39
-
40
- ## The CLI
41
-
42
- The umbrella package installs two binaries, `mantle` and `mantle-harness`. Run them through the package manager, for example `pnpm exec mantle generate`. Defaults shown are the pinned ones. Bare `mantle` / `mantle --help` prints a layered overview of optional surfaces (Minimal Spec + generate, Runtime / adapter, opt-in Admin). `generate --help` and `validate --help` stay on the compile path. After a successful `generate`, the CLI says Admin is opt-in: next steps when `@aotter/mantle-admin-ui` is installed, otherwise an API-only tip.
43
-
44
- | Command | Flags | Does |
45
- |---|---|---|
46
- | `mantle generate` | `--manifests <dir>` (default `./manifests`), `-o, --output <dir>` (default `.mantle/generated`), `--namespace <name>` (default `Mantle`), `--check` | Validate, link and compile manifests; write `mantle.ts`; sync Admin assets when installed. `--check` exits 1 without writing when output is stale. |
47
- | `mantle validate` | `--manifests <dir>`, `--source <dir>` (default `./src`), `--no-source`, `--phase preview\|deploy` (default `preview`), `--format json\|text`, `--json` | Static manifest and handler-source validation. Exit 0 with warnings allowed, 1 on any error, 2 on a CLI invocation problem. |
48
- | `mantle skills` | `--check` | Copy every skill marked `projection: project` into `.agents/skills/mantle-<name>/` and `.claude/skills/mantle-<name>/`. `--check` exits 1 when a projection is stale. |
49
- | `mantle emit-openapi` | `--manifests <dir>`, `--title <str>` (default `mantle`), `--version <str>` (default `0.1.0`), `--session-cookie-name <str>`, `-o, --output <file>` | Emit OpenAPI 3.1 for HTTP Triggers and `GET /api/views/<name>` routes to stdout or a file. MCP is out of scope. |
50
- | `mantle-harness indexes` | `--manifests <dir>`, `--rows <n>` (default 2000), `--require <view>` (repeatable), `--require-public`, `--format text\|json` | Execute compiled Views in crowded SQLite and inspect query plans; exit 1 when a required View lacks its access path. |
51
- | `mantle-harness http` | `--base-url <url>`, `--route <name=path-or-url>` (repeatable, required), `--rounds <n>` (default 20), `--warmup <n>` (default 2), `--format text\|json` | Sample a running Worker and report p50/p95 timings plus query-count and `rows_read` metric headers. |
52
-
53
- Advanced manifest primitives live in the `@aotter/mantle-spec` package's own `mantle-spec` binary: `mantle-spec introspect [--manifests <dir>]` dumps the parsed manifest tree as JSON, and `mantle-spec emit-types [--manifests <dir>] [--namespace <name>] [-o <file>]` emits standalone `.d.ts` declarations. Add `@aotter/mantle-spec` as a direct dependency to run them. The full flag reference is in [HTTP, MCP, CLI and packages](../reference/surface.md).
54
-
55
- ### What `generate` does and does not do
56
-
57
- `generate` reads the manifest directory, runs the same validation as `validate` (without the handler-source grep), links the set, and emits one `.mantle/generated/mantle.ts`. When `@aotter/mantle-admin-ui` is installed it also syncs the **prebuilt** Admin SPA into `public/_mantle/admin/`, excluding the package's `server.*` exports; Core-only installs skip that copy. Any error diagnostic stops the run with exit 1.
58
-
59
- Do not Vite-build Admin unless you are developing `@aotter/mantle-admin-ui` itself. A Cloudflare project that serves Admin must declare Static Assets:
13
+ Choose a host before running the command. The integrated hosts are `cf` and
14
+ `chatgpt-sites`; `--features spec` works without a host. Install one exact
15
+ published SDK version, then let the CLI declare its matching optional packages:
60
16
 
61
- ```jsonc
62
- "assets": { "directory": "./public", "binding": "ASSETS" }
17
+ ```sh
18
+ mkdir my-app && cd my-app
19
+ npm init -y
20
+ npm pkg set type=module
21
+ MANTLE_VERSION=$(npm view @aotter/mantle@latest version)
22
+ npm install --save-exact "@aotter/mantle@$MANTLE_VERSION"
23
+ npx mantle generate --host cf
24
+ npm install
25
+ npx mantle generate
26
+ npm run build
63
27
  ```
64
28
 
65
- That binding is a hard requirement. If `/admin` returns SPA `index.html` (`200`) while `/_mantle/admin/assets/*` is `404`, the page white-screens. Leave `/_mantle` out of `run_worker_first` so those files stay on the assets layer. `generate` warns when it syncs Admin and the local wrangler config has no `ASSETS` binding.
66
-
67
- It does not project skills, update packages, change styling, provision providers, or deploy. It does not create manifests: a missing or empty `manifests/` directory is an error, not a prompt.
68
-
69
- ## The generated module
70
-
71
- `.mantle/generated/mantle.ts` exports:
29
+ Confirm `MANTLE_VERSION` is a stable release, without a prerelease suffix.
30
+ Use `--host chatgpt-sites` for a Site; [its guide](../chatgpt-sites/generated-app.md)
31
+ continues with D1 migration, owner identity and local smoke. If you already
32
+ use pnpm, keep that one package manager and run `pnpm install` /
33
+ `pnpm exec mantle`. The first `generate` may exit asking you to install newly
34
+ declared packages; the second completes generation. A README or lockfile from
35
+ bootstrapping still counts as a new app. Once choices are saved, omit flags on
36
+ rerun.
72
37
 
73
- | Export | Purpose |
74
- |---|---|
75
- | `plan` | The sealed RuntimePlan with its fingerprint. The conventional Worker imports only this. |
76
- | `MantleHandlers<Env>` | The handler map type: one typed function per `handler.kind: ref` Procedure, receiving `(input, ctx)`. |
77
- | `createMantle({ storage, handlers, ports })` | Prepares storage eagerly once and returns the typed binding. No caching or retry. |
78
- | `bindMantle(runtime)` | The same typed binding over a runtime whose lifecycle the host already owns. |
79
-
80
- The binding exposes `mantle.views.<lowerCamelName>()`, `mantle.procedures.<name>(input, ctx)`, `mantle.entries.<collection>.createDraft({ data, authorId })`, typed indexed field reads such as `mantle.entries.<collection>.findManyByDataField({ field, value, limit })`, and the underlying `mantle.runtime`. Generated property names are deterministic lower-camel identifiers; calls keep the authored wire names internally. See [Typed queries](../guides/typed-queries.md) for internal Views and entry-reader examples. Details are in [HTTP, MCP, CLI and packages](../reference/surface.md).
81
-
82
- ## The daily loop
38
+ For a smaller composition, list wanted modules positively:
83
39
 
84
40
  ```sh
85
- pnpm install --frozen-lockfile
86
- pnpm exec mantle validate
87
- pnpm exec mantle generate
88
- pnpm exec mantle generate --check
89
- pnpm exec tsc --noEmit
90
- pnpm test # only when the project declares a test script
91
- pnpm exec mantle-harness indexes --require-public --format text
92
- pnpm exec wrangler dev --local
41
+ npx mantle generate --host cf --features spec,api
42
+ npx mantle generate --features spec
93
43
  ```
94
44
 
95
- Run the harness after any change to a Schema index, View filter or ordering, or public route; declare the smallest ordered index the measured path needs and respect SQLite's leftmost-prefix rule. Before a deploy, run `mantle validate --phase deploy`. Probe at least one declared route on the local origin; a `200` from a public View does not prove Admin or MCP login works. When Admin is installed, also probe `/admin/sign-in` and one `/_mantle/admin/assets/*` URL — both must be `200`. HTML 200 with asset 404 is the white-screen class of bug.
96
-
97
- ## Connecting an agent
45
+ Dependencies are expanded in the saved selection: `api` includes Runtime and
46
+ Spec; `admin` includes Runtime, API and MCP. Supported features are `spec`,
47
+ `runtime`, `api`, `mcp`, `admin`, `web`. No host is needed for Spec-only. Use an
48
+ explicit host in automation so a terminal prompt cannot stall. The selection
49
+ lives in `mantle.config.json`; changing it later requires a deliberate migration,
50
+ not an accidental CLI flag.
98
51
 
99
- `mantle skills` projects the skills the installed package marks `projection: project`. At this version those are `develop`, `plugin`, `theme` and `update`; `install`, `media-gc` and `provision` stay opt-in because they create projects, delete remote objects or handle production secrets. Both tool layouts receive identical bytes. Generation never rewrites these files.
52
+ ## Files and ownership
100
53
 
101
- Install the plugin bundle in the agent host. Cold start uses
102
- the install skill; an already-installed project pins packages from `package.json`:
54
+ | File | Owner | What happens on rerun |
55
+ |---|---|---|
56
+ | `manifests/*.yaml`, `src/handlers.ts`, `src/home.ts` | You | Preserved. Add domain behavior and edit the blank home here. |
57
+ | `package.json`, `mantle.config.json`, `wrangler.jsonc` | Shared | Required versions and scripts are added; existing user values are preserved or conflicts reported. |
58
+ | `.mantle/generated/*`, `src/storage-fingerprint.json` | CLI | Rebuilt from the saved selection and manifests. |
59
+ | `drizzle/*.sql` on Sites | Review and apply | New migrations append; applied migrations are never rewritten. |
60
+ | `public/_mantle/admin/*` | CLI | Prebuilt Admin assets copied from the selected exact package. |
61
+ | `.openai/hosting.json` on Sites | Sites | Binding metadata is created locally; existing project metadata is preserved. |
62
+
63
+ A generated Worker imports the sealed `plan`, your handler map and the selected
64
+ modules. Generated files carry a marker so the CLI can distinguish them from
65
+ user-owned code. A rerun refuses to replace an unmarked file. Existing
66
+ applications without a saved selection keep their direct-authoring compile
67
+ behavior. For integration into an independently authored application, use the
68
+ installed `docs/skills/integrate/SKILL.md` to choose an embedding, incremental
69
+ replacement or rebuild strategy. Generation does not verify arbitrary host
70
+ entry points or deployment wiring.
71
+
72
+ `generate` accepts `--manifests <dir>` (default `./manifests`), `--output <dir>`
73
+ (default `.mantle/generated`), `--namespace <name>`, `--host cf|chatgpt-sites`,
74
+ `--features <comma-list>` and `--check`. Check mode exits nonzero
75
+ on drift and does not write. Sites also accepts `--review-unique-indexes` for
76
+ an explicit, source-bound unique tuple migration and duplicate preflight;
77
+ [review the D1 procedure](../chatgpt-sites/generated-app.md) before applying
78
+ it. `mantle validate` checks grammar and linked
79
+ capabilities; `--phase deploy` adds deployment checks. `mantle skills` projects
80
+ the installed SDK's project skills into `.agents/skills/` and `.claude/skills/`;
81
+ `mantle skills --check` detects drift. `mantle emit-openapi` describes HTTP
82
+ Triggers and View REST routes; `mantle-harness indexes` and `http` inspect
83
+ queries and running routes. [Command reference](../reference/surface.md).
84
+
85
+ ## Verify the assembled app
103
86
 
104
87
  ```sh
105
- # Canonical
106
- npx skills add aotter/mantle --skill install
107
-
108
- # Claude Code — two separate prompts
109
- /plugin marketplace add aotter/mantle
110
- /plugin install mantle@mantle
111
-
112
- # Codex
113
- codex plugin marketplace add aotter/mantle
114
- codex plugin add mantle@mantle
88
+ npx mantle generate --check
89
+ npx mantle skills
90
+ npx mantle skills --check
91
+ npm run typecheck
92
+ npm run build
93
+ npm run dev
115
94
  ```
116
95
 
117
- The projected `develop` skill tells the agent to read `package.json` for the installed version, the manifests and adapter config, and the docs under `node_modules/@aotter/mantle/docs/` before editing. To connect an MCP client to the running Worker, see [MCP and agents](../concepts/mcp-and-agents.md).
118
-
119
- ## Version pins
120
-
121
- - Pin every `@aotter/mantle*` package to one exact version and move them together. Check that release's peer ranges when you move.
122
- - This handbook describes the snapshot in this source tree. Use the docs that ship with the version in `package.json`, not a floating branch.
123
- - The authoring CLI is `generate`, `validate`, `emit-openapi` and `skills`. `mantle-harness` is the measurement binary. There is no `create` / `update` happy path.
124
- - When you change versions: pin the new exact version and refresh the lockfile; keep the Worker, D1, KV identity, origins, auth mode and secrets; then run `generate`, `generate --check`, `skills`, `skills --check`, `validate`, typecheck and tests before deploying.
96
+ Run scripts that exist in the selected project; Spec-only has no server to
97
+ start. Run `npx mantle validate` after adding the first Manifest: the validator
98
+ reports `MANIFEST_ROOT_NOT_FOUND` on an intentionally empty app. A full
99
+ Cloudflare app should serve the blank home and Admin assets.
100
+ For local CF Admin, copy `.dev.vars.example` to `.dev.vars`, replace
101
+ `ADMIN_EMAIL` with the intended owner's address and `BETTER_AUTH_SECRET` with
102
+ a random 32-byte secret, and keep `PUBLIC_ORIGIN` equal to the loopback URL
103
+ wrangler prints. Open `/admin/sign-in` with that email and read the OTP in
104
+ wrangler logs. Check that `/_mantle/admin/assets/*` loads, an anonymous
105
+ `/admin/api/site-settings` request is denied, and the signed-in owner can read
106
+ it. Verify anonymous staff MCP access fails before claiming it works. A full
107
+ Site must also apply its reviewed
108
+ D1 migration before the Worker boots. The public MCP endpoint is discoverable
109
+ without a staff session; the staff endpoint requires the host's verified
110
+ identity and a Mantle role. See [MCP and agents](../concepts/mcp-and-agents.md).
111
+
112
+ For an already installed app, confirm `node_modules/@aotter/mantle/package.json`
113
+ and the lockfile agree. Use that package's CLI and `docs/` tree; the latest
114
+ GitHub handbook may describe a newer release. Keep all selected
115
+ `@aotter/mantle*` packages on one exact version. The prior direct-authoring
116
+ contract remains valid for older installed SDKs; upgrade deliberately using
117
+ [release notes](../releases/index.md).
125
118
 
126
119
  ## Source
127
- - [`docs/direct-authoring.md`](../../../docs/direct-authoring.md)
128
- - [`docs/examples/host-local-admin-otp/README.md`](../../../docs/examples/host-local-admin-otp/README.md)
129
- - [`docs/examples/host-local-admin-otp/wrangler.jsonc`](../../../docs/examples/host-local-admin-otp/wrangler.jsonc)
130
- - [`docs/examples/host-minimal-worker/.gitignore`](../../../docs/examples/host-minimal-worker/.gitignore)
131
- - [`packages/mantle/README.md`](../../../packages/mantle/README.md)
132
- - [`packages/mantle/src/cli/main.ts`](../../../packages/mantle/src/cli/main.ts)
133
- - [`packages/mantle/src/cli/generate.ts`](../../../packages/mantle/src/cli/generate.ts)
134
- - [`packages/mantle/src/cli/skills.ts`](../../../packages/mantle/src/cli/skills.ts)
135
- - [`packages/mantle/src/cli/harness.ts`](../../../packages/mantle/src/cli/harness.ts)
136
- - [`packages/mantle/src/codegen/emitMantleModule.ts`](../../../packages/mantle/src/codegen/emitMantleModule.ts)
137
- - [`packages/mantle-spec/src/infrastructure/cli/ValidateCommand.ts`](../../../packages/mantle-spec/src/infrastructure/cli/ValidateCommand.ts)
138
- - [`packages/mantle-spec/src/infrastructure/cli/EmitOpenapiCommand.ts`](../../../packages/mantle-spec/src/infrastructure/cli/EmitOpenapiCommand.ts)
139
- - [`packages/mantle-spec/src/infrastructure/cli/MantleCli.ts`](../../../packages/mantle-spec/src/infrastructure/cli/MantleCli.ts)
140
- - [`skills/develop/SKILL.md`](../../../skills/develop/SKILL.md)
120
+
121
+ - [Generate CLI](../../../packages/mantle/src/cli/generate.ts)
122
+ - [Project selection and package pins](../../../packages/mantle/src/cli/generate-project.ts)
123
+ - [Cloudflare assembly](../../../packages/mantle/src/cli/generate-cloudflare.ts)
124
+ - [ChatGPT Sites assembly](../../../packages/mantle/src/cli/generate-sites.ts)
@@ -3,9 +3,11 @@ description: "Open local Admin in one shot: follow the official OTP example, bin
3
3
  ---
4
4
  # Quickstart: local Admin
5
5
 
6
- Admin is **opt-in**: use it when humans need a Dev UI. A complete Mantle
7
- service does not require this surface. The default embed path — Spec + Worker
8
- without Admin — is [Quickstart: a minimal Worker](./quickstart-worker.md).
6
+ New generated CF and Sites apps include Admin by default. To leave it out,
7
+ select smaller features explicitly. This tutorial shows the existing
8
+ direct-authored Worker integration with local email OTP; use it when you own
9
+ the Worker entry. [Project layout and CLI](./project-and-cli.md) describes the
10
+ new generated path.
9
11
 
10
12
  The procedural source of truth is the official example:
11
13
 
@@ -29,7 +31,7 @@ Traps (documented on the example):
29
31
  - `pnpm check` / smoke rewrites `.dev.vars` to a smoke-only port — restore it
30
32
  from `.dev.vars.example` before `pnpm dev`.
31
33
 
32
- Install every `@aotter/mantle*` package from the `latest` dist-tag; see
34
+ Pin every selected `@aotter/mantle*` package to the same exact version; see
33
35
  [Versions](../reference/surface.md#versions). Admin needs both
34
36
  `@aotter/mantle-admin` and `@aotter/mantle-admin-ui`, wrangler `ASSETS` on
35
37
  `./public`, and `createAuth` email-otp + `ConsoleEmailSender`.
@@ -3,7 +3,13 @@ description: "Author a minimal Cloudflare Worker from scratch: one Schema, one p
3
3
  ---
4
4
  # Quickstart: a minimal Worker
5
5
 
6
- This page reproduces Core's API-only Worker reference as a from-scratch walkthrough. It is the embed / adapter path: View REST without Admin, Auth or a visitor frontend. Admin is opt-in when humans need a console — [Quickstart: local Admin](./quickstart-admin.md). Resolve the intended release once and pin every `@aotter/mantle*` package to it; see [Versions](../reference/surface.md#versions).
6
+ This page reproduces the API-only Worker reference as a direct-authoring
7
+ walkthrough: View REST without Admin, Auth or a visitor frontend. For a new
8
+ project, `mantle generate --host cf --features spec,api` assembles that smaller
9
+ composition. Omit `--features` to include Admin, MCP and a blank home. The
10
+ [local Admin tutorial](./quickstart-admin.md) covers an authored Worker entry.
11
+ Pin every selected `@aotter/mantle*` package to one exact version; see
12
+ [Versions](../reference/surface.md#versions).
7
13
 
8
14
  ## Prerequisites
9
15
 
@@ -13,10 +19,9 @@ This page reproduces Core's API-only Worker reference as a from-scratch walkthro
13
19
 
14
20
  ## 1. `package.json`
15
21
 
16
- The `latest` entries below are bootstrap placeholders. Step 5 replaces both
17
- with one exact version before the first build. For a prerelease evaluation,
18
- select its exact version explicitly rather than mixing channels. The other
19
- entries are the peers and tools used by this reference.
22
+ Step 5 adds the two Mantle packages at one exact version. For a prerelease
23
+ evaluation, select its exact version explicitly rather than mixing channels.
24
+ The entries below are the peers and tools used by this direct-authored reference.
20
25
 
21
26
  ```json
22
27
  {
@@ -31,8 +36,6 @@ entries are the peers and tools used by this reference.
31
36
  "check": "mantle generate && mantle generate --check && mantle validate && mantle skills && mantle skills --check && tsc --noEmit"
32
37
  },
33
38
  "dependencies": {
34
- "@aotter/mantle": "latest",
35
- "@aotter/mantle-cloudflare": "latest",
36
39
  "better-auth": "1.7.2",
37
40
  "hono": "^4.13.3",
38
41
  "zod": "^4.5.4",
@@ -172,10 +175,13 @@ curl -i http://127.0.0.1:8787/mcp/staff
172
175
  - `.mantle/generated/mantle.ts` — one module with the sealed `plan`, generated types (`MantleHandlers<Env>`), `createMantle` and `bindMantle`. The Worker entry above imports only `plan`.
173
176
  - `public/_mantle/admin/` — the Admin SPA, synced only when `@aotter/mantle-admin-ui` is installed. This project did not install it, so nothing is written there and `/admin` has no assets.
174
177
 
175
- `generate` fails on missing or invalid manifests and never creates a project, a default Schema or a home route. `mantle generate --check` reports stale output without writing. The reference keeps `.mantle/`, `.agents/` and `.claude/` out of git and regenerates them in `check`; see [Project layout and the CLI loop](./project-and-cli.md).
176
-
177
- > **npm and optional peers**
178
- > A cold npm install can fail with `ERESOLVE` when an Auth peer selects a different optional `@libsql/client` than this snapshot declares. If that happens, pin `@libsql/client` in `overrides` to the range in this checkout's `package.json` and rerun `npm install`. Do not use `--force`. Commit the lockfile and use `npm ci` afterwards.
178
+ This walkthrough uses the existing direct-authored Worker entry; in that legacy
179
+ compile mode, `generate` expects the supplied manifests and does not add a
180
+ home route. New applications can instead use `mantle generate --host cf`
181
+ with `--features spec,api` for a smaller assembled Worker. The CLI never
182
+ invents a Schema. `mantle generate --check` reports stale output without
183
+ writing. The reference keeps `.mantle/`, `.agents/` and `.claude/` out of git
184
+ and regenerates them in `check`; see [Project layout and CLI](./project-and-cli.md).
179
185
 
180
186
  ## Next steps
181
187
 
@@ -110,10 +110,11 @@ dist-tag DELETE only added failure and re-run state, and Actions
110
110
  ```
111
111
 
112
112
  Leave the consumer cold-start entry **untagged**: `npx skills add
113
- aotter/mantle --skill install`, `/plugin marketplace add aotter/mantle`,
113
+ aotter/mantle`, `/plugin marketplace add aotter/mantle`,
114
114
  `codex plugin marketplace add aotter/mantle` and the plugin-manifest
115
115
  descriptions carry no `@v…` / `--ref`. Untagged resolves to `main`, which
116
- only moves at a release, so it is always the latest published version
116
+ normally moves at a release but may contain a source-only hotfix; the
117
+ installed npm package remains the version authority
117
118
  (#995, #998). Only "installed version" statements such as
118
119
  `(currently \`X.Y.Z\`)` are bumped.
119
120
 
@@ -65,7 +65,7 @@ release use `docs/examples/host-minimal-worker` from the same reviewed commit.
65
65
  Private consumers can still run the exact-tarball checker in their own repos;
66
66
  public Core PRs receive no cross-repository credentials:
67
67
 
68
- | Consumer | Revision | Gate authority | Manifest paths |
68
+ | Historical consumer | Revision | Gate at the time | Manifest paths |
69
69
  |---|---|---|---|
70
70
  | `aotter/mantle-starters` | `157e8f49e1e25ae1c52c0115f0dd9e8b6017ef0e` | Core CI + release | `blank/manifests/site.yaml`; `overlays/{community,intake,presence,publication,reservation,transaction}/manifests/site.yaml`; `recipes/typed-web/manifests/site.yaml` |
71
71
  | `aotter/mantle-landing` | `4381354dd25d5d94f4096cf3e55a4cb9eecbf3ad` | Landing CI + Core release | `manifests/site.yaml` |
@@ -0,0 +1,258 @@
1
+ ---
2
+ name: develop
3
+ description: Work on any Mantle project using the Core SDK contract. Use for manifest, runtime, content model, handler, adapter, validation, and MCP work after a project already exists.
4
+ metadata:
5
+ source: "@aotter/mantle"
6
+ sourcePath: docs/skills/develop/SKILL.md
7
+ applies_to: mantle grammar v0.1
8
+ projection: project
9
+ ---
10
+
11
+ # Mantle Develop
12
+
13
+ This is the Core workflow skill for an existing Mantle project. Repo-local
14
+ copies are byte-for-byte projections from the installed package; its embedded
15
+ docs govern runtime/API behavior.
16
+
17
+ ## First Read
18
+
19
+ 1. `package.json` for the installed `@aotter/mantle*` versions.
20
+ 2. The manifest directory selected by the project scripts, the actual host
21
+ entry and adapter config (for example `wrangler.jsonc` on Cloudflare).
22
+ Read custom Auth construction there when present.
23
+ 3. Optional local context: `.mantle/plugins.json`, `.mantle/plugins.lock.json`,
24
+ and `.mantle/recipes/`. Legacy launch/handoff files are context only.
25
+ 4. Installed Core docs in `node_modules/@aotter/mantle/docs/`.
26
+
27
+ If `node_modules/` is missing, run `pnpm install --frozen-lockfile` before
28
+ falling back to remote docs. Remote docs must use a tag matching the installed
29
+ version; never use `develop` branch docs for a versioned consumer project.
30
+
31
+ ## Existing Examples
32
+
33
+ Read installed `docs/handbook/start/project-and-cli.md` and
34
+ `docs/examples/README.md`. Use `docs/examples/host-minimal-worker/` for Spec +
35
+ adapter without Admin. Read `docs/examples/host-local-admin-otp/` only when the
36
+ project already has Admin or the human asked for Dev UI — that path is opt-in.
37
+ Ingest only `docs/examples/builtin-*.md` Manifests as grammar for new domains.
38
+ Read `docs/examples/cf-primitives-*.md` before inventing Durable Object, Queue,
39
+ cron, or `ref` handler patterns.
40
+ References are test/documentation, not a Starter or a fixed application shape.
41
+
42
+ Public rendering is opt-in consumer wiring: `mountPublicRoutes`, a
43
+ `TemplateRegistry`, and a matching `publicPathResolver` must agree on the
44
+ exposed collections. Do not auto-publish every Schema. Applications document their mounted URL surface in their own README.
45
+ Import the registry and resolver from `@aotter/mantle/web`; Core runtime does
46
+ not install public rendering by itself.
47
+
48
+ ## Authoring CLI
49
+
50
+ Use the project's scripts first; applications use the shipping
51
+ `mantle` authoring CLI from `@aotter/mantle`. Ask the installed CLI for its
52
+ command list instead of trusting one copied into prose — the surface is
53
+ version-matched and changes between releases:
54
+
55
+ ```bash
56
+ pnpm exec mantle --help
57
+ pnpm validate
58
+ ```
59
+
60
+ On 0.1.5 and newer, `generate --host cf|chatgpt-sites` assembles a new blank
61
+ app; no `--features` selects Spec, Runtime, API, MCP, Admin and Web. Explicit
62
+ `--features` selects a smaller composition. It never invents a business
63
+ Schema. Existing authored apps keep compile mode, and older installed CLIs
64
+ may not support project generation. Check this project's CLI help first.
65
+
66
+ ## Core Model
67
+
68
+ Mantle exposes exactly four declarative atoms:
69
+
70
+ | Atom | Purpose |
71
+ |---|---|
72
+ | `Schema` | Stored entity/table shape. |
73
+ | `View` | Read/query surface. |
74
+ | `Procedure` | Typed mutation or operation. |
75
+ | `Trigger` | HTTP/lifecycle/MCP invocation binding. |
76
+
77
+ Do not invent manifest kinds such as `Form`, `Feature`, `Workflow`, or
78
+ `Membership`. Compose those from the four atoms plus TypeScript only where
79
+ the atoms cannot express the behavior.
80
+
81
+ ## Choose the manifest feature first
82
+
83
+ Read installed `docs/handbook/reference/features.md` to map the requested
84
+ behavior to fields before adding handlers or a custom UI. For host-only reads,
85
+ `surface: internal` keeps a View out of REST/MCP/Admin while preserving its
86
+ `requires` checks. Read `docs/handbook/guides/typed-queries.md` for generated
87
+ View params/results, indexed entry reads, and their authorization boundary.
88
+ Use `from` for portable typed projections; SQL is for queries needing native
89
+ SQLite and produces `unknown` row types.
90
+
91
+ For Admin labels, inputs, collection columns/tabs, reports or action buttons,
92
+ read `docs/handbook/guides/admin-ui.md`. Prefer supported Schema/Procedure/View
93
+ metadata and `uiSchema` before custom frontend code. These control the Admin
94
+ console, not the visitor frontend. Regenerate and verify the actual console;
95
+ never edit generated `public/_mantle/admin/` assets.
96
+
97
+ ## Content Edits
98
+
99
+ - Follow the actual frontend content source. Use Admin or Staff MCP for
100
+ runtime-backed content. Do not invent an overlay/seed homepage.
101
+ - For a new submitted field, update the stored `Schema` and the public
102
+ `Procedure.spec.input` before any form UI. Keep public mutation inputs
103
+ `additionalProperties: false`; otherwise JSON Schema's default may strip an
104
+ undeclared field while returning success.
105
+ - Use `lifecycle: operational` for submissions, inquiries, orders, and other
106
+ Procedure-created operational records that staff inspect or correct. Reserve
107
+ `publishing` for content a person stages and publishes.
108
+ - Lifecycle `before_update` / `after_update` hooks also fire for unpublish,
109
+ archive, and every other status transition whose target is not `published`;
110
+ do not use them for edit-only work.
111
+ - When a form's fixed option values change, update the stored Schema and public
112
+ Procedure input `enum` together. Keep translated labels in the frontend content source;
113
+ Admin and Staff MCP derive their typed controls from the manifest values.
114
+ - If the application has a `page` Schema with sections, update its declared
115
+ section properties when adding display fields; an undeclared property has no
116
+ runtime-backed Admin or Staff MCP path.
117
+ - Update notification handlers when they need the new field. Test the stored
118
+ entry, not only the HTTP `{ "ok": true }` response.
119
+
120
+ ## Locales
121
+
122
+ - `data.locale` is reserved for `localized: true` Schemas. A non-localized
123
+ Schema must use a domain field such as `replyLocale`.
124
+ - Use a standalone localized Schema only for independent locale rows. For
125
+ versions of one entity, use a non-localized parent plus a localized child
126
+ with `translates: { parent, on }`. The child must own at least one field
127
+ besides `locale` and the join field.
128
+ - Parallel locale blocks must keep field names, option values, step IDs, and
129
+ result keys identical; translate display strings only.
130
+ - `siteDefaults.origin`, `siteDefaults.locales`, and `siteDefaults.icons` are
131
+ code-owned and boot-synced. The icon list is shared by browser favicons,
132
+ Admin chrome, and MCP `serverInfo.icons`; keep its static files under
133
+ `public/`. Brand, title, and description seed once, then change through site
134
+ settings.
135
+ - When changing an existing collection from `[slug]` to `[slug, locale]`,
136
+ boot with a Mantle version that reconciles obsolete unique indexes and test
137
+ the same slug in two locales. Do not patch D1 manually.
138
+
139
+ ## Adapter Boundary
140
+
141
+ The runtime is adapter-neutral. A `MantleStorageAdapter` prepares the compiled
142
+ plan into semantic storage ports; `createMantleRuntime` binds that prepared
143
+ storage and selected capabilities. Database drivers and asset serving belong
144
+ to the host/optional composition. Follow the installed adapter guide.
145
+
146
+ Do not assume Cloudflare unless the project imports `@aotter/mantle/cloudflare`
147
+ or its adapter config is visible. A future Netlify adapter should satisfy the
148
+ same Core workflow through its own ports and provider setup.
149
+
150
+ Site code is a consumer of this abstraction. Use Manifests, runtime use cases,
151
+ `runtime.entries`, and optional `runtime.siteConfig`; do not query Mantle-owned `entries` or
152
+ `site_config`, reach through deprecated `runtime.db`, copy generated-column
153
+ names, or construct SDK KV keys. Cloudflare bindings belong only at the
154
+ composition root. If a normal feature cannot be expressed through a
155
+ purpose-shaped surface, treat that as a Core abstraction gap instead of
156
+ teaching the project Mantle internals.
157
+
158
+ ## Auth Composition
159
+
160
+ Generated full apps select Admin by default; smaller selections can omit it.
161
+ A project without `@aotter/mantle-admin-ui` is complete when Admin was not
162
+ selected. If Admin was selected but its package is missing, install the
163
+ CLI-declared exact version and rerun generation.
164
+ When Admin is installed, `createMantleWorker({ auth })` with `email-otp`
165
+ and `ConsoleEmailSender` is the local human path (OTP in wrangler logs).
166
+ That override owns Auth construction; Core still owns `/admin` and
167
+ `/api/auth/*`. Admin also requires wrangler `assets.directory=./public`
168
+ and an `ASSETS` binding. A white screen at `/admin` with HTML 200 and
169
+ `/_mantle/admin/assets/*` 404 is a missing assets binding, not a missing
170
+ frontend build.
171
+
172
+ Generated Cloudflare apps use `MANTLE_AUTH_MODE=local-otp` on loopback after
173
+ copying `.dev.vars.example` to `.dev.vars` and setting a real owner email and
174
+ random secret. Production uses `hosted` or `self-managed` with provider
175
+ credentials and `ADMIN_GITHUB_LOGIN`. Conventional Cloudflare projects that
176
+ do not replace Auth use those two production modes; Core owns that standard
177
+ composition and rejects partial or mixed bindings. Preserve the explicit
178
+ mode recorded in Worker config, keep provider secrets out of source, and
179
+ do not infer a mode from whichever credentials happen to be present.
180
+
181
+ ## Performance Loop
182
+
183
+ After changing a Schema index, View filter/order, public API, or rendered page,
184
+ run the project's index check when present. Otherwise run the installed
185
+ harness directly:
186
+
187
+ ```bash
188
+ pnpm exec mantle-harness indexes --require-public --format text
189
+ ```
190
+
191
+ The check uses crowded real SQLite and the shipped compiler. It complements
192
+ `pnpm validate`; it does not replace correctness validation. Declare the
193
+ smallest ordered index justified by the measured path and respect SQLite's
194
+ leftmost-prefix rule; which columns an index may name and how a public View's
195
+ status predicate shapes it is in the handbook (`reference/schema.md#indexes`).
196
+ Do not change user-visible filter or ordering semantics
197
+ just to make the gate pass. Do not add every permutation or cache every read.
198
+
199
+ For relevant Cloudflare serving changes, start the project and sample the
200
+ actual routes:
201
+
202
+ ```bash
203
+ pnpm exec mantle-harness http \
204
+ --base-url http://127.0.0.1:8787 \
205
+ --route page=/en/example \
206
+ --rounds 20 --warmup 2 --format text
207
+ ```
208
+
209
+ Prefer query plan, query count, `rows_read` scaling, and cache MISS/HIT
210
+ evidence. Do not create CI gates from absolute local milliseconds.
211
+
212
+ ## Loop
213
+
214
+ ```bash
215
+ pnpm install --frozen-lockfile
216
+ pnpm validate
217
+ pnpm check:indexes # when the project provides it
218
+ pnpm typecheck
219
+ pnpm check
220
+ ```
221
+
222
+ Use `pnpm dev` for local preview when the project provides it.
223
+
224
+ ## Connect a Local MCP Client
225
+
226
+ Start the project with `pnpm dev`, then use the exact local origin it prints.
227
+ The conventional Cloudflare adapter exposes:
228
+
229
+ - `http://localhost:8787/mcp` for public tools;
230
+ - `http://localhost:8787/mcp/staff` for authenticated authoring tools.
231
+
232
+ Prefer the client's native remote HTTP + OAuth support. Use a standard
233
+ HTTP-to-stdio bridge such as `npx -y mcp-remote <url>` only when the client
234
+ accepts stdio MCP servers but cannot connect to remote HTTP directly. Mantle
235
+ does not own a separate local proxy or an auth-bypass mode.
236
+
237
+ Before changing client config, confirm the Worker is reachable:
238
+
239
+ ```bash
240
+ curl -i http://localhost:8787/mcp
241
+ ```
242
+
243
+ An OAuth-protected endpoint should respond with `401` and a
244
+ `WWW-Authenticate` resource-metadata challenge before sign-in. After
245
+ connecting, inspect `tools/list`; make one read-only `query_view_*` call when
246
+ available before invoking any mutation. Use project-scoped client config when
247
+ the client offers it, and never commit OAuth tokens or the bridge's token
248
+ cache.
249
+
250
+ ## Rules
251
+
252
+ - Keep content models in the configured manifest directory; its immediate
253
+ `.yaml` and `.yml` files are loaded together.
254
+ - Add TypeScript only for handlers, rendering, adapter wiring, or real behavior.
255
+ - Do not write directly to D1, KV, Postgres, or object storage for content
256
+ authoring. Use runtime use cases, admin APIs, or Staff MCP.
257
+ - Do not commit provider secrets.
258
+ - If the work is an installable capability, switch to `mantle:plugin`.