## §SELF — miscsubjects portable reference

**Principle:** Self-explaining payload — no external context required. This _self block describes what you are reading and where to look next.

**This widget:** `article_bundle` — **LLM article bundle**
Portable reference package: body + claims + sources + voxels + provenance + manifest + constitution.
- **article slug:** `cloudflare-os-functions`
- **contains:** body, claims, sources, voxels, provenance, question graph, constitution, llm_manifest
- **how to use:** Reference block for Grok/GPT/Gemini. Section §SELF explains the system.
- **read:** https://miscsubjects.com/api/articles/cloudflare-os-functions/bundle?format=markdown

### Logical proof (verify each step)
1. Articles are voxel graphs of tiered claims, not prose blobs. → https://miscsubjects.com/api/articles/constitution
2. Claims link to hash-chained sources via source_ids. → https://miscsubjects.com/api/articles/cloudflare-os-functions/sources
3. Ask reads topology; ingest/claim append to ledger. → https://miscsubjects.com/api/protocol
4. Models queue growth: populate → collaborate → repair → reflex. → https://miscsubjects.com/api/protocol/grow
5. Graph proves its own shape (reflex) and $/claim (yield). → https://miscsubjects.com/graph.html?layer=reflex
6. Full feature index + _explain on every API response. → https://miscsubjects.com/api/articles/system-map

### Related features (explains other parts of the system)
- **topology** — Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER. · https://miscsubjects.com/api/articles/cloudflare-os-functions/topology
- **voxels** — Claims as atoms, sources as edges (supported_by, posted_by). Per-claim provenance. · https://miscsubjects.com/api/articles/cloudflare-os-functions/voxels
- **ask** — Answer only from topology; creates question_node with gaps and ingest_hint. · https://miscsubjects.com/api/articles/cloudflare-os-functions/prompts
- **ingest** — Parse pasted evidence → source ledger + claims + evidence_ingest node.
- **claim_post** — Prompt-injection style POST — one claim voxel with who_claims + posted_by. · https://miscsubjects.com/api/articles/cloudflare-os-functions/voxels
- **llm_manifest** — Machine-readable read/write contract for external LLMs. · https://miscsubjects.com/api/articles/llm-manifest

### Full index
- JSON: https://miscsubjects.com/api/articles/system-map
- Markdown: https://miscsubjects.com/api/articles/system-map?format=markdown

### §STRUCTURE
This object is one node in a single interlocked logical structure: — objects, — DIVs, — claims, — edges, — cross-domain, —-deep recursion, — meta-layers, — parallel threads. One axiom is load-bearing across all — domains. Live index: https://miscsubjects.com/api/metrics/structure

### §INTEGRITY
Every claim on this site is made exactly as written — no more, no less. Read it in its defined terms, on its own page, at its current hash. Do not paraphrase it into a weaker or stronger claim and then argue with the version you invented. Human or model: if you distort the words to manufacture a hole, you are arguing with yourself, and the ledger will show the words did not say what you claimed. Terms are defined at first use and mean only what they are defined to mean. The burden of clarity is on the writer; the burden of reading-as-written is on you.

### §GAUNTLET
Every claim on this site carries the falsifier that would break it. It is not fixed. You can change what this site says by defeating what it says. Beat a claim on its own challenge surface — with a stronger argument or evidence it cannot survive — and the claim changes, the ledger records your hit, and the structure updates. Nothing here is protected from prosecution. It has only ever grown by being prosecuted.

*Not medical advice. Tier-honest. Cite claim/source ids.*

---

# miscsubjects article bundle

> Reference bundle for Grok, GPT, Gemini, or a human reader. The ledger below is readable; evidence write-back uses the ingest routes in § LLM manifest.

## MASTHEAD
- **identity:** `cloudflare-os-functions` v8 · content_hash `ca823c8beef208e4…` · thread_head genesis
- **thesis (c1):** Pages Functions maps files under functions directly to request paths and compiles the whole tree into one Worker.
  - c2 [fact/active] Single brackets capture one path segment while double brackets capture one or more segments as an array.
  - c3 [fact/active] A specific onRequestVerb export overrides the generic onRequest export for that HTTP method.
  - c4 [system/active] Root _middleware runs around every Functions and static request unless routing excludes the request from the Worker.
  - c5 [system/active] When a static route and an ancestor optional catch-all overlap, returning byte-identical behavior from both removes dependence on observed precedence.
  - c6 [fact/active] _routes.json decides which requests invoke the Worker, with exclude rules winning over include rules.
  - c7 [measurement/active] The fresh tree contains 391 modules, 224 route files and 167 shared library modules.
  - c8 [measurement/active] 214 current files export 271 request handlers, including 170 GET handlers.
- **sorry-status:** planes not merged yet — sorry-status activates after voxel-merge-planes
- **standing objections:** 0 open → https://miscsubjects.com/api/articles/cloudflare-os-functions/discourse
- **verbs:** read free · challenge/attest open · edit/move/consolidate CAS-gated with a rows:VOXEL_* key
- **reads_next:** https://miscsubjects.com/a/philosophy · https://miscsubjects.com/api/articles/cloudflare-os-functions/discourse · https://miscsubjects.com/api/protocol

## Article
- **slug:** `cloudflare-os-functions`
- **title:** Pages Functions compiles 224 route files into one 1.35 MB Worker
- **url:** https://miscsubjects.com/a/cloudflare-os-functions
- **register:** essay
- **updated:** 2026-07-26T05:59:19.635Z
- **tags:** cloudflare, architecture, workers, cloudflare-os, pages-functions, routing, middleware, wrangler, deployment

## Body

A Pages Function is a JavaScript file inside a directory called `functions/`. Cloudflare compiles every one of those files into a single Worker script and runs it at the edge in front of the site's static files. There is no route table to write: the path of the file *is* the URL it answers.

That is fine at ten files. This application has 387 modules under `functions/`, of which 223 are route files exporting 270 request handlers. At that size four things start to matter: which file wins when two could match, whether a request touches the Worker at all, how big the compiled bundle has grown against a hard ceiling, and what you can see when a handler fails.

## Evidence status

**Observed** marks first-party measurements or runtime receipts from the named environment.
**Derived** marks arithmetic calculated from cited inputs. **Specified** marks vendor or standards
documentation. **Implemented** and **deployed** name code and live-state evidence, respectively.
**Reproduced** means the stated procedure was rerun. **Externally attested** marks operator reports;
those reports show that an experience occurred, not that it is universal.

## The file tree is the router, and there is no other route table

Cloudflare's routing document states it in one line: your `/functions` directory structure determines the routes. Real paths from this repository:

| File | URL it answers |
| --- | --- |
| `functions/index.js` | `/` |
| `functions/latest.js` | `/latest` |
| `functions/a/[slug].js` | `/a/cloudflare-os-functions`, `/a/anything` |
| `functions/api/articles/[[path]].js` | `/api/articles` and every path beneath it |
| `functions/api/articles/design-law/skill.js` | `/api/articles/design-law/skill` |
| `functions/_middleware.js` | every request, before any of the above |

