@aotter/mantle 0.0.11-alpha.62 → 0.0.11-alpha.64

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 (52) hide show
  1. package/README.md +96 -11
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +52 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/generate.d.ts +2 -0
  7. package/dist/generate.d.ts.map +1 -0
  8. package/dist/generate.js +181 -0
  9. package/dist/generate.js.map +1 -0
  10. package/dist/harness-cli.d.ts +3 -0
  11. package/dist/harness-cli.d.ts.map +1 -0
  12. package/dist/harness-cli.js +209 -0
  13. package/dist/harness-cli.js.map +1 -0
  14. package/dist/runtime-testing.d.ts +2 -0
  15. package/dist/runtime-testing.d.ts.map +1 -0
  16. package/dist/runtime-testing.js +2 -0
  17. package/dist/runtime-testing.js.map +1 -0
  18. package/dist/skills.d.ts +2 -0
  19. package/dist/skills.d.ts.map +1 -0
  20. package/dist/skills.js +80 -0
  21. package/dist/skills.js.map +1 -0
  22. package/dist/update.d.ts +2 -0
  23. package/dist/update.d.ts.map +1 -0
  24. package/dist/update.js +387 -0
  25. package/dist/update.js.map +1 -0
  26. package/docs/adapter-guide.md +8 -0
  27. package/docs/adr/0001-four-atom-manifest-model.md +6 -7
  28. package/docs/adr/0007-ai-as-primary-author.md +100 -138
  29. package/docs/adr/0008-structured-diagnostic-shape.md +79 -99
  30. package/docs/adr/0009-consumer-supplied-manifests.md +101 -228
  31. package/docs/adr/0012-views-as-public-rest.md +43 -15
  32. package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +43 -17
  33. package/docs/adr/0018-core-starters-repository-boundary.md +155 -0
  34. package/docs/adr/README.md +8 -6
  35. package/docs/cloudflare-low-level-composition.md +94 -0
  36. package/docs/design-atoms.md +59 -57
  37. package/docs/design-references/editorial-blog-2026-05-05.md +7 -7
  38. package/docs/labels.md +1 -1
  39. package/docs/media-uploads.md +1 -1
  40. package/docs/performance-harness.md +104 -0
  41. package/docs/release-process.md +156 -523
  42. package/docs/schema-indexes.md +14 -1
  43. package/package.json +16 -6
  44. package/skills/README.md +20 -16
  45. package/skills/develop/SKILL.md +42 -4
  46. package/skills/install/SKILL.md +16 -2
  47. package/skills/plugin/SKILL.md +1 -1
  48. package/skills/provision/SKILL.md +1 -1
  49. package/skills/theme/SKILL.md +12 -10
  50. package/skills/update/SKILL.md +31 -19
  51. package/skills/customize-design/SKILL.md +0 -215
  52. package/skills/extend/SKILL.md +0 -257
package/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  Umbrella entry for the Mantle SDK — a manifest-driven CMS for Cloudflare Workers, built around a 4-atom YAML model (Schema / View / Procedure / Trigger) where agents write config and the runtime carries the complexity.
4
4
 
5
- > v0.1.x is in development. APIs may change between minor versions.
5
+ > Mantle is prerelease software. Use this package's `package.json` as the exact
6
+ > installed version; APIs may change between prereleases until v0.1.0.
6
7
 
7
8
  ## Install
8
9
 
@@ -20,6 +21,7 @@ Adopters install this one package and import from subpaths. Sub-packages remain
20
21
  |---|---|
21
22
  | `@aotter/mantle/spec` (or root) | Manifest grammar, validators, JSON-Schema→Zod, diagnostic catalog (no env / no IO) |
22
23
  | `@aotter/mantle/runtime` | Hexagonal runtime: domain ports, use cases, infrastructure helpers (no adapter deps) |
24
+ | `@aotter/mantle/runtime/testing` | Node-only crowded SQLite planner and HTTP sampling helpers |
23
25
  | `@aotter/mantle/cloudflare` | Cloudflare Workers adapter — D1, KV, R2, Better Auth, MCP via `@cloudflare/workers-oauth-provider` |
