@aotter/mantle 0.0.11-alpha.26 → 0.0.11-alpha.28
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/package.json +5 -5
- package/skills/install/SKILL.md +156 -276
- package/skills/provision/SKILL.md +30 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aotter/mantle",
|
|
3
|
-
"version": "0.0.11-alpha.
|
|
3
|
+
"version": "0.0.11-alpha.28",
|
|
4
4
|
"description": "Umbrella entry for @aotter/mantle. Adopters install this one package and import from subpaths: /spec, /runtime, /cloudflare, /admin-ui. Sub-packages remain individually installable on npm for tooling / alt-adapter authors. The Netlify adapter ships as a private workspace stub in v0.1 — its subpath will be added when the impl lands in v0.2.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://mantle.tools/",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"README.md"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@aotter/mantle-admin-ui": "0.0.11-alpha.
|
|
51
|
-
"@aotter/mantle-runtime": "0.0.11-alpha.
|
|
52
|
-
"@aotter/mantle-spec": "0.0.11-alpha.
|
|
53
|
-
"@aotter/mantle-cloudflare": "0.0.11-alpha.
|
|
50
|
+
"@aotter/mantle-admin-ui": "0.0.11-alpha.28",
|
|
51
|
+
"@aotter/mantle-runtime": "0.0.11-alpha.28",
|
|
52
|
+
"@aotter/mantle-spec": "0.0.11-alpha.28",
|
|
53
|
+
"@aotter/mantle-cloudflare": "0.0.11-alpha.28"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@cloudflare/workers-oauth-provider": "^0.7.0",
|
package/skills/install/SKILL.md
CHANGED
|
@@ -1,77 +1,87 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mantle install
|
|
3
|
-
description: Install a
|
|
3
|
+
description: Install a Mantle consumer project from a landing-created launch command/session, then continue into deterministic provision. Use when the user pasted a Mantle launch command or session URL.
|
|
4
4
|
when_to_invoke: |
|
|
5
|
-
|
|
5
|
+
The user has a Mantle landing launch command/session URL and wants a new Mantle site scaffolded.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# mantle install
|
|
9
9
|
|
|
10
|
-
You
|
|
11
|
-
the landing launch flow, a short-lived launch session already carries
|
|
12
|
-
the launch-critical values. Treat that session as the source of truth
|
|
13
|
-
and scaffold first. Do not switch to the retired prompt-composition
|
|
14
|
-
flow.
|
|
10
|
+
You are installing a Mantle site for the user. The normal path is:
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
1. Mantle landing asks the launch questions.
|
|
13
|
+
2. Landing renders a short-lived launch session and `create-mantle`
|
|
14
|
+
command.
|
|
15
|
+
3. You run that command from the parent directory where the project
|
|
16
|
+
should be created.
|
|
17
|
+
4. You validate the generated repo, push it to the user's GitHub, then
|
|
18
|
+
continue with repo-local `mantle:provision`.
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Do not rebuild the old interview harness in chat. If the user has no
|
|
21
|
+
landing-created launch command/session, send them back to Mantle landing
|
|
22
|
+
to create one. Manual flag-by-flag scaffolding is for maintainers
|
|
23
|
+
debugging the scaffolder, not the user-facing install UX.
|
|
24
|
+
|
|
25
|
+
## Ground Truth
|
|
26
|
+
|
|
27
|
+
`@aotter/mantle-*` exposes exactly four declarative atoms scoped to
|
|
28
|
+
`cms.mantle.aotter.net/v1`, mapping 1-to-1 to Postgres primitives:
|
|
19
29
|
|
|
20
30
|
| Atom | Postgres analog | External surface |
|
|
21
31
|
|---|---|---|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
32
|
+
| Schema | `CREATE TABLE` | none directly |
|
|
33
|
+
| View | `CREATE VIEW` | auto-mounted at `GET /api/views/<name>` |
|
|
34
|
+
| Procedure | `CREATE FUNCTION` | none directly |
|
|
35
|
+
| Trigger | `CREATE TRIGGER` + cron + REST route + LISTEN/NOTIFY | binding atom |
|
|
26
36
|
|
|
27
|
-
Anything domain-shaped (Form, Membership, Workflow) is
|
|
37
|
+
Anything domain-shaped (Form, Membership, Workflow) is composed in the
|
|
38
|
+
consumer project from these four atoms plus user TypeScript. Full grammar
|
|
39
|
+
reference:
|
|
40
|
+
<https://raw.githubusercontent.com/aotter/mantle/develop/docs/design-atoms.md>.
|
|
28
41
|
|
|
29
42
|
After `create-mantle` runs, the scaffold's ground truth lives in:
|
|
30
43
|
|
|
31
44
|
| Path | Contents |
|
|
32
45
|
|---|---|
|
|
33
|
-
| `manifests/*.yaml` | Schemas / Views / Procedures / Triggers
|
|
34
|
-
| `src/mantleConfig.ts` | Site defaults, handler
|
|
35
|
-
| `src/handlers/` | Handler implementations
|
|
36
|
-
| `src/.mantle/generated.*.ts` | Scaffolder-owned feature glue
|
|
37
|
-
| `.mantle/features.json` |
|
|
38
|
-
|
|
|
39
|
-
| `
|
|
40
|
-
|
|
41
|
-
Live introspection (run from project root):
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
pnpm introspect # current manifest dump (atoms inventory)
|
|
45
|
-
pnpm emit-openapi # generated HTTP surface
|
|
46
|
-
pnpm emit-types # generated TS types
|
|
47
|
-
pnpm validate # grammar + cross-ref check (preview phase by default).
|
|
48
|
-
# For production-only checks, use
|
|
49
|
-
# `pnpm validate --phase deploy` or `pnpm validate:deploy`.
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Diagnostics are structured JSON with `code` + `suggestion` fields — surface both verbatim, don't paraphrase.
|
|
46
|
+
| `manifests/*.yaml` | Schemas / Views / Procedures / Triggers |
|
|
47
|
+
| `src/mantleConfig.ts` | Site defaults, handler registration, runtime bindings |
|
|
48
|
+
| `src/handlers/` | Handler implementations |
|
|
49
|
+
| `src/.mantle/generated.*.ts` | Scaffolder-owned feature glue |
|
|
50
|
+
| `.mantle/features.json` | Selected feature overlays |
|
|
51
|
+
| `.mantle/launch-state.json` | Non-secret launch choices from landing |
|
|
52
|
+
| `mantle/site.md` | Site semantic layer |
|
|
53
|
+
| `AGENTS.md` | Cross-tool agent entry |
|
|
53
54
|
|
|
54
|
-
##
|
|
55
|
+
## Accepted Inputs
|
|
55
56
|
|
|
56
|
-
Use
|
|
57
|
+
Use the launch-session fast path when the prompt contains either:
|
|
57
58
|
|
|
58
|
-
- a command shaped like `npx <tarball> launch --session <url-or-file
|
|
59
|
-
- a
|
|
59
|
+
- a command shaped like `npx <tarball> launch --session <url-or-file>`;
|
|
60
|
+
- a command shaped like `npx <tarball> <archetype> ...` generated by
|
|
61
|
+
Mantle landing;
|
|
62
|
+
- a launch session URL/file plus instructions to run `create-mantle
|
|
63
|
+
launch`.
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
Landing already collected the launch-critical values. Treat those values
|
|
66
|
+
as user-authorized for scaffolding. Do not ask content, voice, repo, or
|
|
67
|
+
locale questions again before scaffold.
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
The launch session/command authorizes only initial scaffold values:
|
|
64
70
|
|
|
65
|
-
|
|
71
|
+
- project name;
|
|
72
|
+
- brand / site name;
|
|
73
|
+
- archetype;
|
|
74
|
+
- theme and selected feature overlays;
|
|
75
|
+
- locales and canonical locale;
|
|
76
|
+
- GitHub owner / admin login;
|
|
77
|
+
- install description and summary.
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- It must not be copied into committed files, shell history snippets, issue comments, or handoff text. The scaffolder writes `.mantle/launch-state.json` with non-secret resumable metadata and intentionally redacts the raw session URL.
|
|
70
|
-
- It does **not** authorize Cloudflare resources, provider billing, custom domains, or production secrets. Provision still asks the user to complete the Cloudflare Dashboard first deploy and GitHub OAuth App setup in their own accounts.
|
|
79
|
+
It does not authorize Cloudflare resources, provider billing, OAuth
|
|
80
|
+
secrets, custom domains, or production deploy.
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
## Preflight
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
Run these before creating files:
|
|
75
85
|
|
|
76
86
|
```bash
|
|
77
87
|
node --version # need >= 22
|
|
@@ -79,271 +89,141 @@ pnpm --version # need >= 9
|
|
|
79
89
|
git --version
|
|
80
90
|
```
|
|
81
91
|
|
|
82
|
-
Confirm
|
|
92
|
+
Confirm the current working directory is the parent directory where the
|
|
93
|
+
new project should appear. If the child project directory already exists,
|
|
94
|
+
stop and ask the user whether to choose another empty directory. Do not
|
|
95
|
+
merge a fresh scaffold into an existing project.
|
|
96
|
+
|
|
97
|
+
## Scaffold
|
|
83
98
|
|
|
84
|
-
|
|
99
|
+
Run the launch command exactly as supplied. Do not rewrite values. Only
|
|
100
|
+
replace an obvious local file path if the user gave the file out of band.
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
85
103
|
|
|
86
104
|
```bash
|
|
87
105
|
npx <create-mantle-tarball> launch --session <session-url-or-file>
|
|
88
106
|
```
|
|
89
107
|
|
|
90
|
-
|
|
108
|
+
```bash
|
|
109
|
+
npx <create-mantle-tarball> <archetype> \
|
|
110
|
+
--project-name <project-name> \
|
|
111
|
+
--brand "<brand>" \
|
|
112
|
+
--description "<description>" \
|
|
113
|
+
--locales "<locale[,locale]>" \
|
|
114
|
+
--github-owner <github-owner> \
|
|
115
|
+
--admin-github-login <admin-login> \
|
|
116
|
+
--summary "<summary>"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`create-mantle` validates the session before filesystem writes,
|
|
120
|
+
downloads the requested starter ref, merges `_common/` + `<archetype>/`
|
|
121
|
+
+ feature overlays + theme overlays, fills placeholders, runs
|
|
122
|
+
`git init`, runs `pnpm install`, writes `.mantle/launch-state.json`, and
|
|
123
|
+
prints RUN_NOTES JSON.
|
|
91
124
|
|
|
92
125
|
After it returns:
|
|
93
126
|
|
|
94
127
|
1. Read RUN_NOTES.
|
|
95
128
|
2. Read `.mantle/launch-state.json`.
|
|
96
|
-
3. Walk the ground-truth files
|
|
97
|
-
4. Continue
|
|
98
|
-
|
|
99
|
-
Do not ask content/voice questions before scaffold. The natural point for user conversation is after the site exists locally and, preferably, after provision has produced a working URL. If the user explicitly wants to revise content before provision, keep it to the same small adjustment window described later in this Skill.
|
|
129
|
+
3. Walk the ground-truth files above.
|
|
130
|
+
4. Continue with local validation.
|
|
100
131
|
|
|
101
|
-
##
|
|
132
|
+
## Local Validation
|
|
102
133
|
|
|
103
|
-
|
|
134
|
+
From the generated project root:
|
|
104
135
|
|
|
105
136
|
```bash
|
|
106
|
-
|
|
107
|
-
pnpm
|
|
108
|
-
|
|
137
|
+
pnpm validate
|
|
138
|
+
pnpm typecheck
|
|
139
|
+
if node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)"; then
|
|
140
|
+
pnpm test
|
|
141
|
+
else
|
|
142
|
+
echo "No pnpm test script; skipping."
|
|
143
|
+
fi
|
|
109
144
|
```
|
|
110
145
|
|
|
111
|
-
|
|
112
|
-
- node ≥ 22: nvm (`nvm install 22 && nvm use 22`), Homebrew, or the official installer at nodejs.org
|
|
113
|
-
- pnpm ≥ 9: `corepack enable && corepack prepare pnpm@latest --activate`, or `npm install -g pnpm@9`
|
|
114
|
-
- git: system package manager (Homebrew on macOS, apt on Debian/Ubuntu, winget on Windows)
|
|
115
|
-
|
|
116
|
-
Also confirm the current working directory is an appropriate parent directory for the new project, and that no child directory already exists with the authorized `<<PROJECT_NAME>>`. `create-mantle` writes into `./<<PROJECT_NAME>>`; collisions with pre-existing files are surprising and rarely what the user wanted.
|
|
117
|
-
|
|
118
|
-
Do not proceed to manual fallback until preflight passes.
|
|
119
|
-
|
|
120
|
-
## Manual fallback
|
|
121
|
-
|
|
122
|
-
Use this only when there is no valid launch session. The manual path is
|
|
123
|
-
for development, recovery, or a user who did not start from landing. It
|
|
124
|
-
is not the primary UX.
|
|
125
|
-
|
|
126
|
-
Ask only for the values that the `create-mantle` command truly needs.
|
|
127
|
-
Keep it one question at a time and confirm the exact values before
|
|
128
|
-
running the command.
|
|
129
|
-
|
|
130
|
-
### Goal — what you must land before dispatch
|
|
131
|
-
|
|
132
|
-
Listed in discovery order — purpose comes first, brand near the end. **Do not read this table as a top-down checklist to ask in order.** The order below mirrors how the interview should flow:
|
|
133
|
-
|
|
134
|
-
| Value | For |
|
|
135
|
-
|---|---|
|
|
136
|
-
| **purpose / audience** | one-line description and locale choice |
|
|
137
|
-
| **audience scope + locales** | `--locales` (count + first is canonical) |
|
|
138
|
-
| **description** | `--description` — one-line site identity, agent-drafted in user's language |
|
|
139
|
-
| **summary** | `--summary` — one-line install-moment marker, agent-drafted in user's language |
|
|
140
|
-
| **brand** | `--brand` — proposed by you after purpose + audience texture is in; user picks or supplies their own |
|
|
141
|
-
| **github identity** | `--github-owner` and optional `--admin-github-login` |
|
|
142
|
-
|
|
143
|
-
Every value above must be set with the user's explicit confirmation
|
|
144
|
-
before you dispatch. Do not guess from email, folder name, or the
|
|
145
|
-
language of the conversation.
|
|
146
|
-
|
|
147
|
-
### Multi-round purpose discovery — start here, not with brand
|
|
148
|
-
|
|
149
|
-
Open with **what's this site for** — not the brand name. Don't ask cold
|
|
150
|
-
for a full brief. Ask one simple question, summarize back, then move to
|
|
151
|
-
the next required value.
|
|
152
|
-
|
|
153
|
-
User answers -> react -> ask the next missing value. One question per
|
|
154
|
-
turn. Stop as soon as the command values are known.
|
|
155
|
-
|
|
156
|
-
### Stances (the few non-archetype rules)
|
|
157
|
-
|
|
158
|
-
**Audience + locales — ask, don't infer.**
|
|
159
|
-
|
|
160
|
-
Audience scope drives the locale choice and feeds Mantle. Ask the user explicitly who this site is for — is it a domestic audience (and if so, which country / region), or an international audience? Don't infer audience from the user's own writing language alone; a user writing to you in one language may be building for readers in another.
|
|
161
|
-
|
|
162
|
-
- Domestic audience → propose monolingual in the audience's primary language. Confirm.
|
|
163
|
-
- International audience → propose bilingual, canonical = the user's working language, secondary = the audience's language. Confirm.
|
|
164
|
-
- Ambiguous (mixed signals, user not sure) → ask once: monolingual `<primary>` or bilingual `<primary>+<secondary>`?
|
|
165
|
-
- Use Mantle's v0.1 locale subset: BCP 47 language + optional 2-letter region. The runtime canonicalizer rejects script subtags even though they are valid BCP 47 — map Traditional Chinese / `zh-Hant` to `zh-TW`, Simplified Chinese / `zh-Hans` to `zh-CN`, and otherwise use bare-language or `<lang>-<2-letter-region>`.
|
|
166
|
-
|
|
167
|
-
**Description + summary — different roles, both agent-synthesized in the user's language.**
|
|
168
|
-
|
|
169
|
-
These are CLI flags, not separate interview questions. They land in different places and serve different purposes:
|
|
170
|
-
|
|
171
|
-
| Field | Lands in | Role |
|
|
172
|
-
|---|---|---|
|
|
173
|
-
| `description` | `mantle/site.md` frontmatter → `siteDefaults.description` → SEO `<meta description>` on every page | **Site brochure** — what the site *is* (perpetual). |
|
|
174
|
-
| `summary` | `mantle/site.md` `revisions[0].summary` | **Changelog entry** — what *this install moment* did. Provision / extend / customize-design append their own later. |
|
|
175
|
-
|
|
176
|
-
Don't write the same one-liner twice. `description` is a one-sentence site identity. `summary` is a one-line install-moment marker — terse, factual, often as short as "Initial scaffold." or "Site created from publication archetype." The site's actual identity already lives in `description`; `summary` is the timestamp's caption, not a second pitch.
|
|
177
|
-
|
|
178
|
-
Show both drafts when you synthesize; user confirms or corrects.
|
|
179
|
-
|
|
180
|
-
**Brand — propose last, never first.** Only after purpose + audience + voice texture has surfaced through the archetype probes. Then offer two paths: "Tell me a name, or I can propose 2-3 based on what you've described." If user picks the second, propose 2-3 with a one-line rationale each tied to what they actually said. Don't make the user invent a name cold; and don't propose a name before you have material to anchor the proposal in.
|
|
181
|
-
|
|
182
|
-
**GitHub identity — factual, last.** Ask once near the end. Pure config; no elaboration needed.
|
|
183
|
-
|
|
184
|
-
**Other observations — capture without pushing.** Emotional weight, dates that matter, things-not-to-touch, futures — let them surface naturally during the archetype probes. Don't checklist them. Mantle uses whatever you noticed; she doesn't need everything.
|
|
185
|
-
|
|
186
|
-
### Synthesize and confirm
|
|
146
|
+
Run deploy validation if the starter exposes it:
|
|
187
147
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
## When to act
|
|
197
|
-
|
|
198
|
-
### Why running `create-mantle` is a destructive action under Auto Mode
|
|
199
|
-
|
|
200
|
-
Invoking the `create-mantle` release tarball is **not low-risk work**. The command writes the user's site identity — brand, audience, locale, description — into `mantle/site.md` and `src/mantleConfig.ts` `siteDefaults`, then runs `git init` and `pnpm install`. Those values drive, perpetually:
|
|
201
|
-
|
|
202
|
-
- every page's SEO `<meta description>`
|
|
203
|
-
- locale routing for the entire site (canonical + redirects)
|
|
204
|
-
- the persistent site notes in `mantle/site.md`
|
|
205
|
-
- 22 starter files' `{{PLACEHOLDER}}` substitution
|
|
206
|
-
- `revisions[0]` — the permanent install-moment entry in the changelog
|
|
207
|
-
|
|
208
|
-
Wrong values ship into the user's first-load impression and cannot be cleanly walked back without wiping the scaffold and re-scaffolding from empty.
|
|
209
|
-
|
|
210
|
-
**Auto Mode's contract has four clauses. Clauses 1–3 say "execute immediately / minimize interruptions / prefer action". Clause 4 is the carve-out: do not take overly destructive actions without authorization.** This Skill classifies the scaffolder invocation under clause 4. Each create-time value must be either carried by a valid landing session or explicitly confirmed by the user. Auto-derivation — from the user's email, the current working directory's name, the archetype query, the theme query, or "the locale of the message the user wrote to me" — is **not** authorization. That kind of inference is what Auto Mode's clauses 1–3 want for low-risk work. This Skill specifically does not accept it for scaffolding values.
|
|
211
|
-
|
|
212
|
-
If you have not had a turn where the user looked at the exact value and replied affirmatively (or supplied a replacement), the value is unauthorized.
|
|
213
|
-
|
|
214
|
-
Launch-session exception: when the user hands you a landing-created
|
|
215
|
-
`create-mantle launch --session ...` command, the landing session is the
|
|
216
|
-
explicit authorization for those scaffold values. Your job is to
|
|
217
|
-
validate/run it, not to repeat manual fallback before scaffold. If the
|
|
218
|
-
session is invalid or expired, stop and ask the user to regenerate it
|
|
219
|
-
from the landing page; do not infer replacement values.
|
|
220
|
-
|
|
221
|
-
### Prerequisites — each parameter must be user-authorized before invocation
|
|
222
|
-
|
|
223
|
-
Same discovery order as the Goal table above — purpose first, brand later. The order matters because it reflects the interview shape, not arbitrary alphabetization.
|
|
224
|
-
|
|
225
|
-
| Value | Authorized when |
|
|
226
|
-
|---|---|
|
|
227
|
-
| **purpose / audience** | enough texture to summarize the site intent, not inferred |
|
|
228
|
-
| **audience scope** | user explicitly stated domestic/international audience and languages |
|
|
229
|
-
| **locales** | derived from audience scope; user nodded on the resulting BCP 47 list |
|
|
230
|
-
| **description** | agent-drafted in user's language; user nodded on the exact one-liner |
|
|
231
|
-
| **summary** | agent-drafted in user's language; user nodded on the exact one-liner |
|
|
232
|
-
| **brand** | user picked one, supplied one, or accepted your proposal |
|
|
233
|
-
| **project-name** | lowercase-hyphenated slug shown to user and confirmed |
|
|
234
|
-
| **github owner** | user explicitly stated their GitHub login/org, not derived from email |
|
|
235
|
-
|
|
236
|
-
If any value is unauthorized — including auto-derivation that "looks reasonable" — the work is still in the interview. Return there. Step 1 below IS the rehearsal back to the user in their language; it is not the moment you collect authorization for unfilled values.
|
|
237
|
-
|
|
238
|
-
1. **Confirm the synthesized draft.** User accepts or corrects.
|
|
239
|
-
|
|
240
|
-
2. **Run `create-mantle`.** Use the release tarball URL supplied by the
|
|
241
|
-
landing page, release notes, or Mantle starter docs. Fill flags only
|
|
242
|
-
from confirmed values:
|
|
243
|
-
|
|
244
|
-
```bash
|
|
245
|
-
npx <create-mantle-tarball> <archetype> \
|
|
246
|
-
--project-name <project-name> \
|
|
247
|
-
--brand "<brand>" \
|
|
248
|
-
--description "<description>" \
|
|
249
|
-
--locales "<locale[,locale]>" \
|
|
250
|
-
--github-owner <github-owner> \
|
|
251
|
-
--admin-github-login <admin-login> \
|
|
252
|
-
--summary "<summary>" \
|
|
253
|
-
[--theme <theme>] \
|
|
254
|
-
[--feature <feature>]
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
Do not invent `--theme` or `--feature` flags. They must come from
|
|
258
|
-
landing, a starter doc, or an explicit user request.
|
|
259
|
-
|
|
260
|
-
The CLI fetches `sources.json` at runtime from the requested starter ref (`--ref` / `--starter-ref`; release commands should pin a tag or explicit ref), downloads the starters tarball, merges `_common/` + `<archetype>/` + selected feature overlays + (optional) `themes/<theme>/`, fills `{{PLACEHOLDER}}` macros, renames `.template` files, runs `git init` and `pnpm install`. RUN_NOTES JSON arrives on stdout, including `features` when overlays were selected.
|
|
261
|
-
|
|
262
|
-
3. **Read the RUN_NOTES.** The `files_written` list is your scaffold inventory. If `features` is non-empty, read `.mantle/features.json` and the generated `src/.mantle/generated.*.ts` glue before deciding anything else. Walk the ground-truth files — at minimum `manifests/`, `src/mantleConfig.ts`, `mantle/site.md` — before deciding anything else.
|
|
263
|
-
|
|
264
|
-
4. **Adjustment window** (optional, see § below). Only if the interview surfaced a concrete deletion or single-field gap. Always `pnpm validate` after edit.
|
|
265
|
-
|
|
266
|
-
5. **Validate locally:**
|
|
267
|
-
|
|
268
|
-
```bash
|
|
269
|
-
pnpm validate
|
|
270
|
-
pnpm typecheck
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
`pnpm validate` runs in the **preview phase** by default — grammar + cross-Schema checks only. Anything non-zero → surface `code` + `suggestion` verbatim.
|
|
274
|
-
|
|
275
|
-
The deploy-phase variant (`pnpm validate --phase deploy`, or `pnpm validate:deploy` if the starter ships that script) is safe to run on a fresh scaffold. It must not block on unfinished prose in `mantle/site.md`.
|
|
276
|
-
|
|
277
|
-
**Then set up `.dev.vars` so `pnpm dev` works.** Starters that ship `.dev.vars.example` (publication / transaction / intake / presence) require a real `BETTER_AUTH_SECRET` before `pnpm dev` — the worker returns `auth_not_configured` on every request until it's filled. Copy the file, generate a value, and write it in:
|
|
278
|
-
|
|
279
|
-
```bash
|
|
280
|
-
[ -f .dev.vars.example ] && cp .dev.vars.example .dev.vars
|
|
281
|
-
# Generate, then paste the output into the BETTER_AUTH_SECRET= line of .dev.vars
|
|
282
|
-
openssl rand -hex 32
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
This secret is **local only** — `.dev.vars` is gitignored and never reaches Cloudflare. Production's secret is minted separately by `provision:up` (see the provision Skill). Tell the user this distinction explicitly so they don't try to reuse the local value or expect it to follow them to prod.
|
|
148
|
+
```bash
|
|
149
|
+
if node -e "process.exit(require('./package.json').scripts?.['validate:deploy'] ? 0 : 1)"; then
|
|
150
|
+
pnpm validate:deploy
|
|
151
|
+
else
|
|
152
|
+
pnpm validate --phase deploy
|
|
153
|
+
fi
|
|
154
|
+
```
|
|
286
155
|
|
|
287
|
-
|
|
156
|
+
Diagnostics are structured JSON with `code` and `suggestion` fields.
|
|
157
|
+
Surface both verbatim when validation fails.
|
|
288
158
|
|
|
289
|
-
|
|
159
|
+
## Local Preview
|
|
290
160
|
|
|
291
|
-
|
|
161
|
+
If the user wants to see the scaffold locally:
|
|
292
162
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
163
|
+
```bash
|
|
164
|
+
[ -f .dev.vars.example ] && cp .dev.vars.example .dev.vars
|
|
165
|
+
openssl rand -hex 32
|
|
166
|
+
pnpm dev
|
|
167
|
+
```
|
|
298
168
|
|
|
299
|
-
|
|
169
|
+
Paste the generated random value into `.dev.vars` as
|
|
170
|
+
`BETTER_AUTH_SECRET`. This secret is local only and must not be reused
|
|
171
|
+
for production. Use `localhost`, not `127.0.0.1`, in local examples.
|
|
300
172
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
173
|
+
A fresh scaffold may legitimately return 404 for the public home route
|
|
174
|
+
because production content is not seeded yet. Treat that as an empty-site
|
|
175
|
+
state, not a failed install, when validation and admin routes are alive.
|
|
304
176
|
|
|
305
|
-
|
|
177
|
+
## Provision Handoff
|
|
306
178
|
|
|
307
|
-
|
|
179
|
+
Commit the deterministic scaffold:
|
|
308
180
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
`https://raw.githubusercontent.com/aotter/mantle/develop/skills/provision/SKILL.md`.
|
|
181
|
+
```bash
|
|
182
|
+
git status --short
|
|
183
|
+
git add .
|
|
184
|
+
git commit -m "mantle: deterministic scaffold"
|
|
185
|
+
```
|
|
315
186
|
|
|
316
|
-
|
|
187
|
+
Then continue in the same conversation with the repo-local provision
|
|
188
|
+
skill:
|
|
317
189
|
|
|
318
|
-
|
|
190
|
+
```text
|
|
191
|
+
.agent/skills/mantle-provision/SKILL.md
|
|
192
|
+
```
|
|
319
193
|
|
|
320
|
-
|
|
194
|
+
The current provision shape is provider-first:
|
|
321
195
|
|
|
322
|
-
|
|
196
|
+
1. The agent creates/pushes the user's private GitHub repo.
|
|
197
|
+
2. The user creates the first Cloudflare Worker deploy from that GitHub
|
|
198
|
+
repo in Cloudflare Dashboard.
|
|
199
|
+
3. The user reports the Worker URL.
|
|
200
|
+
4. The user creates the per-site GitHub OAuth App.
|
|
201
|
+
5. The agent runs `pnpm run provision:up` to write non-secret config,
|
|
202
|
+
set Worker secrets with Wrangler, commit, push, redeploy, and smoke
|
|
203
|
+
test.
|
|
323
204
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
| Add a single field to an existing Schema, from a concrete interview signal | Small, validated, recoverable |
|
|
328
|
-
| Edit `src/mantleConfig.ts` site defaults beyond what `create-mantle` set | Site-shape, fits Mantle's surface |
|
|
329
|
-
| Tweak `src/theme/` tokens if the user gave a strong visual register | Prefer deferring to the customize-design Skill unless explicit |
|
|
205
|
+
Do not stop at "here is a URL". Walk the provider steps with the user
|
|
206
|
+
until the deployed Worker, GitHub owner sign-in, and Staff MCP endpoint
|
|
207
|
+
are verified.
|
|
330
208
|
|
|
331
|
-
|
|
209
|
+
## Small Adjustments
|
|
332
210
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
| Add a new Schema (beyond single-field tweak), View, Procedure, or Trigger | The extend skill |
|
|
336
|
-
| Substantial theme work (template fork, layout reshape) | The customize-design skill, after deploy |
|
|
337
|
-
| Anything touching DRAFT grammar keys | Never at install — grammar locked at v0.1 |
|
|
211
|
+
Before provision, only make small deterministic edits that come directly
|
|
212
|
+
from the landing answers or the user's explicit request:
|
|
338
213
|
|
|
339
|
-
|
|
214
|
+
- delete an unused manifest;
|
|
215
|
+
- add one clearly requested field to an existing Schema;
|
|
216
|
+
- correct site defaults in `src/mantleConfig.ts`;
|
|
217
|
+
- fix a typo in `mantle/site.md` or `AGENTS.md`.
|
|
340
218
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
- Don't speculate. "I think you might also want X" is generation, not interview.
|
|
219
|
+
Run `pnpm validate` after every edit. Route larger feature work to
|
|
220
|
+
`mantle:development` after production provision.
|
|
344
221
|
|
|
345
222
|
## Don't
|
|
346
223
|
|
|
347
|
-
- Don't
|
|
348
|
-
- Don't
|
|
349
|
-
- Don't
|
|
224
|
+
- Don't resurrect the manual interview / prompt-composition harness.
|
|
225
|
+
- Don't block first deploy on polishing `mantle/site.md` prose.
|
|
226
|
+
- Don't ask for a Cloudflare API token in the base first-run path.
|
|
227
|
+
- Don't commit provider secrets.
|
|
228
|
+
- Don't use `127.0.0.1` in OAuth callback examples; use `localhost`
|
|
229
|
+
locally and the real Worker URL in production.
|
|
@@ -26,6 +26,10 @@ The base flow is deterministic first, provider-browser second:
|
|
|
26
26
|
Mantle landing is not the executor. It provides launch context and a
|
|
27
27
|
handoff; provider authority stays with the user and their coding agent.
|
|
28
28
|
|
|
29
|
+
Do deterministic work before interrupting the user. When provider UI is
|
|
30
|
+
required, give one exact browser task at a time: link, button path,
|
|
31
|
+
expected result, and what value the user should report back.
|
|
32
|
+
|
|
29
33
|
## End State
|
|
30
34
|
|
|
31
35
|
- The scaffold is committed and pushed to the user's private GitHub repo.
|
|
@@ -84,7 +88,13 @@ ask the user to switch/login before creating the repo.
|
|
|
84
88
|
2. Create a private GitHub repo in the selected owner, add the remote,
|
|
85
89
|
commit the scaffold, and push. Use the user's GitHub auth context.
|
|
86
90
|
|
|
87
|
-
3.
|
|
91
|
+
3. Print the deterministic browser plan:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pnpm run provision:plan
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
4. Hand the user directly to Cloudflare's Git import path:
|
|
88
98
|
|
|
89
99
|
```text
|
|
90
100
|
https://dash.cloudflare.com/?to=%2F%3Aaccount%2Fworkers-and-pages
|
|
@@ -92,18 +102,19 @@ https://dash.cloudflare.com/?to=%2F%3Aaccount%2Fworkers-and-pages
|
|
|
92
102
|
|
|
93
103
|
Ask them to create a Worker from the pushed GitHub repo, keep the Worker
|
|
94
104
|
name equal to `wrangler.toml` `name`, wait for deploy, and send back the
|
|
95
|
-
live `*.workers.dev` URL.
|
|
105
|
+
live `*.workers.dev` URL. Ask for the Worker name only if Cloudflare
|
|
106
|
+
forced a name different from the repo/project name.
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
5. After the Worker URL is known, print the worker-specific plan:
|
|
98
109
|
|
|
99
110
|
```bash
|
|
100
|
-
pnpm run provision:plan
|
|
111
|
+
pnpm run provision:plan -- --worker-url <worker-url>
|
|
101
112
|
```
|
|
102
113
|
|
|
103
114
|
Read only the values needed for the current project. Do not dump
|
|
104
115
|
internal notes or placeholder syntax onto a non-coder.
|
|
105
116
|
|
|
106
|
-
|
|
117
|
+
6. Ask the user to create the per-site GitHub OAuth App after the Worker
|
|
107
118
|
URL is known:
|
|
108
119
|
|
|
109
120
|
- Homepage URL: `<worker-url>`
|
|
@@ -113,7 +124,7 @@ internal notes or placeholder syntax onto a non-coder.
|
|
|
113
124
|
Ask for the Client ID in chat. Keep the Client Secret out of chat and
|
|
114
125
|
pass it through the hidden shell prompt below.
|
|
115
126
|
|
|
116
|
-
|
|
127
|
+
7. Authorize Wrangler and apply provision:
|
|
117
128
|
|
|
118
129
|
```bash
|
|
119
130
|
pnpm exec wrangler login
|
|
@@ -122,13 +133,20 @@ pnpm run provision:up -- --worker-url <worker-url> --github-username <gh-login>
|
|
|
122
133
|
unset GITHUB_CLIENT_SECRET
|
|
123
134
|
```
|
|
124
135
|
|
|
125
|
-
|
|
136
|
+
8. Commit and push generated non-secret outputs:
|
|
126
137
|
|
|
127
138
|
```bash
|
|
128
139
|
git status --short -- wrangler.toml src/mantleConfig.ts mantle/site.md AGENTS.md
|
|
140
|
+
git add wrangler.toml src/mantleConfig.ts mantle/site.md AGENTS.md
|
|
141
|
+
git commit -m "mantle: wire production provision"
|
|
142
|
+
git push
|
|
129
143
|
```
|
|
130
144
|
|
|
131
|
-
|
|
145
|
+
Wait for Cloudflare Workers Builds to redeploy from the pushed commit. If
|
|
146
|
+
the dashboard build is unavailable, run `pnpm deploy` from this repo as a
|
|
147
|
+
fallback and explain that fallback to the user.
|
|
148
|
+
|
|
149
|
+
9. Smoke test:
|
|
132
150
|
|
|
133
151
|
- public home route;
|
|
134
152
|
- `/admin/sign-in`;
|
|
@@ -136,6 +154,10 @@ git status --short -- wrangler.toml src/mantleConfig.ts mantle/site.md AGENTS.md
|
|
|
136
154
|
- `/mcp/staff` with an agent client when available;
|
|
137
155
|
- a starter-specific core workflow.
|
|
138
156
|
|
|
157
|
+
A fresh site may have no public home content yet. A 404 on the locale
|
|
158
|
+
homepage is acceptable only after the Worker boots, `/admin/sign-in`
|
|
159
|
+
loads, and auth/MCP boundaries behave correctly.
|
|
160
|
+
|
|
139
161
|
## Feature Overlays
|
|
140
162
|
|
|
141
163
|
If `.mantle/features.json` lists features, run the repo-local feature
|