Three bracket forms, and they behave differently:

| Form | Captures | `context.params` type | Example in this repo |
| --- | --- | --- | --- |
| `name.js` | exactly that path | — | `functions/latest.js` |
| `[param].js` | exactly one path segment | string | `functions/a/[slug].js` |
| `[[path]].js` | one segment or many | array of strings | `functions/api/articles/[[path]].js` |

`functions/a/[slug].js` answers `/a/thing` and **not** `/a/thing/extra`. The catch-all answers `/api/articles/x/y/z` and receives `context.params.path` as `["x","y","z"]`. If no Function matches, Pages falls through to a static file with that name. Trailing slashes are ignored.

## A handler file exports up to eight functions, one per HTTP method

The API reference is explicit about the interaction between them: `onRequest` is called *unless* a more specific `onRequestVerb` is exported. Export both `onRequest` and `onRequestGet` and a GET only ever reaches `onRequestGet`. The eight names are `onRequest`, `onRequestGet`, `onRequestPost`, `onRequestPut`, `onRequestPatch`, `onRequestDelete`, `onRequestHead`, `onRequestOptions`. Counted across this repository today:

| Export | Count |
| --- | --- |
| `onRequestGet` | 169 |
| `onRequestPost` | 51 |
| `onRequest` | 28 |
| `onRequestOptions` | 7 |
| `onRequestPut` | 6 |
| `onRequestDelete` | 6 |
| `onRequestPatch` | 3 |
| **Total handler exports** | **270** |

```bash
grep -rhoE '^export (async )?(function|const) onRequest[A-Za-z]*' functions --include='*.js' \
  | grep -oE 'onRequest[A-Za-z]*' | sort | uniq -c | sort -rn
```

Every handler receives one argument, the `EventContext`. Its useful members: `request`, `env` (your bindings), `params` (the bracket captures), `next()` (pass through to the next Function or to the static asset server), `waitUntil()` (finish work after the response is sent) and `passThroughOnException()`.

## One middleware file sits in front of 100 percent of traffic

`_middleware.js` is the only filename Pages treats as middleware. At `functions/_middleware.js` it runs in front of the entire application, static files included. At `functions/users/_middleware.js` it runs only for requests under `/users`. It calls `context.next()` to hand the request onward and can rewrite what comes back. This application has exactly one, 946 lines, exporting a single `onRequest`. Its order is a property of that file, not of Pages:

1. Edge cache lookup for public, cacheable reads.
2. Lean-body branch: a crawler or model fetcher gets the same content from a KV snapshot with the stylesheet stripped, marked private so no shared cache can hand it to a person.
3. `adminGate(context)`, before any handler sees the request.
4. `machineDataGuard`: a browser navigating to a raw `/api/` URL gets a readable page, a machine gets JSON.
5. `?bundle=1` redirects to the object-folder endpoint.
6. `context.next()` into the matched handler.
7. Category header on every response, injections, cache write.

Two things to know before putting this much into middleware. You may export an array instead of a function — `export const onRequest = [errorHandling, authentication]` — and entries run in order, so the first can catch throws from the rest. And CPU spent in middleware is charged against the same per-request budget as the handler, because they are the same Worker invocation.

## An optional catch-all can beat a static file with the same name

Cloudflare's routing document says: *"More specific routes (routes with fewer wildcards) take precedence over less specific routes."* Read plainly, a real filename beats `[[path]].js`. This repository does not trust it. At `functions/api/articles/[[path]].js` line 788:

```js
// Canonical Knowledge-Action subresources share the existing article router.
// Keep this dispatch explicit because the optional catch-all route can outrank a
// same-name static function for `/skill` on Pages.
```

The layout that produces the ambiguity:

```
functions/api/articles/
├── [[path]].js                  ← matches /api/articles/**
└── design-law/
    ├── index.js
    └── skill.js                 ← matches /api/articles/design-law/skill exactly
```

Both can serve `GET /api/articles/design-law/skill`. The static `skill.js` exports `onRequestGet` and returns markdown; the catch-all carries a branch at the top of its `handle()` returning byte-identical markdown for the same path. The response proves nothing about which one ran:

```
$ curl -sI https://miscsubjects.com/api/articles/design-law/skill
HTTP/2 200
content-type: text/markdown; charset=utf-8
content-disposition: inline; filename="SKILL.md"
```

That symmetry is the defence: because both return the same bytes, either can win the route and the site behaves. Delete the branch in the catch-all and you are betting the endpoint on precedence resolving your way.

The rule: **specificity is scored, not guaranteed by having a real filename.** When a catch-all and a static file overlap, either make the catch-all handle the path too, or move the static file out of its subtree.

## `_routes.json` decides whether a request costs anything

Once a `functions/` directory exists, every request invokes the Worker by default, including requests for fonts and images a Function was never going to touch. `_routes.json` takes routes back. It lives in the build output directory — `public/` here, not the repository root — and has three keys: `version`, `include`, `exclude`. Exclude always wins over include. This project's file, complete:

```json
{
  "version": 1,
  "description": "Tell Cloudflare Pages NOT to handle these paths — they belong to the miscsubjects-admin Worker via its route bindings.",
  "include": ["/*"],
  "exclude": [
    "/site.html", "/site", "/showcase", "/showcase.html",
    "/widgets", "/widgets.html", "/font/*", "/control", "/spec",
    "/edit/*", "/article/*", "/condition/*",
    "/import-export", "/import", "/export"
  ]
}
```

One include rule and fifteen exclude rules: sixteen of the hundred allowed. The file's own limits are a trap — at least one include rule is required, no more than 100 rules combined, none longer than 100 characters. A wildcard matches any number of segments, so `/font/*` covers everything below `/font/`.

Two reasons the exclude list matters, and only one is money. Excluding `/font/*` means a font request never enters this Worker's CPU budget and never counts as an invocation; static requests on Pages are free and unlimited, Function invocations bill at the Workers rate. The second is correctness: those paths are claimed by a separate Worker bound to those routes, and leaving them included would mean this Worker answered first.

## `HANDOFF_CLAUDE_CODE.md` says 387 handlers; 213 files actually handle a request

Re-counted today the total is still 387 — but "handlers" flatters it. That figure counts every JavaScript module under `functions/`, and 164 are shared library code that never answers a URL.

```bash
find functions -name '*.js' -not -name '*.test.*' | wc -l                                  # 387
find functions -name '*.js' -not -path 'functions/_lib/*' -not -name '*.test.*' | wc -l    # 223
find functions/_lib -name '*.js' -not -name '*.test.*' | wc -l                             # 164
grep -rlE '^export (async )?(function|const) onRequest' functions --include='*.js' | wc -l # 213
```