24
26
  | `@aotter/mantle/admin-ui` | Pre-built React 19 admin SPA bundle |
25
27
 
@@ -29,6 +31,84 @@ import { createCmsRuntime } from "@aotter/mantle/runtime";
29
31
  import { mountServerEndpoints } from "@aotter/mantle/cloudflare";
30
32
  ```
31
33
 
34
+ The package also installs `mantle` and `mantle-harness`:
35
+
36
+ ```bash
37
+ pnpm exec mantle generate
38
+ pnpm exec mantle generate --check
39
+ pnpm exec mantle skills
40
+ pnpm exec mantle skills --check
41
+ pnpm exec mantle update --ref <immutable-starter-ref>
42
+ pnpm exec mantle-harness indexes --require-public
43
+ pnpm exec mantle-harness http --base-url http://127.0.0.1:8787 --route page=/en/example
44
+ ```
45
+
46
+ `mantle generate` validates the YAML under `./manifests`, then writes the
47
+ parsed manifest module and handler declarations to `.mantle/generated/`.
48
+ It does not sync skills, update packages, style, provision, or deploy.
49
+ When manifests declare Views, the generated `site.ts` also exports
50
+ `bindMantleSite(runtime)`: its `views` keys, params and returned rows come from
51
+ those manifests, while diagnostics still come directly from `executeView`.
52
+ Dynamic `runtime.viewsByName` access remains available for low-level code.
53
+
54
+ ```ts
55
+ const site = bindMantleSite(runtime);
56
+ const notes = await site.views["published-notes"]();
57
+ ```
58
+
59
+ `mantle skills` explicitly copies the installed package's `develop`, `plugin`,
60
+ `theme`, and `update` skills to matching `.agent/skills/mantle-*` and
61
+ `.claude/skills/mantle-*` paths. Both tool layouts receive identical bytes;
62
+ `--check` detects drift without writing. Manifest generation never rewrites
63
+ agent instructions.
64
+
65
+ `mantle update` compares the recorded source bundle, a target bundle, and the
66
+ local project, then writes `.mantle/update-report.json`. It never applies the
67
+ diff. Configure `.mantle/features.json` `registry.bundleBaseUrl` with a URL
68
+ containing `{ref}`, or pass `--bundle-base-url` for the alpha.63 bridge. The
69
+ report carries the only supported metadata migration; review and apply it
70
+ after porting selected upstream changes.
71
+
72
+ ## Conventional Cloudflare Worker
73
+
74
+ The normal Worker entry delegates Core-owned assembly to the SDK:
75
+
76
+ ```ts
77
+ import { createMantleWorker } from "@aotter/mantle/cloudflare";
78
+ import { manifest } from "../.mantle/generated/site.js";
79
+
80
+ export default createMantleWorker({ manifest });
81
+ ```
82
+
83
+ `createMantleWorker` owns conventional D1/KV/assets bindings, Auth, Admin,
84
+ manifest REST/HTTP routes, OAuth, MCP, cache safety, and rejection-safe
85
+ per-isolate boot. Use its single `extend` seam for application handlers and
86
+ new Hono routes; use the public low-level exports when the deployment does not
87
+ fit the conventional binding or lifecycle contract.
88
+
89
+ Extensions may add routes but may not replace Core surfaces. These paths are
90
+ reserved:
91
+
92
+ - `/admin` and `/admin/*`
93
+ - `/api/auth` and `/api/auth/*`
94
+ - `/api/views` and `/api/views/*`
95
+ - `/oauth` and `/oauth/*`
96
+ - `/mcp` and `/mcp/*`
97
+ - `/.well-known/oauth*`
98
+ - `/favicon.svg`
99
+ - global `*` and `/*` handlers
100
+
101
+ A custom Auth factory's `basePath` and exact manifest-owned method/path pairs
102
+ are also reserved at assembly. Static literal conflicts fail TypeScript during
103
+ the consumer build. Computed paths cannot be proven statically, so the facade
104
+ checks Hono's assembled route table and fails closed before serving requests.
105
+ There is no standard-route override option.
106
+
107
+ For an uncommon deployment that must own the top-level assembly, use the
108
+ embedded [`docs/cloudflare-low-level-composition.md`](docs/cloudflare-low-level-composition.md)
109
+ fixture. It composes the same public primitives without importing package
110
+ internals or rebuilding Mantle's adapters.
111
+
32
112
  ## Getting started
33
113
 
34
114
  Give the [Mantle repo](https://github.com/aotter/mantle) to a coding agent or
@@ -39,20 +119,23 @@ materializes a local project, and verifies it before any provider work.
39
119
 
40
120
  [Mantle landing](https://mantle.tools) uses the same bundles and continues
41
121
  through private GitHub repo creation, Cloudflare deployment, and optional paid
42
- hosted auth. Generated repos vendor Core-owned `mantle:*` skills from this
43
- package for repo-local use.
122
+ hosted auth. Generated repos project Core-owned `mantle:*` skills from their
123
+ installed package for repo-local use.
44
124
 
45
125
  ## Agent marketplace install
46
126
 
47
127
  Install the Mantle Core skill bundle before working on generated repos:
48
128
 
129
+ Replace `<installed-version>` with the exact version from this package's
130
+ `package.json`. Do not point a versioned consumer at a mutable branch.
131
+
49
132
  ```bash
50
133
  # Claude Code
51
- /plugin marketplace add aotter/mantle
134
+ /plugin marketplace add aotter/mantle@v<installed-version>
52
135
  /plugin install mantle@mantle
53
136
 
54
137
  # Codex
55
- codex plugin marketplace add aotter/mantle --ref develop
138
+ codex plugin marketplace add aotter/mantle --ref v<installed-version>
56
139
  codex plugin add mantle@mantle
57
140
  ```
58
141
 
@@ -97,6 +180,8 @@ The `mantle-runtime` package never imports Cloudflare-specific types — adapter
97
180
  Queue wiring, retry/DLQ, idempotency, and delivery guarantees)
98
181
  - `node_modules/@aotter/mantle/docs/schema-indexes.md` (ordered composite
99
182
  JSON-field indexes, D1 query plans, and the safe Procedure SQL helper)
183
+ - `node_modules/@aotter/mantle/docs/performance-harness.md` (crowded SQLite,
184
+ Wrangler-local D1, cache HIT/MISS, and coding-agent guardrails)
100
185
  - `node_modules/@aotter/mantle/docs/adr/`
101
186
  - `node_modules/@aotter/mantle/skills/develop/SKILL.md`
102
187
  - `node_modules/@aotter/mantle/skills/plugin/SKILL.md`
@@ -104,12 +189,12 @@ The `mantle-runtime` package never imports Cloudflare-specific types — adapter
104
189
  - `node_modules/@aotter/mantle/skills/update/SKILL.md`
105
190
  - `node_modules/@aotter/mantle/skills/install/SKILL.md`
106
191
  - `node_modules/@aotter/mantle/skills/provision/SKILL.md`
107
- - [Repo](https://github.com/aotter/mantle)
108
- - [4-atom manifest model (ADR-0001)](https://github.com/aotter/mantle/blob/develop/docs/adr/0001-four-atom-manifest-model.md)
109
- - [API and MCP authorization](https://github.com/aotter/mantle/blob/develop/docs/api-mcp-authorization.md)
110
- - [Deferred lifecycle Queues](https://github.com/aotter/mantle/blob/develop/docs/deferred-lifecycle-queues.md)
111
- - [Schema indexes on D1](https://github.com/aotter/mantle/blob/develop/docs/schema-indexes.md)
112
- - [Release process](https://github.com/aotter/mantle/blob/develop/docs/release-process.md)
192
+ - [4-atom manifest model (ADR-0001)](docs/adr/0001-four-atom-manifest-model.md)
193
+ - [API and MCP authorization](docs/api-mcp-authorization.md)
194
+ - [Deferred lifecycle Queues](docs/deferred-lifecycle-queues.md)
195
+ - [Schema indexes on D1](docs/schema-indexes.md)
196
+ - [Release process](docs/release-process.md)
197
+ - [Source repository](https://github.com/aotter/mantle)
113
198
  - [Issues](https://github.com/aotter/mantle/issues)
114
199
 
115
200
  ## License
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { argv, stderr, stdout } from "node:process";
3
+ import { runEmitOpenapi, runEmitTypes, runIntrospect, runValidate, } from "@aotter/mantle-spec/cli";
4
+ import { runGenerate } from "./generate.js";
5
+ import { runSkills } from "./skills.js";
6
+ import { runUpdate } from "./update.js";
7
+ async function main() {
8
+ const command = argv[2];
9
+ if (!command || command === "--help" || command === "-h") {
10
+ stdout.write(`mantle - SDK authoring CLI
11
+
12
+ Usage: mantle <subcommand> [options]
13
+
14
+ Subcommands:
15
+ generate Compile manifests and handler types
16
+ skills Project version-matched Core skills
17
+ update Compare local work with provision bundles
18
+ validate Static manifest + handler-source validation
19
+ introspect Dump parsed manifest tree as JSON
20
+ emit-openapi Emit OpenAPI 3.1 from Triggers + Views
21
+ emit-types Emit TypeScript declarations from manifests
22
+ `);
23
+ return command ? 0 : 2;
24
+ }
25
+ const rest = argv.slice(3);
26
+ switch (command) {
27
+ case "generate":
28
+ return runGenerate(rest);
29
+ case "skills":
30
+ return runSkills(rest);
31
+ case "update":
32
+ return runUpdate(rest);
33
+ case "validate":
34
+ return runValidate(rest);
35
+ case "introspect":
36
+ return runIntrospect(rest);
37
+ case "emit-openapi":
38
+ return runEmitOpenapi(rest);
39
+ case "emit-types":
40
+ return runEmitTypes(rest);
41
+ default:
42
+ stderr.write(`Unknown subcommand: ${command}\n`);
43
+ return 2;
44
+ }
45
+ }
46
+ main().then((code) => {
47
+ process.exitCode = code;
48
+ }, (error) => {
49
+ stderr.write(`internal error: ${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
50
+ process.exitCode = 2;
51
+ });
52
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;CAYhB,CAAC,CAAC;QACC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,YAAY;YACf,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,cAAc;YACjB,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,YAAY;YACf,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B;YACE,MAAM,CAAC,KAAK,CAAC,uBAAuB,OAAO,IAAI,CAAC,CAAC;YACjD,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,IAAI,CACT,CAAC,IAAI,EAAE,EAAE;IACP,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;IACR,MAAM,CAAC,KAAK,CAAC,mBAAmB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3G,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runGenerate(rawArgs: readonly string[]): Promise<number>;
2
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAoBA,wBAAsB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0C7E"}
@@ -0,0 +1,181 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { cwd, stderr, stdout } from "node:process";
4
+ import { parseArgs } from "node:util";
5
+ import { EmitTypesUseCase, ValidateManifestsUseCase, } from "@aotter/mantle-spec";
6
+ import { loadManifestsFromRoot } from "@aotter/mantle-spec/cli";
7
+ export async function runGenerate(rawArgs) {
8
+ let options;
9
+ try {
10
+ const parsed = parseGenerateArgs(rawArgs);
11
+ if (parsed === null) {
12
+ printHelp();
13
+ return 0;
14
+ }
15
+ options = parsed;
16
+ }
17
+ catch (error) {
18
+ stderr.write(`${message(error)}\n`);
19
+ return 2;
20
+ }
21
+ const loaded = await loadManifestsFromRoot(options.manifests);
22
+ const validation = ValidateManifestsUseCase.run({
23
+ manifests: loaded.manifests,
24
+ filePaths: loaded.filePaths,
25
+ });
26
+ const errors = [...loaded.parseErrors, ...validation.diagnostics]
27
+ .filter((diagnostic) => diagnostic.severity === "error");
28
+ if (errors.length > 0) {
29
+ for (const error of errors) {
30
+ stderr.write(`${error.code} ${error.path}: ${error.message}\n`);
31
+ }
32
+ return 1;
33
+ }
34
+ const output = resolve(cwd(), options.output);
35
+ const files = new Map([
36
+ [join(output, "site.ts"), emitManifestModule(loaded.manifests, options.namespace)],
37
+ [join(output, "types.d.ts"), emitTypes(loaded.manifests, options.namespace)],
38
+ ]);
39
+ let stale = false;
40
+ for (const [path, source] of files) {
41
+ stale = !(await syncText(path, source, options.check)) || stale;
42
+ }
43
+ if (stale && options.check) {
44
+ stderr.write("Mantle generated files are stale; run `mantle generate`.\n");
45
+ return 1;
46
+ }
47
+ return 0;
48
+ }
49
+ function parseGenerateArgs(rawArgs) {
50
+ const { values } = parseArgs({
51
+ args: [...rawArgs],
52
+ options: {
53
+ manifests: { type: "string" },
54
+ output: { type: "string", short: "o" },
55
+ namespace: { type: "string" },
56
+ check: { type: "boolean" },
57
+ help: { type: "boolean", short: "h" },
58
+ },
59
+ });
60
+ if (values.help)
61
+ return null;
62
+ const namespace = values.namespace ?? "MantleSite";
63
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(namespace)) {
64
+ throw new Error(`--namespace must be a TypeScript identifier; got ${JSON.stringify(namespace)}`);
65
+ }
66
+ return {
67
+ manifests: values.manifests ?? "./manifests",
68
+ output: values.output ?? ".mantle/generated",
69
+ namespace,
70
+ check: values.check === true,
71
+ };
72
+ }
73
+ function printHelp() {
74
+ stdout.write(`mantle generate — compile manifests and handler types
75
+
76
+ Usage: mantle generate [options]
77
+
78
+ Options:
79
+ --manifests <dir> Manifest root (default: ./manifests)
80
+ -o, --output <dir> Generated root (default: .mantle/generated)
81
+ --namespace <name> Generated type namespace (default: MantleSite)
82
+ --check Fail without writing when output is stale
83
+ -h, --help This help
84
+ `);
85
+ }
86
+ function emitManifestModule(manifests, namespace) {
87
+ const views = [];
88
+ manifests.forEach((manifest, index) => {
89
+ if (manifest.kind === "View")
90
+ views.push({ manifest, index });
91
+ });
92
+ const notice = "// Generated by `mantle generate`. Do not edit by hand.";
93
+ const specImport = 'import type { Manifest } from "@aotter/mantle/spec";';
94
+ const declaration = `export const manifest = ${JSON.stringify(manifests, null, 2)} as const satisfies readonly Manifest[];`;
95
+ if (views.length === 0)
96
+ return [notice, specImport, "", declaration, ""].join("\n");
97
+ return [
98
+ notice,
99
+ 'import type { CmsRuntime, HandlerContext } from "@aotter/mantle/runtime";',
100
+ specImport,
101
+ 'import type * as MantleGenerated from "./types.js";',
102
+ "",
103
+ declaration,
104
+ "",
105
+ "export interface MantleViewOptions {",
106
+ " readonly page?: number;",
107
+ " readonly show?: number;",
108
+ " readonly ctx?: HandlerContext;",
109
+ "}",
110
+ "",
111
+ "export function bindMantleSite(runtime: CmsRuntime) {",
112
+ " return {",
113
+ " views: {",
114
+ ...views.flatMap(({ manifest: view, index }) => {
115
+ const id = tsId(view.metadata.name);
116
+ const requiredParams = (view.spec.params?.required?.length ?? 0) > 0;
117
+ const requestType = view.spec.params
118
+ ? `MantleViewOptions & { readonly params${requiredParams ? "" : "?"}: MantleGenerated.${namespace}.ViewParams_${id} }`
119
+ : "MantleViewOptions";
120
+ return [
121
+ ` ${JSON.stringify(view.metadata.name)}: (request: ${requestType}${requiredParams ? "" : " = {}"}) =>`,
122
+ ` runtime.executeView.execute<MantleGenerated.${namespace}.ViewRow_${id}>({`,
123
+ ` view: manifest[${index}],`,
124
+ " ctx: request.ctx,",
125
+ " options: {",
126
+ ...(view.spec.params ? [" params: request.params,"] : []),
127
+ " page: request.page,",
128
+ " show: request.show,",
129
+ " },",
130
+ " }),",
131
+ ];
132
+ }),
133
+ " },",
134
+ " } as const;",
135
+ "}",
136
+ "",
137
+ ].join("\n");
138
+ }
139
+ function emitTypes(manifests, namespace) {
140
+ const generated = EmitTypesUseCase.run({ manifests, namespace }).source
141
+ .replace("Generated by `mantle emit-types`", "Generated by `mantle generate`");
142
+ const procedures = manifests.filter((manifest) => manifest.kind === "Procedure" && manifest.spec.handler.kind === "ref");
143
+ if (procedures.length === 0)
144
+ return generated;
145
+ const handlers = new Map();
146
+ for (const procedure of procedures) {
147
+ const name = tsId(procedure.metadata.name);
148
+ const ref = procedure.spec.handler.kind === "ref" ? procedure.spec.handler.ref : "";
149
+ const types = handlers.get(ref) ?? { inputs: [], outputs: [] };
150
+ types.inputs.push(`${namespace}.ProcInput_${name}`);
151
+ types.outputs.push(`${namespace}.ProcOutput_${name}`);
152
+ handlers.set(ref, types);
153
+ }
154
+ return [
155
+ 'import type { HandlerFn } from "@aotter/mantle/runtime";',
156
+ "",
157
+ generated.trimEnd(),
158
+ "",
159
+ "export type MantleHandlers<Env = unknown> = {",
160
+ ...[...handlers].map(([ref, types]) => ` readonly ${JSON.stringify(ref)}: HandlerFn<${types.inputs.join(" | ")}, ${types.outputs.join(" | ")}, Env>;`),
161
+ "};",
162
+ "",
163
+ ].join("\n");
164
+ }
165
+ function tsId(name) {
166
+ return name.replace(/[^a-zA-Z0-9_$]+/g, "_");
167
+ }
168
+ async function syncText(path, expected, check) {
169
+ const current = await readFile(path, "utf8").catch(() => null);
170
+ if (current === expected)
171
+ return true;
172
+ if (check)
173
+ return false;
174
+ await mkdir(dirname(path), { recursive: true });
175
+ await writeFile(path, expected, "utf8");
176
+ return true;
177
+ }
178
+ function message(error) {
179
+ return error instanceof Error ? error.message : String(error);
180
+ }
181
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=harness-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-cli.d.ts","sourceRoot":"","sources":["../src/harness-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env node
2
+ import { argv, stderr, stdout } from "node:process";
3
+ import { parseArgs } from "node:util";
4
+ import { ValidateManifestsUseCase, } from "@aotter/mantle-spec";
5
+ import { loadManifestsFromRoot } from "@aotter/mantle-spec/cli";
6
+ import { benchmarkHttpRoutes, inspectIndexCoverage, } from "@aotter/mantle-runtime/testing";
7
+ async function main() {
8
+ const command = argv[2];
9
+ if (!command || command === "--help" || command === "-h") {
10
+ printHelp();
11
+ return command ? 0 : 2;
12
+ }
13
+ if (command === "indexes")
14
+ return runIndexes(argv.slice(3));
15
+ if (command === "http")
16
+ return runHttp(argv.slice(3));
17
+ stderr.write(`Unknown subcommand: ${command}\n`);
18
+ return 2;
19
+ }
20
+ async function runIndexes(rawArgs) {
21
+ let values;
22
+ try {
23
+ ({ values } = parseArgs({
24
+ args: [...rawArgs],
25
+ options: {
26
+ manifests: { type: "string" },
27
+ rows: { type: "string" },
28
+ require: { type: "string", multiple: true },
29
+ "require-public": { type: "boolean" },
30
+ format: { type: "string" },
31
+ help: { type: "boolean", short: "h" },
32
+ },
33
+ }));
34
+ }
35
+ catch (error) {
36
+ stderr.write(`${message(error)}\n`);
37
+ return 2;
38
+ }
39
+ if (values.help) {
40
+ printIndexesHelp();
41
+ return 0;
42
+ }
43
+ const format = outputFormat(values.format);
44
+ const loaded = await loadManifestsFromRoot(values.manifests ?? "./manifests");
45
+ const validation = ValidateManifestsUseCase.run({
46
+ manifests: loaded.manifests,
47
+ filePaths: loaded.filePaths,
48
+ });
49
+ const errors = [...loaded.parseErrors, ...validation.diagnostics]
50
+ .filter((diagnostic) => diagnostic.severity === "error");
51
+ if (errors.length > 0) {
52
+ emitErrors(errors, format);
53
+ return 1;
54
+ }
55
+ if (loaded.manifests.length === 0) {
56
+ stderr.write(`No manifests found under ${values.manifests ?? "./manifests"}\n`);
57
+ return 2;
58
+ }
59
+ const rows = values.rows === undefined ? undefined : Number(values.rows);
60
+ if (rows !== undefined && (!Number.isFinite(rows) || rows <= 0)) {
61
+ stderr.write("--rows must be a positive number\n");
62
+ return 2;
63
+ }
64
+ const report = await inspectIndexCoverage(loaded.manifests, {
65
+ rowsPerSchema: rows,
66
+ requirePublic: values["require-public"] === true,
67
+ requiredViews: values.require ?? [],
68
+ });
69
+ emitIndexReport(report, format);
70
+ return report.summary.requiredFailures > 0 ? 1 : 0;
71
+ }
72
+ async function runHttp(rawArgs) {
73
+ let values;
74
+ try {
75
+ ({ values } = parseArgs({
76
+ args: [...rawArgs],
77
+ options: {
78
+ route: { type: "string", multiple: true },
79
+ "base-url": { type: "string" },
80
+ rounds: { type: "string" },
81
+ warmup: { type: "string" },
82
+ format: { type: "string" },
83
+ help: { type: "boolean", short: "h" },
84
+ },
85
+ }));
86
+ }
87
+ catch (error) {
88
+ stderr.write(`${message(error)}\n`);
89
+ return 2;
90
+ }
91
+ if (values.help) {
92
+ printHttpHelp();
93
+ return 0;
94
+ }
95
+ if (!values.route || values.route.length === 0) {
96
+ stderr.write("http requires at least one --route name=/path-or-url\n");
97
+ return 2;
98
+ }
99
+ const format = outputFormat(values.format);
100
+ const baseUrl = (values["base-url"] ?? "").replace(/\/$/, "");
101
+ const targets = values.route.map((raw) => {
102
+ const separator = raw.indexOf("=");
103
+ if (separator < 1)
104
+ throw new Error(`invalid --route ${JSON.stringify(raw)}`);
105
+ const name = raw.slice(0, separator);
106
+ const path = raw.slice(separator + 1);
107
+ return { name, url: path.startsWith("/") ? `${baseUrl}${path}` : path };
108
+ });
109
+ if (targets.some(({ url }) => !/^https?:\/\//.test(url))) {
110
+ stderr.write("route URLs must be absolute, or use --base-url with /paths\n");
111
+ return 2;
112
+ }
113
+ let report;
114
+ try {
115
+ report = await benchmarkHttpRoutes({
116
+ targets,
117
+ rounds: numericOption(values.rounds, "--rounds"),
118
+ warmup: numericOption(values.warmup, "--warmup"),
119
+ });
120
+ }
121
+ catch (error) {
122
+ stderr.write(`${message(error)}\n`);
123
+ return 1;
124
+ }
125
+ emitHttpReport(report, format);
126
+ return 0;
127
+ }
128
+ function emitIndexReport(report, format) {
129
+ if (format === "json") {
130
+ stdout.write(`${JSON.stringify(report, null, 2)}\n`);
131
+ return;
132
+ }
133
+ for (const path of report.paths) {
134
+ const status = path.required ? path.passed ? "PASS" : "FAIL" : "ADVISORY";
135
+ const detail = path.findings.length > 0
136
+ ? path.findings.join("; ")
137
+ : path.usedIndexes.join(", ") || "planner found no named index";
138
+ stdout.write(`${status} ${path.view}: ${detail}\n`);
139
+ }
140
+ for (const view of report.summary.missingRequiredViews) {
141
+ stdout.write(`FAIL ${view}: required View not found\n`);
142
+ }
143
+ stdout.write(`views=${report.summary.views} required=${report.summary.required} ` +
144
+ `failures=${report.summary.requiredFailures} rows/schema=${report.rowsPerSchema}\n`);
145
+ }
146
+ function emitHttpReport(report, format) {
147
+ if (format === "json") {
148
+ stdout.write(`${JSON.stringify(report, null, 2)}\n`);
149
+ return;
150
+ }
151
+ for (const result of report.results) {
152
+ const queries = result.queryCount ? ` queries.p95=${result.queryCount.p95}` : "";
153
+ const rows = result.rowsRead ? ` rows_read.p95=${result.rowsRead.p95}` : "";
154
+ stdout.write(`${result.name}: p50=${result.timingMs.p50.toFixed(2)}ms ` +
155
+ `p95=${result.timingMs.p95.toFixed(2)}ms${queries}${rows}\n`);
156
+ }
157
+ }
158
+ function emitErrors(errors, format) {
159
+ if (format === "json")
160
+ stdout.write(`${JSON.stringify({ errors }, null, 2)}\n`);
161
+ else
162
+ for (const error of errors)
163
+ stderr.write(`${error.code} ${error.path}: ${error.message}\n`);
164
+ }
165
+ function outputFormat(raw) {
166
+ if (raw === undefined)
167
+ return stdout.isTTY ? "text" : "json";
168
+ if (raw === "json" || raw === "text")
169
+ return raw;
170
+ throw new Error(`--format must be text or json; got ${JSON.stringify(raw)}`);
171
+ }
172
+ function numericOption(raw, name) {
173
+ if (raw === undefined)
174
+ return undefined;
175
+ const value = Number(raw);
176
+ if (!Number.isFinite(value) || value < 0)
177
+ throw new Error(`${name} must be a non-negative number`);
178
+ return value;
179
+ }
180
+ function message(error) {
181
+ return error instanceof Error ? error.message : String(error);
182
+ }
183
+ function printHelp() {
184
+ stdout.write(`mantle-harness — measured performance checks\n\n` +
185
+ `Usage: mantle-harness <indexes|http> [options]\n\n` +
186
+ ` indexes Execute compiled Views in crowded SQLite and inspect plans\n` +
187
+ ` http Sample a running Worker and report p50/p95 + metric headers\n`);
188
+ }
189
+ function printIndexesHelp() {
190
+ stdout.write(`Usage: mantle-harness indexes [options]\n\n` +
191
+ ` --manifests <dir> Manifest root (default: ./manifests)\n` +
192
+ ` --rows <n> Deterministic rows per Schema (default: 2000)\n` +
193
+ ` --require <view> Fail when this View lacks its access path; repeatable\n` +
194
+ ` --require-public Apply the gate to public Views\n` +
195
+ ` --format <fmt> text or json\n`);
196
+ }
197
+ function printHttpHelp() {
198
+ stdout.write(`Usage: mantle-harness http [options]\n\n` +
199
+ ` --base-url <url> Prefix for route paths\n` +
200
+ ` --route <name=url> Route label and path/URL; repeatable\n` +
201
+ ` --rounds <n> Measured requests per route (default: 20)\n` +
202
+ ` --warmup <n> Warmup requests per route (default: 2)\n` +
203
+ ` --format <fmt> text or json\n`);
204
+ }
205
+ main().then((code) => { process.exitCode = code; }, (error) => {
206
+ stderr.write(`${message(error)}\n`);
207
+ process.exitCode = 2;
208
+ });
209
+ //# sourceMappingURL=harness-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-cli.js","sourceRoot":"","sources":["../src/harness-cli.ts"],"names":[],"mappings":"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"}