@aotter/mantle 0.0.11-alpha.63 → 0.0.11-alpha.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -12
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +52 -0
- package/dist/cli.js.map +1 -0
- package/dist/generate.d.ts +2 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +181 -0
- package/dist/generate.js.map +1 -0
- package/dist/skills.d.ts +2 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +80 -0
- package/dist/skills.js.map +1 -0
- package/dist/update.d.ts +2 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +387 -0
- package/dist/update.js.map +1 -0
- package/docs/adr/0001-four-atom-manifest-model.md +6 -7
- package/docs/adr/0007-ai-as-primary-author.md +100 -138
- package/docs/adr/0008-structured-diagnostic-shape.md +79 -99
- package/docs/adr/0009-consumer-supplied-manifests.md +101 -228
- package/docs/adr/0012-views-as-public-rest.md +43 -15
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +43 -17
- package/docs/adr/0018-core-starters-repository-boundary.md +155 -0
- package/docs/adr/README.md +8 -6
- package/docs/cloudflare-low-level-composition.md +94 -0
- package/docs/design-atoms.md +59 -57
- package/docs/design-references/editorial-blog-2026-05-05.md +7 -7
- package/docs/labels.md +1 -1
- package/docs/media-uploads.md +1 -1
- package/docs/release-process.md +156 -523
- package/package.json +9 -6
- package/skills/README.md +20 -16
- package/skills/develop/SKILL.md +4 -4
- package/skills/install/SKILL.md +16 -2
- package/skills/plugin/SKILL.md +1 -1
- package/skills/provision/SKILL.md +1 -1
- package/skills/theme/SKILL.md +12 -10
- package/skills/update/SKILL.md +31 -19
- package/skills/customize-design/SKILL.md +0 -215
- package/skills/extend/SKILL.md +0 -257
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# ADR-0008: Structured diagnostic shape for AI-parseable errors
|
|
2
2
|
|
|
3
|
-
**Status:** Carried over from POC v0.0.x;
|
|
3
|
+
**Status:** Carried over from POC v0.0.x; amended for the shipped v0.1
|
|
4
|
+
diagnostic emitters and measured harnesses.
|
|
4
5
|
|
|
5
|
-
**Date
|
|
6
|
+
**Date:** 2026-04-30 (POC); last amended 2026-08-03.
|
|
6
7
|
|
|
7
8
|
**Deciders**: phsu
|
|
8
9
|
|
|
@@ -12,11 +13,12 @@
|
|
|
12
13
|
|
|
13
14
|
## Context
|
|
14
15
|
|
|
15
|
-
ADR-0007 commits the SDK to three feedback loops (static
|
|
16
|
-
validation,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
ADR-0007 commits the SDK to three pre-serve feedback loops (static
|
|
17
|
+
validation, local tests/measurements, and boot-time fail-fast) before the
|
|
18
|
+
runtime layer. Authoring/runtime failures need one stable record shape; the
|
|
19
|
+
measured index and HTTP harnesses use their own purpose-shaped JSON reports.
|
|
20
|
+
If each failure emitter used an ad-hoc shape, the consumer agent reading those
|
|
21
|
+
errors would need multiple parsers — defeating the
|
|
20
22
|
"deterministic feedback" property that justified the contract in
|
|
21
23
|
the first place.
|
|
22
24
|
|
|
@@ -32,8 +34,9 @@ free-form message. That is under-specified for the new loops:
|
|
|
32
34
|
the AI author can fix without doing its own grep.
|
|
33
35
|
- A boot error needs to declare **what was checked and what was
|
|
34
36
|
missing**, so the deploy log is self-explanatory.
|
|
35
|
-
-
|
|
36
|
-
so
|
|
37
|
+
- Validation, boot, runtime, and consumer-authored test diagnostics should
|
|
38
|
+
agree on **severity** (error vs warning) so integrations do not need
|
|
39
|
+
per-phase logic.
|
|
37
40
|
|
|
38
41
|
A free-form message field carries all of this in prose, but
|
|
39
42
|
forces the AI author to do natural-language parsing on every
|
|
@@ -41,11 +44,11 @@ diagnostic before it can route a fix. Structure is cheaper.
|
|
|
41
44
|
|
|
42
45
|
## Decision
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
The
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
there.
|
|
47
|
+
Core validation, boot, and runtime emit diagnostics in the following shape.
|
|
48
|
+
The public `test` phase is reserved for consumer test diagnostics; the shipped
|
|
49
|
+
`mantle-harness` commands emit `IndexCoverageReport` and `HttpBenchmarkReport`
|
|
50
|
+
instead. The canonical type, diagnostic-code constants, and shipped phase
|
|
51
|
+
helpers live in `@aotter/mantle-spec`; every other package imports from there.
|
|
49
52
|
|
|
50
53
|
```ts
|
|
51
54
|
type Phase = "validate" | "test" | "boot" | "runtime";
|
|
@@ -90,13 +93,13 @@ by `phase` (this-loop-only handling). Concrete examples:
|
|
|
90
93
|
| `HANDLER_NOT_REGISTERED` | `validate`, `boot`, `runtime` | textual grep miss (warning, validate); registry lookup miss (error, boot); dispatch attempt miss (error, runtime, defense-in-depth) |
|
|
91
94
|
| `TRIGGER_TARGET_PROCEDURE_UNKNOWN` | `validate`, `boot` | dangling reference caught by either loop |
|
|
92
95
|
| `TRIGGER_PATH_COLLISION` | `validate`, `boot` | two http Triggers on same method+path |
|
|
93
|
-
| `NOT_FOUND` | `
|
|
94
|
-
| `INPUT_VALIDATION_FAILED` | `runtime
|
|
96
|
+
| `NOT_FOUND` | `runtime` (`test` reserved) | unknown name in queryView / GET /api/views/X |
|
|
97
|
+
| `INPUT_VALIDATION_FAILED` | `runtime` (`test` reserved) | zod validation failure at the serving boundary |
|
|
95
98
|
|
|
96
|
-
Codes that are
|
|
97
|
-
|
|
98
|
-
`phase: "test"
|
|
99
|
-
|
|
99
|
+
Codes that are phase-exclusive simply never appear with another phase.
|
|
100
|
+
`INVALID_MANIFEST_ENVELOPE` is validate-only. The catalog reserves
|
|
101
|
+
`FIXTURE_SCHEMA_VIOLATION` for consumer-authored `phase: "test"` diagnostics;
|
|
102
|
+
Core does not currently emit it.
|
|
100
103
|
|
|
101
104
|
### Why no prefixes
|
|
102
105
|
|
|
@@ -123,8 +126,8 @@ code string. That was retired because:
|
|
|
123
126
|
### `path` format
|
|
124
127
|
|
|
125
128
|
- For static validation: filesystem path + JSON Pointer fragment,
|
|
126
|
-
e.g. `
|
|
127
|
-
- For test
|
|
129
|
+
e.g. `manifests/recent-published.view.yaml#/spec/from`.
|
|
130
|
+
- For a consumer test diagnostic: test file path + assertion location when
|
|
128
131
|
available, e.g. `tests/handlers/contact.test.ts:42`.
|
|
129
132
|
- For boot-time: manifest pointer (no on-disk path because boot
|
|
130
133
|
reads parsed manifests, not files), e.g.
|
|
@@ -159,53 +162,47 @@ before applying.
|
|
|
159
162
|
### CLI output mode
|
|
160
163
|
|
|
161
164
|
- `--format=json` (default when stdout is **not** a TTY, e.g. CI,
|
|
162
|
-
AI-author): emits `{
|
|
163
|
-
stdout; exit code 1 if any has `severity: "error"`, else 0.
|
|
165
|
+
AI-author): emits `{ phase, diagnostics, errorCount, warningCount }` on
|
|
166
|
+
stdout; exit code 1 if any diagnostic has `severity: "error"`, else 0.
|
|
164
167
|
- `--format=text` (default when stdout **is** a TTY, i.e. human
|
|
165
|
-
at terminal):
|
|
166
|
-
|
|
167
|
-
is set.
|
|
168
|
+
at terminal): prints severity, code, path, structured details, prose message,
|
|
169
|
+
and suggestion when present.
|
|
168
170
|
|
|
169
171
|
The same diagnostic objects power both modes; text mode is a
|
|
170
172
|
formatter, not a separate code path. AI authors invoking the CLI
|
|
171
173
|
get JSON automatically because they pipe through subprocess; no
|
|
172
174
|
flag needed.
|
|
173
175
|
|
|
174
|
-
###
|
|
176
|
+
### Consumer test diagnostic surface
|
|
175
177
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
Tests check `result.ok` and assert against `result.diagnostic.code`
|
|
185
|
-
(stable string), not against thrown exception types. This makes
|
|
186
|
-
test code robust to error-class refactoring inside the SDK.
|
|
178
|
+
Runtime use cases return result objects carrying runtime-phase diagnostics, so
|
|
179
|
+
consumer tests can assert stable `diagnostic.code` values without matching
|
|
180
|
+
exception prose. A consumer that emits its own fixture/setup diagnostic may use
|
|
181
|
+
`makeDiagnostic({ phase: "test", ... })`. Core currently exports no
|
|
182
|
+
`testDiagnostic` helper and its measured planner/HTTP harnesses return their
|
|
183
|
+
purpose-shaped reports instead of `Diagnostic` objects.
|
|
187
184
|
|
|
188
185
|
### Runtime diagnostic surface
|
|
189
186
|
|
|
190
|
-
Runtime HTTP responses on error paths
|
|
191
|
-
|
|
192
|
-
table. The `path`
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
information to untrusted callers.
|
|
187
|
+
Runtime HTTP responses on error paths wrap the same redacted object as
|
|
188
|
+
`{ ok: false, diagnostic }`, plus the HTTP status from the shared error-code
|
|
189
|
+
table. The `path` carries the most specific request/use-case locator available.
|
|
190
|
+
The `candidates` field is **always omitted** at wire egress to avoid leaking
|
|
191
|
+
schema information to untrusted callers.
|
|
196
192
|
|
|
197
193
|
```http
|
|
198
194
|
HTTP/1.1 400 Bad Request
|
|
199
195
|
Content-Type: application/json
|
|
200
196
|
|
|
201
197
|
{
|
|
202
|
-
"
|
|
203
|
-
"
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
198
|
+
"ok": false,
|
|
199
|
+
"diagnostic": {
|
|
200
|
+
"code": "INPUT_VALIDATION_FAILED",
|
|
201
|
+
"phase": "runtime",
|
|
202
|
+
"severity": "error",
|
|
203
|
+
"path": "POST /api/contact#/body/email",
|
|
204
|
+
"message": "Field 'email' must be a valid email address."
|
|
205
|
+
}
|
|
209
206
|
}
|
|
210
207
|
```
|
|
211
208
|
|
|
@@ -221,22 +218,15 @@ runtime validator a manifest author's request body hits is a
|
|
|
221
218
|
zod schema, produced by the JSON-Schema → zod converter in
|
|
222
219
|
`@aotter/mantle-spec` (see [`docs/design-atoms.md`](../design-atoms.md) § "Manifest validation — JSON Schema in, zod at runtime").
|
|
223
220
|
|
|
224
|
-
Concretely,
|
|
225
|
-
|
|
226
|
-
- `issue.path:
|
|
227
|
-
|
|
228
|
-
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
contract stable across validator-library swaps.
|
|
234
|
-
- `invalid_enum_value.options` → `candidates` (validate / test /
|
|
235
|
-
boot phases only; stripped at runtime per the rule above).
|
|
236
|
-
- `issue.message` is treated as fallback prose; the Diagnostic's
|
|
237
|
-
`message` is regenerated from the structured fields by the
|
|
238
|
-
shared formatter, so a future zod upgrade that re-words its
|
|
239
|
-
defaults doesn't ripple into our consumer-facing strings.
|
|
221
|
+
Concretely, runtime entry validation consumes `ZodError.issues`:
|
|
222
|
+
|
|
223
|
+
- `issue.path: PropertyKey[]` becomes an RFC 6901 JSON Pointer (`~` and `/`
|
|
224
|
+
escaped, numeric segments preserved);
|
|
225
|
+
- every issue stays in the stable `INPUT_VALIDATION_FAILED` family rather than
|
|
226
|
+
exposing zod's internal issue-code vocabulary;
|
|
227
|
+
- `issue.message` supplies fallback human prose. Call sites with known
|
|
228
|
+
trust-boundary context may additionally populate `value`, `expected`, or a
|
|
229
|
+
more specific message before wire redaction.
|
|
240
230
|
|
|
241
231
|
The same rule that retired Ajv's per-validator error format as a
|
|
242
232
|
Diagnostic candidate (alternative (d) below) applies to zod —
|
|
@@ -246,8 +236,8 @@ Diagnostic candidate (alternative (d) below) applies to zod —
|
|
|
246
236
|
|
|
247
237
|
### Pros
|
|
248
238
|
|
|
249
|
-
- One parser handles
|
|
250
|
-
|
|
239
|
+
- One parser handles diagnostics from any phase. AI consumer code branches on
|
|
240
|
+
the exact `code` and optionally `phase`, without per-emitter adapters.
|
|
251
241
|
- `candidates` + `suggestion` make the most common author errors
|
|
252
242
|
(typo, unknown name, wrong enum value) one-step fixes — the AI
|
|
253
243
|
author reads the diagnostic and writes the corrected manifest
|
|
@@ -265,9 +255,8 @@ Diagnostic candidate (alternative (d) below) applies to zod —
|
|
|
265
255
|
|
|
266
256
|
### Costs
|
|
267
257
|
|
|
268
|
-
- Shape locked early: any field-shape change forces a doc revise
|
|
269
|
-
|
|
270
|
-
parsers.
|
|
258
|
+
- Shape locked early: any field-shape change forces a doc revise and code
|
|
259
|
+
change across CLI, runtime, adapters, and consumer parsers.
|
|
271
260
|
- Implementing `candidates` and `suggestion` correctly requires
|
|
272
261
|
the validator/dispatcher to track richer context (the set of
|
|
273
262
|
declared Schema names, the registered ref list, etc.). More
|
|
@@ -284,11 +273,10 @@ Diagnostic candidate (alternative (d) below) applies to zod —
|
|
|
284
273
|
failure mode, not by individual assertion. `INVALID_NAME`
|
|
285
274
|
with `expected: "kebab-case, 1-64 chars"` covers the family;
|
|
286
275
|
the `value` and `expected` fields carry the specifics.
|
|
287
|
-
- **`message` and structured fields drift**.
|
|
288
|
-
message
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
diagnostic site.
|
|
276
|
+
- **`message` and structured fields drift**. Mitigation: `makeDiagnostic`
|
|
277
|
+
derives a default message from the structured fields. Explicit contextual
|
|
278
|
+
messages are allowed, but reviewers treat `code`, `phase`, `path`, `value`,
|
|
279
|
+
and `expected` as authoritative and reject contradictions.
|
|
292
280
|
- **`candidates` leaks information at runtime**. Already
|
|
293
281
|
addressed: runtime responses omit `candidates`. Code review
|
|
294
282
|
should treat any runtime path that populates `candidates` as a
|
|
@@ -327,27 +315,19 @@ objects feed *into* the Diagnostic translator described under
|
|
|
327
315
|
code module; do not redeclare per-package.
|
|
328
316
|
- When the same root cause can be caught by multiple loops,
|
|
329
317
|
reuse the code; let `phase` distinguish.
|
|
330
|
-
- Implementation: `
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
`
|
|
334
|
-
|
|
335
|
-
-
|
|
336
|
-
|
|
337
|
-
§ Error catalog with `code`, applicable phases,
|
|
338
|
-
when-it-fires, and an example diagnostic.
|
|
318
|
+
- Implementation: use `makeDiagnostic` or the shipped phase helpers
|
|
319
|
+
`validateDiagnostic`, `bootDiagnostic`, and `runtimeDiagnostic`, all exported
|
|
320
|
+
from `@aotter/mantle-spec`. Consumer test diagnostics call `makeDiagnostic`
|
|
321
|
+
with `phase: "test"` directly.
|
|
322
|
+
- Documentation: keep phase/applicability prose in this ADR and the
|
|
323
|
+
version-matched design/runtime references synchronized with the exported
|
|
324
|
+
catalog.
|
|
339
325
|
|
|
340
326
|
## Implementation status
|
|
341
327
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
`
|
|
346
|
-
`
|
|
347
|
-
|
|
348
|
-
imports them for the dispatcher and the boot validator;
|
|
349
|
-
`@aotter/mantle-cloudflare` imports them for HTTP error
|
|
350
|
-
responses; the admin UI imports them so the in-browser editor
|
|
351
|
-
surfaces the same structured errors the CLI does. The
|
|
352
|
-
`aotter/mantle` v0.1.0 milestone tracks the per-package
|
|
353
|
-
landings.
|
|
328
|
+
Implemented. Canonical declarations live in
|
|
329
|
+
`packages/mantle-spec/src/kernel/diagnostic.ts`; runtime, Cloudflare adapter,
|
|
330
|
+
admin UI, and CLI import the public spec exports. `redactForWire` removes
|
|
331
|
+
`candidates` before REST/MCP egress. The `test` phase and
|
|
332
|
+
`FIXTURE_SCHEMA_VIOLATION` remain reserved compatibility surface; Core ships no
|
|
333
|
+
test-phase helper or emitter today.
|