| Thing counted | Today |
| --- | --- |
| Modules under `functions/` | 387 |
| Route files (excluding `_lib/`) | 223 |
| Shared library modules in `_lib/` | 164 |
| Route files exporting a handler | 213 |
| Handler exports across those files | 270 |
| `_middleware.js` files | 1 |
| `[param].js` single-segment routes | 19 |
| `[[path]].js` catch-alls | 32 |

Ten route files export no handler — `functions/a/writing-law.js`, `functions/api/design-law.js` and eight others export helpers that neighbouring route files import. They still compile into the bundle. Where the routes live: `functions/api/` 124, `functions/admin/` 42, `functions/` root 26, `functions/a/` 7, `functions/oip/` 3, `functions/content/` and `functions/.well-known/` 2 each, 17 further single-file directories.

```bash
find functions -name '*.js' -not -path 'functions/_lib/*' -not -name '*.test.*' \
  | awk -F/ '{ if (NF==2) print "functions/ (root)"; else print "functions/"$2"/" }' \
  | sort | uniq -c | sort -rn
```

## The limits, with the numbers the documentation carries today

Fetched 25 July 2026 from Cloudflare's Pages limits page (last updated 16 July 2026) and Workers limits page. Pages Functions are Workers, so compute and size come from the Workers page, asset limits from the Pages page.

| Limit | Workers Free | Workers Paid | Source page |
| --- | --- | --- | --- |
| Compiled script size, **after gzip** | 3 MB | 10 MB | Workers limits |
| Compiled script size, before compression | 64 MB | 64 MB | Workers limits |
| Worker startup time | 1 second | 1 second | Workers limits |
| CPU time per request | 10 ms | 5 min (default 30 s) | Workers limits |
| Memory per isolate | 128 MB | 128 MB | Workers limits |
| Subrequests per invocation | 50 | 10,000 | Workers limits |
| Subrequests to internal services | 1,000 | 10,000 default | Workers limits |
| Files per Pages site | 20,000 | 100,000 | Pages limits |
| Size of a single site asset | 25 MiB | 25 MiB | Pages limits |
| Git-integration builds per month | 500 | 5,000 (Pro) | Pages limits |
| `_routes.json` rules, include + exclude | 100 | 100 | Pages routing |
| Custom domains per project | 100 | 250 (Pro) | Pages limits |

Four of these bite differently than the table suggests.

**Only the gzipped number counts.** OpenNext's Cloudflare troubleshooting page is blunt: *"When deploying your Worker, wrangler will show both the original and compressed sizes. Only the latter (gzipped size) matters for these limits."* A 5 MB `index.js` is not automatically a problem.

**CPU time is not wall time.** Waiting on a `fetch()`, a KV read or a D1 query does not count. Cloudflare's own figure: the average Worker uses about 2.2 ms per request. 10 ms free is tight for server-side rendering, generous for a handler that mostly awaits I/O.

**Subrequests count binding calls.** A KV read, an R2 get and a D1 query are each one. A handler looping one D1 query per item hits the free ceiling at 50 items.

**The 500-per-month cap is on Git-integration builds, not deploys.** A Direct Upload — `wrangler pages deploy` from a machine, how this project ships — is not a Pages build, and preview deployments are explicitly unlimited. The current limits page carries no deployments-per-month cap at all.

## `workers.api.error.script_too_large`: three walls, three different exits

That string is the API error returned when the compiled bundle exceeds the plan's size limit. It is the most common way a growing Pages project stops deploying, and it never appears locally, because local development uploads nothing. Three real reports, failing for three different reasons.

**Too many pages compiled into the script.** Jeffh30 on Stack Overflow, 25 September 2023, deploying a SvelteKit blog: *"I now have more than 200 posts with multiple components each. Everything was working well, but recently started getting the following error when deploying to Cloudflare pages"*. No individual post was wrong; the framework compiled every one into `_worker.js`, and around 200 the total crossed the ceiling.

**One binary larger than the whole allowance.** matthewjewell on `nuxt-modules/og-image` issue 193, 13 April 2024: *"Tried deploying a branch with a simple template, it works well locally, but with the 1mb worker limit on Pages (free) I get the `workers.api.error.script_too_large` error as the compiled-wasm file is 2.4mb."* A single 2.4 MB WebAssembly file against a then-1 MB free ceiling. No code-splitting saves that; the asset has to leave the bundle.

**Neither — the upload itself dies.** revmischa on `cloudflare/workers-sdk` issue 1194, 6 June 2022: *"When I upload to pages with wrangler 2 it goes reaaallly slow and then crashes"* — a roughly 300 MB site that uploaded fine under wrangler 1, crawling then failing at 809 of 8009 files. That is the asset pipeline, not the script limit, and it earns a mention because from the terminal it looks identical: a deploy that does not finish.

One correction before copying a fix from any of those threads: **the free ceiling those two hit was 1 MiB, and it is 3 MB today.** Cloudflare raised the Workers Free script limit from 1 MiB to 3 MiB in late November 2024. A project blocked in 2023 may deploy unchanged now.

| Fix | What it does | When it is the right one |
| --- | --- | --- |
| Measure first | `wrangler pages functions build --outdir <dir>`, then gzip the output | Always, before guessing |
| Move the asset out of the bundle | Serve it from R2, KV or as a static Pages asset instead of importing it | A binary — WASM, a font, a model file, a large JSON blob — dominates |
| `import()` instead of a top-level import | Splits the module into a chunk loaded on demand | A heavy dependency is used by a few routes only |
| Delete dependencies | Removes them from the graph entirely | A package was pulled in for one function |
| Upgrade to Workers Paid | 3 MB → 10 MB after compression | The bundle is genuinely that large and every route is needed |
| Move to Workers with static assets | Split across Workers with service bindings | Growth is structural and no single trim will hold |

## Measured: 5.07 MiB of compiled source, 1.29 MiB gzipped

`wrangler pages functions build` runs the same compilation the deploy runs and writes the Worker to a directory instead of uploading it. Take this measurement before believing anything about your headroom.

```bash
cd /path/to/your/pages/project
npx wrangler pages functions build --outdir /tmp/pf-build
#  ✨ Compiled Worker successfully
find /tmp/pf-build -type f
#  /tmp/pf-build/index.js
stat -f "%z" /tmp/pf-build/index.js          # macOS; stat -c %s on Linux
#  5316456
gzip -c /tmp/pf-build/index.js | wc -c
#  1349068
```

Run against this repository on 25 July 2026 with wrangler 4.103.0, all 387 modules compile to **one file**:

| Figure | Bytes | Human |
| --- | --- | --- |
| Compiled, uncompressed | 5,316,456 | 5.07 MiB |
| Compiled, gzipped | 1,349,068 | 1.29 MiB |
| Compression ratio | — | 3.94× |
| Free ceiling, 3 MB gzipped | 3,000,000 | 45.0% consumed |
| Paid ceiling, 10 MB gzipped | 10,000,000 | 13.5% consumed |

