{
  "_comment": "The ONE CLI grammar + help manifest. Canonical copy: clients/grammar.json. Both clients ship a byte-identical copy (acsetra_cli/grammar.json, npm lib/grammar.json); `./d publish` re-syncs the copies and tests/test_grammar_manifest.py fails on drift. Edit the canonical file only.",
  "json_args": [
    "allow_hosts",
    "attrs",
    "config",
    "config_schema",
    "decls",
    "input",
    "items",
    "meta",
    "overrides",
    "parts",
    "patches",
    "props",
    "replace_meta",
    "requires",
    "schema",
    "spec",
    "storage",
    "targets",
    "tests",
    "tree",
    "ops",
    "scopes",
    "origins",
    "form_values",
    "members"
  ],
  "int_args": [
    "at",
    "days",
    "limit",
    "max_bytes",
    "ordinal",
    "rate",
    "retries",
    "timeout",
    "ttl_days",
    "generation"
  ],
  "float_args": [
    "backoff"
  ],
  "bool_args": [
    "all_routes",
    "atomic",
    "auth_flow",
    "autoplay",
    "controls",
    "disabled",
    "enabled",
    "force",
    "if_absent",
    "include_deleted",
    "keep",
    "map",
    "muted",
    "probe",
    "replace",
    "run",
    "tools"
  ],
  "primary_json": {
    "set.put": "meta",
    "set.fetch_url": "meta",
    "set.declare_schema": "schema",
    "css.set_rule": "decls",
    "css.set_styles": "styles",
    "css.set_keyframes": "frames",
    "css.set_breakpoints": "breakpoints",
    "component.set": "tree",
    "component.set_route": "props",
    "behavior.attach": "config",
    "head.set": "attrs",
    "record.transact": "targets",
    "record.commit": "patches",
    "authoring.apply": "ops",
    "resource.register": "members"
  },
  "pos": {
    "set.create": [
      "code"
    ],
    "set.put": [
      "set_code",
      "row_code"
    ],
    "set.declare_schema": [
      "code"
    ],
    "set.fetch_url": [
      "set_code",
      "row_code",
      "url"
    ],
    "set.remove_row": [
      "set_code",
      "row_code"
    ],
    "set.drop": [
      "set_code"
    ],
    "set.describe": [
      "set_code"
    ],
    "set.rows": [
      "set_code"
    ],
    "set.link": [
      "alias",
      "source"
    ],
    "pipe.set": [
      "code"
    ],
    "pipe.show": [
      "code"
    ],
    "pipe.remove": [
      "code"
    ],
    "css.set_class": [
      "code"
    ],
    "css.set_rule": [
      "class_code",
      "variant"
    ],
    "css.clear_rule": [
      "class_code"
    ],
    "css.attach": [
      "class_code",
      "target"
    ],
    "css.detach": [
      "code"
    ],
    "css.describe": [
      "class_code"
    ],
    "css.resolve": [
      "page"
    ],
    "css.set_keyframes": [
      "name"
    ],
    "css.clear_keyframes": [
      "name"
    ],
    "css.remove_class": [
      "code"
    ],
    "asset.add": [
      "code",
      "kind"
    ],
    "asset.attach": [
      "asset",
      "slot"
    ],
    "asset.detach": [
      "code"
    ],
    "asset.describe": [
      "code"
    ],
    "asset.resolve": [
      "page"
    ],
    "behavior.add": [
      "code"
    ],
    "behavior.set_enabled": [
      "code",
      "enabled"
    ],
    "behavior.remove": [
      "code"
    ],
    "behavior.attach": [
      "behavior_code",
      "target"
    ],
    "behavior.set_attachment_enabled": [
      "code",
      "enabled"
    ],
    "behavior.detach": [
      "code"
    ],
    "behavior.describe": [
      "code"
    ],
    "component.set": [
      "code"
    ],
    "component.remove": [
      "code"
    ],
    "component.set_route": [
      "code",
      "component"
    ],
    "component.remove_route": [
      "code"
    ],
    "component.describe": [
      "code"
    ],
    "head.set": [
      "code"
    ],
    "head.remove": [
      "code"
    ],
    "record.get": [
      "set_code",
      "code"
    ],
    "record.commit": [
      "set_code",
      "code"
    ],
    "record.transact": [
      "operation_id"
    ],
    "record.replay": [
      "operation_namespace",
      "operation_id"
    ],
    "schedule.set": [
      "code",
      "pipeline",
      "cron"
    ],
    "schedule.show": [
      "code"
    ],
    "schedule.occurrences": [
      "code"
    ],
    "schedule.pause": [
      "code"
    ],
    "schedule.resume": [
      "code"
    ],
    "schedule.run_now": [
      "code"
    ],
    "schedule.remove": [
      "code"
    ],
    "authoring.apply": [
      "operation_id"
    ],
    "connection.set": [
      "service"
    ],
    "connection.list": [],
    "resource.register": [
      "code"
    ],
    "resource.plan": [
      "code"
    ],
    "resource.erase": [
      "code",
      "operation_id"
    ]
  },
  "planes": [
    "asset",
    "behavior",
    "component",
    "css",
    "head",
    "record",
    "schedule",
    "set",
    "authoring",
    "connection",
    "browser"
  ],
  "short": {
    "w": "writes",
    "k": "keys",
    "u": "url",
    "f": "body_from",
    "H": "handler",
    "X": "method",
    "s": "spec",
    "l": "label",
    "i": "input"
  },
  "groups": {
    "set": [
      [
        "create",
        "set.create"
      ],
      [
        "put",
        "set.put"
      ],
      [
        "declare_schema",
        "set.declare_schema"
      ],
      [
        "fetch_url",
        "set.fetch_url"
      ],
      [
        "remove_row",
        "set.remove_row"
      ],
      [
        "drop",
        "set.drop"
      ],
      [
        "link",
        "set.link"
      ],
      [
        "sources",
        "set.sources"
      ],
      [
        "list",
        "set.list"
      ],
      [
        "describe",
        "set.describe"
      ],
      [
        "rows",
        "set.rows"
      ],
      [
        "validate",
        "set.validate"
      ]
    ],
    "css": [
      [
        "init",
        "css.init"
      ],
      [
        "set_class",
        "css.set_class"
      ],
      [
        "set_rule",
        "css.set_rule"
      ],
      [
        "set_styles",
        "css.set_styles"
      ],
      [
        "clear_rule",
        "css.clear_rule"
      ],
      [
        "remove_class",
        "css.remove_class"
      ],
      [
        "set_keyframes",
        "css.set_keyframes"
      ],
      [
        "clear_keyframes",
        "css.clear_keyframes"
      ],
      [
        "set_breakpoints",
        "css.set_breakpoints"
      ],
      [
        "list_breakpoints",
        "css.list_breakpoints"
      ],
      [
        "attach",
        "css.attach"
      ],
      [
        "detach",
        "css.detach"
      ],
      [
        "list_classes",
        "css.list_classes"
      ],
      [
        "list_rules",
        "css.list_rules"
      ],
      [
        "list_attachments",
        "css.list_attachments"
      ],
      [
        "describe",
        "css.describe"
      ],
      [
        "resolve",
        "css.resolve"
      ],
      [
        "validate",
        "css.validate"
      ]
    ],
    "asset": [
      [
        "init",
        "asset.init"
      ],
      [
        "add",
        "asset.add"
      ],
      [
        "attach",
        "asset.attach"
      ],
      [
        "detach",
        "asset.detach"
      ],
      [
        "list",
        "asset.list"
      ],
      [
        "list_attachments",
        "asset.list_attachments"
      ],
      [
        "describe",
        "asset.describe"
      ],
      [
        "resolve",
        "asset.resolve"
      ],
      [
        "validate",
        "asset.validate"
      ],
      [
        "check",
        "asset.check"
      ]
    ],
    "behavior": [
      [
        "init",
        "behavior.init"
      ],
      [
        "add",
        "behavior.add"
      ],
      [
        "set_enabled",
        "behavior.set_enabled"
      ],
      [
        "remove",
        "behavior.remove"
      ],
      [
        "attach",
        "behavior.attach"
      ],
      [
        "set_attachment_enabled",
        "behavior.set_attachment_enabled"
      ],
      [
        "detach",
        "behavior.detach"
      ],
      [
        "list",
        "behavior.list"
      ],
      [
        "list_attachments",
        "behavior.list_attachments"
      ],
      [
        "describe",
        "behavior.describe"
      ],
      [
        "validate",
        "behavior.validate"
      ]
    ],
    "component": [
      [
        "init",
        "component.init"
      ],
      [
        "set",
        "component.set"
      ],
      [
        "remove",
        "component.remove"
      ],
      [
        "set_route",
        "component.set_route"
      ],
      [
        "remove_route",
        "component.remove_route"
      ],
      [
        "list",
        "component.list"
      ],
      [
        "list_routes",
        "component.list_routes"
      ],
      [
        "describe",
        "component.describe"
      ],
      [
        "validate",
        "component.validate"
      ]
    ],
    "head": [
      [
        "init",
        "head.init"
      ],
      [
        "set",
        "head.set"
      ],
      [
        "remove",
        "head.remove"
      ],
      [
        "list",
        "head.list"
      ],
      [
        "validate",
        "head.validate"
      ]
    ],
    "record": [
      [
        "get",
        "record.get"
      ],
      [
        "commit",
        "record.commit"
      ],
      [
        "transact",
        "record.transact"
      ],
      [
        "replay",
        "record.replay"
      ]
    ],
    "schedule": [
      [
        "set",
        "schedule.set"
      ],
      [
        "list",
        "schedule.list"
      ],
      [
        "show",
        "schedule.show"
      ],
      [
        "occurrences",
        "schedule.occurrences"
      ],
      [
        "pause",
        "schedule.pause"
      ],
      [
        "resume",
        "schedule.resume"
      ],
      [
        "run_now",
        "schedule.run_now"
      ],
      [
        "remove",
        "schedule.remove"
      ]
    ],
    "authoring": [
      [
        "apply",
        "authoring.apply"
      ]
    ],
    "connection": [
      [
        "set",
        "connection.set"
      ],
      [
        "list",
        "connection.list"
      ]
    ],
    "resource": [
      [
        "register",
        "resource.register"
      ],
      [
        "plan",
        "resource.plan"
      ],
      [
        "erase",
        "resource.erase"
      ]
    ]
  },
  "group_aliases": {
    "css": {
      "class": "set_class",
      "rule": "set_rule"
    }
  },
  "ops_doc": {
    "set.create": {
      "desc": "create a value set (mint your own plane/registry) \u2014 born a keyed record set: point reads, field patches, revisions/etags, durable receipts; never the legacy whole-collection path",
      "kw": [
        "label",
        "kind",
        "schema"
      ]
    },
    "set.put": {
      "desc": "write/merge a row (--json is the row meta). Every set you mint is a keyed record set: each sent key lands as ONE atomic field patch (disjoint edits compose, a stale edit of a changed field conflicts); MERGES unless --replace; --etag makes the write conditional",
      "kw": [
        "label",
        "ordinal",
        "enabled",
        "replace",
        "etag"
      ]
    },
    "set.declare_schema": {
      "desc": "declare/replace a set's row-meta JSON-Schema contract",
      "kw": []
    },
    "set.fetch_url": {
      "desc": "import remote TEXT into a row (SSRF-guarded https GET)",
      "kw": [
        "key",
        "label",
        "max_bytes",
        "allow_hosts",
        "replace",
        "ordinal"
      ]
    },
    "set.remove_row": {
      "desc": "delete one row from a set",
      "kw": []
    },
    "set.drop": {
      "desc": "drop a whole value set",
      "kw": [
        "force"
      ]
    },
    "set.link": {
      "desc": "wire another app's set (same org) in under a local alias \u2014 reads AND writes follow to the source (source is '<scope-path>/<set-code>'; unlink with set drop)",
      "kw": [
        "label"
      ]
    },
    "set.sources": {
      "desc": "the data catalog: every linkable set outside this scope, with sampled field names",
      "kw": []
    },
    "set.list": {
      "desc": "list value sets at the scope",
      "kw": []
    },
    "set.describe": {
      "desc": "show a set's schema + metadata",
      "kw": []
    },
    "set.rows": {
      "desc": "list a set's rows",
      "kw": []
    },
    "set.validate": {
      "desc": "re-check every set (grammar, bounds, declared schema)",
      "kw": []
    },
    "css.init": {
      "desc": "bootstrap the css plane for a scope",
      "kw": []
    },
    "css.set_class": {
      "desc": "create/define a css class (identity)",
      "kw": [
        "label",
        "description",
        "enabled",
        "ordinal"
      ]
    },
    "css.set_rule": {
      "desc": "set a class's declarations for a variant (--json is the decls)",
      "kw": [
        "ordinal",
        "replace",
        "context",
        "relation"
      ]
    },
    "css.set_styles": {
      "desc": "set many classes/variants in one call (--json is the styles spec; flat decls beside variant blocks, \"a > b\" context keys)",
      "kw": [
        "replace"
      ]
    },
    "css.clear_rule": {
      "desc": "clear a class's rule (one variant or all)",
      "kw": [
        "variant",
        "context",
        "relation"
      ]
    },
    "css.remove_class": {
      "desc": "delete a class completely (row, rules, attachments)",
      "kw": []
    },
    "css.set_keyframes": {
      "desc": "author validated @keyframes (--json is the frames map)",
      "kw": []
    },
    "css.clear_keyframes": {
      "desc": "remove an authored @keyframes row",
      "kw": []
    },
    "css.set_breakpoints": {
      "desc": "declare responsive breakpoints usable as variants (--json is {name: media query})",
      "kw": []
    },
    "css.list_breakpoints": {
      "desc": "list declared breakpoints",
      "kw": []
    },
    "css.attach": {
      "desc": "attach a class to a surface (component:/instance:/part:/raw:/page:)",
      "kw": [
        "label",
        "ordinal"
      ]
    },
    "css.detach": {
      "desc": "remove a css attachment",
      "kw": []
    },
    "css.list_classes": {
      "desc": "list css classes",
      "kw": []
    },
    "css.list_rules": {
      "desc": "list css rules",
      "kw": [
        "class_code"
      ]
    },
    "css.list_attachments": {
      "desc": "list css attachments",
      "kw": []
    },
    "css.describe": {
      "desc": "show a class's rules + attachments",
      "kw": []
    },
    "css.resolve": {
      "desc": "show the resolved cascade for a page",
      "kw": [
        "app"
      ]
    },
    "css.validate": {
      "desc": "re-check every class/rule/attachment",
      "kw": []
    },
    "asset.init": {
      "desc": "bootstrap the asset plane",
      "kw": []
    },
    "asset.add": {
      "desc": "register a media asset (image/svg/icon/video/iframe)",
      "kw": [
        "url",
        "name",
        "alt",
        "provider",
        "svg",
        "fit",
        "controls",
        "muted",
        "autoplay",
        "poster",
        "ordinal",
        "storage",
        "probe"
      ]
    },
    "asset.attach": {
      "desc": "fill a named slot on a target with an asset; --target takes the one durable target spelling (component:/instance:/part:/raw:/page:, the same shape css attach uses) INSTEAD of the page/component/raw/type/part flags",
      "kw": [
        "page",
        "component",
        "raw",
        "type_",
        "part",
        "target",
        "app",
        "ordinal"
      ]
    },
    "asset.detach": {
      "desc": "remove an asset attachment",
      "kw": []
    },
    "asset.list": {
      "desc": "list assets",
      "kw": []
    },
    "asset.list_attachments": {
      "desc": "list asset attachments",
      "kw": []
    },
    "asset.describe": {
      "desc": "show an asset + its attachments",
      "kw": []
    },
    "asset.resolve": {
      "desc": "show resolved asset slots for a page",
      "kw": [
        "app"
      ]
    },
    "asset.validate": {
      "desc": "re-check every asset/attachment (shape only)",
      "kw": []
    },
    "asset.check": {
      "desc": "probe registered asset URLs (HEAD) for liveness",
      "kw": [
        "code",
        "allow_hosts"
      ]
    },
    "behavior.init": {
      "desc": "bootstrap the behavior plane",
      "kw": []
    },
    "behavior.add": {
      "desc": "add a browser ability (mount(ctx) JS body via -b -)",
      "kw": [
        "label",
        "config_schema",
        "enabled",
        "ordinal"
      ],
      "body": true
    },
    "behavior.set_enabled": {
      "desc": "enable/disable a behavior definition",
      "kw": []
    },
    "behavior.remove": {
      "desc": "remove a behavior",
      "kw": []
    },
    "behavior.attach": {
      "desc": "mount a behavior on a target (--json is the config)",
      "kw": [
        "label",
        "enabled",
        "ordinal"
      ]
    },
    "behavior.set_attachment_enabled": {
      "desc": "enable/disable one placed mount",
      "kw": []
    },
    "behavior.detach": {
      "desc": "remove a behavior attachment; refused when it would leave an enabled behavior with nothing that still mounts (add + verify the replacement first, or --force)",
      "kw": [
        "force"
      ]
    },
    "behavior.list": {
      "desc": "list behaviors",
      "kw": []
    },
    "behavior.list_attachments": {
      "desc": "list behavior attachments",
      "kw": []
    },
    "behavior.describe": {
      "desc": "show a behavior + its mounts",
      "kw": []
    },
    "behavior.validate": {
      "desc": "re-check every behavior/attachment",
      "kw": []
    },
    "component.init": {
      "desc": "bootstrap the component+route plane",
      "kw": []
    },
    "component.set": {
      "desc": "author a component's node tree (--json is the tree); --props declares the props this component accepts (prop -> {type} or default)",
      "kw": [
        "parts",
        "props",
        "label",
        "ordinal"
      ]
    },
    "component.remove": {
      "desc": "remove a component",
      "kw": []
    },
    "component.set_route": {
      "desc": "mount a component on a page (--json is route props); --page => page-scoped visibility wrapper (navigation shows/hides; without it extra routes STACK); --pattern => path pattern 'watch/{id}' mapping a served path onto the page (effective page defaults to the route code for patterned routes); --overrides patches THIS placement only, keyed 'raw:<id>' / 'part:<component>:<part>' -> {text, attrs} (the way one mount of a shared component gets its own lede)",
      "kw": [
        "instance",
        "overrides",
        "page",
        "pattern",
        "label",
        "ordinal"
      ]
    },
    "component.remove_route": {
      "desc": "remove a route",
      "kw": []
    },
    "component.list": {
      "desc": "list components",
      "kw": []
    },
    "component.list_routes": {
      "desc": "list routes (pages)",
      "kw": []
    },
    "component.describe": {
      "desc": "show a component's refs + mounting routes",
      "kw": []
    },
    "component.validate": {
      "desc": "re-check every tree + ref",
      "kw": []
    },
    "head.init": {
      "desc": "bootstrap document_head (title/viewport/favicon)",
      "kw": []
    },
    "head.set": {
      "desc": "set/merge a <head> entry (--json is its attrs)",
      "kw": [
        "tag",
        "text",
        "enabled",
        "ordinal",
        "label"
      ]
    },
    "head.remove": {
      "desc": "remove a head entry",
      "kw": []
    },
    "head.list": {
      "desc": "list head entries in order",
      "kw": []
    },
    "head.validate": {
      "desc": "re-check every head entry",
      "kw": []
    },
    "record.get": {
      "desc": "ONE row by code with its record_id / revision / etag (the keyed point read)",
      "kw": [
        "include_deleted"
      ]
    },
    "record.commit": {
      "desc": "atomic commit on one record (--json is the patches list: [{op:set|unset|increment|add_unique|remove_value|test, path:'/field', value}]); action create|patch|replace|delete|restore; expected_etag makes it conditional; items=[\u2026] is a one-row batch with per-item outcomes",
      "kw": [
        "action",
        "tests",
        "items",
        "batch_policy",
        "expected_etag",
        "expected_revision",
        "operation_id",
        "label",
        "ordinal",
        "replace_meta",
        "if_absent"
      ]
    },
    "record.transact": {
      "desc": "several records, ONE operation: <operation_id> names it (a uuid you mint; retry = replay), --json is the targets list [{set_code, code, action?, patches?|items?, expected_etag?, requires?:[{target, item_id?}]}]; --atomic is all-or-none, else one outcome per target",
      "kw": [
        "atomic"
      ]
    },
    "record.replay": {
      "desc": "the stored terminal result of an operation (namespace + id)",
      "kw": []
    },
    "schedule.set": {
      "desc": "create/update an org-catalog five-field cron schedule for the explicit target scope",
      "scope": "required",
      "kw": [
        "label",
        "timezone",
        "input",
        "overlap",
        "misfire",
        "disabled"
      ]
    },
    "schedule.list": {
      "desc": "list schedules for this target; --all-routes lists the org catalog",
      "scope": "required",
      "kw": [
        "all_routes"
      ]
    },
    "schedule.show": {
      "desc": "show one target-addressed schedule",
      "scope": "required",
      "kw": []
    },
    "schedule.occurrences": {
      "desc": "list durable occurrence and launch receipts, newest first",
      "scope": "required",
      "kw": [
        "limit"
      ]
    },
    "schedule.pause": {
      "desc": "pause one schedule and clear its next firing",
      "scope": "required",
      "kw": []
    },
    "schedule.resume": {
      "desc": "revalidate and resume one schedule, rebinding its routed pipeline when detached",
      "scope": "required",
      "kw": []
    },
    "schedule.run_now": {
      "desc": "enqueue once without moving the cron clock; --operation-id makes retries idempotent",
      "scope": "required",
      "kw": [
        "operation_id"
      ]
    },
    "schedule.remove": {
      "desc": "delete one schedule and its occurrence history",
      "scope": "required",
      "kw": []
    },
    "authoring.apply": {
      "desc": "atomically author one scope; --json is a list of {op,args}. Reuse the operation UUID on retries; a changed request with that UUID is refused. Requires edit access.",
      "kw": [],
      "scope": "required"
    },
    "connection.set": {
      "desc": "configure external OAuth using public HTTPS endpoints and org-vault variable names; credentials never enter app rows. Routes are available without restart.",
      "kw": [
        "enabled",
        "authorize_url",
        "token_url",
        "scopes",
        "client_id",
        "header",
        "scheme",
        "config"
      ],
      "scope": "optional"
    },
    "connection.list": {
      "desc": "list external connection definitions in this scope subtree (configuration, never tokens)",
      "kw": [],
      "scope": "optional"
    },
    "resource.register": {
      "desc": "register typed owned resources or shared references in one scope; --json is the members array",
      "kw": [],
      "scope": "required"
    },
    "resource.plan": {
      "desc": "preview permanent erasure, dependencies, retention and a content-sensitive plan hash",
      "kw": [],
      "scope": "required"
    },
    "resource.erase": {
      "desc": "permanently erase the unchanged preview; confirm=erase, stable operation UUID for retries",
      "kw": [
        "plan_hash",
        "confirm"
      ],
      "scope": "required"
    }
  },
  "verbs_doc": {
    "signin": {
      "usage": "signin [--api URL] [--no-browser]",
      "desc": "device-flow sign-in; caches a token"
    },
    "whoami": {
      "usage": "whoami",
      "desc": "show the signed-in user + workspace"
    },
    "workspaces": {
      "usage": "workspaces [--use SLUG]",
      "desc": "list workspaces; --use switches the active one"
    },
    "use": {
      "usage": "use <slug>",
      "desc": "set the active workspace for this project"
    },
    "logout": {
      "usage": "logout",
      "desc": "forget the cached token"
    },
    "usage": {
      "usage": "usage [--days N]",
      "desc": "metered usage vs your plan caps"
    },
    "tokens": {
      "usage": "tokens [new [--name N] | list | revoke <id>]",
      "desc": "manage API tokens"
    },
    "docs": {
      "usage": "docs pull [-S scope]",
      "desc": "refresh CLAUDE.md + AGENTS.md + .runner/docs/* (this app's context)"
    },
    "grammar": {
      "usage": "grammar [<op>] [--json]",
      "desc": "dump the installed CLI grammar as JSON (local manifest; no network). With <op>, just that operation."
    },
    "dev": {
      "usage": "dev <app> [--no-browser]",
      "desc": "open your app's hosted surface in the browser"
    },
    "open": {
      "usage": "open <scope> [--reuse|--new|--background] [--device ID] [--no-fallback]",
      "desc": "open or reuse a scope in paired Runner Chrome; falls back to a cold browser URL"
    },
    "focus": {
      "usage": "focus <scope> [--device ID]",
      "desc": "move to an existing scope tab, creating it when needed"
    },
    "notify": {
      "usage": "notify <scope> [--title T] [--message M] [--new] [--device ID]",
      "desc": "raise a native notification whose click opens or reuses the scope"
    },
    "tabs": {
      "usage": "tabs [--device ID]",
      "desc": "list open Runner scope tabs from the paired browser only"
    },
    "devices": {
      "usage": "devices",
      "desc": "list paired browser devices and live status"
    },
    "checkout": {
      "usage": "checkout <app> [-o dir] [--force]",
      "desc": "materialize a scope subtree as local files in .tmp/ (read-only; grep/edit, write back with the typed verbs)"
    },
    "app": {
      "usage": "app create <name> [--label L]  |  app list",
      "desc": "create / list app scopes"
    },
    "apps": {
      "usage": "apps",
      "desc": "list app scopes (alias of `app list`)"
    },
    "auth": {
      "usage": "auth <app> [--off]  |  auth list [scope]",
      "desc": "gate an app behind home.acsetra.com sign-in \u2014 signed-in visitors are enrolled as members on first visit; --off lifts the gate (no secrets, reuses the main-site realm)"
    },
    "ls": {
      "usage": "ls [-S scope]",
      "desc": "list value sets"
    },
    "inspect": {
      "usage": "inspect [<set>] [-S scope]",
      "desc": "read a set's rows (alias: i); no set => list"
    },
    "read": {
      "usage": "read <code> [-S scope]",
      "desc": "read a value set (me_* = your own per-user zone)"
    },
    "show": {
      "usage": "show <pipeline>",
      "desc": "reconstruct a pipeline from its rows"
    },
    "run": {
      "usage": "run <pipeline> [-i '{json}'] [--at scope | -S scope]",
      "desc": "test-run a pipeline; --at/-S deterministically selects the deepest ancestor route, while an unscoped run selects the globally deepest route and errors on a deepest tie"
    },
    "runs": {
      "usage": "runs <launch_id>",
      "desc": "poll a launch's status/output"
    },
    "compile": {
      "usage": "compile <app>",
      "desc": "link the bundle + cross-plane diagnostics + content hash"
    },
    "doctor": {
      "usage": "doctor <app>",
      "desc": "full static gate over the subtree: validate every plane + link refs + compile code (non-zero exit = broken)"
    },
    "verify": {
      "usage": "verify <app> [--map] [--run]",
      "desc": "render-level check: dead wiring, behavior\u2194surface mismatch, ctx typos. --map = per-node design-as-data; --run executes mount(ctx) and catches throws"
    },
    "pipe": {
      "usage": "pipe <code> -S <scope> [-w code:label | -w scope/code] [--rate N] [--timeout N] [--keep]\n       [--cost-class free|metered|paid] [--requires '{\"approval\":true,\"per_user_daily\":N,\"owner_of\":\"<set>\"}']\n       pipe show <code>  |  pipe list  |  pipe catalog [-S scope] [--tools]  |  pipe remove <code>",
      "desc": "create/upsert a pipeline envelope (resets workers unless --keep). `pipe remove` detaches TERMINAL run history onto the launches (audit preserved) and refuses only ACTIVE launches. `pipe catalog` = the live machine-readable org catalog (accepts/reads/writes/calls/callers/schedules/cost per pipeline; --tools adds OpenAI function schemas) \u2014 feed agents THIS, never a hand-synced registry set. `--requires` gates are enforced at admission for EVERY producer (browser, CLI, schedules, pipeline tier); a per_user_daily cap makes /run answer `remaining`"
    },
    "pipes": {
      "usage": "pipes",
      "desc": "list pipelines (alias of `pipe list`)"
    },
    "w": {
      "usage": "w <pipeline> <tier> [flags]  [-w code | -w scope/code] [--at N] [-S scope]",
      "desc": "add a worker to a pipeline (alias: work). -w names the set its output lands in: a set of this scope, or scope/code = an EXISTING set of another scope of this org (a `set link` alias writes through)",
      "extra": [
        "Tiers:",
        "  snippet   -b <code|->                       DB-isolated Python (sets output / output={'rows':[\u2026]})",
        "  internal  -H/--handler NAME                 a vetted internal handler",
        "  httpx     -u/--url URL [-X METHOD]          call a service; keys injected server-side",
        "            [-k/--keys a,b] [-f/--body-from K]",
        "  read      --set CODE [--mode latest]        resolve a value set into the run data",
        "            [--key K] [--as NAME] [--read-scope S]",
        "  llm       [--provider openai] [--model M]   one model call (keys injected server-side)",
        "            [--system-from K] [--user-from ask] [-k/--keys a,b]",
        "  pipeline  -P/--calls CODE|SCOPE/CODE        run an EXISTING pipeline of this org as this step",
        "            (a real child launch; -s '{\"pick\":[\u2026],\"input\":{\u2026}}' shapes its input)",
        "  batch     -s '{\"over\":\"items\",\"each\":{\"tier\":\u2026,\"spec\":{\u2026}},\"concurrency\":8}'",
        "            ONE run fans a sub-worker over a list: bounded (default 8, max 32), one item's",
        "            failure is its own {error,index}, the answer counts ok/failed \u2014 never loop ctx.run",
        "Every tier: -s '{\"as\":\"key\"}' lands the worker's WHOLE payload under one bag key;",
        "  '{\"when\":{\"<bag key>\": value|[values]}}' gates the step on the bag (skip, never force-run).",
        "snippet also: '{\"reads\":[keys]}' hands the snippet ONLY those bag keys (+ __ stamps, item).",
        "llm also: messages_from (full chat array from the bag), response_format, reasoning (effort),",
        "  max_tokens (clamped to the model's registry ceiling) \u2014 no more raw-httpx model calls.",
        "read also: key_from, fields:[\u2026], where/where_from (mode all), default, transient.",
        "Errors: RAISE is the one error channel \u2014 a raised worker fails the launch with a receipt;",
        "  output={'error':\u2026} is just data and settles nothing.",
        "The full per-tier key map lives in the manifest's worker_spec (CI-checked against the kernel).",
        "Cross-tier -s keys (census wave 2): pick/drop (payload projection at the merge),",
        "  retry (per-worker attempts), until/every/max_polls (poll the SAME worker until a",
        "  condition matches \u2014 no more time.sleep in snippets), writes '{\"set\":\"bag key\"}'",
        "  (multi-set atomic writes from ONE worker), writes_to_from (data-driven target),",
        "  emit (pipeline-tier output contract), imports (snippet_lib modules; `import",
        "  runner_lib` \u2014 the framework stdlib \u2014 is always available).",
        "Zero-worker pipelines are refused at admission; terminal output carries __verdict",
        "  (steps/ran/skipped/rows_written/sets) so done \u2260 silently-did-nothing."
      ]
    },
    "op": {
      "usage": "op <name> [--json '{full args bag}'] [--flag value] [-S scope]",
      "desc": "call any op directly. Here --json IS the full args bag (never a single arg)."
    }
  },
  "verb_aliases": {
    "i": "inspect",
    "work": "w",
    "login": "signin",
    "signout": "logout",
    "co": "checkout"
  },
  "doc_sections": {
    "_comment": "Documentation coverage map for scripts/render_hosted_cli_docs.py: every group in `groups` and every verb in `verbs_doc` must be assigned to EXACTLY ONE hosted doc (design.md or backend.md). Tests reject duplicates and omissions.",
    "design": {
      "groups": [
        "component",
        "css",
        "asset",
        "behavior",
        "head"
      ],
      "verbs": [
        "dev",
        "open",
        "focus",
        "compile",
        "doctor",
        "verify"
      ]
    },
    "backend": {
      "groups": [
        "set",
        "record",
        "schedule",
        "authoring",
        "connection",
        "resource"
      ],
      "verbs": [
        "signin",
        "whoami",
        "workspaces",
        "use",
        "logout",
        "usage",
        "tokens",
        "docs",
        "grammar",
        "notify",
        "tabs",
        "devices",
        "checkout",
        "app",
        "apps",
        "auth",
        "ls",
        "inspect",
        "read",
        "show",
        "run",
        "runs",
        "pipe",
        "pipes",
        "w",
        "op"
      ]
    }
  },
  "worker_spec": {
    "_comment": "Per-tier worker spec keys \u2014 THE discoverability source of truth for what a worker's -s '{json}' understands. tests/test_grammar_manifest.py scans the kernel for every spec key it reads and FAILS when one is missing here (the when/reads-invisible-for-weeks class). _common keys apply to every tier.",
    "_common": {
      "as": "land this worker's ENTIRE payload under this ONE bag key instead of merging top-level (the universal namespacing rule; read/llm resolve `as` in-tier as the rows/reply key)",
      "when": "{\"<bag key>\": value | [values]} \u2014 run this step only while every named key's bag value matches; otherwise SKIP it (no attempt, cursor advances). Authored spec, never a client flag",
      "pick": "[keys] \u2014 keep ONLY these keys of a dict payload before it merges/nests (read/llm resolve their own shape; on the pipeline tier `pick` narrows the CHILD's input \u2014 use `emit` for its output)",
      "drop": "[keys] \u2014 remove these keys from the payload before it merges, so a provider's 41-key envelope never enters the bag (retires the terminal null-out ritual)",
      "retry": "per-worker retries: an int, or {\"attempts\": N, \"backoff\": s} \u2014 overrides the pipeline policy for THIS step only (max 10)",
      "until": "{\"<bag key>\": value | [values]} \u2014 POLL-UNTIL: re-run this worker until the condition matches its merged result (the `when` grammar); exhausting max_polls is a LOUD error, never a silent miss",
      "every": "seconds between polls (with `until`; default 5, clamped 1\u2013300)",
      "max_polls": "poll ceiling (with `until`; default 12, max 60)",
      "writes": "{\"<set> | <scope>/<set>\": \"<bag key>\", \u2026} \u2014 MULTI-SET WRITES: each named set receives that key of this worker's result (a list writes rows, a dict one envelope, a missing key skips), atomically in the same step; own-scope targets are minted at authoring, cross-scope targets must exist. Kills the one-writer-per-set stub tail",
      "writes_to_from": "bag key naming the target set at RUN time ('<code>' or '<scope>/<code>' of an EXISTING same-org set) \u2014 this worker's own result lands there; an empty value skips. The data-driven writes_to (no more N cloned router workers)"
    },
    "snippet": {
      "body": "the Python source \u2014 reads `input`, sets `output` (one row) or output={\"rows\":[\u2026]} (many); DB-isolated subprocess",
      "reads": "[keys] \u2014 hand the snippet ONLY these bag keys (plus the __ stamps and a batch `item`); a pass-through stub stops serialising the whole multi-MB bag",
      "imports": "[modules] \u2014 rows of the scope's `snippet_lib` set (row code = module name, meta.body = Python source), materialized beside the body so `import <name>` works; `import runner_lib` (the framework stdlib: sv, rows_of, meta_of, latest, cur, by_code, sha, slug, iso, clamp, chunk, \u2026) is ALWAYS available with no spec change"
    },
    "read": {
      "set": "value set CODE to resolve",
      "scope": "read a set of ANOTHER scope of this org (default: nearest set at the launch scope)",
      "mode": "latest (one row) | all (the list)",
      "key": "literal row key \u2014 ONE indexed point read",
      "key_from": "dotted bag key(s), first non-empty wins \u2014 one authored worker serves every row",
      "shape": "\"row\" answers the full row with revision/etag (record heads)",
      "fields": "[\u2026] \u2014 carry ONLY these meta keys into the bag (minimal-data projection)",
      "omit": "[keys] or comma-separated keys \u2014 exclude these meta keys in the query (mode all); fields takes precedence when both are supplied",
      "where": "{k: v} \u2014 meta equality filters applied IN THE QUERY (mode all)",
      "where_from": "{k: \"<dotted bag key>\"} \u2014 where values read from the bag",
      "limit": "max rows (mode all)",
      "order": "\"-ordinal\" for newest-first",
      "default": "value answered when a latest/keyed read finds nothing",
      "include_deleted": "a keyed read may answer a tombstoned family's last write",
      "transient": "keep this read's rows OUT of the persisted launch output",
      "optional": "true \u2014 a mode:all read of a set that does not EXIST answers [] instead of failing; default is a loud failure (distinct denial vs empty \u2014 an existing-but-empty set always answers []). me/me_* sets are always tolerant (minted per-user on first write)"
    },
    "llm": {
      "provider": "provider entry (default openai); with `url`, any OpenAI-compatible endpoint",
      "url": "override the provider endpoint",
      "model": "model id (default: the registry's DEFAULT_MODEL)",
      "keys": "key specs \u2014 a connection service (user key PARKS the run until connected) or \"$secrets.NAME\" from the org vault",
      "system": "literal system prompt",
      "system_from": "bag key holding the system prompt",
      "user_from": "bag key holding the user message (default `ask`)",
      "messages_from": "bag key holding a FULL chat `messages` array \u2014 multi-turn conversations without a snippet",
      "response_format": "passed through to the provider (json_schema / json_object)",
      "reasoning": "effort for reasoning models (none|minimal|low|medium|high|xhigh \u2192 reasoning_effort)",
      "max_tokens": "output cap, clamped to the model's registry ceiling (sent as max_completion_tokens to api.openai.com)",
      "response_path": "dotted path to the reply text (default: the provider's)"
    },
    "agent": {
      "model": "model id \u2014 routed by the registry (gpt* \u2192 OpenAI, else Anthropic; HOUSE keys)",
      "system": "literal system prompt",
      "system_from": "bag key holding the system prompt",
      "user_from": "bag key holding the ask (default: bag `ask`/`text`)",
      "reasoning": "thinking effort (low|medium|high; OpenAI also none|minimal|xhigh)",
      "search": "web search is ON by default (the model decides whether to use it) \u2014 false disables"
    },
    "httpx": {
      "url": "the AUTHORED base \u2014 scheme+host are never data-driven (the SSRF gate and the key-carrying host are fixed at authoring)",
      "method": "GET|POST|PUT|PATCH|DELETE|HEAD (default POST)",
      "method_from": "dotted bag key naming the method (allowlisted)",
      "path_from": "dotted bag key holding an ABSOLUTE path(+query) appended to the base \u2014 ids in paths without one worker per id",
      "body_from": "dotted bag key holding the JSON body (default: the whole bag on mutating methods; GET/HEAD send none)",
      "keys": "key specs \u2014 each carries a user/house connection token or \"$secrets.NAME\" (org vault) in its OWN header; a missing USER key parks the run; {\"token_from\": \"<bag key>\", \"header\"?, \"scheme\"?} sends a token MINTED BY THIS RUN (a prior session-mint step) \u2014 no more `import httpx` inside a snippet to carry it",
      "allow_hosts": "pin the SSRF gate tighter than the default private/internal block",
      "max_bytes": "response size ceiling in bytes \u2014 over it the worker fails loudly instead of dragging megabytes into the bag",
      "follow_redirects": "follow up to N redirect hops (max 5): each hop re-proves the SSRF gate, and auth keys are DROPPED the moment the host changes"
    },
    "batch": {
      "over": "bag key holding the list (default `items`)",
      "each": "{tier, spec} \u2014 the sub-worker each item runs (it sees the bag plus `item`); one item's failure is ITS result, never the batch's",
      "concurrency": "parallel items (default 8, max 32)",
      "input_map": "(inside `each`) {\"<child key>\": \"<dotted path>\"} \u2014 name item fields into the child's input ({\"source_id\": \"item.source_id\"}) instead of forcing every fan-out child to open with an unwrap worker for the fixed `item` key"
    },
    "pipeline": {
      "pipeline": "'<code>' or '<scope>/<code>' \u2014 an EXISTING pipeline of this org, run as a REAL child launch driven in-process (own receipts/rows/feed events)",
      "pick": "[keys] \u2014 narrow the bag handed to the child",
      "input": "overlay object templated over the bag before the child launches",
      "emit": "[keys] \u2014 the child call's OUTPUT contract: only these keys of the child's terminal bag join the parent (without it the whole child bag lands \u2014 nine production bridge workers existed only to null that back out)"
    },
    "storage": {
      "op": "store_bytes | start_upload | finalize_upload | fetch_upload \u2014 the byte-asset choreography (tenant code never sees bucket credentials)",
      "from": "store_bytes: bag key holding base64 bytes (default `bytes_b64`)",
      "accept": "content-type allowlist (exact or family wildcard, e.g. [\"image/*\"])",
      "max_bytes": "size ceiling (default 25 MB)",
      "kind": "asset kind for the emitted row (file | image | \u2026)",
      "visibility": "public (default) | \u2026",
      "class": "storage class (default managed)",
      "content_type": "explicit content type (else from data / sniffed)",
      "ext": "explicit file extension (else derived from the content type)",
      "ttl": "fetch_upload: source-fetch timeout seconds (default 60); start_upload: presign TTL (default 600)",
      "asset_code": "explicit asset row code (else from data.asset_code/code)",
      "app_key": "storage key namespace (default: the scope leaf)",
      "rel_scope": "where under the app the object key is filed (default root)",
      "timeout": "fetch_upload: HTTP timeout seconds for the source fetch (default 60)"
    },
    "internal": {
      "handler": "a NAMED vetted function from the internal registry (`record` = declarative row envelope from the input); authoring = atomic scope authoring with trusted launch identity and current edit permission",
      "operations": "authoring handler: required authored allowlist of catalog operation names; cannot be supplied through run input",
      "args_from": "authoring handler: input bag key containing {operation_id,ops}; default authoring. The trusted launch fixes identity and target scope"
    }
  }
}
