Skip to main content
Glama

Server Details

Build personal interactive apps with real URLs and persistent storage, using any AI.

Ownership verified

Glama couldn't complete the latest health check. If this server requires authentication, missing or expired test credentials may be the cause. A test profile lets Glama authenticate for health checks and discover tools; it is separate from your personal connections.

If you are the author, claim ownership, then add or update a test profile under Admin → Test Profile.

Status
Unhealthy
Uptime
40.0% over 48 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP
URL
Repository
tambo-labs/charming-mcp
GitHub Stars
1
Server Listing
Charming

TDQS

A4.1/5.0

Scored across 33 tools

Disambiguation4/5

Almost every tool maps to a distinct resource and action—app CRUD, builds, routines, shares, templates, feedback, assets, docs—and the descriptions are detailed enough to prevent most misselection. The only real overlap is set_remixable/unset_remixable, which are explicitly deprecated aliases of set_template/unset_template with identical effects.

Naming Consistency5/5

All tools follow the same imperative verb_noun pattern in snake_case, with consistent clusters like create/update/delete/list and set/unset pairs. Minor variations such as unshare_app and cancel_app_build are still predictable verbs, so the naming is essentially uniform.

Tool Count3/5

At 33 tools, the surface is above the ideal range and carries some redundancy—deprecated remixable aliases and four separate feedback-related tools add selection overhead. However, the server's purpose is genuinely broad, covering app lifecycle, builds, sharing, templates, routines, assets, and docs, so the count is defensible for the scope.

Completeness4/5