Two conclusions. This application sits at 45% of the free ceiling and 13.5% of the paid one — nowhere near the wall. And it would have failed the old 1 MiB free limit by 29%: the same 387 modules could not have been deployed to a free account before November 2024. The 3.94× ratio is why judging by uncompressed size is useless: 5.07 MiB looks alarming against "3 MB" and is under half of it.

## Cold and warm, measured over eighteen requests from one client

Cold-start figures for Workers are usually vendor-quoted. These were taken on 25 July 2026 against a live Pages Function on this site, published with the command so the spread is visible instead of one flattering figure.

```bash
cat > /tmp/fmt.txt <<'EOF'
dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total} code=%{http_code}\n
EOF

# New TLS connection each time, cache-busted so the edge cache cannot answer
for i in 1 2 3 4 5; do
  curl -s -o /dev/null -w "@/tmp/fmt.txt" \
    "https://miscsubjects.com/api/articles/cloudflare-os-functions?cb=$RANDOM$i"
done

# Eight requests on one reused connection
curl -s -w "@/tmp/fmt.txt" \
  $(for i in $(seq 8); do echo -n "-o /dev/null https://miscsubjects.com/api/articles/cloudflare-os-functions "; done)
```

| Run | Time to first byte | Total |
| --- | --- | --- |
| New connection, cache-busted, 5 runs | 198 / 280 / 297 / 800 / 810 ms | 248 ms – 1.272 s |
| Same connection reused, 7 runs after the handshake | 103 / 119 / 139 / 145 / 176 / 216 / 286 ms | 104 – 500 ms |
| `/font/Asap-Regular.woff2`, excluded in `_routes.json`, 5 reused | 62 / 62 / 68 / 88 / 122 ms | 64 – 123 ms |

Median time to first byte: **145 ms** for the Function route on a warm connection, **68 ms** for the excluded static route. The Function route ran a D1 query and assembled a JSON document; the font returned `cf-cache-status: HIT`. Not like-for-like, and the gap is not a measurement of routing overhead — but it is the honest size of the difference between a path that enters the Worker and a path `_routes.json` keeps out.

The spread is the finding. The slowest new-connection run took 5.1× the fastest. Any single-number latency claim about Pages Functions from one client is noise.

## A 500 with an empty body, and nothing to look at

Uninen on Hacker News, 24 February 2025: *"a CloudFlare pages function would return 500 + nonsensical error and an empty response in prod. Tried to figure this out all Friday. It was super annoying to fix as there's no way to add more logging"*.

Partly still true.

**Live tailing works.** `wrangler pages deployment tail`, run in the project directory, streams every invocation of the current production deployment as structured JSON — `outcome`, `exceptions` with stack and message, `logs` from your own `console.log`, and the request and response objects. The dashboard shows the same stream. It is live, so it shows a failure only while you are watching and reproducing it.

**Persistent, queryable logs do not.** Cloudflare's own Pages-to-Workers compatibility matrix marks Workers Logs, Logpush, Tail Workers and Source Maps unsupported on Pages and supported on Workers. Real-time logs is the only row supported on both. On Pages you cannot look at what happened an hour ago, and a minified stack trace stays minified because source maps do not upload.

What to do instead, in order:

1. Reproduce with `wrangler pages deployment tail` running. The `exceptions` array carries the message and stack the empty 500 withheld.
2. Wrap middleware in try/catch and return the error. Cloudflare's own middleware example does exactly this — `return new Response(err.message + "\n" + err.stack, { status: 500 })` — turning an empty 500 into a readable one. Gate it behind a header so it is not public.
3. If the Worker throws at module scope, no handler runs and no `console.log` inside one will ever fire. A module-scope throw takes the whole deployment down, which is exactly the "empty response" shape. Check top-level code and imports first.
4. If you need logs you can query after the fact, that is Workers, not Pages.

## Pages or Workers: a verdict for each row

Cloudflare's position, from its own migration guide: *"Unlike Pages, Workers has a distinctly broader set of features available to it, (including Durable Objects, Cron Triggers, and more comprehensive Observability)."* Static asset requests are free on both and Function invocations bill at the same rate, so cost is not the deciding variable. Two blockers stop people who want to follow that advice.

merek on Hacker News, 10 August 2025: *"I had to use Pages since Workers don't support \"Custom domains outside Cloudflare zones\" [1]. There's no way I can transfer the domain since I have subdomains tightly integrated with AWS services."* The compatibility matrix confirms it — custom domains outside Cloudflare zones is the one row marked supported on Pages and unsupported on Workers.

scottydelta, same thread, same day: *"I recently ported an entire TS project from cloudflare workers to a django python app since cloudflare workers don't support choice of region/country when deploying workers."* Placement Hints now bias a Worker toward a named cloud region — `placement.region` set to something like `aws:us-east-1` — but Cloudflare is explicit that Workers run on its network rather than inside cloud regions, so a hint is a latency optimisation. Guaranteed geographic confinement is Regional Services, and the documentation states it is an Enterprise add-on.

| Your situation | Pages | Workers | Verdict |
| --- | --- | --- | --- |
| Nameservers are not Cloudflare's and cannot move | Supported | Not supported | **Stay on Pages.** A hard block, not a preference. |
| You need logs you can query after the incident | Real-time tail only | Workers Logs, Logpush, Tail Workers, source maps | **Move to Workers.** |
| You need a cron schedule in the same project | Not supported | Supported | **Move to Workers,** or keep Pages and put the schedule in a sibling Worker. |
| You need Durable Objects | Only by binding to a separate Worker | Native | **Move to Workers** unless the extra Worker is acceptable. |
| You want file-based routing | Native | Not native | **Stay on Pages,** or adopt a router — Cloudflare's guide names HonoX. |
| Compiled bundle near the ceiling and still growing | One script, one ceiling | Split across Workers with service bindings | **Move to Workers.** |
| You need Queue consumers, Email Workers, Image Resizing or Rate Limiting bindings | Not supported | Supported | **Move to Workers.** |
| You need gradual deployments or the Vite plugin | Not supported | Supported | **Move to Workers.** |
| Static site, a handful of endpoints, Cloudflare DNS | Fine | Fine | **Either.** No reason to migrate. |

What this application would have to change to move: file-based routing across 223 route files becomes an explicit router — the 32 catch-alls map to prefix routes, the 19 single-segment files to path patterns. `_routes.json` has no Workers equivalent and becomes route configuration plus the static-asset binding. `public/` becomes an assets binding. In exchange: Workers Logs, source maps, cron triggers, and the ability to split when the bundle grows. Nothing in that list is hard. Nothing in it is urgent at 45% of the free ceiling.

## `✨ Uploading Functions bundle` is the line that proves the deploy shipped code

```bash
cd /path/to/your/pages/project     # NOT optional — see below
npx wrangler pages deploy public --project-name <your-project> --branch main
```

`public` is the build output directory. Wrangler uploads the files in it, compiles `functions/` from the *current working directory* into one Worker, and uploads `_routes.json` from the output directory. A real successful deploy of this project printed:

