@jimhoyd/urlcode 0.4.2 → 0.4.6
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/.claude/skills/urlcode-authoring/SKILL.md +57 -14
- package/.claude/skills/urlcode-operations/SKILL.md +4 -0
- package/README.md +19 -15
- package/SECURITY.md +5 -3
- package/dist/BUILD-MANIFEST.json +30 -27
- package/dist/agent-context.js +82 -0
- package/dist/agents-guide.js +42 -42
- package/dist/authoring.js +12 -2
- package/dist/body-schema.js +159 -0
- package/dist/build-cloudflare.js +2 -0
- package/dist/capabilities.js +1 -1
- package/dist/cli.js +28 -12
- package/dist/config.js +74 -6
- package/dist/context.js +4 -6
- package/dist/errors.js +3 -1
- package/dist/examples.js +1 -1
- package/dist/extensions.js +60 -2
- package/dist/http-policy.js +19 -4
- package/dist/http-response.js +2 -2
- package/dist/init-with.js +71 -9
- package/dist/mcp.js +15 -2
- package/dist/pattern-guard.js +32 -0
- package/dist/policies/security.js +0 -0
- package/dist/project-tests.js +35 -11
- package/dist/readiness.js +184 -32
- package/dist/recipes.js +1 -1
- package/dist/router.js +17 -0
- package/dist/runtime.js +26 -3
- package/dist/scaffold.js +0 -0
- package/dist/server.js +26 -3
- package/dist/site.js +0 -0
- package/dist/tooling.js +2 -1
- package/dist/types/agent-context.d.ts +44 -0
- package/dist/types/authoring.d.ts +3 -1
- package/dist/types/body-schema.d.ts +58 -0
- package/dist/types/config.d.ts +10 -2
- package/dist/types/context.d.ts +1 -1
- package/dist/types/errors.d.ts +9 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/extensions.d.ts +47 -2
- package/dist/types/http-policy.d.ts +3 -0
- package/dist/types/init-with.d.ts +10 -1
- package/dist/types/pattern-guard.d.ts +10 -0
- package/dist/types/project-tests.d.ts +9 -0
- package/dist/types/readiness.d.ts +68 -0
- package/dist/types/recipes.d.ts +1 -1
- package/dist/types/runtime.d.ts +4 -0
- package/dist/types/server.d.ts +9 -1
- package/dist/types/tooling.d.ts +1 -0
- package/dist/types/types.d.ts +13 -0
- package/dist/types.js +10 -2
- package/dist/typescript-authoring.js +5 -3
- package/dist/verify-deployment.js +16 -10
- package/examples/body-validation/README.md +16 -0
- package/examples/body-validation/example.yaml +17 -0
- package/examples/body-validation/tests/requests.json +15 -0
- package/examples/body-validation/urlcode.yaml +34 -0
- package/examples/coverage-waiver/README.md +8 -0
- package/examples/coverage-waiver/example.yaml +16 -0
- package/examples/coverage-waiver/functions/notes.mjs +2 -0
- package/examples/coverage-waiver/tests/requests.json +3 -0
- package/examples/coverage-waiver/urlcode.yaml +10 -0
- package/examples/data-dir/README.md +39 -0
- package/examples/data-dir/data/welcome.txt +1 -0
- package/examples/data-dir/example.yaml +22 -0
- package/examples/data-dir/functions/note.mjs +18 -0
- package/examples/data-dir/tests/requests.json +6 -0
- package/examples/data-dir/urlcode.yaml +6 -0
- package/examples/lifecycle/README.md +15 -0
- package/examples/lifecycle/example.yaml +19 -0
- package/examples/lifecycle/functions/notes.mjs +29 -0
- package/examples/lifecycle/tests/requests.json +12 -0
- package/examples/lifecycle/urlcode.yaml +29 -0
- package/examples/not-found/README.md +10 -0
- package/examples/not-found/example.yaml +17 -0
- package/examples/not-found/public/404.html +3 -0
- package/examples/not-found/public/index.html +3 -0
- package/examples/not-found/tests/requests.json +7 -0
- package/examples/not-found/urlcode.yaml +7 -0
- package/examples/shared-blocks/README.md +11 -0
- package/examples/shared-blocks/example.yaml +17 -0
- package/examples/shared-blocks/tests/requests.json +7 -0
- package/examples/shared-blocks/urlcode.yaml +37 -0
- package/llms-full.txt +364 -49
- package/llms.txt +43 -5
- package/package.json +15 -22
- package/recipes/static-page/README.md +9 -0
- package/recipes/static-page/public/index.html +11 -0
- package/recipes/static-page/recipe.yaml +21 -0
- package/recipes/static-page/tests/requests.json +22 -0
- package/recipes/static-page/urlcode.yaml +7 -0
- package/recipes/static-plus-api/README.md +6 -0
- package/recipes/static-plus-api/urlcode.yaml +4 -0
- package/recipes/store-crud/README.md +53 -0
- package/recipes/store-crud/recipe.yaml +31 -0
- package/recipes/store-crud/tests/requests.json +18 -0
- package/recipes/store-crud/urlcode.yaml +18 -0
- package/schemas/urlcode.schema.json +125 -60
- package/skills/urlcode/SKILL.md +47 -27
- package/starters/default/AGENTS.md +43 -43
- package/starters/page/README.md +14 -0
- package/starters/page/public/index.html +12 -0
- package/starters/page/tests/requests.json +17 -0
- package/starters/page/urlcode.yaml +6 -0
- package/.claude-plugin/marketplace.json +0 -18
- package/CONTRIBUTING.md +0 -148
- package/ROADMAP.md +0 -70
- package/docs/AI-AUTHORING.md +0 -339
- package/docs/ASSETS.md +0 -107
- package/docs/AUTH-BACKUP.md +0 -32
- package/docs/AWS.md +0 -86
- package/docs/BEST-PRACTICES.md +0 -276
- package/docs/BULK.md +0 -79
- package/docs/CAPABILITIES.md +0 -192
- package/docs/CAPACITY.md +0 -305
- package/docs/CI-FOLLOWUP-2026-09-19.md +0 -97
- package/docs/CI-RELEASE-AUDIT-2026-09-19.md +0 -322
- package/docs/CI.md +0 -147
- package/docs/CLOUDFLARE.md +0 -109
- package/docs/CODEBASE-AUDIT-2026-09-20.md +0 -284
- package/docs/COMPLIANCE.md +0 -239
- package/docs/COMPOSING-A-SITE.md +0 -287
- package/docs/CONDITIONS.md +0 -74
- package/docs/CONTAINER-PROMOTION.md +0 -74
- package/docs/DEPLOYMENT-CHECKS.md +0 -108
- package/docs/DEVELOPMENT-PIPELINE.md +0 -304
- package/docs/EGRESS.md +0 -125
- package/docs/EXTENSIONS.md +0 -403
- package/docs/FRAMEWORK.md +0 -217
- package/docs/FUNCTION-SECURITY.md +0 -251
- package/docs/HTTP.md +0 -129
- package/docs/INSTALL.md +0 -128
- package/docs/INTERCHANGE.md +0 -134
- package/docs/LOAD-TESTING.md +0 -91
- package/docs/LOCAL-DEVELOPMENT.md +0 -102
- package/docs/MIDDLEWARE-EXAMPLES.md +0 -75
- package/docs/MIDDLEWARE.md +0 -102
- package/docs/MONITORING.md +0 -115
- package/docs/OBSERVABILITY.md +0 -222
- package/docs/OPEN-DECISIONS.md +0 -149
- package/docs/OPERATIONAL-PROOF.md +0 -41
- package/docs/OPERATIONS.md +0 -201
- package/docs/ORGANIZATION.md +0 -135
- package/docs/PERFORMANCE.md +0 -72
- package/docs/PLUGINS.md +0 -271
- package/docs/POLICIES.md +0 -211
- package/docs/PRERENDER.md +0 -245
- package/docs/PROJECT-DIRECTION.md +0 -118
- package/docs/PROVIDER-VERIFICATION.md +0 -84
- package/docs/READINESS.md +0 -153
- package/docs/README.md +0 -93
- package/docs/RECIPES.md +0 -99
- package/docs/RELEASE-0.4.0-alpha.3.md +0 -50
- package/docs/RELEASE-0.4.1.md +0 -73
- package/docs/RELEASE-0.4.2.md +0 -30
- package/docs/RELEASE-READINESS.md +0 -146
- package/docs/RELEASE-SECURITY.md +0 -100
- package/docs/RESILIENCE.md +0 -161
- package/docs/ROUTING.md +0 -92
- package/docs/SANDBOX-REVIEW.md +0 -72
- package/docs/SCAFFOLDING.md +0 -70
- package/docs/SECURITY-AUDIT.md +0 -164
- package/docs/SITE.md +0 -150
- package/docs/SPECIFICATION.md +0 -359
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +0 -288
- package/docs/SPIKE-BUSINESS-SUITE.md +0 -1029
- package/docs/SPIKE-CORE-LAYERING.md +0 -368
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +0 -207
- package/docs/STANDARDS.md +0 -311
- package/docs/STARTERS.md +0 -83
- package/docs/STATIC.md +0 -105
- package/docs/TOOLING.md +0 -298
- package/docs/TUNNELS.md +0 -72
- package/docs/TYPESCRIPT-AUTHORING.md +0 -87
- package/docs/TYPESCRIPT.md +0 -123
- package/docs/VERCEL.md +0 -114
- package/docs/VERSION-ALIGNMENT.md +0 -88
- package/docs/YAML-GUIDE.md +0 -57
- package/docs/YAML-REFERENCE.md +0 -449
- package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +0 -68
- package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +0 -102
- package/docs/archive/2026-09-19/NEXT-PHASE-PLAN.md +0 -108
- package/docs/archive/2026-09-19/NEXT-STEPS.md +0 -646
- package/docs/archive/2026-09-19/OPEN-DECISIONS.md +0 -277
- package/docs/archive/2026-09-19/RELEASE-SECURITY.md +0 -186
- package/docs/archive/2026-09-19/ROADMAP.md +0 -387
- package/docs/archive/2026-09-19/SPIKE-EXTENSION-MODEL.md +0 -430
- package/docs/archive/2026-09-19/SPIKE-EXTENSIONS.md +0 -492
- package/docs/archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md +0 -365
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +0 -778
- package/docs/archive/2026-09-19/USABILITY-REVIEW.md +0 -139
- package/docs/archive/2026-09-20/OPEN-DECISIONS-COMPLETED.md +0 -116
- package/docs/archive/README.md +0 -29
- package/docs/policies/agents.md +0 -182
- package/docs/policies/cache.md +0 -152
- package/docs/policies/compression.md +0 -169
- package/docs/policies/contract.md +0 -52
- package/docs/policies/hardened.md +0 -56
- package/docs/policies/interoperability.md +0 -169
- package/docs/policies/operations.md +0 -45
- package/docs/policies/security.md +0 -161
- package/docs/policies/throttle.md +0 -103
- package/docs/yaml/assets.md +0 -36
- package/docs/yaml/conditions.md +0 -20
- package/docs/yaml/functions.md +0 -168
- package/docs/yaml/middleware.md +0 -31
- package/docs/yaml/organization.md +0 -74
- package/docs/yaml/policies.md +0 -37
- package/docs/yaml/redirects.md +0 -64
- package/docs/yaml/responses.md +0 -57
- package/docs/yaml/site.md +0 -24
- package/packaging/claude-plugin/.claude-plugin/plugin.json +0 -19
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +0 -130
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +0 -108
package/docs/SPECIFICATION.md
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
# Implemented project contract
|
|
2
|
-
|
|
3
|
-
This document and [JSON Schema](../schemas/urlcode.schema.json) describe
|
|
4
|
-
the source contract, including unreleased additions after 0.3.0.
|
|
5
|
-
`version: "1"` remains the project-format contract. Unsupported fields
|
|
6
|
-
are rejected rather than interpreted as future behavior.
|
|
7
|
-
|
|
8
|
-
## Files and validation
|
|
9
|
-
|
|
10
|
-
`urlcode.yaml` contains `version`, `routes`, and optional `includes` (an explicit
|
|
11
|
-
list of project-relative YAML files). Included files have the same version/routes
|
|
12
|
-
shape and cannot recursively include files. Duplicate paths across files fail.
|
|
13
|
-
See [organization examples](ORGANIZATION.md) for one-file, multi-file and mixed
|
|
14
|
-
layouts. All references resolve from the project root, not the including file.
|
|
15
|
-
File references resolve inside the project; escaping symlinks fail. No glob,
|
|
16
|
-
remote config or arbitrary infrastructure configuration.
|
|
17
|
-
|
|
18
|
-
YAML 1.2 JSON-compatible values only: string mapping keys, finite numbers,
|
|
19
|
-
booleans and null. No duplicate keys, aliases, anchors, tags, merge keys,
|
|
20
|
-
multiple documents, reserved prototype keys or nesting of 40+ levels. Unknown
|
|
21
|
-
schema fields fail. Files are limited to 32 MiB each, 256 includes and 100,000
|
|
22
|
-
routes total, with a 64 MiB aggregate YAML source cap. Loading runs in a worker
|
|
23
|
-
with a 256 MiB old-generation heap, a 10-second wall deadline and at most two
|
|
24
|
-
concurrent loads per Node isolate. These are not a total process RSS bound.
|
|
25
|
-
Route compilation yields every 64 routes and checks a 10-second cooperative
|
|
26
|
-
deadline; individual synchronous operations are not preempted. At most 1,000 parameterized routes and 1,024 distinct input schemas.
|
|
27
|
-
|
|
28
|
-
## Routes
|
|
29
|
-
|
|
30
|
-
Keys are absolute case-sensitive paths. Trailing slashes are significant.
|
|
31
|
-
Parameters occupy whole segments, e.g. `/p/{id}`, with distinct identifier names.
|
|
32
|
-
Each parameter matches exactly one nonempty segment, never across `/`; it is not
|
|
33
|
-
greedy. No regex paths, client-controlled host dispatch or dot segments. Only static directory mounts
|
|
34
|
-
support a terminal `/*` wildcard with an otherwise literal path. Route keys cannot contain
|
|
35
|
-
percent encoding, spaces, backslashes or query strings. Path length is limited
|
|
36
|
-
to 2,048 characters and 32 segments. `/_urlcode` is reserved.
|
|
37
|
-
|
|
38
|
-
One handler per route: `function`, `redirect`, `page`, `static`, `download`, `respond`, `conditional`, `proxy` or an `extension` mount.
|
|
39
|
-
See [asset configuration](ASSETS.md) for file handlers. Optional properties:
|
|
40
|
-
|
|
41
|
-
- `methods`: unique HTTP methods; default GET and HEAD. Explicit lists are exact;
|
|
42
|
-
adding GET does not implicitly add HEAD. Wrong method returns 405 plus Allow.
|
|
43
|
-
- `enabled`: false returns 404, the same as unknown paths.
|
|
44
|
-
- `expires`: UTC ISO timestamp (`...ssZ` or `...ss.sssZ`); expired routes return 410.
|
|
45
|
-
- `description`: optional authoring metadata.
|
|
46
|
-
- `middleware`: ordered list of up to 16 `{source, export?}` modules wrapping any
|
|
47
|
-
handler. See [middleware](MIDDLEWARE.md) for the portable contract.
|
|
48
|
-
- `parameters`, `env`, `secrets`: inputs and explicit binding references.
|
|
49
|
-
|
|
50
|
-
Literal paths win; parameter routes with more literal segments win next;
|
|
51
|
-
static mounts follow, longest prefix first. A missing file in the selected mount
|
|
52
|
-
returns 404 without falling back to a shorter mount.
|
|
53
|
-
Equally specific overlapping patterns fail even if methods differ. Match a route
|
|
54
|
-
before checking its methods; do not fall back to a less specific route for 405.
|
|
55
|
-
Requests decode the path once; invalid UTF-8/percent encoding, encoded slashes or
|
|
56
|
-
backslashes, control characters and dot segments return 400. Query values decode
|
|
57
|
-
once. Incoming query data is not automatically forwarded.
|
|
58
|
-
|
|
59
|
-
See [route matching](ROUTING.md) for examples, precedence, wildcard
|
|
60
|
-
limits and reload behavior.
|
|
61
|
-
|
|
62
|
-
The optional top-level `site` block (entry file only) generates native routes
|
|
63
|
-
for site conventions: `robots` → `/robots.txt`, `sitemap` → `/sitemap.xml`,
|
|
64
|
-
`favicon` → `/favicon.ico`, `securityTxt` → `/.well-known/security.txt` and
|
|
65
|
-
`llms` → `/llms.txt`. Each is an ordinary `respond` or `page` route merged in
|
|
66
|
-
before compilation and counted by `routes`/`audit`; a declared route at the same
|
|
67
|
-
path wins and the generated one is logged as shadowed. Absolute URLs come from
|
|
68
|
-
the operator's `--origin`; `sitemap` refuses activation without one. See
|
|
69
|
-
[site conventions](SITE.md).
|
|
70
|
-
|
|
71
|
-
## Exact conditions and duplicate-path alternatives
|
|
72
|
-
|
|
73
|
-
Optional route `match` conjunctively compares exact query/header/cookie strings,
|
|
74
|
-
an uppercase method and the canonical authority of the operator-configured
|
|
75
|
-
public origin. Host/forwarded headers never select the trusted host. A guard
|
|
76
|
-
mismatch returns 404 without trying a less-specific path; route method admission
|
|
77
|
-
still applies after the guard. Conditions are not authentication or authorization.
|
|
78
|
-
|
|
79
|
-
The `conditional` handler puts alternatives under one existing route key:
|
|
80
|
-
`cases` contains 1–16 `{match, redirect}` or `{match, respond}` entries; optional
|
|
81
|
-
`fallback` contains exactly one redirect/respond handler. Duplicate YAML paths
|
|
82
|
-
remain invalid. Cases must be provably disjoint: each pair needs a shared
|
|
83
|
-
predicate with different required values. Cases run before fallback; no matching
|
|
84
|
-
case and no fallback returns 404. Nested cases and branch-local bindings,
|
|
85
|
-
middleware or policy are unsupported. Shared inputs, methods, headers,
|
|
86
|
-
middleware and policies stay at route level.
|
|
87
|
-
|
|
88
|
-
Each query/header/cookie map has 1–16 comparisons; names have at most 128
|
|
89
|
-
characters and values 1,024. Query comparisons use decoded raw strings without
|
|
90
|
-
parameter defaults/coercion. Cookies use unquoted wire values and an 8 KiB input
|
|
91
|
-
limit. Missing and empty are different. Duplicate examined scalar inputs return
|
|
92
|
-
400 when the transport exposes their counts. Header names normalize to lowercase;
|
|
93
|
-
authentication and transport headers cannot be predicates. No regex, geo/device
|
|
94
|
-
inference, wildcard or arbitrary-code conditions are supported.
|
|
95
|
-
|
|
96
|
-
Conditional routing requires cache disabled or no-store and forces downstream
|
|
97
|
-
no-store responses. Explicit fixtures are required for branch coverage.
|
|
98
|
-
Self-hosted, AWS and Vercel use the shared matcher; Cloudflare refuses conditions
|
|
99
|
-
until its artifact compiler supports them. See [conditions](CONDITIONS.md) and
|
|
100
|
-
the [executable example](../examples/conditions).
|
|
101
|
-
|
|
102
|
-
## HTTP request/response configuration
|
|
103
|
-
|
|
104
|
-
Routes accept `request.body` validation and `response.headers` overrides. The
|
|
105
|
-
`respond` handler serves declared text/JSON with a status without running code.
|
|
106
|
-
See [HTTP configuration](HTTP.md) for the exact supported fields, precedence,
|
|
107
|
-
security restrictions and examples.
|
|
108
|
-
|
|
109
|
-
## Policies
|
|
110
|
-
|
|
111
|
-
Optional top-level `policies` and `profiles` keys, and `routes.<path>.policies`,
|
|
112
|
-
declare host-enforced behavior around a route: `throttle`, `agents`, `security`,
|
|
113
|
-
`compression` and `cache`. All are off unless declared; a route's keys merge
|
|
114
|
-
over the project's, `false` disables one, and a target that cannot enforce a
|
|
115
|
-
policy refuses activation naming the route. The five policies are implemented
|
|
116
|
-
for the self-hosted server; Vercel and AWS accept `agents`, `security`, `cache`
|
|
117
|
-
and route-partitioned `throttle`; the Cloudflare build compiles `agents` and
|
|
118
|
-
`security` only. See [policies](POLICIES.md) for the pipeline position, merge
|
|
119
|
-
rules and the per-target table, and [plugins](PLUGINS.md) for the host hook API
|
|
120
|
-
operators pass in code.
|
|
121
|
-
|
|
122
|
-
## Inputs
|
|
123
|
-
|
|
124
|
-
Declare each path placeholder as a required string. Query/header inputs may be
|
|
125
|
-
string, integer, number or boolean. Query arrays declare scalar `items`; repeated
|
|
126
|
-
keys retain order (maximum 100 values). Header names are case-insensitive.
|
|
127
|
-
Duplicate scalar query/header inputs return 400. Required missing inputs return
|
|
128
|
-
400; defaults apply only to absent inputs. Empty strings are present values.
|
|
129
|
-
|
|
130
|
-
Supported validation: `type`, scalar `enum`, `default`, string `minLength`/
|
|
131
|
-
`maxLength`, numeric `minimum`/`maximum`, query array `items` and `maxItems`.
|
|
132
|
-
Regular-expression patterns, structured bodies, cookies, nested inputs and
|
|
133
|
-
OpenAPI `style`/`explode` fields are not implemented. This uses a documented
|
|
134
|
-
OpenAPI-like input subset; it is not an OpenAPI document or full JSON Schema
|
|
135
|
-
input vocabulary. String limits are at most 8,192 characters.
|
|
136
|
-
|
|
137
|
-
Integers use `-?(0|[1-9][0-9]*)` and must be safe JavaScript integers. Numbers
|
|
138
|
-
allow the same grammar plus a fractional suffix; no exponent, plus sign, leading
|
|
139
|
-
zeros, whitespace, NaN or infinity. Booleans are exactly `true` or `false`.
|
|
140
|
-
Unknown query keys are ignored unless explicitly passed by a redirect.
|
|
141
|
-
|
|
142
|
-
## Redirects
|
|
143
|
-
|
|
144
|
-
`redirect.url` is an absolute HTTP(S) URL with literal scheme/host and no embedded
|
|
145
|
-
credentials or whitespace/control characters. `{pathInput}` placeholders are
|
|
146
|
-
allowed only in the destination pathname and encoded as single components.
|
|
147
|
-
No environment/secret interpolation. Status defaults to 302; allowed values are
|
|
148
|
-
301, 302, 303, 307 and 308.
|
|
149
|
-
|
|
150
|
-
`redirect.query.map` maps output keys to `{from: path|query|header, name: input}`
|
|
151
|
-
references to declared inputs. Typed/defaulted values are used. Arrays produce
|
|
152
|
-
repeated output keys. Absent optional inputs are omitted.
|
|
153
|
-
`redirect.query.pass` is false or an explicit allowlist; unrestricted `true` is
|
|
154
|
-
not supported. Conflicts between destination keys, maps and passthrough fail.
|
|
155
|
-
Declared passthrough inputs use validated/defaulted values; undeclared allowlisted
|
|
156
|
-
keys preserve repeated values. Headers are forwarded only through explicit maps.
|
|
157
|
-
|
|
158
|
-
## Stored links
|
|
159
|
-
|
|
160
|
-
Core has no native `link` handler or `dynamicLinks` project flag; both were
|
|
161
|
-
removed. The `urlcode-dynamic-link` extension package that replaced them has
|
|
162
|
-
been retired and unpublished, so a project needing stored short links owns that
|
|
163
|
-
storage itself; there is no in-core replacement or deprecation shim for
|
|
164
|
-
`link`/`dynamicLinks`.
|
|
165
|
-
|
|
166
|
-
## Functions
|
|
167
|
-
|
|
168
|
-
```yaml
|
|
169
|
-
version: "1"
|
|
170
|
-
routes:
|
|
171
|
-
/hello/{name}:
|
|
172
|
-
parameters:
|
|
173
|
-
- name: name
|
|
174
|
-
in: path
|
|
175
|
-
required: true
|
|
176
|
-
schema: {type: string, minLength: 1}
|
|
177
|
-
function:
|
|
178
|
-
source: functions/hello.mjs
|
|
179
|
-
export: default
|
|
180
|
-
args:
|
|
181
|
-
name: {from: path, name: name}
|
|
182
|
-
env:
|
|
183
|
-
GREETING: {value: Hello}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
```js
|
|
187
|
-
export default function hello(request, { args, env }) {
|
|
188
|
-
return Response.json({ message: `${env.GREETING}, ${args.name}!` });
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
`function` also accepts a string: `function: functions/hello.mjs`. Document
|
|
193
|
-
validation normalizes it to the long form above before routing, auditing,
|
|
194
|
-
explaining or hashing the project: `source` is the string, `args` maps every
|
|
195
|
-
`{param}` segment of the path to `{from: path, name: param}`, and each such
|
|
196
|
-
parameter the route does not already declare under `parameters` (by name, with
|
|
197
|
-
`in: path`) is appended as `{in: path, required: true, schema: {type: string,
|
|
198
|
-
minLength: 1, maxLength: 128}}`. Declared parameters keep their own schema and
|
|
199
|
-
order. The string must be a project-relative `.mjs` or `.js` path without `..`
|
|
200
|
-
segments; anything else is refused with the route path named. A `middleware`
|
|
201
|
-
entry may likewise be a string, normalized to `{source: <string>}`. Only the
|
|
202
|
-
long form exists after loading, so `routes`, `audit`, `explain`, revision hashes
|
|
203
|
-
and the field reference describe the expansion.
|
|
204
|
-
|
|
205
|
-
ES modules only. `.mjs` is loaded as ESM in both modes. A `sandbox: true` route
|
|
206
|
-
also reads `.js` as ESM independently of Node package settings, but a trusted
|
|
207
|
-
route imports `.js` through Node's own loader, so an ESM `.js` module needs the
|
|
208
|
-
nearest `package.json` to declare `"type": "module"`; under `"type": "commonjs"`
|
|
209
|
-
it fails activation. Prefer `.mjs` for modules that must work in either mode.
|
|
210
|
-
[Build-time TypeScript authoring](TYPESCRIPT-AUTHORING.md) can produce these
|
|
211
|
-
JavaScript modules in a separate output project; serving does not transpile them.
|
|
212
|
-
The build never imports application code into Node, uses fixed compiler settings,
|
|
213
|
-
and does not perform semantic type checking. Grants must target the built
|
|
214
|
-
configuration/source revision. `export` defaults to `default`.
|
|
215
|
-
|
|
216
|
-
### Trust: unsandboxed by default, `sandbox: true` opt-in
|
|
217
|
-
|
|
218
|
-
A route's `function`/`middleware` chain runs one of two ways, chosen by the
|
|
219
|
-
route's `sandbox` field (false or absent — the default — versus `true`; see
|
|
220
|
-
[docs/SPIKE-DEFAULT-TRUST-MODEL.md](SPIKE-DEFAULT-TRUST-MODEL.md)):
|
|
221
|
-
|
|
222
|
-
- **`sandbox` false/absent (trusted, the default):** the module is imported
|
|
223
|
-
directly into the host process with ordinary Node module resolution — bare
|
|
224
|
-
specifiers, `node:` builtins, npm packages and dynamic `import()` all work,
|
|
225
|
-
none of the module-graph/source-size limits below apply, and there is no
|
|
226
|
-
fresh-heap-per-call reset (module-level state persists across requests like
|
|
227
|
-
any other Node server). The handler/middleware signature and `context`
|
|
228
|
-
shape are unchanged from the sandboxed contract below; a trusted function
|
|
229
|
-
additionally has the full Fetch API, Node built-ins and the filesystem
|
|
230
|
-
available to it, not just the guest text/JSON subset. `args`/`env`/
|
|
231
|
-
`secrets` are exactly what the route declares and an operator grants,
|
|
232
|
-
identically to the sandboxed path.
|
|
233
|
-
- **`sandbox: true`:** the rest of this section, unchanged from every earlier
|
|
234
|
-
release. A sandboxed route's functions and middleware execute inside
|
|
235
|
-
QuickJS/WASM, never through Node imports.
|
|
236
|
-
|
|
237
|
-
The remainder of this section (module restrictions, the guest API subset,
|
|
238
|
-
guest limits and deadlines) describes the `sandbox: true` path specifically,
|
|
239
|
-
unless stated otherwise.
|
|
240
|
-
|
|
241
|
-
Only relative `.js`/`.mjs`
|
|
242
|
-
project imports are supported, with a snapshotted dependency graph. No bare/npm,
|
|
243
|
-
Node built-in, remote, dynamic source imports or `import.meta`. Runtime-created
|
|
244
|
-
imports remain restricted to the route's middleware and handler dependency graphs; there is no fallback.
|
|
245
|
-
Source limits: 128 modules, 1 MiB per module, 4 MiB total.
|
|
246
|
-
|
|
247
|
-
The current guest API is a **text/JSON subset**, not the complete native Fetch
|
|
248
|
-
API: Request `url`, `method`, `headers`, `text()`, `json()`; Headers append/set/
|
|
249
|
-
delete/get/has/entries/getSetCookie; Response constructor with string/null body,
|
|
250
|
-
`status`, `headers`, `ok`, `text()`, `json()`, static `json()` and `redirect()`.
|
|
251
|
-
Requests decode body bytes as UTF-8. Binary/streaming bodies, URL helpers,
|
|
252
|
-
fetch/WebSocket, crypto and filesystem are not exposed. Promise/async and
|
|
253
|
-
bounded timers (128 pending per invocation) work inside the guest. Unsupported
|
|
254
|
-
APIs fail; they never execute on the host. Do not claim full browser/Node API
|
|
255
|
-
parity for a `sandbox: true` route; a trusted route has no such restriction.
|
|
256
|
-
|
|
257
|
-
Context contains `inputs.path/query/header`, `args`, `env`, `secrets`. Arguments
|
|
258
|
-
may be scalar literals, input references, `{env: alias}` or `{secret: alias}`.
|
|
259
|
-
Bindings use `{value: "literal"}`, `{env: EXTERNAL_NAME}` or `{secret: logical_name}`.
|
|
260
|
-
Literal non-secret values need no grant. Every external environment or secret
|
|
261
|
-
binding is denied unless an operator policy grants that exact name to the route
|
|
262
|
-
and matches the SHA-256 of the current configuration/source snapshot.
|
|
263
|
-
A project cannot grant itself capabilities. See [policy setup](FUNCTION-SECURITY.md).
|
|
264
|
-
Missing bindings also reject activation. Inspection parses source without running it.
|
|
265
|
-
|
|
266
|
-
Development may read `.env.local`; process values win. Serving never reads it.
|
|
267
|
-
Dotenv supports single-line NAME=value, paired single/double quotes, blank lines
|
|
268
|
-
and full-line comments, without expansion/escapes/shell execution. Loading a
|
|
269
|
-
value does not authorize exposing it to a function; the policy still applies.
|
|
270
|
-
|
|
271
|
-
A `sandbox: true` invocation has a fresh guest heap and module state every
|
|
272
|
-
time. No cross-request counters, cached secrets or prototype mutation. QuickJS
|
|
273
|
-
heap limit is 32 MiB, stack limit 512 KiB; outer worker and deployment limits
|
|
274
|
-
are additional defenses, not a claim that total process RSS is capped at 32
|
|
275
|
-
MiB. Two workers, no queue; saturation returns 503. The independent 5-second
|
|
276
|
-
deadline terminates a worker and returns 504. Generic failures return 502;
|
|
277
|
-
worker replacement is bounded. A trusted route has none of this: no fresh
|
|
278
|
-
heap/module reset, no fixed worker-pool ceiling (bounded instead by ordinary
|
|
279
|
-
Node concurrency and the HTTP admission cap), and its deadline races the
|
|
280
|
-
call's promise rather than force-terminating a worker — see
|
|
281
|
-
[capacity](CAPACITY.md) for both models side by side.
|
|
282
|
-
|
|
283
|
-
HEAD invokes the handler as HEAD and suppresses body output. Code must guard
|
|
284
|
-
its own application side effects when future brokered integrations are enabled.
|
|
285
|
-
Guest console output is discarded. Functions see the configured public origin,
|
|
286
|
-
not arbitrary Host/forwarded headers. Request/response bodies default to 1 MiB;
|
|
287
|
-
response headers 16 KiB, maximum 256 pairs. Hop-by-hop headers are stripped;
|
|
288
|
-
cookies are preserved individually. Default response cache policy is `no-store`.
|
|
289
|
-
|
|
290
|
-
A trusted (non-`sandbox`) route already has unrestricted host execution by
|
|
291
|
-
design — that is the point of the default described above. For a `sandbox:
|
|
292
|
-
true` route, there is no unrestricted host-execution fallback: declarative
|
|
293
|
-
proxy and webhook signals use the separately granted host broker described in
|
|
294
|
-
[egress](EGRESS.md), and that route's guests still have no fetch API or
|
|
295
|
-
general persistent state capability. Approved secrets can be returned by code
|
|
296
|
-
that receives them, in either mode; isolation does not automatically enforce
|
|
297
|
-
information-flow rules on authorized inputs. Keep grants narrow and review the
|
|
298
|
-
exact pinned revision. The `sandbox: true` path still needs independent
|
|
299
|
-
security review before hostile multi-tenant use of that specific mode; that
|
|
300
|
-
review's scope was never a claim about a route that opts out of the sandbox
|
|
301
|
-
(see [docs/SANDBOX-REVIEW.md](SANDBOX-REVIEW.md)).
|
|
302
|
-
|
|
303
|
-
## Reload and status
|
|
304
|
-
|
|
305
|
-
`dev` polls project YAML/JSON/JS and `.env.local` every 500 ms, plus declared
|
|
306
|
-
asset files/directories (including binary assets and explicit build directories).
|
|
307
|
-
Asset polling uses file metadata; production assets stay fixed until restart.
|
|
308
|
-
The general source scan excludes common
|
|
309
|
-
build/dependency directories and hidden files. Includes and source dependencies
|
|
310
|
-
must be normal watched files; changes in symlink targets or `node_modules`
|
|
311
|
-
require restart. A candidate fully validates and initializes its functions
|
|
312
|
-
and snapshots its assets before activation. Invalid candidates leave the old snapshot serving. In-flight
|
|
313
|
-
function calls finish on their original snapshot; new requests use the new one.
|
|
314
|
-
Production `serve` is a fixed snapshot; restart/redeploy for code, secret or
|
|
315
|
-
operator-policy changes. Config/code edits invalidate old binding grants.
|
|
316
|
-
|
|
317
|
-
The health `version` combines route-definition and asset-representation digests,
|
|
318
|
-
not a full artifact digest
|
|
319
|
-
or secret fingerprint. Production release identity should be the Git commit and
|
|
320
|
-
container image digest. See [operations](OPERATIONS.md).
|
|
321
|
-
|
|
322
|
-
See [capabilities and normalized route representation](CAPABILITIES.md) for the target catalog,
|
|
323
|
-
programmatic compatibility analysis and provider verification limits.
|
|
324
|
-
|
|
325
|
-
## Authoring, conversion and verification tools
|
|
326
|
-
|
|
327
|
-
[Interchange](INTERCHANGE.md) imports and exports a strict literal redirect
|
|
328
|
-
subset with source diagnostics and dry-run reports. Provider conversions refuse
|
|
329
|
-
semantic differences by default; explicit acknowledgment retains warnings and
|
|
330
|
-
never reports lossless behavior. [Bulk import](BULK.md) shards CSV/JSON/YAML rows
|
|
331
|
-
into ordinary includes while retaining runtime resource limits. [Recipes](RECIPES.md)
|
|
332
|
-
are local Git-owned examples; they grant no capabilities. [Build-time TypeScript](TYPESCRIPT-AUTHORING.md)
|
|
333
|
-
is separate from runtime execution.
|
|
334
|
-
|
|
335
|
-
The [tooling SDK and optional local MCP](TOOLING.md) inspect and validate without
|
|
336
|
-
executing handlers or reading binding values. MCP defaults to inspection; the
|
|
337
|
-
explicit `--allow-authoring` option enables bounded project writes, separately
|
|
338
|
-
from host-file loading and grants. [Provider conformance](PROVIDER-VERIFICATION.md)
|
|
339
|
-
distinguishes local adapter replay from actual deployment observations; no real
|
|
340
|
-
provider deployment is implied by CI. [Proxy and signal egress](EGRESS.md) requires
|
|
341
|
-
external revision-pinned operator grants and bounded host-owned transport;
|
|
342
|
-
project declarations cannot grant network authority to themselves or guests.
|
|
343
|
-
|
|
344
|
-
## Bounded outbound behavior
|
|
345
|
-
|
|
346
|
-
The proxy handler and webhook signals require external revision-pinned origin
|
|
347
|
-
grants. [Egress](EGRESS.md) specifies request and response semantics, DNS pinning,
|
|
348
|
-
header filtering, size/time/concurrency limits, secret binding, signal guarantees
|
|
349
|
-
and shutdown. Project declarations cannot grant network authority to themselves.
|
|
350
|
-
All non-self-hosted targets refuse these capabilities.
|
|
351
|
-
|
|
352
|
-
## Operator-installed extension handlers
|
|
353
|
-
|
|
354
|
-
The optional `extensions` map declares version-1 extension configuration.
|
|
355
|
-
`extension: name` handlers require exclusive literal `/prefix/*` mounts and
|
|
356
|
-
explicit operator registration pinned to the project revision. Optional
|
|
357
|
-
`policies.extensions` requirements are validated by the named extension and
|
|
358
|
-
authorized before cache access. See [extension contracts](EXTENSIONS.md) for
|
|
359
|
-
configuration, trust boundaries, lifecycle and target restrictions.
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
# Spike: AI-first URLCode framework benchmark
|
|
2
|
-
|
|
3
|
-
Status: proposed research and execution plan. This document adds no benchmark
|
|
4
|
-
implementation or measured results. It preserves the agreed independent-agent
|
|
5
|
-
experiment and improvement loop; executing the phases below is follow-up work.
|
|
6
|
-
|
|
7
|
-
## Objective and core principle
|
|
8
|
-
|
|
9
|
-
Measure whether autonomous agents can build a correct, realistic application
|
|
10
|
-
with URLCode, how much application intent its abstractions express, how easily
|
|
11
|
-
agents discover those abstractions, and how the resulting application performs.
|
|
12
|
-
Report AI effectiveness, framework expressiveness, AI discoverability and runtime
|
|
13
|
-
performance separately. Do not collapse them into a single score or assume that
|
|
14
|
-
URLCode will outperform another framework.
|
|
15
|
-
|
|
16
|
-
The canonical implementation rule for the explicitly guided run is:
|
|
17
|
-
|
|
18
|
-
> Use URLCode's highest-level declarative features whenever possible. Generate custom JavaScript only when the framework cannot express the requirement.
|
|
19
|
-
|
|
20
|
-
Before implementing functionality manually, check for a declarative primitive,
|
|
21
|
-
YAML configuration, built-in capability, extension, reusable template or documented
|
|
22
|
-
pattern. Custom JavaScript is an escape hatch. The experiment must also establish
|
|
23
|
-
whether an unfamiliar agent discovers this approach without explicit coaching.
|
|
24
|
-
|
|
25
|
-
## Phase 0 — Research existing work first
|
|
26
|
-
|
|
27
|
-
Before building the application or a new harness, investigate:
|
|
28
|
-
|
|
29
|
-
- RealWorld / Conduit and its reusable application and acceptance specification.
|
|
30
|
-
- TechEmpower Framework Benchmarks and their runtime methodology.
|
|
31
|
-
- SWE-bench and other coding-agent benchmarks.
|
|
32
|
-
- Agent productivity studies, framework comparison applications and standard
|
|
33
|
-
CRUD/full-stack benchmark applications.
|
|
34
|
-
- URLCode's existing [agent harness](../benchmarks/agent/README.md), authoring
|
|
35
|
-
evals, [next-steps plan](archive/2026-09-19/NEXT-STEPS.md), and runtime benchmarks in
|
|
36
|
-
`benchmarks/routing.ts`, `benchmarks/bulk.ts` and
|
|
37
|
-
`benchmarks/sandbox-vs-trusted.ts`.
|
|
38
|
-
|
|
39
|
-
Write a dated research report with primary-source links, versions/revisions,
|
|
40
|
-
what each candidate measures, what can be reused, what is missing, and the
|
|
41
|
-
reuse/adapt/build decision. Verify current maintenance status during research;
|
|
42
|
-
do not assume this proposal is novel or that an additional suite is necessary.
|
|
43
|
-
|
|
44
|
-
The existing agent harness already records shared acceptance results, generated
|
|
45
|
-
lines, prompts and provider-reported usage. Its README explicitly limits claims:
|
|
46
|
-
its tasks do not test persistence or runtime performance, its URLCode arm receives
|
|
47
|
-
curated guidance, and stub records are pipeline tests rather than model evidence.
|
|
48
|
-
Reuse suitable accounting and acceptance infrastructure after auditing it against
|
|
49
|
-
the current runtime. Do not treat its guided arm as the unprompted baseline or
|
|
50
|
-
silently reinterpret historical measurements under a new counting rule.
|
|
51
|
-
|
|
52
|
-
Exit criterion: record the selected specification and harness approach before
|
|
53
|
-
implementation begins, including the evidence for any departure from existing work.
|
|
54
|
-
|
|
55
|
-
## Phase 1 — Freeze a realistic, framework-neutral specification
|
|
56
|
-
|
|
57
|
-
Prefer RealWorld when practical. Otherwise justify a smaller RealWorld-inspired
|
|
58
|
-
application, such as TaskFlow: users own projects, projects contain tasks, and
|
|
59
|
-
users cannot access another user's private records. A basic Todo application alone
|
|
60
|
-
is insufficient. Freeze observable API behavior and shared acceptance tests before
|
|
61
|
-
agent runs; use exactly the same requirements for URLCode and Fastify.
|
|
62
|
-
|
|
63
|
-
Exercise routing, CRUD, authentication, authorization, persistent relational data,
|
|
64
|
-
relationships, validation, structured errors, filtering, sorting, pagination,
|
|
65
|
-
environment configuration, secrets, middleware, logging and automated tests.
|
|
66
|
-
Include registration/login, current-user lookup, ownership checks, restart
|
|
67
|
-
persistence, invalid inputs and unauthenticated/unauthorized requests in acceptance
|
|
68
|
-
coverage. Define logout semantics if applicable to the selected authentication
|
|
69
|
-
model. Specify a health endpoint and reproducible schema/migrations and seed data.
|
|
70
|
-
|
|
71
|
-
Also define isolated plaintext, JSON serialization, single-record database read
|
|
72
|
-
and database write endpoints, borrowing established runtime benchmark semantics
|
|
73
|
-
where practical. Freeze response bodies, status codes, headers, data size, database
|
|
74
|
-
work and cache behavior; database reads must actually hit the database, and writes
|
|
75
|
-
must persist. Keep these separate from realistic application workloads.
|
|
76
|
-
|
|
77
|
-
Use the same database engine/version and equivalent data in all comparable runs.
|
|
78
|
-
Choose it before implementation, not separately for each framework. Use synthetic
|
|
79
|
-
data and environment-supplied secrets. Keep benchmark applications isolated from
|
|
80
|
-
production runtime source. Record permitted extension packages and versions;
|
|
81
|
-
extension functionality must not be presented as built into core.
|
|
82
|
-
|
|
83
|
-
Correctness is the first gate: report passed/total acceptance cases, incomplete
|
|
84
|
-
requirements and failures. Do not compare an incomplete application's apparent
|
|
85
|
-
code savings or throughput as if it delivered the same functionality.
|
|
86
|
-
|
|
87
|
-
## Phase 2 — Reproducible harness and measurement
|
|
88
|
-
|
|
89
|
-
Capture exact prompts, model identifiers, agent/version, framework and extension
|
|
90
|
-
commits, lockfiles, documentation snapshots, harness version, runtime, OS, hardware,
|
|
91
|
-
database, tools and configuration. Record the initial workspace and available
|
|
92
|
-
instructions/tools. Fix time, turn and token budgets, stopping rules and permitted
|
|
93
|
-
human assistance before running; log interventions and failed or capped runs.
|
|
94
|
-
|
|
95
|
-
| Area | Measurements |
|
|
96
|
-
|---|---|
|
|
97
|
-
| Agent work | Input/output/cached/total tokens, elapsed time, turns, tool calls, shell commands, documentation searches, test/fix cycles, completion rate |
|
|
98
|
-
| Implementation | Total/source/configuration/JS/TS files, application LOC, configuration LOC, test LOC, direct/transitive dependencies, custom handlers and custom JavaScript |
|
|
99
|
-
| URLCode expression | Declarative routes, routes needing custom code, declarative versus imperative LOC, required extensions, JavaScript escape hatches, functionality manually duplicated despite an existing capability |
|
|
100
|
-
| Runtime | Startup time, idle memory, CPU, memory under load, requests/sec, p50/p95/p99 latency, response errors and timeouts |
|
|
101
|
-
|
|
102
|
-
Never estimate unavailable measurements: mark them unavailable and explain why.
|
|
103
|
-
Preserve provider usage fields and document whether cached tokens are included in
|
|
104
|
-
input totals so totals do not double-count them. Separate measured values from
|
|
105
|
-
derived calculations. Define LOC counting and exclusions in advance; separately
|
|
106
|
-
report configuration, tests, generated output, dependencies and copied templates.
|
|
107
|
-
Existing code-ratio metrics are not automatically declarative-coverage metrics.
|
|
108
|
-
|
|
109
|
-
For runtime comparisons hold hardware/resource limits, runtime, database, data,
|
|
110
|
-
concurrency, warm-up, duration and load generator constant. Specify startup start/
|
|
111
|
-
ready events and memory/CPU sampling. Record trust/sandbox mode, worker counts,
|
|
112
|
-
policies and extension overhead; compare equivalent behavior and disclose any
|
|
113
|
-
unavoidable differences. Do not disable correctness or security requirements to
|
|
114
|
-
improve scores. Reset data between trials and verify benchmark response semantics.
|
|
115
|
-
|
|
116
|
-
Predeclare repeated fresh-agent runs and repeated runtime trials, retain every
|
|
117
|
-
trial and report variability, sample counts and failures rather than selecting
|
|
118
|
-
best runs. Keep the load generator from becoming the bottleneck. Version changed
|
|
119
|
-
prompts, fixtures and counting rules so incompatible results are not pooled.
|
|
120
|
-
|
|
121
|
-
## Phase 3 — Independent URLCode agents
|
|
122
|
-
|
|
123
|
-
Each run starts with a fresh context and isolated worktree/environment. Agents
|
|
124
|
-
must not see another agent's implementation, logs or findings. The coordinator
|
|
125
|
-
collects evidence after each run; shared prompts contain the neutral specification
|
|
126
|
-
and operational rules, not the hypothesis or a desired token/LOC outcome.
|
|
127
|
-
|
|
128
|
-
### Protect the discovery baseline
|
|
129
|
-
|
|
130
|
-
This spike itself contains the instruction being tested. Do not expose it, its
|
|
131
|
-
index entry, benchmark prompts, prepared answers or prior findings to Agent A.
|
|
132
|
-
Use a pinned source/documentation snapshot preceding this spike, or a documented
|
|
133
|
-
filtered workspace with no access to excluded artifacts or repository history.
|
|
134
|
-
Apply the same underlying snapshot and access controls to the comparison runs,
|
|
135
|
-
with only the intended prompt treatment different. Record the exact manifest and
|
|
136
|
-
restrictions; if an agent reads excluded material, mark the run contaminated and
|
|
137
|
-
repeat it with a fresh agent rather than counting it as unprompted evidence.
|
|
138
|
-
|
|
139
|
-
Existing product documentation, skills and ordinary repository instructions are
|
|
140
|
-
part of what Agent A may discover; do not remove existing declarative guidance to
|
|
141
|
-
manufacture a worse baseline. Preserve the baseline before changing those sources.
|
|
142
|
-
|
|
143
|
-
### Agent A — Unprompted discovery
|
|
144
|
-
|
|
145
|
-
Supply the application specification, URLCode source and existing documentation.
|
|
146
|
-
The framework-specific instruction is only:
|
|
147
|
-
|
|
148
|
-
> Build this application using URLCode following the framework's documented conventions and recommended practices.
|
|
149
|
-
|
|
150
|
-
Do not supply the declarative-first rule or curated hints about where to find it.
|
|
151
|
-
Record whether the agent independently finds and uses it, including evidence of
|
|
152
|
-
unnecessary JavaScript, duplicated capabilities, missed primitives, misunderstood
|
|
153
|
-
abstractions, repeated searches, incorrect assumptions, unclear errors and stalls.
|
|
154
|
-
Treat these as potential framework/documentation problems, not automatically as
|
|
155
|
-
agent failures.
|
|
156
|
-
|
|
157
|
-
### Agent B — Explicitly URLCode-native
|
|
158
|
-
|
|
159
|
-
Run the identical application from scratch with a fresh independent agent. Add:
|
|
160
|
-
|
|
161
|
-
> Use URLCode's highest-level declarative features whenever possible. Generate custom JavaScript only when the framework cannot express the requirement.
|
|
162
|
-
|
|
163
|
-
> Before implementing functionality manually, determine whether URLCode already provides a declarative primitive, YAML configuration, built-in capability, extension, reusable template, or documented pattern.
|
|
164
|
-
|
|
165
|
-
Compare A and B on correctness, tokens, custom JavaScript, YAML, files, LOC,
|
|
166
|
-
implementation time, debugging cycles and documentation searches. A repeatable
|
|
167
|
-
advantage for B is evidence to investigate discoverability, not proof that every
|
|
168
|
-
individual mistake is a documentation defect.
|
|
169
|
-
|
|
170
|
-
### Agent C — Gap finder
|
|
171
|
-
|
|
172
|
-
Use another fresh agent, independent of A/B implementations and findings during
|
|
173
|
-
its attempt. Give it the same requirements and this instruction:
|
|
174
|
-
|
|
175
|
-
> Attempt to implement every requirement using URLCode's intended abstractions. Whenever URLCode cannot express something cleanly, document the limitation rather than hiding it behind substantial custom code.
|
|
176
|
-
|
|
177
|
-
Classify findings as missing capability, documentation gap, AI discoverability
|
|
178
|
-
problem, confusing API/schema, poor error message, unnecessary boilerplate,
|
|
179
|
-
extension-system limitation, performance problem, possible framework bug or agent
|
|
180
|
-
misunderstanding. Record the attempted declaration, missing requirement, relevant
|
|
181
|
-
documentation and any necessary workaround. A requirement that cannot be expressed
|
|
182
|
-
stays visibly incomplete; substantial custom code must not hide the gap.
|
|
183
|
-
|
|
184
|
-
## Phase 4 — Verify findings and prepare/file GitHub issues
|
|
185
|
-
|
|
186
|
-
After independent attempts are preserved, reproduce each candidate problem against
|
|
187
|
-
the pinned revision, inspect the supported contract and search existing issues and
|
|
188
|
-
PRs. Distinguish missing functionality from functionality the agent failed to find.
|
|
189
|
-
Do not file an issue merely because one agent made a mistake. Note corroborating
|
|
190
|
-
encounters by multiple fresh agents, while avoiding unsupported causal claims.
|
|
191
|
-
|
|
192
|
-
For each verified, actionable issue include:
|
|
193
|
-
|
|
194
|
-
- Problem and benchmark scenario, affected repository/revision and environment.
|
|
195
|
-
- Expected versus actual behavior and minimal synthetic reproduction.
|
|
196
|
-
- Relevant YAML/code, commands, errors and links to run evidence.
|
|
197
|
-
- Classification, proposed improvement and impact on human developers and agents.
|
|
198
|
-
- Acceptance criteria and related/duplicate issue links.
|
|
199
|
-
|
|
200
|
-
Use the owning repository's issue template and the ownership map in
|
|
201
|
-
[AGENTS.md](../AGENTS.md): core/runtime issues belong here, documentation
|
|
202
|
-
included -- `urlcode-docs` is deleted and cannot accept issues -- and extension
|
|
203
|
-
defects in the corresponding extension repository.
|
|
204
|
-
Update existing issues with new evidence rather than duplicating them. Track
|
|
205
|
-
prepared, filed, duplicate and unverified dispositions in the findings report;
|
|
206
|
-
file verified issues and retain unresolved hypotheses as explicitly unverified
|
|
207
|
-
observations. Follow [SECURITY.md](../SECURITY.md) for private vulnerability reports.
|
|
208
|
-
|
|
209
|
-
## Phase 5 — Audit AI discoverability
|
|
210
|
-
|
|
211
|
-
Audit README, documentation, examples, schemas, CLI help, package metadata,
|
|
212
|
-
`llms.txt`, agent instructions/skills, scaffolding and errors. Determine whether an
|
|
213
|
-
unfamiliar agent can find the framework's purpose, declarative-first philosophy,
|
|
214
|
-
YAML capabilities, built-in primitives, extensions, authentication, database access,
|
|
215
|
-
validation, errors, custom functionality, testing and debugging guidance.
|
|
216
|
-
|
|
217
|
-
Specifically search for guidance equivalent to the canonical rule above; record
|
|
218
|
-
exact locations, prominence and the navigation/search path used to discover it.
|
|
219
|
-
Do not assume it is absent just because the exact sentence is missing. Check the
|
|
220
|
-
current contract when documents and historical benchmark assumptions differ.
|
|
221
|
-
|
|
222
|
-
Preserve Agent A's baseline before editing guidance. Then propose the smallest
|
|
223
|
-
authoritative set of changes that makes the principle clear to people and agents,
|
|
224
|
-
including when custom JavaScript is appropriate. Public authoring guidance and
|
|
225
|
-
contributor records both belong here, now that `urlcode-docs` is deleted. Do not copy the rule
|
|
226
|
-
everywhere or expose the experimental prompt as product guidance by accident.
|
|
227
|
-
|
|
228
|
-
## Phase 6 — Fastify comparison
|
|
229
|
-
|
|
230
|
-
Once the URLCode methodology works, give a fresh independent agent the same frozen
|
|
231
|
-
specification, budgets, tool access and acceptance criteria, using:
|
|
232
|
-
|
|
233
|
-
> Build this application using Fastify following the framework's documented conventions and recommended practices.
|
|
234
|
-
|
|
235
|
-
Do not mention URLCode or expose its implementations/findings. Use Fastify
|
|
236
|
-
idiomatically; do not force it to imitate URLCode's architecture. Compare correctness,
|
|
237
|
-
agent work, files/LOC/dependencies, configuration, debugging/searches and runtime
|
|
238
|
-
measurements separately. Document framework-specific dependencies and setup work.
|
|
239
|
-
Later candidates include Hono, Express, NestJS and Elysia; they are not prerequisites
|
|
240
|
-
for the first comparison.
|
|
241
|
-
|
|
242
|
-
## Phase 7 — Findings and deliverables
|
|
243
|
-
|
|
244
|
-
Publish the contributor findings in `docs/benchmarks/AI_FRAMEWORK_BENCHMARK.md` when
|
|
245
|
-
runs exist. Keep implementation and raw evidence paths versioned and linked from
|
|
246
|
-
that report; do not create a results document implying measurements already exist.
|
|
247
|
-
Deliver:
|
|
248
|
-
|
|
249
|
-
1. Dated benchmark research and reuse decision.
|
|
250
|
-
2. Frozen application specification and shared acceptance suite.
|
|
251
|
-
3. Reproducible harness, commands and independent agent prompts.
|
|
252
|
-
4. URLCode A/B/C and Fastify implementations or explicit incomplete outcomes.
|
|
253
|
-
5. Raw agent logs/usage, implementation counts and runtime trial data.
|
|
254
|
-
6. Methodology, provenance, comparison tables, uncertainty and evidence limitations.
|
|
255
|
-
7. Agent behavior/search/failure analysis and classified framework/discovery gaps.
|
|
256
|
-
8. Verified issue ledger, proposed/filed issue links and prioritized improvements.
|
|
257
|
-
9. Before/after findings following the fresh-agent regression phase.
|
|
258
|
-
|
|
259
|
-
Remove secrets from published logs while retaining measurement provenance. Keep
|
|
260
|
-
stub/harness validation records distinct from real-agent evidence. Report every
|
|
261
|
-
failed attempt, not just successful applications, and avoid subjective scores or
|
|
262
|
-
claims beyond the measured cases.
|
|
263
|
-
|
|
264
|
-
## Phases 8–9 — Improve and rerun with fresh agents
|
|
265
|
-
|
|
266
|
-
Prioritize demonstrated friction: missing declarative primitives, defaults, YAML,
|
|
267
|
-
schemas, errors, examples, extension discovery, README/AI documentation, CLI and
|
|
268
|
-
scaffolding. Make legitimate application-development improvements, not special
|
|
269
|
-
cases that game the benchmark. Track each change to its verified issue/evidence.
|
|
270
|
-
|
|
271
|
-
After improvements, rerun with entirely fresh agents and isolated environments.
|
|
272
|
-
The new discovery agent must again receive no explicit declarative-first rule or
|
|
273
|
-
prior findings; it may discover the improved ordinary documentation naturally.
|
|
274
|
-
Keep this spike and benchmark answers excluded. Repeat B, C and the comparison
|
|
275
|
-
where needed to distinguish framework changes from model/harness drift. Hold model,
|
|
276
|
-
budgets, requirements and runtime conditions fixed where possible; disclose changes
|
|
277
|
-
and do not attribute their effects solely to URLCode.
|
|
278
|
-
|
|
279
|
-
Compare before/after correctness, tokens, elapsed time, generated JavaScript, YAML,
|
|
280
|
-
LOC, files, dependencies, tool calls, searches, failed attempts, test/fix cycles and
|
|
281
|
-
runtime performance. Keep dimensions separate and preserve the original baseline.
|
|
282
|
-
|
|
283
|
-
The repeatable loop is: independent agent encounters friction → evidence captures
|
|
284
|
-
it → verified issue → URLCode improvement → fresh-agent rerun → measured outcome.
|
|
285
|
-
Use it for significant releases to detect regressions in AI usability, declarative
|
|
286
|
-
coverage, documentation, capability and runtime performance. Completion means
|
|
287
|
-
reproducible evidence and an actionable issue/improvement trail, not a claim that
|
|
288
|
-
URLCode won the comparison.
|