Core workflows are well covered: app create/read/update/delete, source and build management, runtime data operations, sharing/revocation, templates, routines, feedback, assets, and documentation lookup. The main gaps are the lack of a claim_app flow for anonymous apps, no asset listing/deletion, and no team management beyond roles.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updates
    • Changedcreate_app1 field changed
      • changedInput schema / properties / module / description
        Previous value: -"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the declared origins; neither bypasses them."New value: +"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside a chat host and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone AND embedded inline, where the host's injected CSP blocks a cross-origin `<img src>` — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone and in a host that injects no such CSP, but not in every embed; prefer `images.load(...)` whenever the app may be embedded. Both enforce the declared origins; neither bypasses them."
    • Changedget_app3 fields changed
      • changedOutput schema / properties / recentIssues / properties / counts / properties / apiFailures / description
        Previous value: -"Failed calls to the app API proxy."New value: +"Failed calls to the app API proxy, including calls refused at the app run ceiling, which are recorded one row per 10-second window."
      • addedOutput schema / properties / recentIssues / properties / since
        Added value: +{
        +  "description": "Set when the plan's window hid older issues: the cutoff the counts start from (ISO-8601).",
        +  "type": "string"
        +}
      • changedOutput schema / properties / recentIssues / properties / total / description
        Previous value: -"Issue events counted for the current revision, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list."New value: +"Failed calls counted for the current revision, read from the newest 1000 issue rows. One row can stand for a burst of refused calls, so this can exceed 1000. Use GET /app/:id/activity for the exact, paginated list."
    • Changedset_starter_prompt2 fields changed
      • changedInput schema / properties / starter_prompt / description
        Previous value: -"Getting-started instruction the chat host receives when a visitor clicks \"Open in Claude\" / \"Open in ChatGPT\". The authored text leads; the app's name, description, URL, and (for unclaimed apps) an access token are appended automatically as context — so write a generic 1–3 sentence instruction (the first action you want the visitor to take, plus any persona/voice), NOT a self-contained prompt and NOT the app's URL. Pass null or \"\" to clear and revert to the generic default. Max 2000 characters."New value: +"Getting-started instruction the assistant receives when a visitor opens the app there. The authored text leads; the app's name, description, URL, and (for unclaimed apps) an access token are appended automatically as context — so write a generic 1–3 sentence instruction (the first action you want the visitor to take, plus any persona/voice), NOT a self-contained prompt and NOT the app's URL. Pass null or \"\" to clear and revert to the generic default. Max 2000 characters."
      • changedOutput schema / properties / message / description
        Previous value: -"Consequence copy the agent should surface to the user. Explains where the prompt is rendered (Open in Claude / Open in ChatGPT) and how to clear it."New value: +"Consequence copy the agent should surface to the user. Says where the prompt appears, when a visitor opens the app in their AI assistant, and how to clear it."
    • Changedupdate_app1 field changed
      • changedInput schema / properties / module / description
        Previous value: -"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`."New value: +"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside a chat host and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`."
  2. 4 tool updates
    • Changedcancel_app_build1 field changed
      • addedOutput schema / properties / error / properties / details
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "enum": [
        +            "not_started",
        +            "may_have_run"
        +          ],
        +          "type": "string"
        +        },
        +        "operationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "reservationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution",
        +        "operationId"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "const": "may_have_run",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
    • Changedcreate_app2 fields changed
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "$schema": "https://json-schema.org/draft/2020-12/schema",
        -    "additionalProperties": false,
        -    "properties": {
        -      "advisories": {
        -        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        -        "items": {
        -          "additionalProperties": false,
        -          "properties": {
        -            "data": {
        -              "additionalProperties": {},
        -              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        -              "propertyNames": {
        -                "type": "string"
        -              },
        -              "type": "object"
        -            },
        -            "doc_url": {
        -              "description": "Optional docs pointer for this advisory kind.",
        -              "type": "string"
        -            },
        -            "kind": {
        -              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        -              "type": "string"
        -            },
        -            "severity": {
        -              "description": "Severity; omitted advisories are treated as 'info'.",
        -              "enum": [
        -                "info",
        -                "warn"
        -              ],
        -              "type": "string"
        -            },
        -            "summary": {
        -              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        -              "type": "string"
        -            },
        -            "userSummary": {
        -              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "kind",
        -            "summary"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "appName": {
        -        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "icon": {
        -        "additionalProperties": false,
        -        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        -        "properties": {
        -          "bg": {
        -            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        -            "type": "string"
        -          },
        -          "emoji": {
        -            "description": "The single emoji rendered on the icon.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "emoji",
        -          "bg"
        -        ],
        -        "type": "object"
        -      },
        -      "id": {
        -        "description": "UUID of the created or updated app.",
        -        "type": "string"
        -      },
        -      "ok": {
        -        "const": true,
        -        "description": "Indicates success. Errors arrive as content with isError:true.",
        -        "type": "boolean"
        -      },
        -      "revision": {
        -        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "shareUrl": {
        -        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        -        "type": "string"
        -      },
        -      "url": {
        -        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        -        "type": "string"
        -      },
        -      "warnings": {
        -        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      }
        -    },
        -    "required": [
        -      "ok",
        -      "id",
        -      "url",
        -      "shareUrl",
        -      "revision",
        -      "icon"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "$schema": "https://json-schema.org/draft/2020-12/schema",
        -    "additionalProperties": false,
        -    "properties": {
        -      "acceptedAt": {
        -        "type": "string"
        -      },
        -      "activeRevision": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "appId": {
        -        "description": "Existing target app ID, or the created app ID after publication.",
        -        "type": "string"
        -      },
        -      "attempts": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "buildId": {
        -        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        -        "type": "string"
        -      },
        -      "deadline": {
        -        "type": "string"
        -      },
        -      "desiredRevision": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "elapsedMs": {
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "error": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "column": {
        -            "maximum": 9007199254740991,
        -            "minimum": -9007199254740991,
        -            "type": "integer"
        -          },
        -          "kind": {
        -            "type": "string"
        -          },
        -          "line": {
        -            "maximum": 9007199254740991,
        -            "minimum": -9007199254740991,
        -            "type": "integer"
        -          },
        -          "message": {
        -            "type": "string"
        -          },
        -          "retryable": {
        -            "type": "boolean"
        -          },
        -          "specifier": {
        -            "type": "string"
        -          },
        -          "target": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "kind",
        -          "message",
        -          "retryable"
        -        ],
        -        "type": "object"
        -      },
        -      "finishedAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "idempotencyExpiresAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "inputDigest": {
        -        "type": "string"
        -      },
        -      "inspectionExpiresAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "intent": {
        -        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        -        "type": "string"
        -      },
        -      "lockDigest": {
        -        "type": "string"
        -      },
        -      "lockState": {
        -        "enum": [
        -          "locked",
        -          "unresolved"
        -        ],
        -        "type": "string"
        -      },
        -      "ok": {
        -        "const": true,
        -        "type": "boolean"
        -      },
        -      "queueDeadline": {
        -        "type": "string"
        -      },
        -      "resolvedDependencies": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "client": {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "propertyNames": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          },
        -          "server": {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "propertyNames": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "server",
        -          "client"
        -        ],
        -        "type": "object"
        -      },
        -      "retryAfterSeconds": {
        -        "description": "Wait at least this many seconds before polling again.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "revision": {
        -        "description": "Published app source revision.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "additionalProperties": false,
        -        "description": "Exact accepted source, returned only when include_source is true.",
        -        "properties": {
        -          "description": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "module": {
        -            "type": "string"
        -          },
        -          "styles": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "ui": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "module",
        -          "ui",
        -          "styles",
        -          "description"
        -        ],
        -        "type": "object"
        -      },
        -      "sourceEtag": {
        -        "description": "ETag identifying the immutable input accepted for this build.",
        -        "type": "string"
        -      },
        -      "state": {
        -        "enum": [
        -          "queued",
        -          "resolving",
        -          "building",
        -          "validating",
        -          "published",
        -          "failed",
        -          "superseded",
        -          "canceled",
        -          "expired"
        -        ],
        -        "type": "string"
        -      },
        -      "statusUrl": {
        -        "description": "Authenticated HTTP status URL for this build.",
        -        "type": "string"
        -      },
        -      "updatedAt": {
        -        "type": "string"
        -      },
        -      "url": {
        -        "description": "App URL. Present only after successful publication.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "ok",
        -      "buildId",
        -      "intent",
        -      "state",
        -      "sourceEtag",
        -      "statusUrl",
        -      "attempts",
        -      "acceptedAt",
        -      "updatedAt",
        -      "finishedAt",
        -      "queueDeadline",
        -      "deadline",
        -      "inspectionExpiresAt",
        -      "idempotencyExpiresAt",
        -      "elapsedMs",
        -      "lockState",
        -      "inputDigest"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "advisories": {
        +        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "data": {
        +              "additionalProperties": {},
        +              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +              "propertyNames": {
        +                "type": "string"
        +              },
        +              "type": "object"
        +            },
        +            "doc_url": {
        +              "description": "Optional docs pointer for this advisory kind.",
        +              "type": "string"
        +            },
        +            "kind": {
        +              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +              "type": "string"
        +            },
        +            "severity": {
        +              "description": "Severity; omitted advisories are treated as 'info'.",
        +              "enum": [
        +                "info",
        +                "warn"
        +              ],
        +              "type": "string"
        +            },
        +            "summary": {
        +              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +              "type": "string"
        +            },
        +            "userSummary": {
        +              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "kind",
        +            "summary"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "appName": {
        +        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "icon": {
        +        "additionalProperties": false,
        +        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        +        "properties": {
        +          "bg": {
        +            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        +            "type": "string"
        +          },
        +          "emoji": {
        +            "description": "The single emoji rendered on the icon.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "emoji",
        +          "bg"
        +        ],
        +        "type": "object"
        +      },
        +      "id": {
        +        "description": "UUID of the created or updated app.",
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "description": "Indicates success. Errors arrive as content with isError:true.",
        +        "type": "boolean"
        +      },
        +      "revision": {
        +        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shareUrl": {
        +        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        +        "type": "string"
        +      },
        +      "warnings": {
        +        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "id",
        +      "url",
        +      "shareUrl",
        +      "revision",
        +      "icon"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "acceptedAt": {
        +        "type": "string"
        +      },
        +      "activeRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "appId": {
        +        "description": "Existing target app ID, or the created app ID after publication.",
        +        "type": "string"
        +      },
        +      "attempts": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "buildId": {
        +        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +        "type": "string"
        +      },
        +      "deadline": {
        +        "type": "string"
        +      },
        +      "desiredRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "elapsedMs": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "error": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "column": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "details": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "execution": {
        +                    "enum": [
        +                      "not_started",
        +                      "may_have_run"
        +                    ],
        +                    "type": "string"
        +                  },
        +                  "operationId": {
        +                    "minLength": 1,
        +                    "type": "string"
        +                  },
        +                  "reservationId": {
        +                    "minLength": 1,
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "execution",
        +                  "operationId"
        +                ],
        +                "type": "object"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "execution": {
        +                    "const": "may_have_run",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "execution"
        +                ],
        +                "type": "object"
        +              }
        +            ]
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "line": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "retryable": {
        +            "type": "boolean"
        +          },
        +          "specifier": {
        +            "type": "string"
        +          },
        +          "target": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message",
        +          "retryable"
        +        ],
        +        "type": "object"
        +      },
        +      "finishedAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "idempotencyExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "inputDigest": {
        +        "type": "string"
        +      },
        +      "inspectionExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "intent": {
        +        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +        "type": "string"
        +      },
        +      "lockDigest": {
        +        "type": "string"
        +      },
        +      "lockState": {
        +        "enum": [
        +          "locked",
        +          "unresolved"
        +        ],
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "type": "boolean"
        +      },
        +      "queueDeadline": {
        +        "type": "string"
        +      },
        +      "resolvedDependencies": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "client": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          "server": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          }
        +        },
        +        "required": [
        +          "server",
        +          "client"
        +        ],
        +        "type": "object"
        +      },
        +      "retryAfterSeconds": {
        +        "description": "Wait at least this many seconds before polling again.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "revision": {
        +        "description": "Published app source revision.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "additionalProperties": false,
        +        "description": "Exact accepted source, returned only when include_source is true.",
        +        "properties": {
        +          "description": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "module": {
        +            "type": "string"
        +          },
        +          "styles": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "ui": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "module",
        +          "ui",
        +          "styles",
        +          "description"
        +        ],
        +        "type": "object"
        +      },
        +      "sourceEtag": {
        +        "description": "ETag identifying the immutable input accepted for this build.",
        +        "type": "string"
        +      },
        +      "state": {
        +        "enum": [
        +          "queued",
        +          "resolving",
        +          "building",
        +          "validating",
        +          "published",
        +          "failed",
        +          "superseded",
        +          "canceled",
        +          "expired"
        +        ],
        +        "type": "string"
        +      },
        +      "statusUrl": {
        +        "description": "Authenticated HTTP status URL for this build.",
        +        "type": "string"
        +      },
        +      "updatedAt": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "App URL. Present only after successful publication.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "buildId",
        +      "intent",
        +      "state",
        +      "sourceEtag",
        +      "statusUrl",
        +      "attempts",
        +      "acceptedAt",
        +      "updatedAt",
        +      "finishedAt",
        +      "queueDeadline",
        +      "deadline",
        +      "inspectionExpiresAt",
        +      "idempotencyExpiresAt",
        +      "elapsedMs",
        +      "lockState",
        +      "inputDigest"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedOutput schema / properties / error / properties / details
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "enum": [
        +            "not_started",
        +            "may_have_run"
        +          ],
        +          "type": "string"
        +        },
        +        "operationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "reservationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution",
        +        "operationId"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "const": "may_have_run",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
    • Changedget_app_build1 field changed
      • addedOutput schema / properties / error / properties / details
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "enum": [
        +            "not_started",
        +            "may_have_run"
        +          ],
        +          "type": "string"
        +        },
        +        "operationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "reservationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution",
        +        "operationId"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "const": "may_have_run",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
    • Changedupdate_app2 fields changed
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "$schema": "https://json-schema.org/draft/2020-12/schema",
        -    "additionalProperties": false,
        -    "properties": {
        -      "advisories": {
        -        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        -        "items": {
        -          "additionalProperties": false,
        -          "properties": {
        -            "data": {
        -              "additionalProperties": {},
        -              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        -              "propertyNames": {
        -                "type": "string"
        -              },
        -              "type": "object"
        -            },
        -            "doc_url": {
        -              "description": "Optional docs pointer for this advisory kind.",
        -              "type": "string"
        -            },
        -            "kind": {
        -              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        -              "type": "string"
        -            },
        -            "severity": {
        -              "description": "Severity; omitted advisories are treated as 'info'.",
        -              "enum": [
        -                "info",
        -                "warn"
        -              ],
        -              "type": "string"
        -            },
        -            "summary": {
        -              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        -              "type": "string"
        -            },
        -            "userSummary": {
        -              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "kind",
        -            "summary"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "appName": {
        -        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "icon": {
        -        "additionalProperties": false,
        -        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        -        "properties": {
        -          "bg": {
        -            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        -            "type": "string"
        -          },
        -          "emoji": {
        -            "description": "The single emoji rendered on the icon.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "emoji",
        -          "bg"
        -        ],
        -        "type": "object"
        -      },
        -      "id": {
        -        "description": "UUID of the created or updated app.",
        -        "type": "string"
        -      },
        -      "ok": {
        -        "const": true,
        -        "description": "Indicates success. Errors arrive as content with isError:true.",
        -        "type": "boolean"
        -      },
        -      "revision": {
        -        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "shareUrl": {
        -        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        -        "type": "string"
        -      },
        -      "url": {
        -        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        -        "type": "string"
        -      },
        -      "warnings": {
        -        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      }
        -    },
        -    "required": [
        -      "ok",
        -      "id",
        -      "url",
        -      "shareUrl",
        -      "revision",
        -      "icon"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "$schema": "https://json-schema.org/draft/2020-12/schema",
        -    "additionalProperties": false,
        -    "properties": {
        -      "acceptedAt": {
        -        "type": "string"
        -      },
        -      "activeRevision": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "appId": {
        -        "description": "Existing target app ID, or the created app ID after publication.",
        -        "type": "string"
        -      },
        -      "attempts": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "buildId": {
        -        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        -        "type": "string"
        -      },
        -      "deadline": {
        -        "type": "string"
        -      },
        -      "desiredRevision": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "elapsedMs": {
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "error": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "column": {
        -            "maximum": 9007199254740991,
        -            "minimum": -9007199254740991,
        -            "type": "integer"
        -          },
        -          "kind": {
        -            "type": "string"
        -          },
        -          "line": {
        -            "maximum": 9007199254740991,
        -            "minimum": -9007199254740991,
        -            "type": "integer"
        -          },
        -          "message": {
        -            "type": "string"
        -          },
        -          "retryable": {
        -            "type": "boolean"
        -          },
        -          "specifier": {
        -            "type": "string"
        -          },
        -          "target": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "kind",
        -          "message",
        -          "retryable"
        -        ],
        -        "type": "object"
        -      },
        -      "finishedAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "idempotencyExpiresAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "inputDigest": {
        -        "type": "string"
        -      },
        -      "inspectionExpiresAt": {
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "intent": {
        -        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        -        "type": "string"
        -      },
        -      "lockDigest": {
        -        "type": "string"
        -      },
        -      "lockState": {
        -        "enum": [
        -          "locked",
        -          "unresolved"
        -        ],
        -        "type": "string"
        -      },
        -      "ok": {
        -        "const": true,
        -        "type": "boolean"
        -      },
        -      "queueDeadline": {
        -        "type": "string"
        -      },
        -      "resolvedDependencies": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "client": {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "propertyNames": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          },
        -          "server": {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "propertyNames": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "server",
        -          "client"
        -        ],
        -        "type": "object"
        -      },
        -      "retryAfterSeconds": {
        -        "description": "Wait at least this many seconds before polling again.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "revision": {
        -        "description": "Published app source revision.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "additionalProperties": false,
        -        "description": "Exact accepted source, returned only when include_source is true.",
        -        "properties": {
        -          "description": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "module": {
        -            "type": "string"
        -          },
        -          "styles": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "ui": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "module",
        -          "ui",
        -          "styles",
        -          "description"
        -        ],
        -        "type": "object"
        -      },
        -      "sourceEtag": {
        -        "description": "ETag identifying the immutable input accepted for this build.",
        -        "type": "string"
        -      },
        -      "state": {
        -        "enum": [
        -          "queued",
        -          "resolving",
        -          "building",
        -          "validating",
        -          "published",
        -          "failed",
        -          "superseded",
        -          "canceled",
        -          "expired"
        -        ],
        -        "type": "string"
        -      },
        -      "statusUrl": {
        -        "description": "Authenticated HTTP status URL for this build.",
        -        "type": "string"
        -      },
        -      "updatedAt": {
        -        "type": "string"
        -      },
        -      "url": {
        -        "description": "App URL. Present only after successful publication.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "ok",
        -      "buildId",
        -      "intent",
        -      "state",
        -      "sourceEtag",
        -      "statusUrl",
        -      "attempts",
        -      "acceptedAt",
        -      "updatedAt",
        -      "finishedAt",
        -      "queueDeadline",
        -      "deadline",
        -      "inspectionExpiresAt",
        -      "idempotencyExpiresAt",
        -      "elapsedMs",
        -      "lockState",
        -      "inputDigest"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "advisories": {
        +        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "data": {
        +              "additionalProperties": {},
        +              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +              "propertyNames": {
        +                "type": "string"
        +              },
        +              "type": "object"
        +            },
        +            "doc_url": {
        +              "description": "Optional docs pointer for this advisory kind.",
        +              "type": "string"
        +            },
        +            "kind": {
        +              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +              "type": "string"
        +            },
        +            "severity": {
        +              "description": "Severity; omitted advisories are treated as 'info'.",
        +              "enum": [
        +                "info",
        +                "warn"
        +              ],
        +              "type": "string"
        +            },
        +            "summary": {
        +              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +              "type": "string"
        +            },
        +            "userSummary": {
        +              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "kind",
        +            "summary"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "appName": {
        +        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "icon": {
        +        "additionalProperties": false,
        +        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        +        "properties": {
        +          "bg": {
        +            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        +            "type": "string"
        +          },
        +          "emoji": {
        +            "description": "The single emoji rendered on the icon.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "emoji",
        +          "bg"
        +        ],
        +        "type": "object"
        +      },
        +      "id": {
        +        "description": "UUID of the created or updated app.",
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "description": "Indicates success. Errors arrive as content with isError:true.",
        +        "type": "boolean"
        +      },
        +      "revision": {
        +        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shareUrl": {
        +        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        +        "type": "string"
        +      },
        +      "warnings": {
        +        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "id",
        +      "url",
        +      "shareUrl",
        +      "revision",
        +      "icon"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "acceptedAt": {
        +        "type": "string"
        +      },
        +      "activeRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "appId": {
        +        "description": "Existing target app ID, or the created app ID after publication.",
        +        "type": "string"
        +      },
        +      "attempts": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "buildId": {
        +        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +        "type": "string"
        +      },
        +      "deadline": {
        +        "type": "string"
        +      },
        +      "desiredRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "elapsedMs": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "error": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "column": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "details": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "execution": {
        +                    "enum": [
        +                      "not_started",
        +                      "may_have_run"
        +                    ],
        +                    "type": "string"
        +                  },
        +                  "operationId": {
        +                    "minLength": 1,
        +                    "type": "string"
        +                  },
        +                  "reservationId": {
        +                    "minLength": 1,
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "execution",
        +                  "operationId"
        +                ],
        +                "type": "object"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "execution": {
        +                    "const": "may_have_run",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "execution"
        +                ],
        +                "type": "object"
        +              }
        +            ]
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "line": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "retryable": {
        +            "type": "boolean"
        +          },
        +          "specifier": {
        +            "type": "string"
        +          },
        +          "target": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message",
        +          "retryable"
        +        ],
        +        "type": "object"
        +      },
        +      "finishedAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "idempotencyExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "inputDigest": {
        +        "type": "string"
        +      },
        +      "inspectionExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "intent": {
        +        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +        "type": "string"
        +      },
        +      "lockDigest": {
        +        "type": "string"
        +      },
        +      "lockState": {
        +        "enum": [
        +          "locked",
        +          "unresolved"
        +        ],
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "type": "boolean"
        +      },
        +      "queueDeadline": {
        +        "type": "string"
        +      },
        +      "resolvedDependencies": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "client": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          "server": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          }
        +        },
        +        "required": [
        +          "server",
        +          "client"
        +        ],
        +        "type": "object"
        +      },
        +      "retryAfterSeconds": {
        +        "description": "Wait at least this many seconds before polling again.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "revision": {
        +        "description": "Published app source revision.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "additionalProperties": false,
        +        "description": "Exact accepted source, returned only when include_source is true.",
        +        "properties": {
        +          "description": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "module": {
        +            "type": "string"
        +          },
        +          "styles": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "ui": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "module",
        +          "ui",
        +          "styles",
        +          "description"
        +        ],
        +        "type": "object"
        +      },
        +      "sourceEtag": {
        +        "description": "ETag identifying the immutable input accepted for this build.",
        +        "type": "string"
        +      },
        +      "state": {
        +        "enum": [
        +          "queued",
        +          "resolving",
        +          "building",
        +          "validating",
        +          "published",
        +          "failed",
        +          "superseded",
        +          "canceled",
        +          "expired"
        +        ],
        +        "type": "string"
        +      },
        +      "statusUrl": {
        +        "description": "Authenticated HTTP status URL for this build.",
        +        "type": "string"
        +      },
        +      "updatedAt": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "App URL. Present only after successful publication.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "buildId",
        +      "intent",
        +      "state",
        +      "sourceEtag",
        +      "statusUrl",
        +      "attempts",
        +      "acceptedAt",
        +      "updatedAt",
        +      "finishedAt",
        +      "queueDeadline",
        +      "deadline",
        +      "inspectionExpiresAt",
        +      "idempotencyExpiresAt",
        +      "elapsedMs",
        +      "lockState",
        +      "inputDigest"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedOutput schema / properties / error / properties / details
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "enum": [
        +            "not_started",
        +            "may_have_run"
        +          ],
        +          "type": "string"
        +        },
        +        "operationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "reservationId": {
        +          "minLength": 1,
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution",
        +        "operationId"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "execution": {
        +          "const": "may_have_run",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "execution"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
  3. 1 tool update
    • Changedget_app3 fields changed
      • addedOutput schema / properties / api / properties / operations / items / properties / idempotent
        Added value: +{
        +  "description": "True when repeating the call with the same input has no further effect.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / api / properties / operations / items / properties / openWorld
        Added value: +{
        +  "description": "True when the route may reach beyond the app, such as the network. Default true.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / api / properties / operations / items / required
        Previous value: -[
        -  "op",
        -  "method",
        -  "path",
        -  "url",
        -  "readOnly",
        -  "destructive",
        -  "public",
        -  "tool",
        -  "discoveredFrom"
        -]New value: +[
        +  "op",
        +  "method",
        +  "path",
        +  "url",
        +  "readOnly",
        +  "destructive",
        +  "idempotent",
        +  "openWorld",
        +  "public",
        +  "tool",
        +  "discoveredFrom"
        +]
  4. 33 tool updates
    • Addedacknowledge_feedback_responses
    • Addedcancel_app_build
    • Changedcreate_app41 fields changed
      • addedInput schema / properties / expected_revision
        Added value: +{
        +  "description": "Required when ESM source reuses an existing manifest.id. Pass the desired revision from get_app_source.",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "description": "Required for ESM builds: 8–128 visible ASCII characters. Retry the exact request with the same key to recover its build; use a new key for changed source.",
        +  "type": "string"
        +}
      • addedInput schema / properties / migrate_contract
        Added value: +{
        +  "description": "Set true to migrate an existing legacy manifest.id to ESM, together with expected_revision. Source submissions do not roll back contracts. History can explicitly restore a retained validated existing-contract revision.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / module / description
        Previous value: -"ES module source for the app backend. Export a `manifest`; to persist any state its `capabilities.imports` must include \"buildy:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). All persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"buildy:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export `routes` (recommended) or a default `fetch` handler serving `/api/<opName>`, each returning `{ ok: true, value }` or `{ ok: false, error: { kind, message } }`. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"buildy:browser/microphone@1.0\" (getUserMedia audio), \"buildy:browser/camera@1.0\" (getUserMedia video), \"buildy:browser/geolocation@1.0\", \"buildy:browser/clipboard-read@1.0\" (reading the clipboard), \"buildy:browser/display-capture@1.0\" (getDisplayMedia screen share), \"buildy:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"buildy:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"buildy:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"buildy:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"buildy:network/fetch@1.0\" — backend `fetch` is blocked by default and this enables it (public-only: private/loopback/cloud-metadata addresses stay blocked; claim-gated). Restrict it to the hosts the app needs with `manifest.capabilities.fetchHosts` (concrete https hosts, like imageHosts) — default-deny, any non-listed host is blocked; omit to allow any public host. For an endpoint that needs an API key, declare \"buildy:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values host-side, so the key never enters app source or the sandbox; the app OWNER sets the value in the dashboard at `/app/<id>/secrets` and the agent only references the NAME. Never embed API keys in source. To render remote images, list each https host in `manifest.capabilities.imageHosts`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.buildy.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.buildy.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the imageHosts allowlist; neither bypasses it."New value: +"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the declared origins; neither bypasses them."
      • addedInput schema / properties / team_id
        Added value: +{
        +  "description": "Optional destination team id. Only a team owner or admin can create an App there. Omit it to create a personal App.",
        +  "type": "string"
        +}
      • changedInput schema / properties / ui / description
        Previous value: -"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example."New value: +"Under the explicit ESM contract, this is an ES module: import declared client packages and import { api, onStateChange } from \"charming:ui/app@1.0\" to call this app and subscribe to its state changes. Under the existing contract, follow the classic JavaScript rules below. Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.charming.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.charming.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.charming.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example."
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "advisories": {
        +        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "data": {
        +              "additionalProperties": {},
        +              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +              "propertyNames": {
        +                "type": "string"
        +              },
        +              "type": "object"
        +            },
        +            "doc_url": {
        +              "description": "Optional docs pointer for this advisory kind.",
        +              "type": "string"
        +            },
        +            "kind": {
        +              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +              "type": "string"
        +            },
        +            "severity": {
        +              "description": "Severity; omitted advisories are treated as 'info'.",
        +              "enum": [
        +                "info",
        +                "warn"
        +              ],
        +              "type": "string"
        +            },
        +            "summary": {
        +              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +              "type": "string"
        +            },
        +            "userSummary": {
        +              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "kind",
        +            "summary"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "appName": {
        +        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "icon": {
        +        "additionalProperties": false,
        +        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        +        "properties": {
        +          "bg": {
        +            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        +            "type": "string"
        +          },
        +          "emoji": {
        +            "description": "The single emoji rendered on the icon.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "emoji",
        +          "bg"
        +        ],
        +        "type": "object"
        +      },
        +      "id": {
        +        "description": "UUID of the created or updated app.",
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "description": "Indicates success. Errors arrive as content with isError:true.",
        +        "type": "boolean"
        +      },
        +      "revision": {
        +        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shareUrl": {
        +        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        +        "type": "string"
        +      },
        +      "warnings": {
        +        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "id",
        +      "url",
        +      "shareUrl",
        +      "revision",
        +      "icon"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "acceptedAt": {
        +        "type": "string"
        +      },
        +      "activeRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "appId": {
        +        "description": "Existing target app ID, or the created app ID after publication.",
        +        "type": "string"
        +      },
        +      "attempts": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "buildId": {
        +        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +        "type": "string"
        +      },
        +      "deadline": {
        +        "type": "string"
        +      },
        +      "desiredRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "elapsedMs": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "error": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "column": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "line": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "retryable": {
        +            "type": "boolean"
        +          },
        +          "specifier": {
        +            "type": "string"
        +          },
        +          "target": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message",
        +          "retryable"
        +        ],
        +        "type": "object"
        +      },
        +      "finishedAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "idempotencyExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "inputDigest": {
        +        "type": "string"
        +      },
        +      "inspectionExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "intent": {
        +        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +        "type": "string"
        +      },
        +      "lockDigest": {
        +        "type": "string"
        +      },
        +      "lockState": {
        +        "enum": [
        +          "locked",
        +          "unresolved"
        +        ],
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "type": "boolean"
        +      },
        +      "queueDeadline": {
        +        "type": "string"
        +      },
        +      "resolvedDependencies": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "client": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          "server": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          }
        +        },
        +        "required": [
        +          "server",
        +          "client"
        +        ],
        +        "type": "object"
        +      },
        +      "retryAfterSeconds": {
        +        "description": "Wait at least this many seconds before polling again.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "revision": {
        +        "description": "Published app source revision.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "additionalProperties": false,
        +        "description": "Exact accepted source, returned only when include_source is true.",
        +        "properties": {
        +          "description": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "module": {
        +            "type": "string"
        +          },
        +          "styles": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "ui": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "module",
        +          "ui",
        +          "styles",
        +          "description"
        +        ],
        +        "type": "object"
        +      },
        +      "sourceEtag": {
        +        "description": "ETag identifying the immutable input accepted for this build.",
        +        "type": "string"
        +      },
        +      "state": {
        +        "enum": [
        +          "queued",
        +          "resolving",
        +          "building",
        +          "validating",
        +          "published",
        +          "failed",
        +          "superseded",
        +          "canceled",
        +          "expired"
        +        ],
        +        "type": "string"
        +      },
        +      "statusUrl": {
        +        "description": "Authenticated HTTP status URL for this build.",
        +        "type": "string"
        +      },
        +      "updatedAt": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "App URL. Present only after successful publication.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "buildId",
        +      "intent",
        +      "state",
        +      "sourceEtag",
        +      "statusUrl",
        +      "attempts",
        +      "acceptedAt",
        +      "updatedAt",
        +      "finishedAt",
        +      "queueDeadline",
        +      "deadline",
        +      "inspectionExpiresAt",
        +      "idempotencyExpiresAt",
        +      "elapsedMs",
        +      "lockState",
        +      "inputDigest"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedOutput schema / properties / acceptedAt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / activeRevision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / advisories / description
        Previous value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path."
      • addedOutput schema / properties / appId
        Added value: +{
        +  "description": "Existing target app ID, or the created app ID after publication.",
        +  "type": "string"
        +}
      • removedOutput schema / properties / appName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / appName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / attempts
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / buildId
        Added value: +{
        +  "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / deadline
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / desiredRevision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / elapsedMs
        Added value: +{
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "column": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "kind": {
        +      "type": "string"
        +    },
        +    "line": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "retryable": {
        +      "type": "boolean"
        +    },
        +    "specifier": {
        +      "type": "string"
        +    },
        +    "target": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "kind",
        +    "message",
        +    "retryable"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / finishedAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / icon / description
        Previous value: -"The effective home-screen icon stored for the app, after normalization. Read this back to confirm what stuck: if you sent a `manifest.icon` and this is the default `{ emoji: \"🧱\", bg: \"#3b82f6\" }`, your icon was invalid and rejected — see `warnings`."New value: +"The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`."
      • addedOutput schema / properties / idempotencyExpiresAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / inputDigest
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / inspectionExpiresAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / intent
        Added value: +{
        +  "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / lockDigest
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / lockState
        Added value: +{
        +  "enum": [
        +    "locked",
        +    "unresolved"
        +  ],
        +  "type": "string"
        +}
      • removedOutput schema / properties / ok / description
        Removed value: -"Indicates success. Errors arrive as content with isError:true."
      • addedOutput schema / properties / queueDeadline
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / resolvedDependencies
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "client": {
        +      "additionalProperties": {
        +        "type": "string"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "server": {
        +      "additionalProperties": {
        +        "type": "string"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "server",
        +    "client"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / retryAfterSeconds
        Added value: +{
        +  "description": "Wait at least this many seconds before polling again.",
        +  "exclusiveMinimum": 0,
        +  "maximum": 9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / revision
        Added value: +{
        +  "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / source
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Exact accepted source, returned only when include_source is true.",
        +  "properties": {
        +    "description": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "module": {
        +      "type": "string"
        +    },
        +    "styles": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ui": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "module",
        +    "ui",
        +    "styles",
        +    "description"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / sourceEtag
        Added value: +{
        +  "description": "ETag identifying the immutable input accepted for this build.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / state
        Added value: +{
        +  "enum": [
        +    "queued",
        +    "resolving",
        +    "building",
        +    "validating",
        +    "published",
        +    "failed",
        +    "superseded",
        +    "canceled",
        +    "expired"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / statusUrl
        Added value: +{
        +  "description": "Authenticated HTTP status URL for this build.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / updatedAt
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / properties / url / description
        Previous value: -"Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead."New value: +"App URL. Present only after successful publication."
      • removedOutput schema / properties / version
        Removed value: -{
        -  "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.",
        -  "maximum": 9007199254740991,
        -  "minimum": -9007199254740991,
        -  "type": "integer"
        -}
      • changedOutput schema / properties / warnings / description
        Previous value: -"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches, or when a provided `manifest.icon` was invalid and coerced to the default. The write succeeded; fix by adding the backend op, renaming the UI call, or correcting the icon `{ emoji, bg }`."New value: +"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field."
      • changedOutput schema / required
        Previous value: -[
        -  "ok",
        -  "id",
        -  "url",
        -  "shareUrl",
        -  "version",
        -  "icon"
        -]New value: +[
        +  "ok"
        +]
    • Addedcreate_routine
    • Changeddelete_app1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addeddelete_routine
    • Changedget_app25 fields changed
      • addedOutput schema / properties / $schema
        Added value: +{
        +  "description": "Exact dated canonical manifest schema URL. Omitted for legacy apps.",
        +  "enum": [
        +    "https://charm.ing/schema/app-manifest/2026-07-31.json",
        +    "https://charm.ing/schema/app-manifest/2026-09-05.json"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / api / description
        Previous value: -"Full API surface — same shape as `_meta.buildy.api`, but model-facing."New value: +"Full API surface — same shape as `_meta.charming.api`, but model-facing."
      • changedOutput schema / properties / api / properties / operations / items / properties / input / description
        Previous value: -"JSON Schema for the field. Same shape passed to `route.input`/`route.output`."New value: +"JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`."
      • removedOutput schema / properties / api / properties / operations / items / properties / name
        Removed value: -{
        -  "description": "Back-compat alias of `op`. Read either; prefer `op` for new consumers.",
        -  "type": "string"
        -}
      • changedOutput schema / properties / api / properties / operations / items / properties / output / description
        Previous value: -"JSON Schema for the field. Same shape passed to `route.input`/`route.output`."New value: +"JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`."
      • removedOutput schema / properties / appName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / appName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / appVersion / description
        Previous value: -"Author-declared version string for the app (whatever the manifest source set as `manifest.version`, e.g. \"0.0.1\"). Distinct from the concurrency `version` int and from `manifestVersion` (Charming contract date)."New value: +"Canonical apps return decimal String(revision). Legacy apps return their stored effective SemVer."
      • removedOutput schema / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / manifestVersion / description
        Previous value: -"Charming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour."New value: +"Deprecated public contract marker. Canonical apps return null; legacy apps return their stored contract date."
      • changedOutput schema / properties / manifestVersion / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / recentIssues / description
        Previous value: -"Runtime failures recorded against the current app version since it was published (#1133): contract misses, runtime JS errors, CSP violations, and failed API calls. Present only when the current version has at least one such event — absence means a clean render. The same summary is appended to the text content. Fetch full detail with GET /app/:id/activity."New value: +"Runtime failures recorded against the current app revision since it was published (#1133): contract misses, runtime JS errors, CSP violations, and failed API calls. Present only when the current revision has at least one such event — absence means a clean render. The same summary is appended to the text content. Fetch full detail with GET /app/:id/activity."
      • addedOutput schema / properties / recentIssues / properties / counts / properties / externalResourceFailures
        Added value: +{
        +  "description": "Failed external image requests, including failures caught by app code.",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / recentIssues / properties / counts / required
        Previous value: -[
        -  "contractMisses",
        -  "runtimeErrors",
        -  "cspViolations",
        -  "apiFailures",
        -  "appLoadErrors"
        -]New value: +[
        +  "contractMisses",
        +  "runtimeErrors",
        +  "cspViolations",
        +  "apiFailures",
        +  "externalResourceFailures",
        +  "appLoadErrors"
        +]
      • changedOutput schema / properties / recentIssues / properties / examples / items / properties / category / enum
        Previous value: -[
        -  "contractMisses",
        -  "runtimeErrors",
        -  "cspViolations",
        -  "apiFailures",
        -  "appLoadErrors"
        -]New value: +[
        +  "contractMisses",
        +  "runtimeErrors",
        +  "cspViolations",
        +  "apiFailures",
        +  "appLoadErrors",
        +  "externalResourceFailures"
        +]
      • changedOutput schema / properties / recentIssues / properties / examples / items / properties / kind / description
        Previous value: -"Underlying durable event kind: `diag_report` (runtime errors and CSP violations, distinguished by category), `contract_validation` (contract misses), `api_proxy_result` (API failures), or `app_load_error` (caught load failures)."New value: +"Underlying durable event kind: `diag_report` (runtime errors and CSP violations, distinguished by category), `contract_validation` (contract misses), `api_proxy_result` (API failures), `app_load_error` (caught load failures), or `image_proxy_result` (external image failures)."
      • addedOutput schema / properties / recentIssues / properties / sinceRevision
        Added value: +{
        +  "description": "The app revision the issues are attributed to (the current revision at call time). Legacy nulls normalize to 0.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • removedOutput schema / properties / recentIssues / properties / sinceVersion
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "maximum": 9007199254740991,
        -      "minimum": -9007199254740991,
        -      "type": "integer"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "description": "The app version the issues are attributed to (the current version at call time). Null on legacy rows that predate versioning."
        -}
      • changedOutput schema / properties / recentIssues / properties / total / description
        Previous value: -"Issue events counted for the current version, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list."New value: +"Issue events counted for the current revision, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list."
      • changedOutput schema / properties / recentIssues / required
        Previous value: -[
        -  "sinceVersion",
        -  "total",
        -  "counts",
        -  "examples"
        -]New value: +[
        +  "sinceRevision",
        +  "total",
        +  "counts",
        +  "examples"
        +]
      • addedOutput schema / properties / revision
        Added value: +{
        +  "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • removedOutput schema / properties / version
        Removed value: -{
        -  "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.",
        -  "maximum": 9007199254740991,
        -  "minimum": -9007199254740991,
        -  "type": "integer"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "ok",
        -  "id",
        -  "url",
        -  "shareUrl",
        -  "displayName",
        -  "description",
        -  "manifestId",
        -  "version",
        -  "appVersion",
        -  "manifestVersion",
        -  "api"
        -]New value: +[
        +  "ok",
        +  "id",
        +  "url",
        +  "shareUrl",
        +  "displayName",
        +  "description",
        +  "manifestId",
        +  "revision",
        +  "appVersion",
        +  "manifestVersion",
        +  "api"
        +]
    • Addedget_app_build
    • Changedget_app_source17 fields changed
      • addedOutput schema / properties / $schema
        Added value: +{
        +  "description": "Exact dated canonical manifest schema URL. Omitted for legacy apps.",
        +  "enum": [
        +    "https://charm.ing/schema/app-manifest/2026-07-31.json",
        +    "https://charm.ing/schema/app-manifest/2026-09-05.json"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / advisories / description
        Previous value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path."
      • changedOutput schema / properties / appVersion / description
        Previous value: -"Author-declared version string for the app (whatever the manifest source set as `manifest.version`, e.g. \"0.0.1\"). Distinct from the concurrency `version` int and from `manifestVersion` (Charming contract date)."New value: +"Canonical apps return decimal String(revision). Legacy apps return their stored effective SemVer."
      • changedOutput schema / properties / capabilities / properties / imports / description
        Previous value: -"WIT-style capability ids the app requests (e.g. \"buildy:storage/kv@1.0\"). Empty if the app declares none."New value: +"WIT-style capability ids the app requests (e.g. \"charming:storage/kv@1.0\"). Empty if the app declares none."
      • removedOutput schema / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / expiresAt / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / expiresAt / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / manifestVersion / description
        Previous value: -"Charming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour."New value: +"Deprecated public contract marker. Canonical apps return null; legacy apps return their stored contract date."
      • changedOutput schema / properties / manifestVersion / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / revision
        Added value: +{
        +  "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • removedOutput schema / properties / source / properties / styles / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / source / properties / styles / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / source / properties / ui / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / source / properties / ui / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / version
        Removed value: -{
        -  "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.",
        -  "maximum": 9007199254740991,
        -  "minimum": -9007199254740991,
        -  "type": "integer"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "ok",
        -  "id",
        -  "url",
        -  "manifestId",
        -  "sourceManifestId",
        -  "displayName",
        -  "description",
        -  "version",
        -  "appVersion",
        -  "manifestVersion",
        -  "capabilities",
        -  "claimed",
        -  "expiresAt",
        -  "source"
        -]New value: +[
        +  "ok",
        +  "id",
        +  "url",
        +  "manifestId",
        +  "sourceManifestId",
        +  "displayName",
        +  "description",
        +  "revision",
        +  "appVersion",
        +  "manifestVersion",
        +  "capabilities",
        +  "claimed",
        +  "expiresAt",
        +  "source"
        +]
    • Changedlist_app_shares3 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / shares / items / properties / accepted_at / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / shares / items / properties / accepted_at / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedlist_apps9 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / apps / items / properties / appName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / apps / items / properties / appName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / apps / items / properties / capabilities / properties / exports / description
        Previous value: -"Operations this app exposes to other apps via `window.buildy.api(<id>).<export>()`. Use to plan cross-app integrations without round-tripping through get_app_source."New value: +"Operations this app exposes to other apps via `window.charming.api(<id>).<export>()`. Use to plan cross-app integrations without round-tripping through get_app_source."
      • changedOutput schema / properties / apps / items / properties / capabilities / properties / imports / description
        Previous value: -"Capability tokens the app depends on (e.g. \"buildy:storage/kv@1.0\", \"buildy:browser/microphone@1.0\")."New value: +"Capability tokens the app depends on (e.g. \"charming:storage/kv@1.0\", \"charming:browser/microphone@1.0\")."
      • removedOutput schema / properties / apps / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / apps / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / apps / items / properties / revision
        Added value: +{
        +  "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / apps / items / required
        Previous value: -[
        -  "id",
        -  "role",
        -  "displayName",
        -  "description",
        -  "url",
        -  "shareUrl",
        -  "lastUpdatedAt",
        -  "claimed",
        -  "capabilities"
        -]New value: +[
        +  "id",
        +  "role",
        +  "displayName",
        +  "revision",
        +  "description",
        +  "url",
        +  "shareUrl",
        +  "lastUpdatedAt",
        +  "claimed",
        +  "capabilities"
        +]
    • Changedlist_feedback8 fields changed
      • changedInput schema / properties / since / pattern
        Previous value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / cursor / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / cursor / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / items / items / properties / text / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / items / items / properties / text / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / items / items / properties / user_id / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / items / items / properties / user_id / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Addedlist_feedback_responses
    • Addedlist_routines
    • Changedmutate_app1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedquery_app1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addedread_docs
    • Changedrename_app1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addedsearch_templates
    • Changedset_handle1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedset_public3 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / message / description
        Previous value: -"Consequence copy the agent should surface verbatim to the user. WARNS that anyone with the URL can read and overwrite (or wipe) the shared data, with no login and no per-visitor isolation."New value: +"Consequence copy the agent should surface verbatim to the user. It states that anyone with the URL can view the live App with no login but cannot change its data or source."
      • changedOutput schema / properties / public_url / description
        Previous value: -"Public URL for the now-public app. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Anyone can open this URL with no login and read AND write the app's SHARED data. Free of write-capable `?t=` tokens."New value: +"Public URL for the now-Public App. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Anyone can open this URL with no login and view the live App and its data, but cannot change data or source. Free of write-capable `?t=` tokens."
    • Changedset_remixable2 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / public_url / description
        Previous value: -"Public share URL for the now-remixable app. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Visitors opening this URL get their own brand-new editable copy; the original is never mutated. Free of write-capable `?t=` tokens."New value: +"Canonical `/templates/<handle>/<app-name>` Template page when the owner and App have public names. A person who can already read the source App can choose to create an editable copy after signing in; the original is never mutated. Free of write-capable `?t=` tokens."
    • Changedset_starter_prompt3 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / starter_prompt / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / starter_prompt / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Addedset_template
    • Changedshare_app3 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / message / description
        Previous value: -"Consequence copy the agent should surface verbatim: the invitee has no access until they accept, and what they will be able to do once they do."New value: +"Consequence copy the agent should surface verbatim: the invitee has no access until they choose Open app, and what their role permits after the durable grant succeeds."
      • changedOutput schema / properties / status / description
        Previous value: -"Sharing creates an invitation, not access. `pending` = the grantee has a Charming account and must accept (dashboard or invite email). `invited` = the email has no account yet; it becomes a pending share once they register and verify that address. `updated` = the grantee already had a share and re-sharing with a `role` changed it in place (no new invitation, no second email)."New value: +"Sharing creates an invitation, not access. `pending` = the grantee has a Charming account and gets access only when that account chooses Open app. `invited` = the email has no account yet; it becomes a pending share once they register and verify that address. `updated` = the grantee already had a share and re-sharing with a `role` changed it in place (no new invitation, no second email)."
    • Changedsubmit_feedback1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedunset_public1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedunset_remixable1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addedunset_template
    • Changedunshare_app1 field changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedupdate_app42 fields changed
      • changedInput schema / properties / edits / description
        Previous value: -"Edits path. Array of exact-string find/replace operations applied atomically. Pass `expected_version` alongside to gate optimistic-concurrency. Mutually exclusive with full-source fields (`module` / `ui` / `styles`)."New value: +"Edits path. Array of exact-string find/replace operations applied atomically. Pass the last-read revision through `expected_revision` to gate optimistic concurrency. Mutually exclusive with full-source fields (`module` / `ui` / `styles`)."
      • addedInput schema / properties / expected_revision
        Added value: +{
        +  "description": "Revision precondition. Required for every ESM save and for existing-contract edits[]. Pass revision from your last get_app_source response. A new request against a stale desired revision fails with revision_mismatch; an identical idempotent retry returns its original build.",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedInput schema / properties / expected_version / description
        Previous value: -"Required when `edits[]` is present. Pass the `version` from your last get_app_source or update_app response. If the stored version has advanced, the edit is rejected with `version_mismatch` and the current version is surfaced so you can re-read and retry."New value: +"Deprecated compatibility input. Use `expected_revision`; while legacy hosts remain active, expected_version maps to the same revision precondition."
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "description": "Required for ESM saves. Retry the exact request with the same key; use a new key and current expected_revision for a new save.",
        +  "type": "string"
        +}
      • addedInput schema / properties / migrate_contract
        Added value: +{
        +  "description": "Set true only when replacing a legacy app with a complete valid dated manifest and routes contract. Source submissions do not roll back contracts. History can explicitly restore a retained validated existing-contract revision.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / module / description
        Previous value: -"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus route handlers that use env.storage.get/put. default.fetch is optional; Charming supplies a generic 404 handler when it is absent. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`."
      • changedInput schema / properties / ui / description
        Previous value: -"Full-source path only. Optional replacement frontend JavaScript. Same contract as create_app: must (a) populate #app innerHTML BEFORE attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — NOT `api.operation(name, params)` and NOT raw fetch(). The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors. Cap the reading measure on an INNER wrapper only for text-heavy views, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement frontend JavaScript. Follow the create_app rules for the selected contract. Existing-contract UI must (a) populate #app innerHTML BEFORE attaching event listeners, and (b) call operations as `window.charming.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — NOT `api.operation(name, params)` and NOT raw fetch(). The signed-in caller is exposed synchronously as `window.charming.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors. Cap the reading measure on an INNER wrapper only for text-heavy views, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Mutually exclusive with `edits`."
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "advisories": {
        +        "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "data": {
        +              "additionalProperties": {},
        +              "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +              "propertyNames": {
        +                "type": "string"
        +              },
        +              "type": "object"
        +            },
        +            "doc_url": {
        +              "description": "Optional docs pointer for this advisory kind.",
        +              "type": "string"
        +            },
        +            "kind": {
        +              "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +              "type": "string"
        +            },
        +            "severity": {
        +              "description": "Severity; omitted advisories are treated as 'info'.",
        +              "enum": [
        +                "info",
        +                "warn"
        +              ],
        +              "type": "string"
        +            },
        +            "summary": {
        +              "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +              "type": "string"
        +            },
        +            "userSummary": {
        +              "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "kind",
        +            "summary"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "appName": {
        +        "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "icon": {
        +        "additionalProperties": false,
        +        "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.",
        +        "properties": {
        +          "bg": {
        +            "description": "The icon background as a hex color (e.g. \"#1d8a4e\").",
        +            "type": "string"
        +          },
        +          "emoji": {
        +            "description": "The single emoji rendered on the icon.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "emoji",
        +          "bg"
        +        ],
        +        "type": "object"
        +      },
        +      "id": {
        +        "description": "UUID of the created or updated app.",
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "description": "Indicates success. Errors arrive as content with isError:true.",
        +        "type": "boolean"
        +      },
        +      "revision": {
        +        "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shareUrl": {
        +        "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.",
        +        "type": "string"
        +      },
        +      "warnings": {
        +        "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "id",
        +      "url",
        +      "shareUrl",
        +      "revision",
        +      "icon"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "$schema": "https://json-schema.org/draft/2020-12/schema",
        +    "additionalProperties": false,
        +    "properties": {
        +      "acceptedAt": {
        +        "type": "string"
        +      },
        +      "activeRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "appId": {
        +        "description": "Existing target app ID, or the created app ID after publication.",
        +        "type": "string"
        +      },
        +      "attempts": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "buildId": {
        +        "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +        "type": "string"
        +      },
        +      "deadline": {
        +        "type": "string"
        +      },
        +      "desiredRevision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "elapsedMs": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "error": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "column": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "kind": {
        +            "type": "string"
        +          },
        +          "line": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "retryable": {
        +            "type": "boolean"
        +          },
        +          "specifier": {
        +            "type": "string"
        +          },
        +          "target": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "kind",
        +          "message",
        +          "retryable"
        +        ],
        +        "type": "object"
        +      },
        +      "finishedAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "idempotencyExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "inputDigest": {
        +        "type": "string"
        +      },
        +      "inspectionExpiresAt": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "intent": {
        +        "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +        "type": "string"
        +      },
        +      "lockDigest": {
        +        "type": "string"
        +      },
        +      "lockState": {
        +        "enum": [
        +          "locked",
        +          "unresolved"
        +        ],
        +        "type": "string"
        +      },
        +      "ok": {
        +        "const": true,
        +        "type": "boolean"
        +      },
        +      "queueDeadline": {
        +        "type": "string"
        +      },
        +      "resolvedDependencies": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "client": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          "server": {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "propertyNames": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          }
        +        },
        +        "required": [
        +          "server",
        +          "client"
        +        ],
        +        "type": "object"
        +      },
        +      "retryAfterSeconds": {
        +        "description": "Wait at least this many seconds before polling again.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "revision": {
        +        "description": "Published app source revision.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "additionalProperties": false,
        +        "description": "Exact accepted source, returned only when include_source is true.",
        +        "properties": {
        +          "description": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "module": {
        +            "type": "string"
        +          },
        +          "styles": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "ui": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "module",
        +          "ui",
        +          "styles",
        +          "description"
        +        ],
        +        "type": "object"
        +      },
        +      "sourceEtag": {
        +        "description": "ETag identifying the immutable input accepted for this build.",
        +        "type": "string"
        +      },
        +      "state": {
        +        "enum": [
        +          "queued",
        +          "resolving",
        +          "building",
        +          "validating",
        +          "published",
        +          "failed",
        +          "superseded",
        +          "canceled",
        +          "expired"
        +        ],
        +        "type": "string"
        +      },
        +      "statusUrl": {
        +        "description": "Authenticated HTTP status URL for this build.",
        +        "type": "string"
        +      },
        +      "updatedAt": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "App URL. Present only after successful publication.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "ok",
        +      "buildId",
        +      "intent",
        +      "state",
        +      "sourceEtag",
        +      "statusUrl",
        +      "attempts",
        +      "acceptedAt",
        +      "updatedAt",
        +      "finishedAt",
        +      "queueDeadline",
        +      "deadline",
        +      "inspectionExpiresAt",
        +      "idempotencyExpiresAt",
        +      "elapsedMs",
        +      "lockState",
        +      "inputDigest"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedOutput schema / properties / acceptedAt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / activeRevision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / advisories / description
        Previous value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path."
      • addedOutput schema / properties / appId
        Added value: +{
        +  "description": "Existing target app ID, or the created app ID after publication.",
        +  "type": "string"
        +}
      • removedOutput schema / properties / appName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / appName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / attempts
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / buildId
        Added value: +{
        +  "description": "Durable build ID. Use get_app_build to inspect progress or source.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / deadline
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / desiredRevision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / elapsedMs
        Added value: +{
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "column": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "kind": {
        +      "type": "string"
        +    },
        +    "line": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "message": {
        +      "type": "string"
        +    },
        +    "retryable": {
        +      "type": "boolean"
        +    },
        +    "specifier": {
        +      "type": "string"
        +    },
        +    "target": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "kind",
        +    "message",
        +    "retryable"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / finishedAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / icon / description
        Previous value: -"The effective home-screen icon stored for the app, after normalization. Read this back to confirm what stuck: if you sent a `manifest.icon` and this is the default `{ emoji: \"🧱\", bg: \"#3b82f6\" }`, your icon was invalid and rejected — see `warnings`."New value: +"The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`."
      • addedOutput schema / properties / idempotencyExpiresAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / inputDigest
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / inspectionExpiresAt
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / intent
        Added value: +{
        +  "description": "The accepted operation: create, update, migrate, restore, or copy.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / lockDigest
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / lockState
        Added value: +{
        +  "enum": [
        +    "locked",
        +    "unresolved"
        +  ],
        +  "type": "string"
        +}
      • removedOutput schema / properties / ok / description
        Removed value: -"Indicates success. Errors arrive as content with isError:true."
      • addedOutput schema / properties / queueDeadline
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / resolvedDependencies
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "client": {
        +      "additionalProperties": {
        +        "type": "string"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "server": {
        +      "additionalProperties": {
        +        "type": "string"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "server",
        +    "client"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / retryAfterSeconds
        Added value: +{
        +  "description": "Wait at least this many seconds before polling again.",
        +  "exclusiveMinimum": 0,
        +  "maximum": 9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / revision
        Added value: +{
        +  "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / source
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Exact accepted source, returned only when include_source is true.",
        +  "properties": {
        +    "description": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "module": {
        +      "type": "string"
        +    },
        +    "styles": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ui": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "module",
        +    "ui",
        +    "styles",
        +    "description"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / sourceEtag
        Added value: +{
        +  "description": "ETag identifying the immutable input accepted for this build.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / state
        Added value: +{
        +  "enum": [
        +    "queued",
        +    "resolving",
        +    "building",
        +    "validating",
        +    "published",
        +    "failed",
        +    "superseded",
        +    "canceled",
        +    "expired"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / statusUrl
        Added value: +{
        +  "description": "Authenticated HTTP status URL for this build.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / updatedAt
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / properties / url / description
        Previous value: -"Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead."New value: +"App URL. Present only after successful publication."
      • removedOutput schema / properties / version
        Removed value: -{
        -  "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.",
        -  "maximum": 9007199254740991,
        -  "minimum": -9007199254740991,
        -  "type": "integer"
        -}
      • changedOutput schema / properties / warnings / description
        Previous value: -"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches, or when a provided `manifest.icon` was invalid and coerced to the default. The write succeeded; fix by adding the backend op, renaming the UI call, or correcting the icon `{ emoji, bg }`."New value: +"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field."
      • changedOutput schema / required
        Previous value: -[
        -  "ok",
        -  "id",
        -  "url",
        -  "shareUrl",
        -  "version",
        -  "icon"
        -]New value: +[
        +  "ok"
        +]
    • Addedupdate_routine
    • Changedupload_asset2 fields changed
      • addedOutput schema / properties / advisories
        Added value: +{
        +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "data": {
        +        "additionalProperties": {},
        +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "doc_url": {
        +        "description": "Optional docs pointer for this advisory kind.",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
        +        "type": "string"
        +      },
        +      "severity": {
        +        "description": "Severity; omitted advisories are treated as 'info'.",
        +        "enum": [
        +          "info",
        +          "warn"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
        +        "type": "string"
        +      },
        +      "userSummary": {
        +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / url / description
        Previous value: -"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.buildy.assets.getUrl(key)."New value: +"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.charming.assets.getUrl(key)."
  5. 1 tool update
    • Changedupdate_app1 field changed
      • changedInput schema / properties / module / description
        Previous value: -"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus a default.fetch handler that routes /api/<opName> requests using env.storage.get/put. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus route handlers that use env.storage.get/put. default.fetch is optional; Charming supplies a generic 404 handler when it is absent. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."
  6. 1 tool update
    • Changedcreate_app1 field changed
      • changedInput schema / properties / ui / description
        Previous value: -"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the buildy:app-guide prompt for a canonical example."New value: +"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example."
  7. 21 tool updates
    • First observedcreate_app
    • First observeddelete_app
    • First observedget_app
    • First observedget_app_source
    • First observedlist_app_shares
    • First observedlist_apps
    • First observedlist_feedback
    • First observedmutate_app
    • First observedquery_app
    • First observedrename_app
    • First observedset_handle
    • First observedset_public
    • First observedset_remixable
    • First observedset_starter_prompt
    • First observedshare_app
    • First observedsubmit_feedback
    • First observedunset_public
    • First observedunset_remixable
    • First observedunshare_app
    • First observedupdate_app
    • First observedupload_asset

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.