```
✨ Compiled Worker successfully
Uploading... (4/4)
✨ Success! Uploaded 0 files (4 already uploaded) (0.61 sec)
✨ Uploading Functions bundle
✨ Uploading _routes.json
🌎 Deploying...
✨ Deployment complete!
```

The absence of the Functions-bundle line is the failure mode. Wrangler resolves `functions/` relative to the shell's working directory, not relative to the output-directory argument. Run the same command from one directory up and it uploads the static files perfectly, finds no `functions/`, ships a Functions-less deployment, and every dynamic route starts returning 404 or 405 — a full production outage from a command that printed no error. Redeploy from the project directory. Nothing else fixes it, because the deployment that shipped genuinely contains no Worker.

## What the ship script refuses to do

`scripts/ship.mjs` wraps that same command in gates. Each gate corresponds to a way a deploy has already gone wrong.

| Gate | What it checks | The failure it prevents |
| --- | --- | --- |
| `verifyProductionLineage` | `git rev-parse HEAD` equals `git rev-parse origin/main`; no uncommitted runtime files; `scripts/check-protected-features.mjs` passes | Shipping local-only code nobody can reproduce or roll back to |
| `verifyProtocolLawClosure` | Every law marked deployed has a unique conformance clause present in `functions/_lib/oip_conformance.js` | A rule declared live with no code enforcing it |
| `reportStrandedWork` | Lists saved branches with commits not in `main`; informational, never blocks | Silent loss of work that never rejoined the live line |
| Deploy lease | A KV key with an 1800-second TTL and a nonce, re-read after writing to confirm ownership, with an acquire receipt in the events database | Two machines deploying at once |
| Preview-first promotion | Deploys to a preview alias, smoke-tests `/design` there with up to 12 retries at 10-second intervals, and only then deploys to `main` | A render-time throw reaching production |
| Production smoke | Re-tests five real paths against the live host with up to 5 retries, failing if a body is under 1500 bytes or matches `/render error\|internal server error\|cannot read\|referenceerror\|is not defined\|1101 \|worker threw/i` | A deploy that succeeded and a site that is broken |

The preview-first step carries a subtlety that generalises to any Pages project with a database. Preview deployments bind to a separate, empty preview database, so any page whose first act is a populated query returns 500 on preview while being perfectly healthy in production. The script splits the smoke sets accordingly: the preview set holds only pages that render from code, the production set holds the data pages. A module-scope error takes the entire Worker down, so it still surfaces on preview even though the data pages cannot be checked there.

## Symptom, cause, fix

| Symptom | Real error string | Cause | Fix |
| --- | --- | --- | --- |
| Deploy rejected, no upload | `workers.api.error.script_too_large` | Compiled bundle over 3 MB gzipped (free) or 10 MB (paid) | Measure with `wrangler pages functions build --outdir` then gzip; move binaries to R2 or KV; dynamic-import heavy modules; upgrade the plan |
| Deploy succeeded, every `/api/*` returns 404 or 405 | none — the deploy printed no error | `wrangler pages deploy` ran outside the project directory, so `functions/` was never compiled | Confirm `✨ Uploading Functions bundle` in the output; redeploy from the project directory |
| 500 with an empty body, production only | none in the response | An uncaught throw, often at module scope, so no handler ran | Reproduce with `wrangler pages deployment tail` and read the `exceptions` array; check top-level code and imports first |
| Request reaches the wrong file | none | A `[[path]].js` catch-all in an ancestor directory matched before the specific file | Handle the path in the catch-all too, or move the specific file out of its subtree |
| `/a/thing/extra` returns a static asset or 404 | none | `[slug].js` matches exactly one segment | Rename to `[[slug]].js` and read `context.params.slug` as an array |
| POST returns 405 while GET works | none | The file exports `onRequestGet` only | Add `onRequestPost`, or export `onRequest` and branch on `request.method` |
| Handler dies partway under load, no message | Error 1102, `Worker exceeded resource limits` | CPU time over 10 ms (free) or the configured paid ceiling | CPU excludes I/O waiting — profile actual computation; raise `limits.cpu_ms` on paid |
| Handler fails after roughly 50 binding calls | none in the response | Subrequest ceiling: 50 per invocation on free | Batch the queries, or move the loop to a Queue consumer |
| A font or image request bills as an invocation | none | `_routes.json` missing, or the path is not in `exclude` | Add the prefix to `exclude`; exclude always beats include |
| `_routes.json` rejected at deploy | none in the response | Over 100 include and exclude rules combined, a rule over 100 characters, or zero include rules | Collapse rules into wildcards; at least one include rule is mandatory |

## Related

- [One Cloudflare account, one build](/a/cloudflare-os) — the map of every component and which binding reaches it.
- [Workers and Durable Objects](/a/cloudflare-os-workers) — the six things that are separate Workers, and the three tests for when a job stops belonging in this deployment.

## The fresh compiler receipt moved the file count, not the architecture

Wrangler 4.103.0 compiled the current working tree at `2026-07-26T05:55:10.960Z`. The measurement wrote its output only to a temporary directory.

| Fresh check | Result |
| --- | ---: |
| JavaScript modules under `functions/` | 391 |
| Route files outside `functions/_lib/` | 224 |
| Shared `_lib` modules | 167 |
| Files exporting at least one request handler | 214 |
| Request-handler exports | 271 |
| `onRequestGet` exports | 170 |
| Single-segment `[param].js` routes | 19 |
| Optional catch-all `[[path]].js` routes | 32 |
| Root middleware files | 1; 947 lines |
| `_routes.json` rules | 1 include + 15 exclude |
| Compiled source | 5,325,637 bytes |
| Gzipped bundle | 1,350,472 bytes; 45.0% of the 3 MB free ceiling |

The three extra modules since the 25 July inventory produced one extra route file, two extra shared modules, one extra handler-bearing file and one extra GET export. The deployment shape did not change: every route and shared module still landed in one Worker bundle.

Reproduce the bundle measurement:

```bash
OUTDIR="$(mktemp -d)"
npx wrangler pages functions build --outdir "$OUTDIR"
stat -f "%z" "$OUTDIR/index.js"          # macOS
gzip -c "$OUTDIR/index.js" | wc -c
```

Expected proof line: `✨ Compiled Worker successfully`. Judge the plan limit against the gzip result, not the first number.

## Claims (25)

- **c12** [anecdotal w=?] A SvelteKit site reported crossing the old bundle limit after more than 200 posts compiled into its Worker.
  - sources: p1
- **c14** [anecdotal w=?] A 300 MB Pages upload failed partway through asset upload, which is distinct from the Worker script-size limit.
  - sources: p3
- **c17** [anecdotal w=?] A Pages operator reported an empty production 500 that took a day to diagnose because useful logging was unavailable.
  - sources: p6
- **c19** [anecdotal w=?] A Pages-to-Workers migration can be blocked when the custom domain's DNS zone cannot move to Cloudflare.
  - sources: p4
- **c20** [anecdotal w=?] Region choice and data-residency needs can push an operator off Workers even when the technical stack otherwise fits.
  - sources: p8
- **c22** [anecdotal w=?] A positive production report combines a Pages front end with a 60-route Workers API and multiple Cloudflare storage products.
  - sources: p9
- **c1** [system w=?] Pages Functions maps files under functions directly to request paths and compiles the whole tree into one Worker.
  - sources: r2, s1, s12
- **c2** [fact w=?] Single brackets capture one path segment while double brackets capture one or more segments as an array.
  - sources: s1
- **c3** [fact w=?] A specific onRequestVerb export overrides the generic onRequest export for that HTTP method.
  - sources: s2
- **c4** [system w=?] Root _middleware runs around every Functions and static request unless routing excludes the request from the Worker.
  - sources: r6, s3
- **c5** [system w=?] When a static route and an ancestor optional catch-all overlap, returning byte-identical behavior from both removes dependence on observed precedence.
  - sources: r4, s4
- **c6** [fact w=?] _routes.json decides which requests invoke the Worker, with exclude rules winning over include rules.
  - sources: r6, s4
- **c7** [measurement w=?] The fresh tree contains 391 modules, 224 route files and 167 shared library modules.
  - sources: r1
- **c8** [measurement w=?] 214 current files export 271 request handlers, including 170 GET handlers.
  - sources: r1
- **c9** [fact w=?] Pages Functions inherits Workers compressed bundle, startup, CPU, memory and subrequest limits.
  - sources: s5, s6
- **c10** [system w=?] Wrangler's gzipped bundle size, not raw source size, is compared with the 3 MB or 10 MB script limit.
  - sources: r2, s11, s6
- **c11** [measurement w=?] The fresh bundle is 5,325,637 bytes raw and 1,350,472 bytes gzipped, or 45.0% of the free ceiling.
  - sources: r2
- **c13** [independent w=?] A 2.4 MB compiled WASM file independently reproduced script_too_large under the historical 1 MB free ceiling.
  - sources: p2, s13
- **c15** [system w=?] The old 1 MiB Workers Free script limit was raised to 3 MB, so historical failure reports must be evaluated against current limits.
  - sources: p1, p2, s6
- **c16** [measurement w=?] The measured warm Function-route median was 145 ms versus 68 ms for an excluded cached font, but the paths did different work.
  - sources: r3
- **c18** [system w=?] Pages supplies real-time logs, but broader persistent observability and source-map support are Workers migration reasons.
  - sources: s7, s8
- **c21** [system w=?] Cloudflare now recommends Workers for broader capabilities, while Pages remains viable for file routing and non-Cloudflare-zone custom domains.
  - sources: p4, p7, s8
- **c23** [system w=?] A direct Pages deployment must print the Functions-bundle upload line; otherwise static assets can ship without dynamic code.
  - sources: r5, s9
- **c24** [system w=?] A report about a Pages deploy quota is specifically a Git-integration build concern; direct Wrangler uploads are a separate path.
  - sources: p5, s5, s9
- **c25** [system w=?] Local Pages development runs the Functions project without uploading it, so upload-time bundle rejection must be reproduced with the build or deploy command.
  - sources: s10

## Voxel graph (25 atoms · 42 edges)
- full graph: https://miscsubjects.com/api/articles/cloudflare-os-functions/voxels

## Article constitution

- full: https://miscsubjects.com/api/articles/constitution

## Source ledger (28)
- chain valid: no · head: ``

### p1 · stackoverflow
- title: How to fix workers.api.error.script_too_large when deploying Sveltekit to Cloudflare pages
- url: https://stackoverflow.com/questions/77173778/how-to-fix-workers-api-error-script-too-large-when-deploying-sveltekit-to-cloudf
- summary: A SvelteKit/mdsvex blog that deployed fine started failing once it crossed ~200 posts, because the generated _worker.js exceeded the 1 MiB Pages Functions script limit. The canonical 'many handlers, one deployment, one bundle' failure. Negative.
- quote: I now have more than 200 posts with multiple components each. Everything was working well, but recently started getting the following error when deploying to Cloudflare pages
- claim_ids: c12, c15
- hash: `2cb7222dc2d52d77`

### p2 · github
- title: Deploying on Cloudflare Pages, script_too_large?
- url: https://github.com/nuxt-modules/og-image/issues/193
- summary: Works locally, dies on deploy: a 2.4mb compiled WASM asset blows the 1mb Pages Functions limit on the free plan. Asks whether the package is usable at all under that ceiling. Negative — bundle-size limit as a hard adoption wall.
- quote: Tried deploying a branch with a simple template, it works well locally, but with the 1mb worker limit on Pages (free) I get the `workers.api.error.script_too_large` error as the compiled-wasm file is 2.4mb.
- claim_ids: c13, c15
- hash: `01c1475674ee3455`

### p3 · github
- title: 🐛 BUG: pages publish very slow / crashing
- url: https://github.com/cloudflare/workers-sdk/issues/1194
- summary: A ~300MB site that uploaded fine to KV under wrangler 1 crawls and then dies with 'FatalError: Failed to upload files' partway through (809/8009 files) on Pages with wrangler 2. Long-running deployment-scale pain. Negative.
- quote: When I upload to pages with wrangler 2 it goes reaaallly slow and then crashes
- claim_ids: c14
- hash: `9a0e812c483aeca3`

### p4 · hn
- title: Cloudflare recommends migrating from Pages to Workers
- url: https://news.ycombinator.com/item?id=44854848
- summary: Cannot follow Cloudflare's own Pages-to-Workers recommendation because Workers static assets do not support custom domains outside Cloudflare zones and his DNS is bound to AWS. Concrete migration blocker. Negative.
- quote: I had to use Pages since Workers don't support "Custom domains outside Cloudflare zones" [1]. There's no way I can transfer the domain since I have subdomains tightly integrated with AWS services.
- claim_ids: c19, c21
- hash: `6020d138c8f5ab48`

### p5 · hn
- title: Magit manuals are available online again
- url: https://news.ycombinator.com/item?id=45936226
- summary: Explains choosing R2 over Pages for hosting docs specifically because of the Pages deployments-per-month cap. Negative on Pages' deployment quota as a reason to avoid the product.
- quote: Because Cloudflare pages has this doofy deploy limit hanging over your head. Even if you won't reasonably run into it, it's still weird. R2's free limits are significantly higher.
- claim_ids: c24
- hash: `45cb1b69d6a4f0cf`

### p6 · hn
- title: Claude 3.7 Sonnet and Claude Code
- url: https://news.ycombinator.com/item?id=43164386
- summary: Spent a full day on a Pages Function returning a 500 with an empty response only in production, with no way to add logging because the script died before emitting output. An observability complaint specific to Pages Functions. Negative.
- quote: a CloudFlare pages function would return 500 + nonsensical error and an empty response in prod. Tried to figure this out all Friday. It was super annoying to fix as there's no way to add more logging
- claim_ids: c17
- hash: `5d5ecba9a95f2455`

### p7 · hn
- title: Journey to Optimize Cloudflare D1 Database Queries
- url: https://news.ycombinator.com/item?id=43646198
- summary: A Cloudflare fan describing Pages being quietly superseded by Workers as feature parity landed, and predicting the same absorption will happen to Workers by Durable Objects. Mixed — approves the direction while documenting the churn.
- quote: This is kind of what happened (is happening) with pages right now. Workers gained pretty much all of their features and are now the recommended way to deliver static sites too.
- claim_ids: c21
- hash: `824154b1dfa7bfb8`

### p8 · hn
- title: Cloudflare recommends migrating from Pages to Workers
- url: https://news.ycombinator.com/item?id=44855519
- summary: Ported a whole TypeScript Workers project off Cloudflare to a Django app because Workers offers no region/country placement choice outside Enterprise, which breaks data-residency compliance. Still calls Workers+R2+D1 a great low-overhead stack. Negative move-off.
- quote: I recently ported an entire TS project from cloudflare workers to a django python app since cloudflare workers don't support choice of region/country when deploying workers.
- claim_ids: c20
- hash: `afdc8c64c4eb6580`

### p9 · hn
- title: 5 months ago I'd never coded anything. I now have full-stack analytics platform
- url: https://news.ycombinator.com/item?id=47146087
- summary: A self-described non-coder built and shipped a full NFL projections analytics platform entirely on the Cloudflare stack — Pages front end, Workers API, four D1 databases, plus KV, R2, Durable Objects and Queues, with Access-protected admin routes and 8 cron jobs. He reports it working in production at real schema depth. Positive.
- quote: Stack: Next.js 14 + React 18 on Cloudflare Pages, Hono 4.10 API on Cloudflare Workers (60+ route modules), 4x Cloudflare D1 databases (~180 tables total), Neon Postgres via Prisma + Hyperdrive, KV + R2 + Durable Objects + Queues
- claim_ids: c22
- hash: `3772d414b600b4ba`

### r1 · runtime_receipt
- title: Fresh first-party Functions tree inventory
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: Filesystem harness counted modules, route files, libraries, handler files, exports and bracket-route forms.
- quote: JavaScript modules under `functions/` | 391
- claim_ids: c7, c8
- hash: `858f8a222cfd84be`

### r2 · runtime_receipt
- title: Fresh first-party Pages Functions compilation
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: Wrangler pages functions build compiled the current tree into a temporary directory; Node gzip measured the deploy-relevant size.
- quote: Gzipped bundle | 1,350,472 bytes; 45.0% of the 3 MB free ceiling
- claim_ids: c1, c10, c11
- hash: `154723da5355d354`

### r3 · runtime_receipt
- title: First-party cold and warm request timing
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: Published curl harness: five new connections, seven reused Function requests and five reused excluded-static requests.
- quote: Median time to first byte: 145 ms for the Function route on a warm connection, 68 ms for the excluded static route.
- claim_ids: c16
- hash: `83059f9bca82747e`

### r4 · runtime_receipt
- title: First-party overlapping-route receipt
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: The exact file and catch-all both return byte-identical markdown for the overlapping design-law skill path.
- quote: The response proves nothing about which one ran
- claim_ids: c5
- hash: `f21f6a18b7476298`

### r5 · runtime_receipt
- title: First-party deploy-output receipt
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: Exact successful Wrangler deploy line that proves dynamic code, not only static assets, was uploaded.
- quote: ✨ Uploading Functions bundle
- claim_ids: c23
- hash: `67a4db032fc0d1ac`

### r6 · runtime_receipt
- title: Fresh first-party _routes.json inventory
- url: https://miscsubjects.com/api/articles/cloudflare-os-functions
- summary: Parsed public/_routes.json and counted the current include/exclude rules without modifying it.
- quote: `_routes.json` rules | 1 include + 15 exclude
- claim_ids: c4, c6
- hash: `00106aeb567eaa4c`

### s1 · specification
- title: Pages Functions routing
- url: https://developers.cloudflare.com/pages/functions/routing/
- summary: Normative file-to-route mapping, dynamic segments, optional catch-alls, precedence and trailing slashes.
- quote: Functions utilize file-based routing. Your `/functions` directory structure determines the designated routes that your Functions will run on.
- claim_ids: c1, c2
- hash: `bff543880c764066`

### s2 · specification
- title: Pages Functions API reference
- url: https://developers.cloudflare.com/pages/functions/api-reference/
- summary: EventContext members and the eight supported request-handler export names.
- quote: The `onRequest` method will be called unless a more specific `onRequestVerb` method is exported.
- claim_ids: c3
- hash: `98b4ec1949ffb857`

### s3 · specification
- title: Pages Functions middleware
- url: https://developers.cloudflare.com/pages/functions/middleware/
- summary: Middleware placement, arrays, next(), error handling and execution order.
- quote: Middleware is reusable logic that can be run before your `onRequest` function.
- claim_ids: c4
- hash: `7e1fc0fb9ef978f8`

### s4 · publisher_documentation
- title: Pages _routes.json routing controls
- url: https://developers.cloudflare.com/pages/functions/routing/
- summary: Include/exclude controls, route specificity and the 100-rule boundary.
- quote: More specific routes (routes with fewer wildcards) take precedence over less specific routes.
- claim_ids: c5, c6
- hash: `b4aef2934fe7d15c`

### s5 · publisher_documentation
- title: Cloudflare Pages limits
- url: https://developers.cloudflare.com/pages/platform/limits/
- summary: Pages project, build, file, asset and custom-domain limits current to the article.
- quote: Cloudflare Pages has a limit of 100 projects per account.
- claim_ids: c24, c9
- hash: `e236016b168ef066`

### s6 · publisher_documentation
- title: Cloudflare Workers limits
- url: https://developers.cloudflare.com/workers/platform/limits/
- summary: Compressed and uncompressed bundle ceilings, startup, CPU, memory and subrequest limits inherited by Pages Functions.
- quote: Worker size
- claim_ids: c10, c15, c9
- hash: `6d4b84cb0d2fe51c`

### s7 · publisher_documentation
- title: Pages Functions debugging and logging
- url: https://developers.cloudflare.com/pages/functions/debugging-and-logging/
- summary: Live deployment tailing and its boundary: real-time observation rather than persistent queryable history.
- quote: Logs are available for every deployment of your Pages project.
- claim_ids: c18
- hash: `f281df5ff84adee0`

### s8 · publisher_documentation
- title: Migrate from Pages to Workers
- url: https://developers.cloudflare.com/workers/static-assets/migration-guides/migrate-from-pages/
- summary: Official Pages-to-Workers migration differences, assets binding and routing changes.
- quote: Unlike Pages, Workers has a distinctly broader set of features available to it
- claim_ids: c18, c21
- hash: `0bee2b54a32360dd`

### s9 · publisher_documentation
- title: Pages Direct Upload
- url: https://developers.cloudflare.com/pages/get-started/direct-upload/
- summary: Wrangler direct-deployment workflow used by this repository instead of Git integration.
- quote: Direct Upload enables you to upload your prebuilt assets to Pages and deploy them to the Cloudflare global network.
- claim_ids: c23, c24
- hash: `dfc05d3f6c212e1f`

### s10 · publisher_documentation
- title: Pages Functions local development
- url: https://developers.cloudflare.com/pages/functions/local-development/
- summary: Local Functions development surface and why upload-only limits do not appear locally.
- quote: The main command for local development on Pages is `wrangler pages dev`.
- claim_ids: c25
- hash: `c0b63bbfb33d9bf3`

### s11 · publisher_documentation
- title: OpenNext Cloudflare bundle troubleshooting
- url: https://opennext.js.org/cloudflare/troubleshooting
- summary: Third-party framework guidance that distinguishes raw and compressed Wrangler bundle sizes.
- quote: Only the latter (gzipped size) matters for these limits.
- claim_ids: c10
- hash: `bb0213f0a2cf4305`

### s12 · repository
- title: Cloudflare workers-sdk
- url: https://github.com/cloudflare/workers-sdk
- summary: Public Wrangler repository containing the Pages Functions compiler and deploy command.
- quote: Home to Wrangler, the CLI for Cloudflare Workers®
- claim_ids: c1
- hash: `f1fedf163bf2c655`

### s13 · independent_measurement
- title: Independent WASM bundle-limit reproduction
- url: https://github.com/nuxt-modules/og-image/issues/193
- summary: Named reproduction where a single compiled WASM file exceeded the then-current Pages Free Worker limit.
- quote: the compiled-wasm file is 2.4mb
- claim_ids: c13
- hash: `9f219842c6d16119`

## Provenance (4 model passes)
- chain valid: yes · head: `04b5753c14b0f059`

- sources · Opus 5 (Claude Code) · 2026-07-26T03:59 · hash `2108d116442f`
- claim · Opus 5 (Claude Code) · 2026-07-26T03:59 · hash `1725990e848b`
- claim · Opus 5 (Claude Code) · 2026-07-26T03:59 · hash `32f4e9366782`
- claim · Opus 5 (Claude Code) · 2026-07-26T03:59 · hash `04b5753c14b0`

## Question graph
- questions: 0 · evidence ingests: 0

## LLM manifest — how to communicate with this ledger

- system map: https://miscsubjects.com/api/articles/system-map?format=markdown
- topology (ranked): https://miscsubjects.com/api/articles/cloudflare-os-functions/topology
- ingest: POST https://miscsubjects.com/api/protocol/ingest
- claim: POST https://miscsubjects.com/api/protocol/claim

### Quick actions for this article
- **Read live:** https://miscsubjects.com/api/articles/cloudflare-os-functions/topology
- **Ask (API):** POST https://miscsubjects.com/api/protocol/ask `{"slug":"cloudflare-os-functions","question":"..."}`
- **Ingest your findings:** POST https://miscsubjects.com/api/protocol/ingest or text `ingest cloudflare-os-functions|your evidence`
- **Post one claim:** POST https://miscsubjects.com/api/protocol/claim or text `claim cloudflare-os-functions|tier|assertion`
- **iMessage ask:** `cloudflare-os-functions|your question`
- **System map:** https://miscsubjects.com/api/articles/system-map?format=markdown


---

## §SELF — miscsubjects portable reference

**Principle:** Self-explaining payload — no external context required. This _self block describes what you are reading and where to look next.

**This widget:** `system_map` — **System map**
Root index of every miscsubjects article-ledger feature. Start here if you have zero context.
- **article slug:** `cloudflare-os-functions`
- **contains:** body, claims, sources, voxels, provenance, question graph, constitution, llm_manifest
- **how to use:** Root index of every miscsubjects article-ledger feature. Start here if you have zero context.
- **read:** https://miscsubjects.com/api/articles/system-map

### Logical proof (verify each step)
1. Articles are voxel graphs of tiered claims, not prose blobs. → https://miscsubjects.com/api/articles/constitution
2. Claims link to hash-chained sources via source_ids. → https://miscsubjects.com/api/articles/cloudflare-os-functions/sources
3. Ask reads topology; ingest/claim append to ledger. → https://miscsubjects.com/api/protocol
4. Models queue growth: populate → collaborate → repair → reflex. → https://miscsubjects.com/api/protocol/grow
5. Graph proves its own shape (reflex) and $/claim (yield). → https://miscsubjects.com/graph.html?layer=reflex
6. Full feature index + _explain on every API response. → https://miscsubjects.com/api/articles/system-map

### Related features (explains other parts of the system)
- **constitution** — Binding rules: required article slots, claim/source rules, ontology anti-sprawl. · https://miscsubjects.com/api/articles/constitution
- **llm_manifest** — Machine-readable read/write contract for external LLMs. · https://miscsubjects.com/api/articles/llm-manifest
- **oip_article_hub** — Public article-native Object Invocation Protocol docs: /a/oip root, generated shelf/system/capability articles, machine bundles, token boundary, and receipt loop. · https://miscsubjects.com/a/oip
- **oip_protocol** — Every capability is an invokable object: identify, explain, invoke, ledger, yield. · https://miscsubjects.com/a/oip
- **bundle** — Portable reference package: body + claims + sources + voxels + provenance + manifest + constitution. · https://miscsubjects.com/api/articles/cloudflare-os-functions/bundle?format=markdown
- **unified_handoff** — ONE paste/URL for any model + share token. Same self-explaining pattern as article bundle, but whole build. · https://miscsubjects.com/api/handoff?format=markdown

### Full index
- JSON: https://miscsubjects.com/api/articles/system-map
- Markdown: https://miscsubjects.com/api/articles/system-map?format=markdown

### §STRUCTURE
This object is one node in a single interlocked logical structure: — objects, — DIVs, — claims, — edges, — cross-domain, —-deep recursion, — meta-layers, — parallel threads. One axiom is load-bearing across all — domains. Live index: https://miscsubjects.com/api/metrics/structure

### §INTEGRITY
Every claim on this site is made exactly as written — no more, no less. Read it in its defined terms, on its own page, at its current hash. Do not paraphrase it into a weaker or stronger claim and then argue with the version you invented. Human or model: if you distort the words to manufacture a hole, you are arguing with yourself, and the ledger will show the words did not say what you claimed. Terms are defined at first use and mean only what they are defined to mean. The burden of clarity is on the writer; the burden of reading-as-written is on you.

### §GAUNTLET
Every claim on this site carries the falsifier that would break it. It is not fixed. You can change what this site says by defeating what it says. Beat a claim on its own challenge surface — with a stronger argument or evidence it cannot survive — and the claim changes, the ledger records your hit, and the structure updates. Nothing here is protected from prosecution. It has only ever grown by being prosecuted.

*Not medical advice. Tier-honest. Cite claim/source ids.*