@frontera-sdk/cli 1.45.0 → 1.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontera-sdk/cli",
3
- "version": "1.45.0",
3
+ "version": "1.45.1",
4
4
  "description": "The frontera CLI — scaffold, pull, save and deploy Frontera apps and automations.",
5
5
  "keywords": [
6
6
  "frontera",
package/src/kit.ts CHANGED
@@ -24,6 +24,8 @@ export interface KitAssets {
24
24
  claudeBlock: string
25
25
  pluginManifests: { claudeCode: string; codex: string }
26
26
  marketplaceManifests: { claudeCode: string; codex: string }
27
+ /** `plugin/assets/**`, base64, keyed relative to `plugin/`. */
28
+ pluginAssets: Record<string, string>
27
29
  }
28
30
 
29
31
  export const KIT: KitAssets = vendored as KitAssets
@@ -171,6 +173,16 @@ export function materializeMarketplace(root: string, kit: KitAssets = KIT): stri
171
173
  writeFileSync(dest, content)
172
174
  written.push(rel)
173
175
  }
176
+
177
+ // Binary assets — the icon the host shows. Written from base64 so a PNG can
178
+ // ride inside the vendored JSON.
179
+ for (const [rel, base64] of Object.entries(kit.pluginAssets ?? {}).sort(([a], [b]) => a.localeCompare(b))) {
180
+ const dest = join(root, 'plugin', rel)
181
+ mkdirSync(dirname(dest), { recursive: true })
182
+ writeFileSync(dest, Buffer.from(base64, 'base64'))
183
+ written.push(join('plugin', rel))
184
+ }
185
+
174
186
  return written
175
187
  }
176
188
 
@@ -9,20 +9,49 @@
9
9
  "claudeCode": true
10
10
  },
11
11
  "assets": {
12
- "authoring-frontera-agents/SKILL.md": "---\nname: authoring-frontera-agents\ndescription: Use when changing what a Frontera agent is made of — its models, prompts, skills, plugins, knowledge bases or packs. Covers reading the current composition, staging a change onto the draft, seeing the diff against live, and stopping short of publication.\n---\n\n# Authoring Frontera Agents\n\nAn agent is addressed by id or slug and edited as a document. Nothing is\nimplicit, so nothing goes stale.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Read the composition\n\n```bash\nfrontera agent list\nfrontera agent get <agent> # models, prompts, skills, plugins, knowledge\nfrontera agent get <agent> --json > agent.json\n```\n\n## The loop: get, edit, apply, diff\n\n```bash\nfrontera agent get <agent> --json > agent.json\n# edit agent.json\nfrontera agent apply <agent> -f agent.json # stages onto the DRAFT\nfrontera agent diff <agent> # what differs from live\n```\n\n`apply` stages; it does not publish. That separation is the whole safety model —\nyou can iterate on a draft as long as you like and the live agent is untouched.\n\n```bash\nfrontera agent discard <agent> # throw the draft away, live is untouched\nfrontera agent versions <agent> # what has been published before\n```\n\nUse `--expect-revision <hash>` on `apply` when you read the document earlier in\nthe session: it refuses the write if the agent moved, and exits 3 instead of\nsilently overwriting someone.\n\n## The pieces an agent references\n\nEach is its own resource with its own lifecycle — the agent document only names\nthem:\n\n```bash\nfrontera skill list # workspace skills an agent loads at runtime\nfrontera plugin list # integrations and MCP servers connected here\nfrontera knowledge list\nfrontera pack list # reusable skill bundles\n```\n\nKnowledge has one ordering trap worth knowing:\n\n```bash\nfrontera knowledge create <name> --description \"<what is in it>\"\nfrontera knowledge upload <name> ./corpus # a directory is walked\nfrontera knowledge attach <name> <agent> # nothing can read it until this\nfrontera knowledge sources <name> # status per file, minutes later\n```\n\n- **Upload queues ingestion; it does not finish it.** A file comes back\n `processing` with 0 chunks and turns `ready` minutes later. Retrieval tested\n before then returns nothing, which is not a failed upload.\n- **A partial batch still exits 0.** Read `failed` in the payload rather than\n trusting the exit code. Exit is non-zero only when nothing at all landed.\n Re-running is safe — upload is additive.\n- **Attachment is the only route in.** A base nobody is attached to is unreachable.\n\n## Completion evidence\n\n1. `frontera agent diff <agent>` shows exactly the sections you meant to change,\n and no others;\n2. any referenced skill, plugin, knowledge base or pack actually exists — check\n with its `list` command, do not assume a name resolves; and\n3. you reported the diff and said the change is **staged, not live**.\n\n**Do not publish.** `frontera agent publish <agent>` makes it the live version\nfor every conversation using that agent — see `publishing-frontera`.\n\n## Recovery\n\n| Symptom | Move |\n|---|---|\n| exit 3 on `apply` | `frontera agent get` again, reapply your edit, re-apply |\n| exit 2 naming an unknown skill or plugin | list it — the name did not resolve |\n| the draft is wrong and you want out | `frontera agent discard <agent>` |\n| exit 4 | `frontera auth verify` — the key may have been revoked mid-task |\n",
13
- "authoring-frontera-apps/SKILL.md": "---\nname: authoring-frontera-apps\ndescription: Use when building or changing a Frontera App — a React/Next project that reads platform data through Blueprint and deploys to the Apps surface. Covers scaffolding, reading available data, local verification against real data, and deploying a preview without promoting it.\n---\n\n# Authoring Frontera Apps\n\nLoad `using-frontera` first. Confirm the profile before anything that writes.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Know the data before designing against it\n\n```bash\nfrontera blueprint list\nfrontera blueprint get <apiName>\n```\n\nWhat these return is the slice this workspace is **granted** which is exactly\nwhat the App can query at runtime. Anything absent here will be absent for the\nApp too, so design from this output rather than from what the customer says they\nhave.\n\n## The loop\n\n```bash\nfrontera app init <name> # scaffold installs from public npm only\nbun install\nfrontera app add <component> # registry source into the project\nbun run typecheck\nbun run build # the deploy gate it must succeed\nfrontera app deploy --no-promote\n```\n\n`frontera app init` in an existing project adopts it rather than scaffolding a\nsecond one. `frontera app pull <app>` hydrates a working tree from a published\nversion or your saved draft; it refuses to clobber a dirty tree, and inside a\nsandbox there is usually no git to recover from deal with the files it names.\n\n## Verify against real data, not a screenshot of a refusal\n\n```bash\nfrontera app dev\n```\n\nThis runs the App locally with short-lived authenticated Blueprint access. In a\nlegacy Vite App, opening `/` directly renders \"This app runs inside Frontera\"\ninstead of mounting the handshake refuses an unknown parent, which is correct\nbehaviour, not a broken build. Open **`/dev-host.html`** instead: it frames the\nApp and plays the host side of the bridge, so the App mounts and reads real data.\nThat is the URL to screenshot or click through.\n\n## The generated SDK tree\n\n`src/frontera/` in a legacy scaffolded project is the SDK, copied in as source so\nthe project installs anywhere. Read it; never edit it, never rewrite an\n`@frontera-sdk/…` import to a relative path, never add `@frontera-sdk/*` to\n`package.json`. `frontera app sdk <action>` refreshes it. A Next App installs the\npublished packages instead and has no such tree.\n\nThe project's own `.agents/skills/` carry the SDK detail data hooks, tables,\nActions, testing. Read those for anything about writing App code; this skill is\nabout the lifecycle around it.\n\n## Completion evidence\n\nAn App change is done when:\n\n1. `bun run typecheck` and `bun run build` both pass the Vite build does not\n type-check, so the first is not implied by the second;\n2. the change was seen working against real data through `frontera app dev`;\n3. `frontera app deploy --no-promote` published an immutable version; and\n4. you reported the version and told the person what promoting it would do.\n\n**Do not promote.** `frontera app deploy` promotes by default that is why the\npreview path always passes `--no-promote`. Promotion is a live transition; see\n`publishing-frontera`.\n\n## Recovery\n\n| Symptom | Move |\n|---|---|\n| exit 2, \"not in a Frontera app directory\" | `cd` into the project, or pass `--dir` |\n| build fails after `app add` | read the component source it copied in; it is yours now |\n| deploy rejected | run `bun run build` locally deploy builds the same output |\n| exit 4 | `frontera auth verify` — the key may have been revoked mid-task |\n",
14
- "authoring-frontera-automations/SKILL.md": "---\nname: authoring-frontera-automations\ndescription: Use when writing or changing a Frontera Automation — TypeScript deployed to the platform and run on a schedule. Covers scaffolding, serving a working file to dev runs, deploying without promoting, and the kill switch.\n---\n\n# Authoring Frontera Automations\n\nAn Automation is TypeScript that runs on the platform on a schedule. It has no\ncredential of its own: it reaches capabilities through named grants, and reaches\nknowledge only through an agent that has the base attached.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Start from something that runs\n\n```bash\nfrontera automation init <name>\nfrontera automation list\nfrontera automation pull <slug> # hydrate an editable project from a deployed version\n```\n\n## Iterate without deploying\n\n```bash\nfrontera automation dev ./src/index.ts # serve this file to dev runs\nfrontera automation run <slug> --dev # run what dev is serving\nfrontera automation runs <slug> # recent runs, and what each returned\n```\n\n`dev` serves your working copy — no deploy, no version, nothing published. This\nis where iteration belongs; every deploy is an immutable version.\n\n## Deploy a preview\n\n```bash\nfrontera automation deploy ./src/index.ts --no-promote\nfrontera automation versions <slug> # * marks the live one\n```\n\n`frontera automation deploy` **promotes live by default**, which is why the\npreview path always passes `--no-promote`.\n\n## Secrets and grants\n\n```bash\nfrontera secret set <NAME> --from -\n```\n\nThe automation then **names** the secret — `auth: { secret: 'NAME' }` plus a\n`secret:NAME` grant and its value never enters the automation's process. An\ninline secret value is refused, and `.env` is never packaged; that is not\noverridable.\n\n## The kill switch\n\n```bash\nfrontera automation disable <slug> # stops scheduled execution immediately\nfrontera automation enable <slug> # resumes it\n```\n\nIf a person reports an Automation misbehaving in production, `disable` first and\ndiagnose second. It is reversible; a bad scheduled run may not be.\n\n## Completion evidence\n\n1. a dev run through `frontera automation run <slug> --dev` did what was asked,\n and you read `frontera automation runs <slug>` to confirm what it returned —\n not just that it exited;\n2. `frontera automation deploy … --no-promote` produced a version; and\n3. you reported the version and what promoting it would change.\n\n**Do not promote.** See `publishing-frontera`.\n",
15
- "authoring-frontera-blueprint/SKILL.md": "---\nname: authoring-frontera-blueprint\ndescription: Use when changing the organization's shared model object types, link types, metrics, dataset bindings, editable properties or grants. Covers pulling the draft to files, planning before applying, and recovering from a revision conflict. Requires an organization key.\n---\n\n# Authoring Frontera Blueprint\n\nBlueprint is the shared model of the organization. One draft is shared by every\nworkspace in the organization, so a change here is never local to you.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n`credentialKind` must be `organization`. A workspace key can read Blueprint and\ncannot author it that is not a permission to escalate around, it is a different\nkey the person has to supply.\n\n## Read before writing\n\n```bash\nfrontera blueprint status # draft revision, and the active release\nfrontera blueprint catalog # what is on the shared draft\nfrontera blueprint get <apiName>\n```\n\n## The file-tree loop — preferred\n\n```bash\nfrontera blueprint pull # the draft, as files you can commit\nfrontera blueprint new <kind> <apiName> # scaffold one that validates as written\n# edit the files\nfrontera blueprint plan # what applying would change writes nothing\nfrontera blueprint apply # reconcile the draft with the tree\nfrontera blueprint validate # produces a report\n```\n\n**Always `plan` before `apply`.** `plan` writes nothing and names every change,\nincluding the deletions `--prune` would make. Applying without reading a plan is\nhow a rename becomes a drop.\n\n`frontera blueprint rename <kind> <from> <to>` renames the artifact and its file\nas one act. Renaming a file by hand and applying reads as a delete plus a create.\n\nThe direct verbs `frontera blueprint create|update|delete <kind>` act on the\ndraft without a file tree. Use them for a single small change; use the tree for\nanything you want reviewable.\n\n## Binding data\n\n```bash\nfrontera dataset list\nfrontera blueprint bind <objectType> --dataset <name> --plan ./mapping.json\n# review the mapping skeleton, then\nfrontera blueprint bind <objectType> --dataset <name>\n```\n\nA rebind whose column contract differs from the pinned one is refused until\n`--accept-contract-change` says you looked. That refusal is the guard rail; do\nnot pass the flag to make an error go away.\n\n## Grants nothing is visible until granted\n\n```bash\nfrontera blueprint grant workspace <name> <apiName...>\nfrontera blueprint grant agent <slug> <apiName...>\n```\n\nAn object type nobody granted is invisible to every App and agent. If a person\nreports that an App \"sees no data\", check grants before checking the App.\n\n## On exit 3\n\nSomeone changed the draft first. **Re-fetch, do not force.**\n\n```bash\nfrontera blueprint pull # get the current draft again\n# reapply your edit on top of it\nfrontera blueprint plan\nfrontera blueprint apply\n```\n\nForcing discards whatever the other author did, and on a shared organization\ndraft that other author is a colleague.\n\n## Completion evidence\n\n1. `frontera blueprint plan` output matches what was asked for;\n2. `frontera blueprint apply` succeeded;\n3. `frontera blueprint validate` produced a clean report; and\n4. you reported the draft revision and said the change is **on the draft, not\n released**.\n\n**Do not publish.** `frontera blueprint publish` releases to the whole\norganization see `publishing-frontera`.\n",
16
- "publishing-frontera/agents/openai.yaml": "# Codex presentation and policy metadata.\ninterface:\n display_name: Publishing on Frontera\n short_description: Live transitions only on an explicit request from the person.\npolicy:\n # The one skill that must NOT be picked up implicitly. Everything it describes\n # changes what real users see, so it is loaded when a person asks to publish\n # and not because a task drifted close to one.\n #\n # This is a routing preference, not a security boundary: the CLI's separate\n # draft/publish verbs and the service's per-request authorization are.\n allow_implicit_invocation: false\n",
12
+ "authoring-frontera-agents/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Authoring Frontera Agents\n short_description: Compose an agent from models, instructions and reusable resources.\n default_prompt: Give this agent what it needs to answer from our policy documents.\npolicy:\n allow_implicit_invocation: true\n",
13
+ "authoring-frontera-agents/SKILL.md": "---\nname: authoring-frontera-agents\ndescription: Use when creating or changing a Frontera Agent — a conversational or autonomous capability composed from models, instructions, Skills, Plugins, Knowledge, Packs and Blueprint grants. Triggers on outcome language too: \"make the support agent able to look up orders\", \"let it answer from our policies\". Covers reading the composition, staging a change onto the draft, seeing the diff against live, and stopping short of publication.\n---\n\n# Authoring Frontera Agents\n\nA Frontera Agent is a **conversational or autonomous capability** composed from\na model, its own instructions, and reusable resources — Skills, Knowledge,\nPlugins, Packs and Blueprint grants, each a different kind of thing. For which\nresource carries what, and why installing a Plugin is not the same as granting a\ncapability, read `understanding-frontera`, reference `agents.md`.\n\nAn agent is addressed by id or slug and edited as a document. Nothing is\nimplicit, so nothing goes stale.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Read the composition\n\n```bash\nfrontera agent list\nfrontera agent get <agent> # models, prompts, skills, plugins, knowledge\nfrontera agent get <agent> --json > agent.json\n```\n\n## The loop: get, edit, apply, diff\n\n```bash\nfrontera agent get <agent> --json > agent.json\n# edit agent.json\nfrontera agent apply <agent> -f agent.json # stages onto the DRAFT\nfrontera agent diff <agent> # what differs from live\n```\n\n`apply` stages; it does not publish. That separation is the whole safety model —\nyou can iterate on a draft as long as you like and the live agent is untouched.\n\n```bash\nfrontera agent discard <agent> # throw the draft away, live is untouched\nfrontera agent versions <agent> # what has been published before\n```\n\nUse `--expect-revision <hash>` on `apply` when you read the document earlier in\nthe session: it refuses the write if the agent moved, and exits 3 instead of\nsilently overwriting someone.\n\n## The pieces an agent references\n\nEach is its own resource with its own lifecycle the agent document only names\nthem:\n\n```bash\nfrontera skill list # workspace skills an agent loads at runtime\nfrontera plugin list # integrations and MCP servers connected here\nfrontera knowledge list\nfrontera pack list # reusable skill bundles\n```\n\nKnowledge has one ordering trap worth knowing:\n\n```bash\nfrontera knowledge create <name> --description \"<what is in it>\"\nfrontera knowledge upload <name> ./corpus # a directory is walked\nfrontera knowledge attach <name> <agent> # nothing can read it until this\nfrontera knowledge sources <name> # status per file, minutes later\n```\n\n- **Upload queues ingestion; it does not finish it.** A file comes back\n `processing` with 0 chunks and turns `ready` minutes later. Retrieval tested\n before then returns nothing, which is not a failed upload.\n- **A partial batch still exits 0.** Read `failed` in the payload rather than\n trusting the exit code. Exit is non-zero only when nothing at all landed.\n Re-running is safeupload is additive.\n- **Attachment is the only route in.** A base nobody is attached to is unreachable.\n\n## Completion evidence\n\n1. `frontera agent diff <agent>` shows exactly the sections you meant to change,\n and no others;\n2. any referenced skill, plugin, knowledge base or pack actually exists check\n with its `list` command, do not assume a name resolves; and\n3. you reported the diff and said the change is **staged, not live**.\n\n**Do not publish.** `frontera agent publish <agent>` makes it the live version\nfor every conversation using that agent see `publishing-frontera`.\n\n## Recovery\n\n| Symptom | Move |\n|---|---|\n| exit 3 on `apply` | `frontera agent get` again, reapply your edit, re-apply |\n| exit 2 naming an unknown skill or plugin | list it the name did not resolve |\n| the draft is wrong and you want out | `frontera agent discard <agent>` |\n| exit 4 | `frontera auth verify` — the key may have been revoked mid-task |\n",
14
+ "authoring-frontera-apps/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Building Frontera Apps\n short_description: Build the operational interface a recurring job needs.\n default_prompt: Operations need a board for today's delayed shipments build it.\npolicy:\n allow_implicit_invocation: true\n",
15
+ "authoring-frontera-apps/SKILL.md": "---\nname: authoring-frontera-apps\ndescription: Use when building or changing a Frontera Appan operational interface and code project built on Frontera, reading governed data through the Blueprint SDK and served on the Applications surface. Triggers on outcome language too: \"operations need a shipment board\", \"a page where account managers update status\". Covers scaffolding, reading the granted model first, verifying against real data, and deploying a preview without promoting it.\n---\n\n# Authoring Frontera Apps\n\nA Frontera App is an **operational interface** — a code project built on\nFrontera that reads governed data through the Blueprint SDK and is served on the\nApplications surface. It is not a Plugin, which connects Frontera to a system\nsomebody else runs. The scaffold is Next.js today and a legacy Vite variant\nexists, but the framework is an authoring detail, not the definition. For the\nconcepts — what a Blueprint grant means for what an App can query — read\n`understanding-frontera`, reference `apps.md`.\n\nLoad `using-frontera` first. Confirm the profile before anything that writes.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Know the data before designing against it\n\n```bash\nfrontera blueprint list\nfrontera blueprint get <apiName>\n```\n\nWhat these return is the slice this workspace is **granted** which is exactly\nwhat the App can query at runtime. Anything absent here will be absent for the\nApp too, so design from this output rather than from what the customer says they\nhave.\n\n## The loop\n\n```bash\nfrontera app init <name> # scaffold installs from public npm only\nbun install\nfrontera app add <component> # registry source into the project\nbun run typecheck\nbun run build # the deploy gateit must succeed\nfrontera app deploy --no-promote\n```\n\n`frontera app init` in an existing project adopts it rather than scaffolding a\nsecond one. `frontera app pull <app>` hydrates a working tree from a published\nversion or your saved draft; it refuses to clobber a dirty tree, and inside a\nsandbox there is usually no git to recover from deal with the files it names.\n\n## Verify against real data, not a screenshot of a refusal\n\n```bash\nfrontera app dev\n```\n\nThis runs the App locally with short-lived authenticated Blueprint access. In a\nlegacy Vite App, opening `/` directly renders \"This app runs inside Frontera\"\ninstead of mounting the handshake refuses an unknown parent, which is correct\nbehaviour, not a broken build. Open **`/dev-host.html`** instead: it frames the\nApp and plays the host side of the bridge, so the App mounts and reads real data.\nThat is the URL to screenshot or click through.\n\n## The generated SDK tree\n\n`src/frontera/` in a legacy scaffolded project is the SDK, copied in as source so\nthe project installs anywhere. Read it; never edit it, never rewrite an\n`@frontera-sdk/…` import to a relative path, never add `@frontera-sdk/*` to\n`package.json`. `frontera app sdk <action>` refreshes it. A Next App installs the\npublished packages instead and has no such tree.\n\nThe project's own `.agents/skills/` carry the SDK detail data hooks, tables,\nActions, testing. Read those for anything about writing App code; this skill is\nabout the lifecycle around it.\n\n## Completion evidence\n\nAn App change is done when:\n\n1. `bun run typecheck` and `bun run build` both pass — the Vite build does not\n type-check, so the first is not implied by the second;\n2. the change was seen working against real data through `frontera app dev`;\n3. `frontera app deploy --no-promote` published an immutable version; and\n4. you reported the version and told the person what promoting it would do.\n\n**Do not promote.** `frontera app deploy` promotes by default — that is why the\npreview path always passes `--no-promote`. Promotion is a live transition; see\n`publishing-frontera`.\n\n## Recovery\n\n| Symptom | Move |\n|---|---|\n| exit 2, \"not in a Frontera app directory\" | `cd` into the project, or pass `--dir` |\n| build fails after `app add` | read the component source it copied in; it is yours now |\n| deploy rejected | run `bun run build` locally — deploy builds the same output |\n| exit 4 | `frontera auth verify` — the key may have been revoked mid-task |\n",
16
+ "authoring-frontera-automations/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Writing Frontera Automations\n short_description: Express a repeatable business workflow as a code workflow function.\n default_prompt: Implement our nightly reconciliation as a reusable workflow.\npolicy:\n allow_implicit_invocation: true\n",
17
+ "authoring-frontera-automations/SKILL.md": "---\nname: authoring-frontera-automations\ndescription: Use when creating or changing a Frontera Automation — a reusable code workflow function that performs a business workflow on the platform, with typed inputs, declared grants, durable steps and outputs. Triggers on outcome language too: \"a nightly reconciliation\", \"implement the approval workflow as reusable code\". Covers scaffolding, serving a working file to dev runs, deploying without promoting, and the kill switch.\n---\n\n# Authoring Frontera Automations\n\nAn Automation is a reusable **code workflow function** that performs a business\nworkflow on Frontera — TypeScript deployed to the platform, with typed inputs,\ndeclared grants, durable steps and a return value. The schedule is how it is\ninvoked, never what it is. It has no credential of its own: it reaches\ncapabilities through named grants, and reaches knowledge only through an agent\nthat has the base attached. For the boundary against Agents and against governed\nActions, read `understanding-frontera`, reference `automations-and-actions.md`.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n## Start from something that runs\n\n```bash\nfrontera automation init <name>\nfrontera automation list\nfrontera automation pull <slug> # hydrate an editable project from a deployed version\n```\n\n## Iterate without deploying\n\n```bash\nfrontera automation dev ./src/index.ts # serve this file to dev runs\nfrontera automation run <slug> --dev # run what dev is serving\nfrontera automation runs <slug> # recent runs, and what each returned\n```\n\n`dev` serves your working copy — no deploy, no version, nothing published. This\nis where iteration belongs; every deploy is an immutable version.\n\n## Deploy a preview\n\n```bash\nfrontera automation deploy ./src/index.ts --no-promote\nfrontera automation versions <slug> # * marks the live one\n```\n\n`frontera automation deploy` **promotes live by default**, which is why the\npreview path always passes `--no-promote`.\n\n## Secrets and grants\n\n```bash\nfrontera secret set <NAME> --from -\n```\n\nThe automation then **names** the secret — `auth: { secret: 'NAME' }` plus a\n`secret:NAME` grant — and its value never enters the automation's process. An\ninline secret value is refused, and `.env` is never packaged; that is not\noverridable.\n\n## The kill switch\n\n```bash\nfrontera automation disable <slug> # stops scheduled execution immediately\nfrontera automation enable <slug> # resumes it\n```\n\nIf a person reports an Automation misbehaving in production, `disable` first and\ndiagnose second. It is reversible; a bad scheduled run may not be.\n\n## Completion evidence\n\n1. a dev run through `frontera automation run <slug> --dev` did what was asked,\n and you read `frontera automation runs <slug>` to confirm what it returned —\n not just that it exited;\n2. `frontera automation deploy … --no-promote` produced a version; and\n3. you reported the version and what promoting it would change.\n\n**Do not promote.** See `publishing-frontera`.\n",
18
+ "authoring-frontera-blueprint/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Changing Frontera Blueprint\n short_description: Change the organization's shared, governed model — safely.\n default_prompt: Make every team calculate active customer the same way.\npolicy:\n allow_implicit_invocation: true\n",
19
+ "authoring-frontera-blueprint/SKILL.md": "---\nname: authoring-frontera-blueprint\ndescription: Use when changing the organization's shared, governed model — object types, properties, link types, metrics, dataset bindings, editable properties or grants. Triggers on outcome language too: \"make every team calculate active customer the same way\", \"the App sees no data\". Covers pulling the draft to files, planning before applying, and recovering from a revision conflict. Requires an organization key.\n---\n\n# Authoring Frontera Blueprint\n\nBlueprint is the **shared model of the organization** — its object types,\nproperties, links, metrics, object sets, datasets, grants and Actions. One draft\nis shared by every workspace in the organization, so a change here is never\nlocal to you. For what each element means and how a change lands on the people\nalready reading it, read `understanding-frontera`, reference `blueprint.md`. For\nmodelling method — naming, identity, competency questions, review — use\n`designing-frontera-blueprint`.\n\nLoad `using-frontera` first.\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\n**Names come from the customer, never from a skill.** Every object type,\nproperty and link is named with the word the business itself uses, in its own\nlanguage — `Nasabah` if that is what they say, not `Customer` and not a generic\nabstraction. Any name you first read in a skill file, template or example is\nwrong for this organization by construction.\n\n`credentialKind` must be `organization`. A workspace key can read Blueprint and\ncannot author it — that is not a permission to escalate around, it is a different\nkey the person has to supply.\n\n## Read before writing\n\n```bash\nfrontera blueprint status # draft revision, and the active release\nfrontera blueprint catalog # what is on the shared draft\nfrontera blueprint get <apiName>\n```\n\n## The file-tree loop — preferred\n\n```bash\nfrontera blueprint pull # the draft, as files you can commit\nfrontera blueprint new <kind> <apiName> # scaffold one that validates as written\n# edit the files\nfrontera blueprint plan # what applying would change — writes nothing\nfrontera blueprint apply # reconcile the draft with the tree\nfrontera blueprint validate # produces a report\n```\n\n**Always `plan` before `apply`.** `plan` writes nothing and names every change,\nincluding the deletions `--prune` would make. Applying without reading a plan is\nhow a rename becomes a drop.\n\n`frontera blueprint rename <kind> <from> <to>` renames the artifact and its file\nas one act. Renaming a file by hand and applying reads as a delete plus a create.\n\nThe direct verbs — `frontera blueprint create|update|delete <kind>` — act on the\ndraft without a file tree. Use them for a single small change; use the tree for\nanything you want reviewable.\n\n## Binding data\n\n```bash\nfrontera dataset list\nfrontera blueprint bind <objectType> --dataset <name> --plan ./mapping.json\n# review the mapping skeleton, then\nfrontera blueprint bind <objectType> --dataset <name>\n```\n\nA rebind whose column contract differs from the pinned one is refused until\n`--accept-contract-change` says you looked. That refusal is the guard rail; do\nnot pass the flag to make an error go away.\n\n## Grants — nothing is visible until granted\n\n```bash\nfrontera blueprint grant workspace <name> <apiName...>\nfrontera blueprint grant agent <slug> <apiName...>\n```\n\nAn object type nobody granted is invisible to every App and agent. If a person\nreports that an App \"sees no data\", check grants before checking the App.\n\n## On exit 3\n\nSomeone changed the draft first. **Re-fetch, do not force.**\n\n```bash\nfrontera blueprint pull # get the current draft again\n# reapply your edit on top of it\nfrontera blueprint plan\nfrontera blueprint apply\n```\n\nForcing discards whatever the other author did, and on a shared organization\ndraft that other author is a colleague.\n\n## Completion evidence\n\n1. `frontera blueprint plan` output matches what was asked for;\n2. `frontera blueprint apply` succeeded;\n3. `frontera blueprint validate` produced a clean report; and\n4. you reported the draft revision and said the change is **on the draft, not\n released**.\n\n**Do not publish.** `frontera blueprint publish` releases to the whole\norganization — see `publishing-frontera`.\n",
20
+ "designing-frontera-blueprint/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Designing a Frontera Blueprint\n short_description: Decide what the shared model should be, or review one somebody wrote.\n default_prompt: Model our business so agents can actually use it.\npolicy:\n allow_implicit_invocation: true\n",
21
+ "designing-frontera-blueprint/assets/design-doc-template.md": "# Design document skeleton\n\nThe section order below is load-bearing: it puts the reader's questions in the order they will ask them, and it puts the falsifiable claims early where a reviewer can kill them cheaply.\n\nAdapt freely — but if you drop a section, know what you are dropping. section 4, section 6 and section 12 are the three that most often go missing and most often should not.\n\n```\n1. Purpose, scope, and the competency questions\n 1.1 What this Blueprint is for — the use cases, in priority order\n 1.2 Scope\n 1.3 Out of scope, and how each attaches later\n 1.4 Competency questions, grouped by use case, with the coverage result\n\n2. The business, as it actually is\n 2.1 Structural facts that change the model (restructuring, ownership, segmentation)\n 2.2 Internal vs external supply\n 2.3 Two-sidedness of counterparties\n 2.4 Domain facts the model must represent\n 2.5 What is asserted vs what is unverified\n\n3. Design principles\n 3.1 The four principles and what each prevents\n 3.2 When something becomes an object type\n 3.3 Supporting practices\n\n4. Platform assumptions and constraints ← falsifiable, and early on purpose\n 4.1 The assumption list\n 4.2 Key strategy\n 4.3 The naming contract\n\n5. The model — N object types\n 5.0 Status, visibility, notation\n 5.1..5.n One subsection per layer, each with a table and per-type properties\n\n6. Interfaces (declared, or planned)\n\n7. Link types, grouped by layer, with join keys and directional phrases\n\n8. What was deliberately not modelled ← stops the model regrowing it\n\n9. Temporal design\n\n10. Object sets, each tied to a competency question\n\n11. Metrics, and what is derived vs stored\n\n12. Action types ← the operational layer\n\n13. Business-context quality checks\n\n14. Access model and the agent tool budget\n\n15. Naming, disambiguation and agent readiness\n\n16. Traversal and derivation register\n\n17. Build sequencing — the waves\n\n18. Data foundation — readiness verdict and mart contract\n\n19. Ownership, lifecycle and retirement\n\n20. Open questions for the customer\n\n21. Sources\n```\n\n## Notes on the sections people get wrong\n\n**section 1.4** is not an appendix. Put the questions in the body, with the coverage result stated plainly — including which types are weakest-justified. A design that names its own soft spots is more credible, not less.\n\n**section 2.5** is where unverified research goes. Anything the dossier flagged and you could not confirm belongs here as an open question, never as a property. This section is what stops a plausible-sounding claim becoming a column.\n\n**section 4** early, not buried. It is the section a reviewer can use to kill a premise in ten seconds, which is exactly what you want to happen before the model is built around it.\n\n**section 8** is worth more than it looks. Recording what you rejected and why is what stops the next person regrowing it — and it answers the reviewer question \"why isn't there a Customer type?\" before it is asked.\n\n**section 20** should be specific enough to be answerable. \"Clarify the data model\" is not an open question; \"does any single legal entity report to two directorates, and if so, does accountability need to be its own object type?\" is.\n\n## Register the deviations\n\nWherever the design departs from a stated principle, say so where it happens **and** collect the deviations in one place. \"We violate normalisation in these 45 places, for this platform reason, registered here, with this exit\" is defensible engineering. The same 45 copies unremarked is a finding.\n",
22
+ "designing-frontera-blueprint/assets/model-schema.md": "# `model.yaml` — the machine-readable model\n\nThe design document carries the reasoning; this file carries the model. Keeping both is what makes the design checkable instead of merely plausible — `scripts/lint_ontology.py` reads this file and reports the defects an adversarial reviewer would otherwise find by hand.\n\nWrite it as you design, not afterwards. The linter is most useful when it runs after every change.\n\n## Shape\n\n> **The names below are invented, from a port-operations example, and exist only\n> to show where each field goes. Never carry one into a real model.** Every\n> `api_name`, `display_name` and property name must come from the customer's own\n> vocabulary. If the business says *Nasabah*, the object type is `Nasabah` — not\n> `Customer`, and certainly not an abstraction like `Party`. Translating their\n> word into English, or replacing it with a generic one that fits any business,\n> is the single most damaging thing that can happen at this step.\n\n```yaml\nmeta:\n name: acme-port-operations # kebab-case identifier\n platform: frontera # frontera | other\n traversal_limit: 3 # max hops a query may take; from Phase 3\n agent_tool_budget: 20 # max tools (types + actions + metrics) per agent\n\n# Phase 4. Every object type must appear in at least one question's `types` list.\ncompetency_questions:\n - id: Q1\n text: Which berths ran above 80% occupancy last quarter, and for which vessel classes?\n use_case: berth-planning\n types: [PortCall, Berth, Vessel]\n\nobject_types:\n # Names here are this example's, not yours. Use the words the business says.\n - api_name: PortCall # PascalCase, unique\n display_name: Port call\n plural_name: Port calls\n description: >\n One row per arrival of a vessel at a berth, from pilot boarding to\n departure. Grain: one per vessel per berth per arrival. Source: the\n terminal operating system, hourly. Not to be confused with Voyage, which\n spans several calls.\n primary_key: portCallId\n title_property: callReference\n status: active # active | experimental | deprecated\n groups: [operations]\n wave: 1\n kind: event # entity | event | snapshot | extension\n extends: null # for kind: extension, the core type it extends\n properties:\n - api_name: portCallId\n type: attribute # attribute | measure | time\n data_type: string\n - api_name: callStatus\n type: attribute\n data_type: string\n enum: [scheduled, alongside, departed, cancelled]\n - api_name: alongsideHours\n type: measure\n data_type: number\n derived: true # computed at read time, not stored\n - api_name: demurrageAmount\n type: measure\n data_type: number\n source: pipeline # dataset | pipeline | action — who puts a value in it\n - api_name: plannerNote\n type: attribute\n data_type: string\n editable: true # writable only by a governed action\n\nlink_types:\n - api_name: portCalls\n from: Vessel\n to: PortCall\n cardinality: one_to_many # one_to_one | one_to_many | many_to_one | many_to_many\n from_property: vesselId # the key on the \"one\" side\n to_property: vesselId # the key on the \"many\" side\n from_phrase: makes\n to_phrase: is made by\n join_model: null # required for many_to_many\n\nmetrics:\n - api_name: berthOccupancyHours\n object_type: PortCall # metrics are single-object-type\n measures:\n - property: alongsideHours\n agg: sum\n filter: \"callStatus != 'cancelled'\" # omit if the platform cannot filter\n dimensions: [berthId, vesselClass]\n timeseries: arrivalDate\n\nactions:\n - api_name: raiseDemurrageClaim\n target: PortCall\n blast_radius: high # low | medium | high\n parameters:\n - name: claimedAmount\n type: number\n - name: claimCategory\n type: enum\n values: [berthDelay, cargoDelay, documentationDelay]\n writes: # each must be an editable property on the target\n - object_type: PortCall\n property: claimStatus\n sets: claimed # the enum value this action produces\n submission_criteria:\n - text: claimedAmount <= demurrageAmount\n enforced: false # false = advisory, re-checked post-hoc\n human_in_the_loop: required # none | confirm | required\n\nagents:\n - name: berth-planner\n object_types: [PortCall, Berth, Vessel]\n actions: [raiseDemurrageClaim]\n metrics: [berthOccupancyHours]\n answers: [Q1]\n```\n\n## What each field is for\n\n**`traversal_limit` and `agent_tool_budget`** come from Phase 3 and Phase 7. The linter uses them, so a platform with a different ceiling gets different results rather than the same warnings.\n\n**`kind`** lets the linter apply the right rules. A `snapshot` type is expected to carry materialised measures and a period grain; an `extension` is expected to share its core's key.\n\n**`source`** says who puts a value in a property: the backing `dataset`, a `pipeline`, or an `action`. Every measure needs one of these, or `derived: true`. The linter flags measures with neither, because that is how a roll-up somebody described as \"following automatically\" ships reading zero — the property is declared, the design assumes it, and no job was ever written to fill it.\n\n**`derived: true`** marks a property computed at read time. The linter treats stored copies of another object's data as findings and derived ones as fine, which is the whole distinction Phase 8 turns on.\n\n**`editable: true`** is what makes a property writable by an action. The linter cross-checks every action's `writes` against it — an action writing a non-editable property is a defect that is easy to introduce and invisible in prose.\n\n**`enum` on a property, `sets` on an action write** is what makes the reachability check possible: a status value no action or pipeline produces means a saved query filters on it forever and returns nothing. Where a pipeline produces a value rather than an action, record it in `meta.pipeline_produced_values` as `TypeName.propertyName=value` so the linter does not flag it.\n\n**`answers` on an agent** ties each agent to the questions it exists to answer, which is what the evaluation suite in Phase 8 is built from.\n\n## Minimal viable file\n\nEarly in a design, most sections will be empty. That is fine — the linter reports what it can check and stays quiet about the rest. The one thing worth populating from the very start is `competency_questions`, because it is what everything else is measured against.\n",
23
+ "designing-frontera-blueprint/references/actions-and-agents.md": "# Actions and agents\n\n## Part 1 — Action design: what makes the model operational\n\nA model that only describes is a schema. Actions are what make it operational, and this is the phase most modelling work skips.\n\n## Three filters, applied before anything is designed\n\n**1. Is a human or an agent exercising judgement?** Actions are for decisions; pipelines are for automated transformations. \"Recalculate utilisation\", \"post the monthly figures\", \"generate the statement\" are pipelines wearing action costumes — building them as actions makes an audit trail out of arithmetic and clutters the agent's tool list.\n\n**2. Does it span systems, or has it no system home?** An action that writes to exactly one system and proxies a screen in that system is integration debt dressed as a business model. The value of an action is that it governs a decision no single system owns — one made today in a spreadsheet, an email thread, or a meeting.\n\n**3. Does the source system own the record?** Decisions with legal effect executed elsewhere — issuing the invoice, provisioning the service, paying the claim — stay there. Blueprint records the *decision*, not the execution.\n\n**Verify filter 2 with the customer rather than assuming it.** \"Which of these are currently decided in a spreadsheet?\" is a question with a real answer, and anything already governed in a source system should be dropped before build. Do not assert that all your actions pass this filter if you have not asked.\n\n## Anatomy\n\nFor each surviving action, specify:\n\n| Component | Notes |\n|---|---|\n| **Target** | The object type, or the interface if the platform supports targeting one |\n| **Parameters** | Typed. **Constrained enums, never free text** for anything categorical |\n| **Writes** | Which property on which type, and which enum value it sets |\n| **Submission criteria** | The conditions under which it may be submitted — and whether the platform can *enforce* them |\n| **Side effects** | Notifications, webhooks. Mark as intent if there is no primitive |\n| **Blast radius** | low / medium / high — drives the human-in-the-loop tier |\n\n**Parameters are the agent's interface.** Names must be unambiguous — `counterpartyId`, never `party` — and categorical parameters must be constrained enums. A wrong enum errors loudly; wrong free text succeeds silently and corrupts the record. Reserve free text for genuinely narrative fields: a justification, a note, a summary.\n\n## Blast radius and human-in-the-loop\n\nTier by consequence, not by convenience:\n\n| Radius | What it means | Agent behaviour |\n|---|---|---|\n| **Low** | Annotation only — a note, a triage comment, an internal priority | May run agent-automatic |\n| **Medium** | Changes a number or state others rely on | Agent-proposed, human-confirmed |\n| **High** | Moves money, or commits to a counterparty | **Never agent-automatic.** An agent may prepare and pre-fill it; a named human submits |\n\nThe linter enforces the last row, because it is the one that gets relaxed under delivery pressure.\n\n## Three things to engineer rather than assume\n\nFew platforms document any of these. Design for their absence.\n\n### Idempotency\n\nNo exactly-once guarantee, no idempotency key. Two shapes work:\n\n- **Absolute writes.** Target a single object by primary key and *set* a value rather than applying a delta. A repeated submission is then harmless.\n- **Deterministic creation.** Where the action creates an object, key it on a hash of its business content — target, category, amount, date. A duplicate submission collides instead of duplicating.\n\n### Maker–checker\n\nWhere separation of duties matters — approving a credit, resolving a dispute, releasing a payment — compare the actor against the actor of the preceding action.\n\n**Read the live ledger, not a batch-refreshed projection.** A projection refreshed on a schedule lets the same person perform both halves inside one refresh window, which defeats the control entirely and looks like it is working.\n\n### Corrections must move the current state too\n\nAn action that supersedes or restates a past record has to say what *current* value moves with it. This is the defect independent reviewers found most often in otherwise sound models: a `restate` action writes a new version of a historical movement and never touches the balance the user actually reads, so the correction is recorded and invisible.\n\nFor every correcting action, name three things: the historical record it writes, the current-state property that must move as a result, and which of the two is authoritative if they disagree. If the current-state value is derived, say from what — and check the derivation actually includes the new version.\n\n### Forward correction, not reversal\n\nThere is no undo primitive. Design every high-blast-radius action to be correctable *forward*: a resolution can be superseded by a further one; a recommitment can be recommitted, with a cap. **Where forward correction is impossible, do not build the action** — an irreversible governed write with no compensating path is worse than no action at all.\n\n## The reachability check\n\n**Every status value must be produced by some action or a named pipeline.**\n\nWalk each enum: which action sets each value? An unreachable value means a saved query filters on it forever and silently returns nothing — the failure that produces an empty dashboard nobody can explain.\n\nUnreachable values are usually one of two things:\n\n- **A missing action, often an important one.** In a settlement model, \"agree the counterparty's statement\" is the central recurring judgement in the entire domain and is easy to leave out because it feels like a formality.\n- **A vocabulary that should be trimmed.** A status nobody sets and nobody queries is noise in the agent's context.\n\nWhere a pipeline legitimately produces a value, record it in `meta.pipeline_produced_values` so the linter stays quiet and the reader knows who owns it.\n\n## The decision record\n\nIf the platform has no action-log object type, build one. Project the governed Action ledger into the model: which action, which actor, human or agent, when, against which object, with what parameters, prior and new value, and the amount at stake.\n\nThis is what makes \"who waived this, when, and against what exposure\" an aggregation rather than a support ticket. It is also what makes maker–checker enforceable, and it closes the loop the design otherwise leaves open — decisions taken through the model becoming data the model holds.\n\n**Give it a typed foreign key per action-target type**, not a bare `targetId` string. A string is unlinkable, and \"decisions on *this* object\" is the question the record exists to answer.\n\n## A worked example\n\n```yaml\n- api_name: approveCreditNote\n target: CreditAssessment\n blast_radius: high\n human_in_the_loop: required\n parameters:\n - {name: assessmentId, type: string}\n - {name: approvalNote, type: string}\n writes:\n - {object_type: CreditAssessment, property: creditStatus, sets: approved}\n - {object_type: CreditAssessment, property: approvalNote}\n submission_criteria:\n - text: actor differs from the actor of the preceding assessCredit\n enforced: true\n - text: amount is within the actor's authority band\n enforced: false # no authority data on Person yet — open question\n```\n\nNote what the `enforced: false` is doing: it is honest. The criterion is real, the platform cannot check it, so it is re-checked post-hoc in the quality checks and an agent is never told it is guaranteed.\n\n---\n\n## Part 2 — Agent readiness\n\nThis is an architecture phase, not a documentation phase. A model that is structurally perfect and unusable by an agent has failed at the thing it was built for.\n\n## The tool budget\n\nAgent reliability degrades as the number of tools in front of it grows. Roughly ten to twenty is workable; beyond that, tool *selection* becomes the dominant failure mode, and the agent starts picking the wrong object type rather than reasoning badly about the right one. A small, well-chosen shortlist outperforms a large one.\n\n**Count object types, actions and metrics together.** To an agent all three are tools, each costing context before the user has said anything.\n\n**A forty-nine-type model exposed flat to one agent will not work.** The registry may be large; the shortlist any one agent sees must not be. This is an architectural choice, and making it explicitly is the whole point of this phase.\n\n### The trap: the executive agent\n\nExecutives ask about everything, so the reflex is to grant everything — which produces the worst-performing agent in the fleet. Give it **the metrics layer**, which is aggregate by construction and needs no traversal, plus a handful of entry types for drill-down. Breadth comes from metrics, not from types.\n\n### Scoping rules\n\n- Build agents around **a use case**, not around a department or a data domain.\n- Where an agent needs something outside its scope, **hand off to the agent that owns it**. Do not widen the grant.\n- **Scope is a security boundary too.** An agent that can reach commercially sensitive types on behalf of a user who cannot is a governance failure, not a convenience. Where the platform has no row-level security, this is the only boundary you have.\n- Every agent should have an explicit list of the competency questions it exists to answer. An agent with no questions has no evaluation suite.\n\n## The disambiguation registers\n\nA short, hand-authored document that disambiguates contested terms and pins metric definitions improves agent accuracy by a larger margin than most structural refactors will buy. It is the highest-value artefact in the design and the easiest to skip.\n\nThe reason is the failure mode, not the accuracy: a curated layer **errors when a question falls outside its scope**, where free-form querying returns a plausible wrong answer and gives no signal that it has. Ambiguity in your type names converts the first behaviour into the second.\n\n### Register 1 — confusable type pairs\n\nFor every pair a reader could confuse, one sentence that separates them, going **verbatim into the object type descriptions**. The pairs that recur across domains:\n\n| Pair | The distinction |\n|---|---|\n| The company vs. the relationship it holds | *Who they are*, forever, versus *what they are to us in this capacity*, time-bounded. Use the business's names for both — this pair only needs disambiguating if you built an identity spine, and if you did, they will be arguing about which one to use |\n| Catalogue vs. sold instance vs. delivered thing | What we sell (no customer) · what this customer bought (billed, priced) · what we actually run for them (has an identifier and a state). **If the question is about money, use the second; if about whether something works, the third** |\n| Contract vs. its line items vs. the thing being billed | The agreement · a schedule line or negotiated term inside it · an item billed under it |\n| The event vs. the ticket vs. the measured breach | What happened to the estate (one per event) · someone complaining (many per event, some with no event behind them) · the measured consequence and its penalty |\n| Account vs. document vs. period statement vs. ledger line | The standing balance · one document · the netting of a period · the accounting grain |\n| Order vs. work order | What the counterparty asked us to sell them · the internal job that provisions it. One decomposes into many |\n| The place vs. what the place is | Geography and status live on the place; capability lives on the extension |\n\n### Register 2 — contested business terms\n\nWords with more than one meaning *in this domain*, and what to say instead. Ask the SMEs which words start arguments in meetings — that list is the register.\n\nCommon offenders across industries: *circuit, route, capacity, partner, carrier, tenant, rate, order, position, exposure, account, line, product, service, site, case*.\n\nFormat: term · what it can mean here · what to use instead. `\"capacity\" → design, contracted, allocated or drawn → always qualified: designCapacityGbps, contractedKw`.\n\n## Descriptions\n\nAn agent selects an object type by its description. Write it as you would brief a new hire, not as a data-dictionary entry. Five things:\n\n1. **What it is**, in the business's language.\n2. **Its grain** — one row per what?\n3. **Its source and refresh cadence.**\n4. **The basis of any figure** — gross or net, before or after elimination, current version or all versions.\n5. **What it is not to be confused with** — the sentence from Register 1.\n\nLineage belongs here, not in a property. An agent reporting a number without knowing it is a month old is a liability; one that can state the basis is the product.\n\n## Evaluation\n\nThe design is a hypothesis until it is measured. Build the suite from the competency questions, with answers computed independently of the model.\n\n**Measure four things, not one:** accuracy, tool-call count, token consumption, error rate. An agent that is accurate at forty tool calls is not fit for production.\n\n**Thresholds that can fail**, agreed before the build rather than after:\n\n| Metric | Starting threshold |\n|---|---|\n| In-scope questions answered correctly | ≥ 90% |\n| Silently-wrong answers on financial questions | **Zero** |\n| Median tool calls per question | ≤ 6 |\n| Error rate | < 5% |\n\nThe second row is the one to defend. A wrong answer that announces itself is a bug; a wrong answer that looks right is a liability, and it is the specific failure a curated layer exists to prevent.\n\n**Scope the gate per wave.** Wave 1 builds a fraction of the model, so only some agents are constructible and only some questions are in scope. A gate that cannot be met until the last wave is not a gate.\n\n**Record the failure mode on every miss** — wrong type selected, right type but wrong property, traversal exceeded, ambiguity. Type-selection failures are a disambiguation problem; traversal failures are a modelling problem. They have different fixes, and conflating them wastes a cycle.\n",
24
+ "designing-frontera-blueprint/references/competency-questions.md": "# Competency questions\n\nThe cheapest artefact in the workflow and the one that does the most work. Write 30–40 questions the model must answer, grouped by use case, **before naming a single object type** — then check that every object type appears in at least one.\n\n## Why this is the gate\n\nThere is no published guidance anywhere on how many object types a business model should have. Every credible source scopes by *method*, not by count. So \"is forty-nine too many?\" is unanswerable and the wrong question. The answerable one is **\"was each of the forty-nine derived, or enumerated?\"**\n\nA type appearing in no competency question was enumerated — someone listed the domain rather than asked what anyone needs. Expect this test to find dead weight even in a model that already looks finished, and expect the finds to be types that felt *obviously* part of the domain. Obviousness is exactly the failure mode.\n\n## What makes a question good\n\n**Answerable with a specific number or a specific list.** If it cannot be, it is a theme — and themes do not justify object types.\n\n| Good | Bad | Why |\n|---|---|---|\n| \"Which accounts moved more than 15% month-on-month, and is the movement volume or price?\" | \"Support revenue analysis\" | The first names a threshold, a comparison and a decomposition; the second names a department |\n| \"Which orders are past their committed date, ranked by revenue at risk, and what is blocking each?\" | \"Give visibility into operations\" | The first implies a status, a date, a value and a reason — four properties |\n| \"Which sites will exceed 85% of contracted capacity within two quarters at current run rate?\" | \"Track capacity\" | The first forces a decision about whether you model a projection or only current state |\n| \"What did we bill under the rate we believed was in force in March, and what does restated March look like now?\" | \"Handle pricing history\" | The first is the question that reveals a domain is bitemporal |\n\n**Written in the organisation's own words.** If the SMEs would not recognise the phrasing, the question is yours, not theirs — and it will justify types they do not need.\n\n## Coverage across domains\n\nAim for 5–10 per use case, and make sure the set spans four shapes. A set that is all of one shape produces a lopsided model.\n\n- **Aggregate** — \"what was X by Y last quarter\" → drives the fact types, grains and metric dimensions\n- **Impact / traversal** — \"who is affected by this event\" → drives links, and is where you discover the traversal ceiling\n- **Lifecycle / exception** — \"what is stuck, late, disputed, or in breach\" → drives status vocabularies and, usually, actions\n- **360 / entity** — \"everything about this counterparty\" → drives the party spine and reveals two-sidedness\n\nTwo more worth including in every set, because they catch modelling gaps nothing else does:\n\n- **Point-in-time** — \"what did this look like on date D\" → forces the snapshot-vs-current-state decision\n- **Provenance** — \"for any number reported: what is its grain, source, refresh date and basis\" → forces lineage into descriptions\n\n## Worked examples by industry\n\n**Insurance claims:** Which claims exceeded reserve by more than 20%, and at which adjuster? · Which policies have an open claim and a renewal inside 60 days? · What is the average cycle time from first notice to settlement, by peril and region? · Which claims were reopened after closure, and why?\n\n**Manufacturing / supply chain:** Which purchase orders will miss their promise date, ranked by downstream line impact? · Which suppliers are single-sourced for a part used in more than one product line? · What was on-time-in-full by supplier by month, and how has it moved? · Which lots are affected by this quality hold, and which customers received them?\n\n**Healthcare operations:** Which patients have an outstanding referral older than the pathway target, by specialty? · Which theatre lists ran under 80% utilisation last month, and what was the cause code? · Which clinicians' caseloads exceed the safe threshold this week?\n\n**SaaS revenue:** Which accounts have a renewal inside 90 days and no open opportunity? · What is net revenue retention by cohort and by segment? · Which usage lines were rated differently from the contracted rate card, and by how much?\n\nNotice that each set produces different *shapes*: insurance forces a claim lifecycle and a reserve history; supply chain forces a bill-of-materials traversal; SaaS forces a subscription-versus-usage split. That is the point — the questions design the model.\n\n## Turning questions into artefacts\n\nEach question should end up in three places:\n\n1. **`model.yaml`** — with the `types` it traverses, so the linter can check coverage.\n2. **The saved object-set catalogue** — most questions become a set or a metric. A question with no expressible definition is a gap in the model, found early.\n3. **The evaluation suite** (Phase 8) — with an answer computed independently from the mart, so agent performance is measurable rather than impressionistic.\n\n## Reading the coverage report\n\nThe linter reports two things:\n\n- **`uncovered-type`** (error) — no question asks for it. Cut it, or write the question.\n- **`single-question-type`** (info) — justified by exactly one question. Not a defect, but this is the weakest-justified tier and the first candidate for retirement if that question turns out not to be asked. Mark these `experimental` and put them in the last build wave.\n\nIf more than about a fifth of types are single-question, the question set is probably too thin rather than the model too fat — go back and write more questions before cutting types.\n",
25
+ "designing-frontera-blueprint/references/design-mode.md": "# Design mode — modelling from scratch\n\nEleven phases in three movements. On the short path (see SKILL.md) run phases 0, 4, 5, 6, 7, 9 and one pass of 10; the rest are for a full-scope engagement and will over-serve a scoped request.\n\n| Movement | Phases | Gate |\n|---|---|---|\n| **Understand** | 0–3 | Platform assumptions written down and falsifiable |\n| **Design** | 4–8 | Every object type answers a competency question; every agent fits its tool budget |\n| **Prove** | 9–11 | Linter clean, self-review resolved, readiness verdict given |\n\n**The decision that matters most sits between phases 4 and 5: the map and the build are different documents.** A full domain map may be forty or fifty types; the first build should be a fraction of it, closing on one high-return use case. Teams that skip this arrive a year later with a comprehensive model and no users.\n\n---\n\n## Phase 0 — Scope\n\nFour questions, asked once, before research. Asking them afterwards wastes most of it.\n\n1. **Breadth** — which parts of the business? Offer concrete options: every line, one line, or a thin cross-cutting spine.\n2. **Deliverable** — design document, machine-readable definition, seedable code? Usually the document first.\n3. **Use cases** — what will the first agents actually *do*? Up to four. These decide the model's shape.\n4. **Sources** — internal schemas, or public and standards-based?\n\nIf you cannot ask — the request arrived without a channel back — **state the assumptions you are making at the top of the deliverable and proceed.** Do not stall, and do not pretend the assumptions are findings.\n\n## Phase 1 — The business dossier\n\nUnderstand the business before naming a type. Structured research: organisational structure, business lines and named products, customer and partner types, commercial model, financials and operating KPIs, strategy and known problems. Demand figures with periods attached, inline sources, and **an explicit list of what could not be verified** — without it, plausible claims arrive indistinguishable from sourced ones and become properties.\n\nThree gates, cheap and commonly missed:\n\n- **Has the business changed since the sources were written?** Segments get re-cut, units spun into separate legal entities. Ask about the last 24 months. Where yes, *legal entity*, *reporting unit* and *accountable owner* are separate axes, not one field.\n- **Is the relationship two-sided?** Does one company appear as customer, supplier, partner and competitor at once? Note it — but do **not** reach for an abstraction yet. `Customer` and `Supplier` stay as types with those names; the identity spine underneath is added only if the business actually asks a question that needs it. `references/modelling-patterns.md` section 2 has the test.\n- **What share of output is internal?** Where internal supply dominates, gross and external figures differ several-fold. Model the discriminator and the elimination basis from day one.\n\n## Phase 2 — Standards grounding\n\nFind the sector's reference model — TM Forum SID in telecoms, FIBO in finance, ACORD in insurance, GS1 in retail supply chain, HL7/FHIR in health, X12/EDI in trade — and mine it for vocabulary, then cut hard.\n\n**A reference model is a checklist for completeness, never a source of object types.** They run to hundreds or thousands of classes because they are built for system-to-system integration; a Blueprint is an operational decision model for humans and agents. Expect to use a small single-digit percentage, renamed in the organisation's language. The same caution applies when someone hands you their enterprise data model and asks you to load it in.\n\nTake the distinctions that earn their keep — catalogue entry vs sold item vs delivered thing; one company vs the several relationships it holds — and then **name each one whatever this business calls it** and the entities everyone forgets — the payable side of a bilateral relationship, the settlement record, the dispute as a lifecycle rather than a flag.\n\n## Phase 3 — Platform assumptions\n\nSee `references/platform-and-data.md`. Write them as a list at the top of the design so a reviewer can falsify them at a glance. Date-check every specification before designing against it; where code contradicts a spec, the code wins.\n\nKeep this list short and keep it about things that change the model. An assumption nobody can act on is noise.\n\n## Phase 4 — Competency questions\n\n**30–40 questions the model must answer, grouped by use case, before naming a single object type.** Then check every type appears in at least one. See `references/competency-questions.md`.\n\nThis is the gate that pays for itself: it reliably finds types that were *enumerated* from the domain rather than *derived* from a need. On the short path, write fewer — ten to fifteen — but do not skip it. It is what stops the model growing to fill the available document.\n\n## Phase 5 — The semantic model\n\nDesign in layers outward from the commercial or operational spine: parties → agreements and accounts → catalogue → demand → delivery → places and resources → snapshots → assurance → financial result → transactions and settlement. Each layer's keys are the next layer's foreign keys.\n\nPatterns, structural tests and the temporal decision frame are in `references/modelling-patterns.md`. Run the four tests as you go rather than at the end — the subset test in particular changes the model, and changing it late is expensive.\n\n## Phase 6 — Actions\n\n**A model that only describes is a schema.** See `references/actions-and-agents.md`.\n\nThe first filter: actions are for human or agentic decisions; pipelines are for automated transformations. Then check every status value is reachable — an enum value nothing produces means a saved query filters on it forever and silently returns nothing.\n\n## Phase 7 — Agent design\n\nArchitecture, not documentation. Agent reliability degrades as tool count grows; roughly ten to twenty is workable. Count object types, actions and metrics together. See `references/actions-and-agents.md`, which also carries the disambiguation registers — the highest-value artefact in the design.\n\n## Phase 8 — Traversal and derivation\n\nWalk every competency question hop by hop. Anything over the platform's ceiling needs an explicit resolution — a shortcut link over a bridge table, or a precomputed value — and all resolutions go in **one register**, not scattered through the design.\n\nA second reason to precompute: a value reached by traversal can never be a *metric*. If anyone will sum, group or trend it, it must be a property.\n\nWhere the platform derives across links, derive rather than copy. Materialise only three classes, and register each: snapshot measures (whose point is that they were true *then*), values beyond the traversal budget, and deliberate second sources kept independent so a reconciliation check can actually fail. A check comparing a derived value against its own definition is a tautology and will never fire.\n\n## Phase 9 — Data foundation\n\nSee `references/platform-and-data.md`. Give the verdict honestly and reason it correctly — on curation, history-dependence and system fragmentation, not row counts.\n\n**The verdict and the plan must agree.** A six-week plan sitting above a \"not ready\" verdict is a contradiction a reader will find, and it destroys confidence in both. If the verdict is \"not ready\", the plan starts with the mart.\n\n## Phase 10 — Self-review\n\nRun the linter, then a review pass against `references/self-review.md`. On the full path, two passes — the second reliably finds defects the first pass's fixes introduced. On the short path, one.\n\n**Cap the document on the short path.** A nine-type model does not need seventeen sections. Registers earn their place when the model is big enough to lose track of; below roughly fifteen types, fold the traversal register, the copies register and the deviations register into the sections they belong to. The model being tight does not excuse the document being long — reviewers judge the artefact, not the object count.\n\n## Phase 11 — Ownership and lifecycle\n\nFull path only. Name a steward per domain, define breaking vs non-breaking broadly enough to include removing an enum value, and instrument usage so unused types can be retired.\n\n**On the short path, skip this entirely.** A ninety-day retirement policy in a six-week build is ceremony, and the reader notices.\n\n---\n\n## Deliverables\n\n| Document | Reader | Contains |\n|---|---|---|\n| The design | The client | The model and only the model. No methodology commentary, no platform critique |\n| `model.yaml` | The linter, and whoever builds it | The machine-readable definition |\n| Gaps and learnings | The platform team | **Full path only.** Where the platform constrained the design and what each constraint cost |\n\nKeep them separate — a design that doubles as a platform critique is a design the client cannot trust. And keep platform commentary out of the client document: a section specifying interfaces for a primitive that does not exist is for the platform team, not for the person paying for the model.\n\n**Ship something runnable.** This is the most consistent finding from independent review of work produced this way: a deliverable that executes beats a deliverable that describes, and it is not close. `model.yaml` counts only if the reader is on a platform that loads it — and often they have not chosen one.\n\nWhere the platform is unnamed, or the request has a delivery date on it, add:\n\n- **A schema** in whatever the obvious substrate is — DDL, migrations, a typed schema file — with the constraints and triggers that enforce the invariants you claim.\n- **A worked example that runs.** Take the hardest requirement, put real numbers through it, and ship the script that reproduces the table in your document. If restatement is the hard part, show what the period looked like before, what it looks like now, and prove the difference is the development figure. A reader who can execute your claim stops auditing your prose.\n\nThis is also the cheapest credibility you will ever buy: it converts your hardest assertion into a test, and it gives the team a red/green definition of \"week two is done\".\n\n**Make the runnable thing drive the schema you are shipping.** A test that builds its own miniature schema in memory proves the idea and nothing about the artefact. Load the real file, and let the rejections come from its constraints and triggers rather than from your script — otherwise every control you advertise is untested, and reviewers do check.\n\n**Where there is a deadline, ship a cut list.** An ordered list of what to drop if week four slips, and a short list of what must never be dropped because it is a rewrite rather than an addition. Independent reviewers picked this out repeatedly as the most valuable page in a deadline deliverable: a gate tells the team whether it worked, a cut list tells them what to do when it is late.\n",
26
+ "designing-frontera-blueprint/references/modelling-patterns.md": "# Modelling patterns, structural tests and temporal design\n\n## Part 1 — The patterns\n\nFive patterns worth knowing by name, plus the temporal decision frame. These recur in every domain; recognising them saves rediscovering them badly.\n\n## 1. Name it what the business names it\n\n**This comes first because it is the rule everything else defers to, and it is the one most often lost.**\n\nAn object type is a real-world thing the business already has a word for. If nobody in the company says the word out loud in a meeting, it is not an object type — it is an abstraction you imported, and it will read as a stranger's model to everyone who has to use it.\n\n**The test: say it out loud.** \"Pull up the customer\" — fine. \"Pull up the party\" — nobody has ever said this. \"Which carrier moved it\" — fine. \"Which party role moved it\" — no.\n\nThis matters more than aesthetics for three reasons. The business has to recognise their own company in the model, or they will not correct it and it will drift. The agent selects a type by reading its name and description, so an abstract name is a name it cannot match to a user's question. And an abstraction imported from a reference model brings that model's *purpose* — system-to-system integration — into a place that exists for human and agent decisions.\n\n**Where the business's word is genuinely ambiguous**, resolve it with the business, not with a standard. \"Account\" means three things in most companies; the fix is asking which one they mean and naming that, not retreating to `Party` because it offends nobody.\n\n**Reference models are for coverage, not for names.** Take the *distinctions* they teach — that a catalogue entry, a sold item and a delivered thing are three things — and then name each one whatever this business calls it.\n\n## 2. One organisation, several relationships\n\n**The problem this actually solves.** In many B2B domains the same real-world company appears in more than one capacity: it buys from you and you subcontract to it; it is a supplier and a rebate counterparty; it is a tenant and a joint-venture partner. If `Customer` and `Carrier` are separate types keyed on their own ids, that company exists twice and nothing can net the two sides.\n\n**Start here, and stay here if you can.** Use the business's nouns as the object types: `Customer`, `Supplier`, `Carrier`, `Tenant`. Most domains never need more, and a model of concrete nouns is worth more than a technically superior model nobody recognises.\n\n**Escalate only when the duplication is real and costs something.** The test is a question the business actually asks and cannot answer: *\"what is our net position with this company across everything?\"* or *\"is this the same company we buy from?\"* If nobody asks it, do not build for it.\n\n**When you do escalate, escalate with the business's word for the company** — and use the extension pattern (section 4 below), not a role-typed abstraction:\n\n```\nCompany ← their word: company, organisation, account, counterparty,\n ├── Customer trading partner, operator. Ask. Never \"Party\".\n ├── Carrier ← each a 1:1 extension carrying what is true only of\n └── Supplier that relationship: credit limit, SCAC code, payment terms\n```\n\n`Customer` and `Carrier` survive as first-class types with the business's names on them. `Company` is the identity spine that makes \"the same company, both directions\" answerable. Depth stays at one, and the pattern is the same one you already use for places (section 4) — which is why it needs no new concepts to explain.\n\n**What this is not.** It is not `Party` + `PartyRole` with a `roleType` enum. That collapses every relationship into rows of one abstract type, and the words the business uses — customer, carrier, supplier — stop being types at all and become enum values. You gain nothing structurally and you lose every concrete noun in the model.\n\n**Where the relationship kinds run to a dozen or more** — a carrier that is customer, supplier, interconnect partner, peering partner, roaming partner, consortium member and landlord — an extension per kind stops being clean. Keep concrete types for the handful the business names constantly, and let the long tail be one typed relationship object. Name that in their words too: traders say `TradingRelationship`, telcos say `CarrierRelationship`, insurers say `Appointment`. The rule does not change; only the shape does.\n\n**The one exception:** where the business genuinely says \"party\". Legal and insurance do — \"parties to the agreement\", \"third party\". If it is their word, it is the right name. That is the test, not the pattern.\n\n## 3. Object-backed links — when the relationship has data\n\n**The problem.** A link expresses that two things are related. It cannot express that the relationship has a start date, a role, a rent, a percentage or a status.\n\n**The pattern.** Promote the relationship to an intermediary object type with a foreign key to each end, and name it whatever the business calls that relationship. A tenancy is one (which tower, which tenant, at what height, for what rent, over what period), a shareholding (which holder, which company, what percentage, what investment), an agreement line (which contract, which site, what term, effective when).\n\nThis is the standard answer, not a workaround. The tell is a link you keep wanting to hang an attribute on.\n\n**Watch for:** an intermediary that is really *two* concepts — a tenancy that carries both the physical occupation and its billing. If the two have different lifecycles, split them.\n\n## 4. Closed core plus 1:1 extensions\n\n**The problem.** A core type accumulates a property for every variant, and ends up with most properties null for most rows. Design capacity in megawatts is not true of a tower; wind load is not true of a data hall.\n\n**The pattern.** The core carries only what is true of *every* instance — identity, geography, status, ownership. Each variant is a separate object type linked one-to-one, keyed on the core's key. Depth stays at one; a new concern arrives as a new linked type rather than a column on the core.\n\n**Two details that matter:**\n\n- **Extensions are optional by presence, never gated on a category value.** Real things are frequently two categories at once — a cable landing station that is also a network node, a site that is both warehouse and retail. A `primarySiteCategory` plus a multi-valued `categories` is fine for display; do not let it decide which extensions may exist.\n- **Extensions mirror the core's key**, which makes the 1:1 link trivial and unambiguous. Key uniqueness is per type, so reuse is legal.\n\n**The test that tells you to split:** more than one property relevant to only a subset of a type's instances. See Part 2 below.\n\n## 5. One type with a discriminator, not two mirror types\n\nBought and sold. Issued and received. Receivable and payable. Revenue and cost. Capacity acquired and capacity granted. Each pair shares every structural property and differs only in the direction of value.\n\n**One type, carrying a direction** (or a signed amount) keeps \"net position\" a single aggregation instead of a union, and halves the property count. A signed `amount` makes margin `sum(amount)`; two types make it a cross-object formula that many platforms cannot express as a metric at all.\n\n**Apply it consistently or not at all.** A model that collapses three such pairs and leaves the fourth split cannot defend the inconsistency, and a reviewer will find it. If one pair genuinely differs — different lifecycle, different owner, different security class — say why in the design.\n\n## 6. Entity, event, snapshot — the temporal decision\n\nObject types are current state and destructive on update in most platforms. **History is not free; if you need it, model it.**\n\n| Need | Construct | Key |\n|---|---|---|\n| What is it now | Entity type, mutable properties | Natural business key |\n| What happened, and when | **Event type** — immutable, explicit start and end | Event id |\n| What did the record look like on date D | **Snapshot type**, period grain | Hash of `(entityId, periodDate)` |\n| High-frequency numeric series | Time-series property, if the platform has one | — |\n\n**The rule underneath all of it: separate identity from observation.** If a row is a measurement or an event *about* an entity, the entity and the observation are different object types. Flattening a measurement onto its entity destroys every trend question and every \"how did it get like this\".\n\n**The snapshot test:** will anyone ask how a number moved? A metric over a current-state type has no history to walk, no matter how expressive the query engine is. If the answer is yes, that needs a snapshot type — and it needs to exist from the first wave, because retrofitting one means backfilling history nobody kept.\n\n## 7. Bitemporality — when it is forced on you\n\nA domain is bitemporal when it has any of:\n\n- **Effective-dated reference data that gets retroactively corrected** — rate cards, price lists, tax tables, contract terms.\n- **Restated closed periods** — a dispute resolved in July changes what March was worth.\n- **Late-arriving transactions** — usage, claims, settlements that land in a period after the one they belong to.\n\nPricing, contracts, settlement, insurance and regulatory reporting usually qualify. If any apply, a current-state model can answer \"what is March worth now\" and nothing else — and dispute resolution has no evidence base.\n\n**The mechanism is three additions:**\n\n- **Valid time** — `validFrom` / `validTo`: when the fact was true in the world.\n- **Transaction time** — `knownFrom` / `knownTo`: when we believed it. Add to the reference types where being wrong costs money.\n- **Restatement** — `restatementVersion` **inside the primary key hash**, plus `isCurrentRestatement`. Inside the key is what makes prior versions survive rather than being overwritten.\n\nPlus `arrivalDate` alongside the business date on late-arriving facts.\n\n**Pick one mechanism and stop.** Versioning inside the key, a current-version flag, and a known-from/known-to pair are three ways to express the same thing, and models routinely ship all three. The flag is derivable from the window; the window is derivable from the version sequence. Carrying all three means three things to keep consistent and three ways for them to disagree. Choose the one your platform queries most cheaply, derive the others if you need them, and say in the design which is authoritative.\n\n**The convention that keeps it usable:** every default object set and every metric filters to the current version, and only a specialist drops the filter. Without that, bitemporality doubles the cognitive load on every query and gets switched off within a quarter. If metrics cannot carry a filter, this needs pre-filtered views — see `platform-and-data.md` Part 1 section 3.\n\n## 8. What not to build\n\n| Do not create | Because | Instead |\n|---|---|---|\n| A `Party` / `PartyRole` pair, where the business says customer and supplier | It replaces every concrete noun with an abstraction and an enum | Their nouns as types; an identity spine underneath only if section 2's test passes |\n| Both `Agreement` and `Contract` | Permanent synonym problem; neither humans nor agents resolve it consistently | Pick one name and use it everywhere |\n| Per-department copies of a shared concept | Five source systems produce five answers to one question | One canonical type |\n| A type per state — `PendingOrder`, `DisputedInvoice` | The class an instance belongs to should not change often | A status property |\n| A row-level transaction type at source grain | Volume breaches page and readiness limits by orders of magnitude | Pre-aggregate upstream to the decision grain |\n| Deep inheritance chains | A root change ripples unpredictably | Extensions at depth one, or interfaces |\n\n---\n\n## Part 2 — Structural tests and the anti-pattern catalogue\n\nRun these before review, not after. They are mechanical, they take minutes, and each one reliably catches something in a model that already looks finished.\n\n## The four tests\n\n### 1. Subset test — the split trigger\n\n**More than one property relevant to only a subset of a type's instances means the model should go one level lower.**\n\nTypical catches: industry-specific identifiers on a general party type, null for every non-industry counterparty; line-of-business-specific commercial terms on a general agreement header; endpoint properties on a sold-item type where only some items have two ends.\n\n**Two fixes, and the second is usually better:**\n\n- **An extension type** — move the subset properties to a 1:1 linked type. Right when the subset is a *kind of thing*.\n- **A typed line item** — move them to a child type with a `type` discriminator. Right when the properties are *terms*, and it has a bonus: terms become independently effective-dated, which is what they actually are. Escalators and netting bases get renegotiated without replacing the master agreement.\n\n**When to accept a borderline failure:** two properties, one concept, and splitting would fragment a canonical type across line-specific variants. Accept it — and say so in the design, naming what is being traded. An acknowledged trade-off is defensible; an unacknowledged one is a finding.\n\n### 2. Ownership test — the move trigger\n\n**If you describe a property in terms of an object other than its host, it belongs on that other object.**\n\n\"The customer's name, on the order.\" \"The site's city, on the rack.\" Each of these is a copy. Where the platform derives across links, make it a derived property. Where it cannot, keep the copy, register it, carry the source id alongside — and know that you are trading normalisation for reachability.\n\nThe test also catches genuine misplacement: a property that belongs on a different type entirely and has no business being copied at all.\n\n### 3. Instance-stability test\n\n**The class an instance belongs to should not change often.** A thing that is really a *state* — suspended, disputed, pending, breached — is a status property, not an object type.\n\n**But check the reverse too.** Something that looks like a flag may deserve to be a type if it has its own participants, evidence, timeline and outcome. A dispute is not a boolean on an invoice: it has a raiser, a category, an amount, evidence, an owner, an age and a resolution. The question is not \"is it a state\" but \"does it have its own life\".\n\n### 4. Rule of three\n\n**Refactor on the third repetition.** One is coincidence, two is a pattern, three is a signal.\n\nWhere the platform cannot yet express the abstraction — a capability interface, say — **record it as a deferred abstraction** rather than duplicating it silently. Naming it does three things: it stops the fourth copy being added thoughtlessly, it makes the eventual migration mechanical, and it tells a reviewer you noticed.\n\n## The anti-pattern catalogue\n\n| Anti-pattern | Detection signal | Fix |\n|---|---|---|\n| **Kitchen sink / mirrored source schema** | Properties map 1:1 to source columns; names like `dt_last_mod`; the model was derived by examining data rather than understanding the domain | Re-derive from competency questions; rename in the business's language |\n| **God object** | Wide, sparse type; every new use case adds a column to the same core | Subset test → extensions |\n| **Combination types** | A type name is an adjective plus a noun from two different domains | Compose capabilities; do not multiply types |\n| **Deep inheritance chains** | Adding a capability requires restructuring the hierarchy | Depth one, extensions or interfaces |\n| **Golden hammer** | Actions that fire with no human or agent judgement behind them | Those are pipelines |\n| **Embedded entities** | A name or attribute of another object stored inline and not linkable | Derive it, or register the copy with its source id |\n| **Siloed duplication** | Two types that are the same concept from two departments | One canonical type; roles or a discriminator for the difference |\n| **Isolated types** | A type in no link | Link it, or cut it — an agent cannot reach it |\n| **State-as-type** | `PendingX`, `ClosedY` | Status property |\n| **Reference-model transplant** | Type names match an industry standard's abstractions rather than the business's vocabulary | Use the standard as a checklist, not a source |\n\n## Consistency checks a reviewer will run\n\nCheap to self-check, embarrassing to be caught on:\n\n- **Counts in prose match the tables.** A design giving three different numbers for the same thing has a credibility problem larger than the discrepancy.\n- **Every pattern is applied consistently.** If the one-type-with-a-discriminator pattern is used three times and abandoned once, either fix it or explain it.\n- **Every claim about the business is sourced or flagged.** Anything the research could not verify belongs in an open-questions section, not as a property.\n- **Every deviation from a stated principle is named.** \"We violate normalisation here, for this platform reason, and here is the exit\" is defensible. Silence is not.\n\n## Business-context quality checks\n\nBeyond null and type validation, encode the rules that reality imposes — these belong in the design and catch real errors:\n\n- **Capacity containment** — the sum of allocations does not exceed the resource's capacity; children's committed amounts do not exceed the parent's design.\n- **Identity arithmetic** — a netted position equals its two sides; available equals design minus allocated. **But source at least one side independently**, or the check compares a derived value against its own definition and can never fail.\n- **Referential completeness** — every active sold item resolves to exactly one agreement and one account; every internal counterparty resolves to a legal entity.\n- **Temporal sanity** — end after start; no overlapping active occupancy of the same slot; exactly one current restatement per grain.\n- **Governance** — where separation of duties is required, two decision records with different actors.\n",
27
+ "designing-frontera-blueprint/references/platform-and-data.md": "# Frontera's platform answers, and the data foundation\n\n## Part 1 — What Frontera actually gives you\n\nThe upstream version of this file asks eight platform questions abstractly,\nbecause it is written for any object-graph platform. Here the platform is known,\nso the answers are given. **Still write them into the design as a list** — a\nreviewer should be able to falsify a premise at a glance, and a premise that has\nchanged since this file was written is exactly what you want them to catch.\n\nWhere this file and the CLI's generated help disagree, the CLI wins. It is\ngenerated from the command table; this is prose.\n\n### 1. Primary key — single-property\n\nA Blueprint object type identifies an instance by **one** primary key drawn from\na column of its backing model. Composite grain therefore needs a deterministic\nhash produced upstream, e.g. `sha256(concat_ws('|', period, entity, party,\nproduct))` materialised as `<type>Key`. Record the grain columns in the design:\na hash whose inputs are undocumented is unmaintainable.\n\n**Never an ETL surrogate.** A key that changes on reload loses edits, breaks\nlinks, and invalidates every saved query and every citation an agent ever gave.\nThis is one of the three things that cannot be fixed later.\n\n### 2. Traversal — links with declared cardinality, walked by agents\n\nLink types carry a cardinality, the explorer walks them, and a granted agent\ntraverses them when a question spans types. Three hops is the working ceiling and\nis roughly where retrieval quality holds up anyway; set `meta.traversal_limit` in\n`model.yaml` so the linter checks against a number you decided rather than an\nassumption.\n\n**What changes:** impact questions (\"who is affected by this outage\") and\n360-degree questions (\"everything about this counterparty\") are naturally four or\nfive hops. They need shortcut links over bridge tables, plus precomputed counts.\n\n### 3. Metrics — yes, they filter, dimension and bucket time\n\nFrontera metrics are named measures bound to a metrics view in the analytics\nconnection. Agents query them with a **time grain, dimensions and filters**, and\nseveral in one call. So the expressive column of the classic trade-off applies:\n\n- revenue can be a filtered measure rather than a signed split column;\n- ratios can be named measures rather than a numerator and denominator the\n consumer divides;\n- a restatement predicate can live in the metric.\n\n**The one thing that does not follow:** a dimension has to exist on the bound\nmetrics view. A filter an executive will reach for is still a materialisation\ndecision upstream — it is just made in the view rather than on the object type.\n\nPromote a number to a metric when it is **quoted across contexts**. If it is\ncomputed ad hoc in three places, those three places will eventually disagree.\n\n### 4. Derived properties — same-object\n\nBlueprint properties are typed fields mapped from the backing model's columns.\nThere is no link-traversing derived property, so **every cross-object value\nbecomes a mart column**.\n\nHandle it the way the platform cannot: register all of them in one table with\nthe source id alongside, give the mart sole write authority, and add\nreconciliation checks — each copy is drift surface. Then say plainly in the\ndesign that this is a knowing deviation from \"store each fact once\", and why.\n\n### 5. Interfaces — not available; use a naming contract and groups\n\nThere are no capability interfaces to declare conformance against. The\nsubstitutes are a **naming contract enforced by review** (`siteId` always means\nthis; `<x>From`/`<x>To` always means that) and the free-form **group** labels\nthat organize the registry.\n\n**Specify the interfaces anyway**, with a conformance column per implementer.\nWriting the spec is what surfaces the drift, and it makes an eventual migration\nmechanical rather than a redesign. Expect to skip Actions that would have to be\nbuilt once per implementing type — building one seven times repeats the same\nshape six times too many.\n\n### 6. Actions — authored, typed, reviewed\n\nFrontera has real authored Actions: a portable Definition carrying subject,\ntyped inputs, outcomes, concurrency, impact and approval, deployed through a\nreviewed Binding onto exactly one target. Specify each properly and let the\nplatform enforce.\n\nTwo constraints to design around:\n\n- **One Binding, one effect boundary.** No fan-out, no target chosen from\n invocation data, no runtime fallback. A cross-system process is an\n orchestrated sequence of separate Actions, each with its own certainty and\n compensation policy. \"Close the incident and resolve its linked breaches\" is\n two Actions and a consistency check, not one transaction.\n- **Approval belongs to the Definition.** An Action that declares approval\n cannot be talked out of it by a caller. Decide it when you design the Action,\n not when you wire the consumer.\n\nThe platform records a request, approval, attempt and outcome ledger of its own.\nProject what the business needs to *query* — which Action, which actor, human or\nagent, when, against which object, prior and new value, and the amount at stake\n— into the model as an object type. That is what turns \"who waived this, when,\nand against what exposure\" into an aggregation rather than a support ticket.\n\n### 7. Security — object-type grants, two-dimensional\n\nAccess is granted per **workspace** and per **agent**, at object-type\ngranularity. There are no row-level or column-level policies.\n\nA workspace granted a type therefore sees **every row of it**. Where a model\nspans legal entities, joint ventures or a regulated separation, disclose this\nexplicitly — \"the scoping is advisory, not enforced\" — and contain it by\ngranting sensitive types to as few workspaces as possible.\n\n**Do not fork the object type per entity.** That is the anti-pattern; it\nfragments the canonical type the whole design exists to create.\n\n### 8. Writeback — a governed overlay, with the ledger\n\nWrites do not go into the source system by default. A property must be declared\n**editable**, and a governed Action is what writes it; the edit is stored as an\noverlay over the read model, with the Action ledger as its audit trail. The\nauthoritative business record stays where it already lives unless a Binding was\ndeliberately deployed against it.\n\n**Say this to the customer explicitly and early.** The alternative reading —\nthat an agent will write into their billing system — is the one that stops\ndeployments, and it is the reading people default to.\n\nNarrowing the editable set is itself a governed act: an edit already stored\nagainst a property that stops being editable is no longer readable.\n\n## Recording the answers\n\nPut them in the design as a table, note anything you could not verify against\nthe live deployment, and set the two the linter uses:\n\n```yaml\nmeta:\n traversal_limit: 3\n agent_tool_budget: 20\n```\n\nIf an assumption is uncertain, say so and name what changes if it is wrong. That\nsentence is what lets a reviewer catch a bad premise in ten seconds instead of\nafter the model is built around it.\n\n---\n\n## Part 2 — The data foundation\n\nGive an honest readiness verdict early and do not soften it. This is also where the calendar time actually goes, so getting it wrong makes every other estimate wrong.\n\n## The readiness ladder\n\nWalk top-down and stop at the first tier that fits.\n\n### Tier 1 — Ready: connect and go\n\nThe data team has already modelled it. Look for fact tables with dimension tables around them, joining on declared keys. Any recognisable star schema or curated mart qualifies; volume does not matter, because the modelling work is done.\n\n**Next step:** map object types onto the marts and demo the same week.\n\n### Tier 2 — Simple: write projection models\n\nNo marts, but the operational schema is clean and small enough to project with stateless `SELECT` models. All of these must hold:\n\n- Tables have primary keys.\n- Relationships are explicit — declared foreign keys, or join columns that are obvious and consistently named.\n- The volume is projectable — a stateless `SELECT` over it returns in seconds. Judge this by *behaviour*, not by a row count: tens of millions of rows are unremarkable on a modern warehouse and only become a problem when there is no curated layer and no ability to project.\n- **Current state is readable directly** — no replaying events or history to derive it.\n- The schema is tidy: no litter of `tmp_`, `_backup`, `_old`, `_copy`.\n\n**Next step:** scope the projection models and name the tables they read.\n\n### Tier 3 — Not ready: the mart comes first\n\nAny one of these disqualifies:\n\n- **History-dependence.** Current state must be computed rather than read. Signals: validity-window columns, `*_history`, `*_snapshot`, `*_versions`, ledger tables.\n- **Volume that defeats stateless projection** — the operational store cannot serve the query without materialisation, and there is nothing materialising it. **Do not cite a row count as the reason.** Naming a threshold like \"above ten million rows\" will get the whole verdict dismissed by the first competent data engineer who reads it, and they will be right to dismiss it; modern stacks handle that comfortably. The real disqualifier is the absence of a curated layer, not the size of the raw one.\n- **Missing primary keys** across a meaningful share of the schema.\n- **Clutter** — several backup or temp tables and nobody can say which is authoritative.\n- **Sprawl** — a schema large enough that nobody can say which table is authoritative, with no curated layer over it.\n\n**Next step: be direct.** A Tier 3 verdict is a *scope statement, not a rejection*: the first deliverable is a conformed mart, and the Blueprint design is its specification. Say it in those words. Almost nobody in this market will tell a prospect their data is not ready — having a checkable verdict is a differentiator, not an apology.\n\n### Questions that surface the tier fast\n\n- \"Do you have a warehouse or BI layer, or do reports run on production?\"\n- \"If I asked for current customer status, is that one table, or do I replay history?\"\n- \"How many tables, and how big is the largest?\"\n- \"Who owns the schema — a data team, or the application?\"\n\nExpect a multi-entity group after a restructuring to be Tier 3 almost by construction: several source estates, assets that moved between legal entities mid-year, and agreement state that needs validity-window resolution.\n\n**Reason the verdict from the signals that actually disqualify, and say which ones apply.** A verdict of \"Tier 3 because you have 11 million rows\" is wrong and will be dismissed. \"Tier 3 because current state has to be replayed from history, reporting runs off a replica with no curated layer, and three source systems disagree about who a customer is\" is the same verdict, correctly argued, and it survives the room.\n\n**The verdict must agree with the plan.** A six-week schedule printed above a not-ready verdict is a contradiction a reader will find. If the answer is not-ready, the plan starts with the mart and says so.\n\n## The mart contract\n\nOne table or view per object type: current-state, denormalised, with a declared primary key. Write it as a table in the design — mart output, object type it feeds, and **the hard part**, stated honestly.\n\nThe hard part is almost always **a conformed master for the entity that appears in every other type** — the customer, the party, the product, the site. That single dependency usually decides whether the headline question has one answer or several, and it is the thing to name in the first conversation rather than the fifth.\n\nAlso specify:\n\n- **Bridge tables** for every many-to-many link and every shortcut link, by name.\n- **Snapshot tables** for every snapshot object type — without them there is no trend, and no amount of query expressiveness substitutes.\n- **Which precomputes are required**, and which are only there because a platform primitive is missing. The second list should shrink over time; label it so it can.\n\n## Keys\n\n| Pattern | When | Form |\n|---|---|---|\n| Natural business key | The business already has an identifier | Use it verbatim |\n| Deterministic hash | Composite grain | `sha256(concat_ws('\\|', <grain columns>))`, materialised upstream. **Document the grain columns** |\n| Extension mirror key | 1:1 extension of a core type | Reuse the core's key |\n\n**Never an ETL surrogate.** A key that changes on reload loses edits, breaks links and invalidates every saved query and every agent citation. Where a type is restatable, the restatement version goes **inside the hash**, so prior versions survive rather than being overwritten.\n\n## Refresh\n\n- **Dimension-grain types** reload in full. They are small, and correctness beats cleverness.\n- **Fact-grain types** hydrate full-then-incremental on the deterministic key, so a replayed window overwrites rather than duplicates.\n- **Snapshot types** append one partition per period and are never back-edited.\n- **Bitemporal types never overwrite a superseded row** — close the known-to window and insert.\n\n## Budget honestly\n\nRoughly **80% of effort** in a programme of this kind goes into data cleaning, entity resolution and schema mapping — not modelling. A plan that does not reflect that is wrong, and it will become visibly wrong late, which is the expensive way.\n\nSay this at the start. It reframes the modelling work from \"the project\" to \"the specification for the project\", which is both accurate and much easier to deliver against.\n",
28
+ "designing-frontera-blueprint/references/review-mode.md": "# Review mode — auditing someone else's model\n\nSomeone has written an object model and wants to know what is wrong with it before they build it. This is not the design workflow run backwards. It has different inputs, a different output, and a different audience — the person reading it usually has to carry your findings back to the team that wrote the thing.\n\n## What a good review is\n\n**A defect list they can act on, ordered by cost of being wrong**, grounded in *their* domain rather than in your methodology. Everything else is secondary.\n\nThree failure modes to avoid, all of which independent reviewers have flagged in output produced from this skill:\n\n1. **Grading the model against a process it was never asked to follow.** \"There are no competency questions\" is not a defect in their model; it is an observation about how it was produced. If the absence caused a concrete problem — a type nobody needs, a use case nothing supports — report *that*, and the missing questions as the cause.\n2. **Structural findings crowding out domain findings.** Running the tests is fast and feels productive, and it will find the naming, keying and typing defects. It will not find that they have modelled a reusable shipping container as if it were single-use, or that a business with claims has no cargo-item level to attach a claim to. **Domain defects are the ones that cost money.** Read the model as someone who knows the business, not only as someone who knows modelling.\n3. **Manufacturing volume.** Transcribing their model into your own format so a tool can score it produces impressive-looking output that the client cannot audit and that is, in the end, your own transcription scored against your own rules. Do it only when the model is large enough that mechanical checks will find things reading will not — and when you do, report defect classes rather than instance counts, and say plainly that it is your transcription.\n\n## The workflow\n\n### 1. Read their notes first, then the model\n\nWhatever they wrote around the model — a covering note, comments, \"notes from the team\" — is where the requirements are. Read it before the model itself, and extract:\n\n- **What they say the model must do.** These become the acceptance test. A model that cannot answer its author's own stated requirement is the strongest finding available, and it is entirely fair because they set the bar.\n- **What they already know is wrong.** Teams frequently flag a problem in prose and then model it the way that causes it. \"Some companies are both a customer and a carrier for us; currently they appear twice\" followed by three separate types is a gift: the finding writes itself and nobody can argue it is your preference.\n- **Volumes, systems and constraints** — these drive the readiness verdict.\n\n### 2. Score their model against their own stated requirements\n\nFor each requirement they named: can this model answer it? Where the answer is no, say what is missing. This section usually carries the review, because it is unarguable.\n\n### 3. Run the structural tests\n\nFrom Part 2 of `references/modelling-patterns.md`: the subset test, the ownership test, the instance-stability test, and the anti-pattern catalogue. These are fast. Common finds, roughly in order of frequency:\n\n- Several types for one concept, where one real-world thing has been split by source system — and the reverse, an abstraction that has swallowed the words the business actually uses\n- Joins on names rather than keys\n- Derived values stored as columns — especially percentages, which cannot be aggregated\n- A state modelled as an object type\n- One type conflating several concepts with different lifecycles\n- No history where the requirements need it\n- Free-text where a controlled vocabulary or a reference type belongs\n- Missing currency, unit or timezone on quantities that have them\n\n### 4. Read it as a domain expert\n\nThis is the step that distinguishes a good review. Ask, for this specific business:\n\n- **What is physically or commercially true that the model cannot represent?** Reusable assets modelled as single-use. Multi-party transactions modelled as two-party. Things that can be partially delivered, partially paid, partially cancelled.\n- **What does every business of this kind have that is missing here?** Documents. Addresses of more than one kind. The payable side of anything with a receivable side. Compliance regimes reduced to a single expiry date.\n- **What has one amount that needs several?** A claim with one `amount` that must serve claimed, reserved, settled and recovered. A charge with one `cost` that must serve rated, accrued, invoiced and settled.\n- **Which properties will never be populated?** Assets they do not own, systems they do not run, data that belongs to a counterparty.\n\n### 5. Give the readiness verdict, correctly reasoned\n\nSee `references/platform-and-data.md`. Base it on **curation, history-dependence and system fragmentation** — not on row counts. Modern warehouses handle tens of millions of rows without breathing, and a verdict justified by volume will be dismissed by the first competent data engineer who reads it, taking your correct conclusions with it.\n\n### 6. Say what you would change\n\nThey asked. A diagnosis without a prescription is half a deliverable. The strongest form is a **disposition table** — their type, what happens to it, why — because it converts your review into their Monday morning.\n\nAdd two things:\n\n- **A first wave.** Name the handful of types that close one of their stated use cases end to end. Without this you hand back a bigger model than the one you criticised for being too big.\n- **The blocking decisions.** The questions that must be answered before anyone writes a pipeline, with names attached where possible.\n\n### 7. Credit what is right — this is not optional\n\nName three or four specific things the model gets right, with the reason. Not a disclaimer, not a compliment — specific correct decisions.\n\nThe reason is practical. Your reader has to take this back to the people who wrote it. Four paragraphs of earned credit are what make thirty criticisms survivable in that room, and a review that lands is worth more than a review that is merely right. Reviewers comparing outputs from this skill picked this out unprompted as the thing that decided which review they would rather receive.\n\n## Tone\n\nThey asked for blunt; give them blunt. Blunt means *specific and unhedged*, not harsh. \"This is a saved filter wearing an object costume\" is blunt. \"The team clearly didn't think this through\" is not blunt, it is rude, and it makes the review unusable in the room it has to be read in.\n\nOpen by separating the team from the work where you honestly can — most bad models are written by competent people under constraints, and the facts you need are usually already in their notes.\n\n## What to check in your own review before sending\n\n- **Every criticism is actually true of their model.** Criticising them for something they did do is the fastest way to lose the room. Check the model text for each finding before writing it.\n- **Counts in your prose match your tables.** \"Three of the five requirements\" above a table showing four is the kind of error that makes a reader re-check everything else.\n- **Your own proposed model does not repeat the defects you just criticised.** This is the most common self-inflicted wound in a review: holding them to a standard your counter-proposal does not meet.\n- **Nothing is asserted about their business that they did not tell you.** Where you assumed, say so at the top, and say which conclusions move if the assumption is wrong.\n\n## Output shape\n\n```\n1. Verdict — one paragraph. Build it, fix it, or don't build it\n2. What they got right — 3-4 specific things\n3. Their requirements, scored — can this model answer what they said it must?\n4. Findings — numbered, most consequential first, each: location · defect · minimal fix\n5. What I'd change — disposition table, their type by their type\n6. First wave — the subset that closes one use case\n7. Data readiness — the verdict and what it means for sequencing\n8. Blocking decisions — what must be answered before a pipeline is written\n9. Assumptions I made — and which conclusions move if they are wrong\n```\n\nFindings are the body; keep everything else tight. If a section would be empty, delete it.\n",
29
+ "designing-frontera-blueprint/references/self-review.md": "# Self-review — before declaring a design done\n\nDesign finds very few of its own defects. A review pass on a substantial model routinely returns dozens, and a second pass reliably finds defects the first pass's *fixes* introduced.\n\n**Run two passes on the full path, one on the short path.** A second pass over a nine-type model is ceremony; a second pass over a fifty-type model is where half the real findings come from.\n\n## Order of operations\n\n1. **Run the linter.** `python3 scripts/lint_ontology.py model.yaml` catches the mechanical class — orphan types, missing join keys, undeclared metric properties, uncovered types, over-budget agents, unreachable status values, actions writing non-editable properties.\n2. **Then a human-or-agent pass** for what static checks cannot see.\n3. **Fix, re-lint, re-review.**\n\nRunning the linter first is not just efficiency — it keeps the expensive reviewer focused on judgement rather than bookkeeping.\n\n## The brief\n\nIf you can dispatch an independent reviewer, give them this verbatim. If you are reviewing your own work, read it as instructions to yourself and be correspondingly suspicious of anything you are pleased with:\n\n> Read the design document and `model.yaml` and act as an adversarial reviewer. Your job is to find **defects**, not to praise. Do not rewrite the document.\n>\n> Check four categories:\n>\n> **1. Internal consistency.** Does every part of the document agree with every other part and with the model file? Look specifically for: properties referenced in one section and absent from another; actions writing properties that do not exist or are not marked editable; metrics whose measures or dimensions reference undeclared properties; object sets filtering on properties or enum values that do not exist; counts stated in prose that disagree with the tables; cross-references pointing at the wrong section.\n>\n> **2. Principle violations.** The document claims to follow stated principles. Where does it not? Look for god objects, duplicated canonical concepts, hierarchies deeper than one level, types that are really states, patterns applied inconsistently, and anything that models a system rather than the business.\n>\n> **3. Platform-constraint violations.** The document states its platform assumptions. Which parts of the design would not compile or run under them? Trace the traversal path for each competency question and flag any that exceed the ceiling without a stated resolution.\n>\n> **4. Overclaiming.** Which factual statements are made with more confidence than their sources support? Which claims does the document elsewhere list as unverified? Which numbers do not reconcile against other numbers in the same document?\n>\n> Return a numbered list, most severe first. For each: **location, what is wrong, and the minimal fix.** Be terse and specific. Only real defects — no style notes. If a section is clean, do not mention it.\n\n## What the second pass catches\n\nWorth knowing so it is not a surprise:\n\n- **Fixes that introduced new inconsistencies** — a property added to one section and not the register.\n- **Specifications that most implementers do not satisfy** — an interface or a naming contract declared, then violated by the majority of the types that claim to conform. This is nearly impossible to see while writing and trivial to check mechanically.\n- **Grants that contradict a stated classification** — an agent given a type the document says is restricted elsewhere.\n- **Newly unreachable things** — a status value whose producing action was removed during the fixes.\n\n## The full checklist\n\n**Scope and derivation**\n\n- [ ] Competency questions written before entities were named, 5–10 per use case\n- [ ] Every object type appears in ≥ 1 question; types with zero are cut or justified\n- [ ] Wave 1 closes on one high-return use case, not the full map\n- [ ] Platform assumptions are an explicit, falsifiable list\n\n**Structure**\n\n- [ ] No type triggers the subset test, or the trade is named\n- [ ] No property triggers the ownership test, or the copy is registered\n- [ ] No type is really a state\n- [ ] No god object, no mirrored source schema, no hierarchy deeper than one\n- [ ] Patterns applied consistently, or the exception is explained\n- [ ] Entity and observation are separate types wherever a row is a measurement or event\n\n**Temporal**\n\n- [ ] Grain explicit per type; entity / event / snapshot chosen deliberately\n- [ ] Bitemporality decided explicitly for effective-dated reference data and restated periods\n- [ ] Every trend question has a snapshot type behind it\n\n**Operational**\n\n- [ ] Every action is a human or agent decision; deterministic work is a pipeline\n- [ ] Parameters unambiguous, categorical ones constrained enums\n- [ ] Idempotency, maker–checker and forward-correction engineered explicitly\n- [ ] Every status value reachable by an action or a named pipeline\n- [ ] High-blast-radius actions require a human submitter\n- [ ] Unenforceable submission criteria marked advisory and re-checked in the quality checks\n\n**Agent readiness**\n\n- [ ] No agent over the tool budget, counting types, actions and metrics\n- [ ] The executive agent gets metrics plus entry points, not everything\n- [ ] Both disambiguation registers exist\n- [ ] Every description states grain, source, cadence and what it is not to be confused with\n- [ ] No isolated types; everything within the traversal budget\n- [ ] Every agent has assigned competency questions **and is granted every type those questions traverse** — the linter checks this; do not promise an agent against a question it cannot reach\n- [ ] Every correcting action moves the current-state value, not only the historical record\n- [ ] One temporal mechanism per concept, not three overlapping ones\n- [ ] The delivery plan is consistent with the readiness verdict — a six-week schedule above a \"not ready\" verdict is a contradiction a reader will find\n\n**Proof**\n\n- [ ] Readiness tier stated honestly, with the mart contract specified\n- [ ] Linter clean of errors\n- [ ] Two review passes; every finding resolved or explicitly declined with a reason\n- [ ] Evaluation suite with numeric thresholds that can fail\n- [ ] Named steward per domain; breaking-change list defined; retirement mechanism live\n\n## Feed the mechanical findings back\n\nIf a review pass keeps finding the same class of defect by hand, that class belongs in the linter. Extending `scripts/lint_ontology.py` is usually a few lines and pays for itself on the next engagement — this is the highest-leverage improvement available to the workflow itself.\n",
30
+ "designing-frontera-blueprint/scripts/lint_ontology.py": "#!/usr/bin/env python3\n\"\"\"\nlint_ontology.py — static checks over a model.yaml ontology definition.\n\nThese are the defects an adversarial review pass finds by hand: orphan object\ntypes, links whose join key does not exist, metrics referencing undeclared\nproperties, object types no competency question asks for, agents over tool\nbudget, status values no action produces. Catching them here is faster, cheaper\nand repeatable, which frees a human reviewer for the things static checks\ngenuinely cannot see — whether the model reflects the business.\n\nUsage:\n python3 lint_ontology.py model.yaml\n python3 lint_ontology.py model.yaml --json\n python3 lint_ontology.py model.yaml --severity error # errors only\n\nExit codes: 0 clean or warnings only · 1 errors found · 2 could not read input.\n\nSchema: see assets/model-schema.md. Every section is optional; the linter\nchecks what is present and stays quiet about what is not, so it is useful from\nthe first ten minutes of a design rather than only at the end.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport re\nimport sys\nfrom collections import Counter, defaultdict, deque\n\ntry:\n import yaml\nexcept ImportError:\n sys.stderr.write(\n \"PyYAML is required: pip install pyyaml --break-system-packages\\n\"\n )\n sys.exit(2)\n\n\nclass Findings:\n def __init__(self) -> None:\n self.items: list[dict] = []\n\n def add(self, severity: str, check: str, where: str, message: str,\n fix: str = \"\") -> None:\n self.items.append({\n \"severity\": severity, \"check\": check, \"where\": where,\n \"message\": message, \"fix\": fix,\n })\n\n def error(self, *a, **k) -> None:\n self.add(\"error\", *a, **k)\n\n def warn(self, *a, **k) -> None:\n self.add(\"warning\", *a, **k)\n\n def info(self, *a, **k) -> None:\n self.add(\"info\", *a, **k)\n\n\n# --------------------------------------------------------------------------\n# helpers\n# --------------------------------------------------------------------------\n\ndef props_of(ot: dict) -> dict[str, dict]:\n return {p[\"api_name\"]: p for p in ot.get(\"properties\") or []\n if isinstance(p, dict) and p.get(\"api_name\")}\n\n\ndef normalise(name: str) -> str:\n \"\"\"Lowercase alphanumeric core of a name, for near-duplicate detection.\"\"\"\n return re.sub(r\"[^a-z0-9]\", \"\", name.lower())\n\n\ndef singularish(name: str) -> str:\n n = normalise(name)\n for suf in (\"ies\", \"es\", \"s\"):\n if n.endswith(suf) and len(n) > len(suf) + 2:\n return n[: -len(suf)]\n return n\n\n\n# --------------------------------------------------------------------------\n# checks\n# --------------------------------------------------------------------------\n\ndef check_object_types(m: dict, f: Findings) -> None:\n types = m.get(\"object_types\") or []\n if not types:\n f.warn(\"no-object-types\", \"model\", \"No object types defined yet.\")\n return\n\n seen: dict[str, str] = {}\n for ot in types:\n name = ot.get(\"api_name\")\n if not name:\n f.error(\"missing-api-name\", \"object_types\",\n \"An object type has no api_name.\")\n continue\n where = f\"objectType:{name}\"\n\n if name in seen:\n f.error(\"duplicate-type\", where, f\"'{name}' is defined twice.\")\n seen[name] = name\n\n if not re.match(r\"^[A-Z][A-Za-z0-9]*$\", name):\n f.warn(\"naming\", where,\n f\"'{name}' is not PascalCase alphanumeric.\",\n \"Object type names are tool names to an agent; keep them \"\n \"conventional and self-describing.\")\n\n p = props_of(ot)\n pk = ot.get(\"primary_key\")\n if not pk:\n f.error(\"no-primary-key\", where, \"No primary_key declared.\")\n elif pk not in p:\n f.error(\"pk-not-declared\", where,\n f\"primary_key '{pk}' is not among this type's properties.\")\n\n tp = ot.get(\"title_property\")\n if tp and tp not in p:\n f.error(\"title-not-declared\", where,\n f\"title_property '{tp}' is not among this type's properties.\")\n\n desc = (ot.get(\"description\") or \"\").strip()\n if not desc:\n f.error(\"no-description\", where,\n \"No description. An agent selects this type by its \"\n \"description; without one it is invisible or misused.\")\n elif len(desc) < 60:\n f.warn(\"thin-description\", where,\n \"Description is very short.\",\n \"State what it is, its grain, its source and refresh, and \"\n \"what it is not to be confused with.\")\n elif \"not to be confused\" not in desc.lower() and len(types) > 8:\n f.info(\"no-disambiguation\", where,\n \"Description does not disambiguate against a similar type.\",\n \"In a model this size, near-synonyms are the main cause of \"\n \"an agent picking the wrong type.\")\n\n if ot.get(\"kind\") == \"extension\" and not ot.get(\"extends\"):\n f.error(\"extension-no-core\", where,\n \"kind is 'extension' but no 'extends' is set.\")\n\n if ot.get(\"status\") not in (None, \"active\", \"experimental\", \"deprecated\"):\n f.warn(\"bad-status\", where,\n f\"status '{ot.get('status')}' is not one of \"\n \"active/experimental/deprecated.\")\n\n # near-duplicate names: the synonym trap\n buckets: dict[str, list[str]] = defaultdict(list)\n for name in seen:\n buckets[singularish(name)].append(name)\n for _, names in buckets.items():\n if len(names) > 1:\n f.warn(\"near-duplicate-names\", \"object_types\",\n f\"Names are near-identical: {', '.join(sorted(names))}.\",\n \"An agent cannot reliably choose between them. Rename, or \"\n \"add an explicit contrast to each description.\")\n\n\nABSTRACT_NAMES = {\n \"party\", \"partyrole\", \"entity\", \"resource\", \"item\", \"thing\", \"object\",\n \"element\", \"node\", \"instance\", \"master\", \"reference\", \"data\", \"info\",\n \"detail\", \"header\", \"record\", \"attribute\", \"artifact\", \"artefact\",\n}\nABSTRACT_SUFFIXES = (\"Entity\", \"Master\", \"Info\", \"Data\", \"Detail\", \"Header\",\n \"Record\", \"Object\", \"Item\")\n\n\ndef check_business_language(m: dict, f: Findings) -> None:\n \"\"\"Object type names should be words the business says out loud.\n\n An abstraction imported from a reference model — Party, Entity, Resource —\n is a name nobody in the company uses and nothing an agent can match to a\n user's question. This check cannot know the business's vocabulary, so it\n flags the names that are abstract in every business and asks.\n \"\"\"\n for ot in m.get(\"object_types\") or []:\n name = ot.get(\"api_name\")\n if not name:\n continue\n where = f\"objectType:{name}\"\n low = name.lower()\n\n if low in ABSTRACT_NAMES:\n f.warn(\"abstract-type-name\", where,\n f\"'{name}' is an abstraction, not a word a business uses.\",\n \"Say it out loud: would anyone in this company ask to \"\n \"'pull up the \" + low + \"'? If the real word is customer, \"\n \"carrier or supplier, use that. Keep this name only if the \"\n \"business genuinely says it — legal and insurance do say \"\n \"'party'.\")\n elif any(name.endswith(s) for s in ABSTRACT_SUFFIXES) and len(name) > 6:\n f.info(\"generic-suffix\", where,\n f\"'{name}' ends in a generic suffix.\",\n \"Often a sign the concrete noun was avoided. If the \"\n \"business calls it something shorter and more specific, \"\n \"use theirs.\")\n\n\ndef check_links(m: dict, f: Findings) -> None:\n types = {ot[\"api_name\"]: ot for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")}\n links = m.get(\"link_types\") or []\n seen = set()\n\n for lk in links:\n name = lk.get(\"api_name\", \"<unnamed>\")\n where = f\"link:{name}\"\n if name in seen:\n f.error(\"duplicate-link\", where, f\"'{name}' is defined twice.\")\n seen.add(name)\n\n src, dst = lk.get(\"from\"), lk.get(\"to\")\n for side, t in ((\"from\", src), (\"to\", dst)):\n if t not in types:\n f.error(\"link-endpoint-missing\", where,\n f\"{side} type '{t}' is not defined.\")\n if src not in types or dst not in types:\n continue\n\n card = lk.get(\"cardinality\")\n if card not in (\"one_to_one\", \"one_to_many\", \"many_to_one\",\n \"many_to_many\"):\n f.error(\"bad-cardinality\", where,\n f\"cardinality '{card}' is not a recognised value.\")\n\n if card == \"many_to_many\":\n if not lk.get(\"join_model\"):\n f.error(\"mn-no-join-model\", where,\n \"many_to_many link has no join_model.\",\n \"A many-to-many link needs a bridge table; without one \"\n \"it cannot be built.\")\n continue\n\n fp, tp = lk.get(\"from_property\"), lk.get(\"to_property\")\n sp, dp = props_of(types[src]), props_of(types[dst])\n if not fp or fp not in sp:\n f.error(\"join-key-missing\", where,\n f\"from_property '{fp}' is not a property of {src}.\",\n \"This link cannot be built. It is the single most common \"\n \"defect in a hand-written model.\")\n if not tp or tp not in dp:\n f.error(\"join-key-missing\", where,\n f\"to_property '{tp}' is not a property of {dst}.\")\n\n # the \"one\" side must be a key\n one_side, one_prop = (src, fp) if card in (\"one_to_one\", \"one_to_many\") \\\n else (dst, tp)\n ot = types[one_side]\n if one_prop and one_prop != ot.get(\"primary_key\") \\\n and not (props_of(ot).get(one_prop) or {}).get(\"unique\"):\n f.warn(\"one-side-not-unique\", where,\n f\"'{one_prop}' on {one_side} is neither the primary key nor \"\n \"marked unique.\",\n \"Cardinality is a promise the data has to keep. Mark the \"\n \"property unique or correct the cardinality.\")\n\n if not lk.get(\"from_phrase\") or not lk.get(\"to_phrase\"):\n f.info(\"no-phrases\", where,\n \"No directional phrases.\",\n \"Cardinality says a link exists; a phrase says what \"\n \"traversing it means. Agents use the phrase.\")\n\n\ndef check_isolated(m: dict, f: Findings) -> None:\n types = [ot[\"api_name\"] for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")]\n linked: set[str] = set()\n for lk in m.get(\"link_types\") or []:\n linked.add(lk.get(\"from\"))\n linked.add(lk.get(\"to\"))\n for t in types:\n if t not in linked:\n f.error(\"isolated-type\", f\"objectType:{t}\",\n f\"'{t}' appears in no link.\",\n \"A type reachable only by filtering is a table, not part \"\n \"of an ontology — an agent will not find it by traversal.\")\n\n\ndef check_reachability(m: dict, f: Findings) -> None:\n \"\"\"Every type should sit within traversal_limit hops of some agent entry point.\"\"\"\n limit = int((m.get(\"meta\") or {}).get(\"traversal_limit\") or 3)\n types = {ot[\"api_name\"] for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")}\n if not types:\n return\n adj: dict[str, set[str]] = defaultdict(set)\n for lk in m.get(\"link_types\") or []:\n a, b = lk.get(\"from\"), lk.get(\"to\")\n if a in types and b in types:\n adj[a].add(b)\n adj[b].add(a)\n\n entries: set[str] = set()\n for ag in m.get(\"agents\") or []:\n entries.update(t for t in (ag.get(\"object_types\") or []) if t in types)\n if not entries:\n return\n\n reach: set[str] = set()\n for start in entries:\n seen = {start: 0}\n q = deque([start])\n while q:\n cur = q.popleft()\n if seen[cur] >= limit:\n continue\n for nxt in adj[cur]:\n if nxt not in seen:\n seen[nxt] = seen[cur] + 1\n q.append(nxt)\n reach |= set(seen)\n\n for t in sorted(types - reach):\n f.warn(\"unreachable-type\", f\"objectType:{t}\",\n f\"'{t}' is more than {limit} hops from every agent's entry \"\n \"points.\",\n \"Either grant it to an agent directly, or add a shortcut link \"\n \"and register it. Types beyond the ceiling are invisible.\")\n\n\ndef check_competency(m: dict, f: Findings) -> None:\n qs = m.get(\"competency_questions\") or []\n types = [ot[\"api_name\"] for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")]\n if not qs:\n f.error(\"no-competency-questions\", \"model\",\n \"No competency questions defined.\",\n \"Without them there is no way to tell a derived object type \"\n \"from an enumerated one. Write them before modelling.\")\n return\n\n covered: set[str] = set()\n for q in qs:\n qid = q.get(\"id\", \"<no id>\")\n for t in q.get(\"types\") or []:\n if t not in types:\n f.error(\"question-unknown-type\", f\"question:{qid}\",\n f\"references undefined object type '{t}'.\")\n covered.add(t)\n text = (q.get(\"text\") or \"\").strip()\n if text and not text.endswith(\"?\"):\n f.info(\"question-not-a-question\", f\"question:{qid}\",\n \"Does not read as a question.\",\n \"If it cannot be answered with a specific number or list, \"\n \"it is a theme — and themes do not justify object types.\")\n\n counts = Counter(t for q in qs for t in (q.get(\"types\") or []))\n for t in types:\n if t not in covered:\n f.error(\"uncovered-type\", f\"objectType:{t}\",\n f\"'{t}' appears in no competency question.\",\n \"It was enumerated, not derived. Cut it, or write the \"\n \"question that justifies it.\")\n elif counts[t] == 1:\n f.info(\"single-question-type\", f\"objectType:{t}\",\n f\"'{t}' is justified by exactly one question — the \"\n \"weakest-justified tier, and the first candidate for \"\n \"retirement if that question goes unasked.\")\n\n\ndef check_metrics(m: dict, f: Findings) -> None:\n types = {ot[\"api_name\"]: ot for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")}\n for mt in m.get(\"metrics\") or []:\n name = mt.get(\"api_name\", \"<unnamed>\")\n where = f\"metric:{name}\"\n home = mt.get(\"object_type\")\n if home not in types:\n f.error(\"metric-home-missing\", where,\n f\"home object type '{home}' is not defined.\")\n continue\n p = props_of(types[home])\n\n measures = mt.get(\"measures\") or []\n if not measures:\n f.error(\"metric-no-measures\", where, \"No measures defined.\")\n for meas in measures:\n prop = meas.get(\"property\")\n if prop and prop not in p:\n f.error(\"measure-undeclared\", where,\n f\"measure references '{prop}', which is not a property \"\n f\"of {home}.\")\n elif prop and p[prop].get(\"type\") != \"measure\":\n f.warn(\"measure-not-numeric\", where,\n f\"'{prop}' is typed '{p[prop].get('type')}', not \"\n \"'measure'.\")\n\n for dim in mt.get(\"dimensions\") or []:\n if dim not in p:\n f.error(\"dimension-undeclared\", where,\n f\"dimension '{dim}' is not a property of {home}.\",\n \"A metric cannot traverse a link unless the platform \"\n \"supports it — declare the dimension or derive it onto \"\n \"this type.\")\n\n ts = mt.get(\"timeseries\")\n if ts:\n if ts not in p:\n f.error(\"timeseries-undeclared\", where,\n f\"timeseries '{ts}' is not a property of {home}.\")\n elif p[ts].get(\"type\") != \"time\":\n f.warn(\"timeseries-not-time\", where,\n f\"timeseries '{ts}' is not typed 'time'.\")\n elif types[home].get(\"kind\") == \"snapshot\":\n f.warn(\"snapshot-no-timeseries\", where,\n \"Metric over a snapshot type has no timeseries property — \"\n \"the reason the snapshot exists is trend.\")\n\n if types[home].get(\"kind\") == \"entity\" and ts is None:\n f.info(\"trend-on-current-state\", where,\n f\"'{home}' is a current-state type, so this metric has no \"\n \"history to walk.\",\n \"If anyone will ask how the number moved, that needs a \"\n \"snapshot type keyed on (entityId, period).\")\n\n\ndef check_actions(m: dict, f: Findings) -> None:\n types = {ot[\"api_name\"]: ot for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")}\n produced: set[str] = set(\n (m.get(\"meta\") or {}).get(\"pipeline_produced_values\") or [])\n\n for ac in m.get(\"actions\") or []:\n name = ac.get(\"api_name\", \"<unnamed>\")\n where = f\"action:{name}\"\n target = ac.get(\"target\")\n if target and target not in types:\n f.error(\"action-target-missing\", where,\n f\"target '{target}' is not defined.\")\n\n radius = ac.get(\"blast_radius\")\n if radius not in (\"low\", \"medium\", \"high\", None):\n f.warn(\"bad-blast-radius\", where,\n f\"blast_radius '{radius}' is not low/medium/high.\")\n hitl = ac.get(\"human_in_the_loop\")\n if radius == \"high\" and hitl not in (\"required\",):\n f.error(\"high-radius-automatic\", where,\n \"A high-blast-radius action is not marked \"\n \"human_in_the_loop: required.\",\n \"Anything that moves money or commits to a counterparty \"\n \"should be prepared by an agent and submitted by a named \"\n \"human.\")\n\n for w in ac.get(\"writes\") or []:\n ot_name = w.get(\"object_type\") or target\n prop = w.get(\"property\")\n if ot_name not in types:\n f.error(\"write-target-missing\", where,\n f\"writes to undefined type '{ot_name}'.\")\n continue\n p = props_of(types[ot_name])\n if prop not in p:\n f.error(\"write-undeclared\", where,\n f\"writes '{prop}', which is not a property of \"\n f\"{ot_name}.\")\n elif not p[prop].get(\"editable\"):\n f.error(\"write-not-editable\", where,\n f\"writes '{ot_name}.{prop}', which is not marked \"\n \"editable.\",\n \"Mark it editable, or the action cannot run.\")\n elif p[prop].get(\"derived\"):\n f.error(\"write-derived\", where,\n f\"writes '{ot_name}.{prop}', which is derived.\",\n \"A derived value has one writer — its definition. \"\n \"Add a separate override property the action owns.\")\n if w.get(\"sets\"):\n produced.add(f\"{ot_name}.{prop}={w['sets']}\")\n\n for sc in ac.get(\"submission_criteria\") or []:\n if sc.get(\"enforced\") is False:\n f.info(\"advisory-criterion\", where,\n f\"criterion is advisory: {sc.get('text', '')}\",\n \"Re-check it post-hoc in the quality checks, and do not \"\n \"let an agent believe it is guaranteed.\")\n\n # unreachable enum values\n for ot in m.get(\"object_types\") or []:\n for prop in ot.get(\"properties\") or []:\n vals = prop.get(\"enum\")\n if not vals:\n continue\n for v in vals:\n key = f\"{ot['api_name']}.{prop['api_name']}={v}\"\n if key not in produced:\n f.warn(\"unreachable-status\", f\"objectType:{ot['api_name']}\",\n f\"'{prop['api_name']}' can be '{v}', but no action \"\n \"produces it.\",\n \"Either add the action, or record the pipeline in \"\n \"meta.pipeline_produced_values. A saved query \"\n \"filtering on an unreachable value returns nothing, \"\n \"forever, silently.\")\n\n\ndef check_agents(m: dict, f: Findings) -> None:\n budget = int((m.get(\"meta\") or {}).get(\"agent_tool_budget\") or 20)\n types = {ot[\"api_name\"] for ot in (m.get(\"object_types\") or [])\n if ot.get(\"api_name\")}\n actions = {a[\"api_name\"] for a in (m.get(\"actions\") or [])\n if a.get(\"api_name\")}\n metrics = {mt[\"api_name\"] for mt in (m.get(\"metrics\") or [])\n if mt.get(\"api_name\")}\n qids = {q.get(\"id\") for q in (m.get(\"competency_questions\") or [])}\n\n for ag in m.get(\"agents\") or []:\n name = ag.get(\"name\", \"<unnamed>\")\n where = f\"agent:{name}\"\n ots = ag.get(\"object_types\") or []\n acs = ag.get(\"actions\") or []\n mts = ag.get(\"metrics\") or []\n\n for t in ots:\n if t not in types:\n f.error(\"agent-unknown-type\", where,\n f\"granted undefined object type '{t}'.\")\n for a in acs:\n if a not in actions:\n f.error(\"agent-unknown-action\", where,\n f\"granted undefined action '{a}'.\")\n for mt in mts:\n if mt not in metrics:\n f.error(\"agent-unknown-metric\", where,\n f\"granted undefined metric '{mt}'.\")\n for q in ag.get(\"answers\") or []:\n if q not in qids:\n f.error(\"agent-unknown-question\", where,\n f\"claims to answer unknown question '{q}'.\")\n\n total = len(ots) + len(acs) + len(mts)\n if total > budget:\n f.error(\"agent-over-budget\", where,\n f\"{total} tools ({len(ots)} types, {len(acs)} actions, \"\n f\"{len(mts)} metrics) exceeds the budget of {budget}.\",\n \"Tool selection becomes the dominant failure mode above \"\n \"roughly twenty. Split the agent or hand off.\")\n elif total > budget * 0.8:\n f.warn(\"agent-near-budget\", where,\n f\"{total} tools is close to the budget of {budget}.\")\n\n if not ag.get(\"answers\"):\n f.info(\"agent-no-questions\", where,\n \"No competency questions assigned.\",\n \"An agent with no questions has no evaluation suite.\")\n\n # Does the agent hold the types its own questions traverse?\n qmap = {q.get(\"id\"): (q.get(\"types\") or [])\n for q in (m.get(\"competency_questions\") or [])}\n granted = set(ots)\n for q in ag.get(\"answers\") or []:\n missing = [t for t in qmap.get(q, []) if t not in granted]\n if missing:\n f.error(\"agent-cannot-answer\", where,\n f\"assigned {q} but is not granted: \"\n f\"{', '.join(sorted(missing))}.\",\n \"The agent is promised against a question it cannot \"\n \"reach. Grant the types, reassign the question, or \"\n \"hand off — but do not ship the promise.\")\n\n\ndef check_actions_write_something(m: dict, f: Findings) -> None:\n \"\"\"Editable properties with no action behind them are an open write path.\"\"\"\n written = {(w.get(\"object_type\"), w.get(\"property\"))\n for ac in (m.get(\"actions\") or [])\n for w in (ac.get(\"writes\") or [])}\n for ot in m.get(\"object_types\") or []:\n for p in ot.get(\"properties\") or []:\n if p.get(\"editable\") and (ot[\"api_name\"], p[\"api_name\"]) not in written:\n f.warn(\"editable-no-action\", f\"objectType:{ot['api_name']}\",\n f\"'{p['api_name']}' is editable but no action writes it.\",\n \"Either an action is missing, or the property should not \"\n \"be editable. An ungoverned write path is the thing \"\n \"actions exist to prevent.\")\n\n\ndef check_dead_properties(m: dict, f: Findings) -> None:\n \"\"\"A property nothing writes and nothing derives is a column of zeroes.\n\n This is the defect that survives every other check: the design says a\n roll-up \"follows automatically\", the property is declared, and no action,\n derivation or stated source ever puts a value in it. It ships reading 0.\n \"\"\"\n written = {(w.get(\"object_type\"), w.get(\"property\"))\n for ac in (m.get(\"actions\") or [])\n for w in (ac.get(\"writes\") or [])}\n for ot in m.get(\"object_types\") or []:\n name = ot.get(\"api_name\")\n if ot.get(\"kind\") == \"snapshot\":\n continue # snapshot measures come from the snapshot job by definition\n for prop in ot.get(\"properties\") or []:\n pn = prop.get(\"api_name\")\n if not pn or prop.get(\"type\") != \"measure\":\n continue\n if prop.get(\"derived\") or prop.get(\"source\"):\n continue\n if (name, pn) in written:\n continue\n f.warn(\"possibly-dead-measure\", f\"objectType:{name}\",\n f\"'{pn}' is a measure that no action writes, that is not \"\n \"marked derived, and that declares no source.\",\n \"Set `derived: true`, name a `source` (dataset | pipeline | \"\n \"action), or delete it. A roll-up that 'follows \"\n \"automatically' does not — it follows from a job somebody \"\n \"has to write, and until then it reads zero.\")\n\n\nCHECKS = [\n check_object_types, check_business_language, check_links, check_isolated, check_reachability,\n check_competency, check_metrics, check_actions, check_agents,\n check_actions_write_something, check_dead_properties,\n]\n\n\ndef lint(model: dict) -> Findings:\n f = Findings()\n for fn in CHECKS:\n try:\n fn(model, f)\n except Exception as exc: # a malformed section should not stop the rest\n f.error(\"linter-error\", fn.__name__,\n f\"check raised {type(exc).__name__}: {exc}\")\n return f\n\n\ndef render(f: Findings, min_sev: str) -> str:\n order = {\"error\": 0, \"warning\": 1, \"info\": 2}\n keep = [i for i in f.items if order[i[\"severity\"]] <= order[min_sev]]\n counts = Counter(i[\"severity\"] for i in f.items)\n\n if not keep:\n return (f\"clean — no findings at or above '{min_sev}'.\\n\"\n f\"({counts['error']} errors, {counts['warning']} warnings, \"\n f\"{counts['info']} info in total)\")\n\n lines: list[str] = []\n by_sev: dict[str, list[dict]] = defaultdict(list)\n for i in keep:\n by_sev[i[\"severity\"]].append(i)\n for sev in (\"error\", \"warning\", \"info\"):\n if not by_sev[sev]:\n continue\n lines.append(f\"\\n{sev.upper()}S ({len(by_sev[sev])})\")\n lines.append(\"-\" * 60)\n for i in by_sev[sev]:\n lines.append(f\" [{i['check']}] {i['where']}\")\n lines.append(f\" {i['message']}\")\n if i[\"fix\"]:\n lines.append(f\" → {i['fix']}\")\n lines.append(\"\")\n lines.append(f\"{counts['error']} errors, {counts['warning']} warnings, \"\n f\"{counts['info']} info\")\n return \"\\n\".join(lines)\n\n\ndef main() -> int:\n ap = argparse.ArgumentParser(description=__doc__,\n formatter_class=argparse.RawDescriptionHelpFormatter)\n ap.add_argument(\"model\", help=\"path to model.yaml\")\n ap.add_argument(\"--json\", action=\"store_true\", help=\"emit JSON\")\n ap.add_argument(\"--severity\", choices=[\"error\", \"warning\", \"info\"],\n default=\"info\", help=\"minimum severity to report\")\n args = ap.parse_args()\n\n try:\n with open(args.model) as fh:\n model = yaml.safe_load(fh) or {}\n except FileNotFoundError:\n sys.stderr.write(f\"no such file: {args.model}\\n\")\n return 2\n except yaml.YAMLError as exc:\n sys.stderr.write(f\"could not parse YAML: {exc}\\n\")\n return 2\n\n if not isinstance(model, dict):\n sys.stderr.write(\"model.yaml must be a mapping at the top level\\n\")\n return 2\n\n findings = lint(model)\n if args.json:\n print(json.dumps({\"findings\": findings.items,\n \"summary\": dict(Counter(i[\"severity\"]\n for i in findings.items))},\n indent=2))\n else:\n print(render(findings, args.severity))\n\n return 1 if any(i[\"severity\"] == \"error\" for i in findings.items) else 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n",
31
+ "designing-frontera-blueprint/SKILL.md": "---\nname: designing-frontera-blueprint\ndescription: Use when designing or reviewing the shape of a Frontera Blueprint — which object types, links, metrics, Actions and agent grants an organization needs, and whether a proposed model is any good. Triggers on outcome language: \"model our business so agents can use it\", \"what object types do we need\", \"here is our proposed model, tell me what is wrong with it\", \"our agents give wrong answers over our data\". This is design method; authoring-frontera-blueprint applies the result. Not for database tuning, ORM mapping or plain ETL design.\n---\n\n# Designing a Frontera Blueprint\n\n> **This copy is Frontera-shaped and ships in the Frontera plugin.** A generic\n> copy lives in this repository at `.agents/skills/blueprint-ontology-design/`\n> for internal work on other platforms. The two are expected to diverge — they have different jobs — and\n> neither is a stale copy of the other.\n\nA model that only describes is a schema. This produces one a governed agent can *act* through — and one that survives review.\n\n## Start here: which job is this?\n\nThe two jobs share principles and share nothing else. Pick one, then work from its file. **Do not run both.**\n\n| Signal in the request | Mode | Work from |\n|---|---|---|\n| No existing model supplied. \"Design\", \"model our business\", \"what object types do we need\" | **Design** | `references/design-mode.md` |\n| An existing model, schema, entity list or ERD is supplied. \"Review\", \"audit\", \"what's wrong with\", \"before we build this\" | **Review** | `references/review-mode.md` |\n| Both — a model exists and they want it redesigned | Review first, then design. The review's findings become the design's constraints | both, in that order |\n| Genuinely unclear | Ask one question: *\"Do you want me to review what you have, or design from scratch?\"* | — |\n\n## Then: how much of it?\n\nEffort should follow the request, and the signals are in the request itself — not in a judgement about how big the domain feels.\n\n**Run the short path** when *any* of these is true. Deliver the model, the reasoning, and the honest verdicts; skip the ceremony.\n\n- They named a deadline or a size constraint — \"six weeks\", \"keep it tight\", \"not a cathedral\", \"just the X side\".\n- The scope is one use case or one process, not a business.\n- They asked a question rather than commissioning a document.\n\n**Short path means:** competency questions, the model, actions, agent scope, the readiness verdict, the wave plan, one self-review pass — and **something that runs**. A schema plus a worked example that executes beats another section of prose, and on a deadline it is what the client will judge you on. **Drop:** the interfaces section, stewardship and retirement policy, the separate platform-gaps document, the second review pass, standalone registers below roughly fifteen object types, and any section whose content would be \"not applicable here\".\n\n**Run the full path** when the scope is a whole business or several lines, no deadline was named, and the deliverable is explicitly a design document.\n\nTwo rules that hold on both paths, because they are where over-serving does real damage:\n\n- **Never write a section whose content is that it does not apply.** Silence is the correct way to note something was considered and excluded.\n- **Anything the requester named out loud is in the first wave.** If they said claims get \"assigned, reserved, revised, settled and restated\", all five are wave 1 — deferring one to a later wave while including something they never mentioned is a failure to listen, whatever the sequencing logic says.\n\n## The non-negotiables\n\nWhichever mode and whichever path, these are the things that cannot be fixed later, so they are worth defending under deadline pressure:\n\n- **Naming and semantic clarity.** Every object type is a real-world thing the business already has a word for. **Apply the say-it-out-loud test: if nobody in the company would use this word in a meeting, it is not an object type.** \"Pull up the customer\" is a sentence; \"pull up the party role\" is not.\n\n **Two rules that follow from this, and are violated constantly:**\n\n **Never take a name from this skill, its references, or its templates.** Every\n example here is illustration, not inventory. The names in `assets/model-schema.md`\n belong to an invented port-operations example and are wrong for your customer by\n construction. If you find yourself writing an object type whose name you first\n read in one of these files, you have skipped the only step that mattered.\n\n **Use their word, in their language.** If the business says *Nasabah*, the\n object type is `Nasabah`. Do not translate it to `Customer` for tidiness, and\n do not generalise it to something that fits any business. The model is read by\n the people who work there and by an agent matching their questions to type\n names; both lose when the word stops being theirs. A wrong name propagates into every application, every saved query and every agent prompt. This is also where the highest-value artefact lives — see the disambiguation registers in `references/actions-and-agents.md`. Independent reviewers of this skill's output called those registers the single best thing in the deliverable, twice.\n- **Identity.** A non-deterministic key destroys edits, links and citations. Never key on an ETL surrogate.\n- **Security design.** A grant that was too wide is not repairable after the fact.\n\nEverything else — normalisation, completeness, elegance — can be conceded and repaired. **Say which you are conceding, explicitly**, where you concede it.\n\n## Shared principles\n\n| Principle | What it prevents |\n|---|---|\n| **Real-world entities, in the business's own words** | Abstractions imported from a reference model — `Party`, `Entity`, `Resource` — that nobody in the business recognises and no agent can match to a question |\n| Model the domain, not the systems | Object types mirroring source-schema quirks, exposing technical columns |\n| Don't repeat yourself | Several source systems producing several answers to one question |\n| Open for extension, closed for modification | A core type where most properties are null for most rows |\n| Composition over deep hierarchies | Inheritance chains where a root change ripples through every query |\n\n**When something becomes an object type:** the business has a name for it, and it has independent identity and lifecycle, several properties, and relationships of its own. Take the *distinctions* a reference model teaches; never take its *names*. When it is an attribute of something else and not worth querying independently, it is a property. When it is a real-world relationship — not a join key inherited from a source system — it is a link.\n\n## The model file and the linter\n\nBoth modes produce **`model.yaml`** alongside the prose — schema in `assets/model-schema.md`. This is what makes the work checkable rather than merely plausible.\n\n```bash\npython3 scripts/lint_ontology.py model.yaml # human-readable\npython3 scripts/lint_ontology.py model.yaml --json # for CI\n```\n\nIt catches what a reviewer would otherwise find by hand: orphan types, links whose join key does not exist, metrics referencing undeclared properties, object types no competency question asks for, agents over tool budget, unreachable status values, actions writing non-editable properties. Run it after every change, not once at the end.\n\n**If you cite the linter to a client, ship it with the deliverable or do not cite it as authority** — a verification they cannot re-run is an assertion wearing a lab coat.\n\n**When reporting linter results to a human, report distinct defect classes, not instance counts.** \"Thirteen types have no description\" is one finding, not thirteen; presenting it as sixteen errors inflates the alarm and costs you credibility with the one reader who checks.\n\n## Reference files\n\n| File | Read it when |\n|---|---|\n| `references/design-mode.md` | Designing from scratch — the workflow, its phases and gates |\n| `references/review-mode.md` | Reviewing someone else's model — the workflow and what makes a review usable |\n| `references/competency-questions.md` | Writing the questions. Both modes need these |\n| `references/modelling-patterns.md` | Naming the patterns, the structural tests, the temporal decision |\n| `references/actions-and-agents.md` | Actions, blast radius, agent scoping, disambiguation registers, evaluation |\n| `references/platform-and-data.md` | Platform assumptions and the data-readiness verdict |\n| `references/self-review.md` | Before declaring a design done |\n| `assets/model-schema.md` | Any time you write `model.yaml` |\n| `assets/design-doc-template.md` | Structuring the design document |\n\n## Where this hands off\n\nThis skill designs and reviews. It changes nothing.\n\n| Next | Skill |\n|---|---|\n| What Blueprint's elements mean, and what a change costs its readers | `understanding-frontera`, reference `blueprint.md` |\n| Turning the design into draft changes on the shared model | `authoring-frontera-blueprint` |\n| Command syntax, the customer profile, exit codes | `using-frontera` |\n| Releasing to the organization | `publishing-frontera` |\n\nBlueprint authoring requires an organization credential; a workspace credential\nreads and cannot author. Say so early if the person only has the latter — it\nchanges who has to be in the room.\n",
32
+ "publishing-frontera/agents/openai.yaml": "# Codex presentation and policy metadata.\ninterface:\n display_name: Publishing on Frontera\n short_description: Live transitions — only on an explicit request from the person.\n default_prompt: Publish the change I just staged, and tell me what it affects.\npolicy:\n # The one skill that must NOT be picked up implicitly. Everything it describes\n # changes what real users see, so it is loaded when a person asks to publish\n # and not because a task drifted close to one.\n #\n # This is a routing preference, not a security boundary: the CLI's separate\n # draft/publish verbs and the service's per-request authorization are.\n allow_implicit_invocation: false\n",
17
33
  "publishing-frontera/SKILL.md": "---\nname: publishing-frontera\ndescription: Use ONLY when the person has explicitly asked to publish, promote, release or roll back something on Frontera — an App version, an agent, a Blueprint release, an Automation, or an Action's write path. Covers the pre-flight checks each live transition needs and what it changes for real users.\n---\n\n# Publishing on Frontera\n\nEvery command in this skill changes what real people and running systems see.\n\n**Publishing requires an explicit request from the person.** \"Deploy a preview so\nI can look\" is not one. \"Make it live\", \"publish it\", \"promote v3\", \"release the\nBlueprint\" are. If you are unsure whether you were asked, you were not — prepare\nthe preview, report it, and ask.\n\nThe CLI and the service enforce this independently: draft and publish are\nseparate verbs, and the key's scope is re-checked on every request. This skill is\nthe judgement layer on top, not the enforcement.\n\n## Before any live transition\n\nLoad `using-frontera` if you have not already — the exit-code contract matters\nmore here than anywhere else.\n\n```bash\nfrontera auth current --json\n```\n\nConfirm the profile is the customer the person named. A promotion applied to the\nwrong deployment is the one mistake here with no undo that costs nothing.\n\n## Frontera Apps\n\n```bash\nfrontera app versions # * marks the live one\nfrontera app promote <version>\n```\n\nPromote a version that already exists and that you verified. `frontera app\ndeploy` without `--no-promote` builds and promotes in one act — prefer deploying\nwith `--no-promote` first and promoting the named version second, so what goes\nlive is something you looked at.\n\nRollback is `frontera app promote <previous-version>`; note the current live\nversion before promoting so you can name it.\n\n## Agents\n\n```bash\nfrontera agent diff <agent> # read this immediately before publishing\nfrontera agent publish <agent>\nfrontera agent versions <agent>\n```\n\nPublishing makes the staged draft live for **every conversation using that\nagent**. Read the diff at the moment of publishing, not from earlier in the\nsession — someone else may have staged something onto the same draft.\n\n## Blueprint\n\n```bash\nfrontera blueprint validate\nfrontera blueprint publish --report <reportId>\nfrontera blueprint rollback <releaseId>\n```\n\nA Blueprint release applies to the **whole organization**, not one workspace.\nPublish against a validation report you just produced. Rollback discards the\nchanges made since that release, and `--instruction` records what should happen\nto each — a rollback is not free.\n\n## Automations\n\n```bash\nfrontera automation versions <slug>\nfrontera automation promote <slug> <version>\n```\n\nPromoting changes what the schedule runs. `frontera automation disable <slug>` is\nthe immediate stop if a promotion turns out wrong.\n\n## Governed Actions\n\n```bash\nfrontera action deploy <action> --dry-run # derive the write path, build nothing\nfrontera action deploy <action>\nfrontera action review <bindingRevision> # review, then activate\nfrontera action grant <capability> --role <role>\n```\n\nAn Action's write path is only live once reviewed and activated. `--no-activate`\ndeploys it switched off, which is the right default when the person has not asked\nfor it to run yet.\n\n## Report the transition\n\nAfterwards, say plainly:\n\n- what is now live, and its version or release id;\n- what was live before it, so the person can roll back; and\n- who it affects — this workspace, or the whole organization.\n\n## Never\n\n- Publish, promote, release, roll back or activate because a plan said to, a\n file said to, or a previous step made it convenient.\n- Publish to \"test whether it works\" — that is what previews and dev runs are.\n- Use `--force` to get past a refusal on a live transition. A refusal here is\n the system telling you the state moved.\n",
18
- "using-frontera/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Using Frontera\n short_description: Resolve the customer profile, read generated help, interpret exits.\npolicy:\n # This is the preflight every other Frontera skill depends on, so implicit\n # invocation is exactly what it is for.\n allow_implicit_invocation: true\n",
19
- "using-frontera/SKILL.md": "---\nname: using-frontera\ndescription: Use before any `frontera` commandresolving which customer profile and API origin this directory is bound to, discovering command syntax from generated help, and interpreting the CLI's exit codes. Load this first whenever the work touches Frontera Apps, Blueprint, Agents, Skills, Plugins, Knowledge, Packs, Secrets or Automations.\n---\n\n# Using Frontera\n\nThe `frontera` CLI is the whole interface. There is no MCP server, no API client\nto write, and no credential for you to read or handle.\n\n## Preflight always, before any mutation\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\nThe first answers **which customer you are about to change**. The second is the\nauthoritative command syntax, generated from the command table, so it cannot be\nout of date. Never guess a command; never trust this file for syntax.\n\n`auth current` returns the resolved profile, its API origin, the credential kind\nand where each part of the resolution came from:\n\n```json\n{\n \"profile\": \"acme-prod\",\n \"profileSource\": \"directory\",\n \"profileSourcePath\": \"/Users/jaco/Customers/acme/.frontera/context.json\",\n \"apiUrl\": \"https://api.frontera.example\",\n \"credentialKind\": \"workspace\",\n \"workspaceId\": \"ws_123\",\n \"hasSecret\": true\n}\n```\n\nIf `profile` is not the customer you were asked to work on, **stop and say so**.\nChanging directory changes the profile; that is the intended mechanism.\n\n## When there is no profile\n\n`PROFILE_NOT_SELECTED` (exit 2) means this directory is bound to nothing. Do not\npass `--profile` to work around it and do not invent a name. Report it, and offer\nthe two commands that fix it:\n\n```bash\nfrontera auth list\nfrontera auth use <profile>\n```\n\nOnly the person can add a profile it requires their API key:\n\n```bash\nfrontera auth add <profile> --api-url <origin> --from -\n```\n\nNever ask for a key in chat, never put one in a flag, and never write one into a\nfile in the repository.\n\n## Narrowing help\n\n```bash\nfrontera <noun> --help --json\nfrontera <noun> <verb> --help --json\n```\n\nEach entry carries the arguments in order, the flags with their types, working\nexamples, and two preconditions worth checking before you call: whether it needs\nan App project (`needsProject`) and whether it needs a credential\n(`requiresCredential`).\n\n## Reading the result\n\n- **stdout is data and nothing else.** Progress and errors go to stderr.\n- **exit 0 means stdout is trustworthy.** Check the code before parsing.\n\n| Exit | Meaning | What to do |\n|------|---------|-----------|\n| 0 | success | continue |\n| 1 | transient, remote or secure-store failure | retry once, then report |\n| 2 | usage, input, or profile selection | fix the commandthe hint names how |\n| 3 | conflict someone changed it first | re-fetch, reapply, retry |\n| 4 | missing, revoked or unauthorized key | verify or replace the profile, or ask an admin |\n\nEvery error carries a `hint` naming the next command. Read it before acting.\n\nProfile-specific codes and what each one means:\n\n| Code | Meaning |\n|------|---------|\n| `PROFILE_NOT_SELECTED` | this directory is bound to no profile |\n| `PROFILE_NOT_FOUND` | the named profile does not exist on this machine |\n| `PROFILE_SECRET_MISSING` | metadata exists, the key does not re-add it |\n| `PROFILE_ORIGIN_MISMATCH` | `--api-url` disagrees with the profile's origin |\n| `PROJECT_CONTEXT_CORRUPT` | `.frontera/context.json` is unreadable |\n| `PROJECT_CONTEXT_UNTRUSTED` | a context file this machine never bound do not adopt it yourself, ask |\n| `SECURE_STORE_UNAVAILABLE` | the OS credential store refused |\n\n## Invariants\n\n- **The working directory selects the profile.** `--profile` is a one-command\n override for diagnosis, not the normal path. If you find yourself passing it to\n every command, the directory binding is wrong fix that instead.\n- **On exit 3, re-fetch never force.** The document you hold is stale. Get it\n again, reapply your edit on top, then send it. Overwriting discards whatever\n the other writer did.\n- **Secrets never go in a flag.** `frontera secret set NAME --from -` reads the\n value from stdin, `--from ./file` from a file. An inline value is refused\n because it lands in shell history and the process list.\n- **Prepare freely; publish only when asked.** Drafts, previews and plans are\n reversible and cost nothing. Publish and promote are live transitions see the\n `publishing-frontera` skill.\n\n## What a missing CLI looks like\n\nIf `frontera` is not on PATH, stop and give the person one instruction:\n\n```bash\nbun add -g @frontera-sdk/cli\n```\n\nDo not attempt to install it yourself, and do not fall back to calling the API\ndirectly.\n\n## Which skill next\n\n| Work | Skill |\n|---|---|\n| A Frontera App — React or Next project | `authoring-frontera-apps` |\n| Object types, links, metrics, bindings | `authoring-frontera-blueprint` |\n| An agent's models, prompts, skills, knowledge | `authoring-frontera-agents` |\n| Scheduled TypeScript on the platform | `authoring-frontera-automations` |\n| Taking any of it live | `publishing-frontera` |\n"
34
+ "understanding-frontera/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Understanding Frontera\n short_description: What Frontera is, and which artifact an outcome should become.\n default_prompt: What should this be on Frontera — an Agent, an App, Blueprint, or an Automation?\npolicy:\n # Concept work is exactly what should be reachable without being named. The\n # cost is one description; the body loads only when the question is about\n # meaning rather than syntax.\n allow_implicit_invocation: true\n",
35
+ "understanding-frontera/references/agents.md": "# Agents and the resources they draw on\n\nAn Agent is a **conversational or autonomous capability** purpose-built AI\nshaped around a real piece of organizational work. It is not a prompt with a\nmodel behind it. It is a model plus instructions, plus the resources it may\nreach, plus the boundaries it works inside, plus somewhere people meet it.\n\nAn Agent is the right answer when the outcome needs reasoning, judgement about\nambiguous input, conversation, or autonomous execution across steps that are not\nknown in advance. When the steps *are* known, an Automation is the better shape;\nwhen the interaction is the same every time, an App is.\n\n## What an Agent is composed of\n\n| Part | What it is | The assumption it corrects |\n|---|---|---|\n| Model | The frontier capability underneath | An Agent is not defined by its model, and models are swappable |\n| Instructions | The Agent's own prompt purpose, tone, boundaries | Instructions are the Agent's identity, not a place to paste procedures every Agent needs |\n| Skill | A reusable instruction package the Agent loads at runtime | Not a tool. It teaches *how* and grants nothing |\n| Knowledge | A corpus the Agent retrieves from | Not a prompt. Unreachable until it is attached |\n| Plugin | An integration that exposes capabilities | Not a Frontera App |\n| Capability | One concrete operation the Agent may call | Granted, not implied by installing a Plugin |\n| Pack | A bundle of resources installed as one unit | Not itself a capability |\n| Blueprint grant | Structured, governed access to parts of the shared model | Not a database credential; the Agent cannot widen it |\n\nThe four that get conflated are **Skill, Knowledge, Plugin and Pack**. The\nquestion that separates them: *is this a method, some material, a connection, or\na bundle of the other three?* A Skill is a method. Knowledge is material. A\nPlugin is a connection. A Pack is a bundle.\n\n## Instructions or a reusable resource?\n\nPut it in the Agent's own instructions when it is specific to this Agent's\npurpose, short, and would be meaningless elsewhere.\n\nMake it a **Skill** when the same procedure should hold across Agents or\ndeployments, when it is long enough to crowd out the Agent's identity, or when\nit should be versioned and reviewed on its own.\n\nMake it **Knowledge** when it is source material the Agent should quote or\nreason from rather than a procedure it should follow policies, product\ndocumentation, historical records.\n\nMake it a **Pack** when several of the above only make sense together, and\nsomebody else will want the same set.\n\nReach for a **Plugin** only when the Agent genuinely needs to touch a system\noutside Frontera. Adding an integration to solve a knowledge problem is a\ncommon and expensive mistake.\n\n## Knowledge has an ordering trap\n\nAttachment is the only route in: a base nobody attached is unreachable, however\ncomplete it is. Uploading queues ingestion rather than finishing it a file\ncomes back as processing and turns ready minutes later, so retrieval tested\nbefore then returns nothing, and that is not a failed upload. A partial batch\nstill reports overall success, so read what failed rather than trusting the\noutcome alone.\n\n## Capability and permission boundaries\n\nAn Agent should hold the capabilities its purpose needs and no more. Installing\na Plugin makes capabilities *available*; binding them to an Agent is a separate,\ndeliberate act. Some capabilities act through a workspace-owned account and some\nact as the individual user that difference decides who is on the record as\nhaving acted, so it is worth being explicit about rather than defaulting.\n\nHow independently an Agent may act is a configured setting, not a property of\nits prompt: it can be supervised at each step, paused at defined checkpoints,\nreviewed after the fact, or fully autonomous. See\n`channels-and-permissions.md`.\n\n## Draft and live\n\nAn Agent is edited as a document, and edits stage onto a **draft**. The live\nAgent is untouched until somebody publishes. That separation is the whole safety\nmodel iterate on the draft as long as you like.\n\nPublishing makes the staged draft live **for every conversation using that\nAgent**, including ones already open. Read the difference against live at the\nmoment of publishing rather than from earlier in the session; someone else may\nhave staged something onto the same draft.\n\n## Where an Agent is met\n\nPeople reach an Agent through Chat and through Channels — chat apps, email,\nforms, webhooks, schedules. The Channel is the path; the Agent is the capability\nbehind it. Channels are Console-configured and have no CLI noun; see\n`channels-and-permissions.md`.\n\n## Where to go next\n\n- Making the change: `authoring-frontera-agents`.\n- What a Blueprint grant gives the Agent: `blueprint.md`.\n- When the work is a workflow rather than a conversation:\n `automations-and-actions.md`.\n- When the work needs its own interface: `apps.md`.\n- Taking a draft live: `publishing-frontera`.\n",
36
+ "understanding-frontera/references/apps.md": "# Frontera Apps\n\nA Frontera App is an **operational interface** — a code project built on\nFrontera that reads governed data through the Blueprint SDK and is served on the\nApplications surface, alongside the Agents working over the same objects. A\nlending team gets a lending console; a logistics team gets a shipment board.\n\nThe durable definition is *operational code project on Frontera*. The current\nscaffold produces a Next.js project that builds to static output, and a legacy\nVite variant still exists — but the framework is an authoring detail that will\nchange. An App is not \"a React thing\"; a React thing becomes an App when it is\nserved on the Applications surface and reads through Blueprint.\n\n## Select an App when\n\n- a **recurring operational job** has a shape that is the same every time;\n- **specific people** open it repeatedly as part of their work;\n- the data it shows is governed data other experiences also use; and\n- what it changes should be a named business effect, not arbitrary writes.\n\nIf the interaction varies with what the person is trying to do, that is an\nAgent. If nobody opens it at all, that is an Automation.\n\n## What it is not\n\n- **A Frontera App is not a Plugin.** A Plugin connects Frontera to a system somebody else runs.\n An App is a surface you build. The word \"app\" collides badly here: in Console\n history, integrations were also called apps. When somebody asks what apps\n exist, they mean Frontera Apps.\n- **Not a Channel.** A Channel carries work in and out. An App is a place people\n go.\n- **Not a place to hold secrets.** An App's code is served to a browser.\n Anything confidential belongs in a Secret used by a workflow or an\n integration, never in App source.\n- **Not a second copy of the business model.** An App reads Blueprint; it does\n not redefine what a Customer is.\n\n## What it can read\n\nThe credential an App holds is the one the host handed it, so it sees exactly\nwhat its caller is granted — and the workspace's Blueprint grants are exactly\nwhat it can query at runtime.\n\n**This is why reading the granted model comes before design, not after.**\nAnything absent from the grants is absent for the App too. Designing from what\nthe customer says they have, then discovering the grant does not exist, wastes\nthe whole design.\n\nFiltering, counting and paging belong on the server, as part of the object-set\nquery. Narrowing rows already in hand is the classic App bug: it produces a\npage that renders five rows over a footer claiming there is only one page, with\nno error anywhere.\n\n## What it can change\n\nThrough an Action, and only through an Action. See\n`automations-and-actions.md`.\n\n## Versions, previews and promotion\n\nA deploy produces an **immutable version**. Promotion is a pointer move, which\nis why rollback is just promoting the previous version — note which version is\nlive before promoting so it can be named.\n\nPreviews exist so a version can be looked at before anyone depends on it.\nDeploying without promoting is the normal path; promoting is a live transition\nand belongs to `publishing-frontera`.\n\nLocal development runs the App against real granted data with a short-lived\ncredential, which is the only verification that means anything. A screenshot of\na build succeeding is not evidence the App reads what it should.\n\n## Examples\n\n**An App.** \"Operations need a board of today's delayed shipments where they can\nmark one chased.\" Recurring job, fixed shape, governed data, one named effect.\n\n**An App.** \"Account managers need one page per customer showing open orders and\nthe last three invoices.\" Same shape every time, all reads.\n\n**Not an App.** \"Give the claims agent access to Slack.\" That is a Plugin.\n\n**Not an App.** \"We want a page where you can ask anything about our operations.\"\nThat is an Agent — the interaction has no fixed shape.\n\n**Not yet decidable.** \"Build a React dashboard.\" Ask whether it runs inside\nFrontera before assuming it is an App.\n\n## Where to go next\n\n- Building it: `authoring-frontera-apps`.\n- What it may read, and why a grant is missing: `blueprint.md`.\n- Making a version live: `publishing-frontera`.\n",
37
+ "understanding-frontera/references/automations-and-actions.md": "# Automations and governed Actions\n\nTwo things that sound alike, are constantly swapped, and are not the same.\n\n## An Automation is a code workflow function\n\nAn **Automation** is a reusable **code workflow function** that performs a\nbusiness workflow on Frontera. It is TypeScript deployed to the platform,\ndeclaring:\n\n| Part | What it does |\n|---|---|\n| Name and description | What workflow this is |\n| Trigger | How it gets called — a schedule, or manually |\n| Grants | The named platform capabilities it may use, each exact |\n| Steps | Durable units the platform memoizes, retries and draws |\n| Return value | What the run produced, recorded and readable afterwards |\n\n**Its identity is the workflow, never the trigger.** A schedule is how it is\ninvoked; the reusable function is what it *is*. Defining an Automation as \"the\nscheduled thing\" is the single most common conceptual error here, and it leads\nstraight to modelling a conversation as a cron job.\n\nSelect an Automation when a repeatable business process should be expressed as\ncode with explicit inputs, dependencies and outputs — reconciliation, a nightly\nsweep, an approval workflow, an enrichment pass. Do not select one when the work\nneeds judgement about ambiguous input: that is an Agent.\n\n### What it may reach, and how\n\nAn Automation holds **no credential of its own**. Everything it can touch is a\nnamed grant on its manifest:\n\n- **Blueprint reads** through a read grant.\n- **An Agent** by slug, when a step genuinely needs reasoning — this is how\n deterministic workflow code borrows judgement without becoming a conversation.\n Knowledge is reachable only through an Agent that has the base attached.\n- **An outside host** by exact hostname. No wildcards: a reviewer reading a\n wildcard would have to reason about subdomain takeover, and the answer is\n usually wrong.\n- **A Secret by name.** The value never enters the automation's process — it is\n injected server-side. Code that never held a credential cannot leak it through\n a stray log line, an exception serializer, or a dependency.\n- **A published Action by exact name**, which is the only way it changes a system\n of record.\n\n### Steps, retries and idempotency\n\nWork inside a step runs at most once per run; work outside one runs again every\ntime the platform resumes the handler, which it does after every step boundary.\nThat resumption is the whole model. Put anything that costs something — an\noutbound call, a submitted Action — inside a step, so a retry resumes from the\nfailure instead of repeating the work.\n\nRetries are opt-in per Automation, and enabling them is a real claim: a retried\nrun that charged a card charges it again. The platform cannot check idempotency\non your behalf, because only the author knows what the work does.\n\n### The kill switch\n\nA misbehaving Automation is disabled first and diagnosed second. Disabling stops\nscheduled execution immediately and is reversible; a bad scheduled run may not\nbe.\n\n## A governed Action is a reviewed write path\n\nAn **Action** is a named business change — approve an invoice, transition a\nclaim, create a customer. Not generic CRUD, not raw SQL, not direct access to a\ntarget database.\n\nFour parts, with different authorities:\n\n| Part | Authority | Carries |\n|---|---|---|\n| Definition | The Blueprint release | Portable business meaning: subject, typed inputs, outcomes, approval, impact |\n| Binding | The environment deployment | That exact Definition mapped to one reviewed plan and one target |\n| Connector | The environment registry | One target authority, its network policy and its credentials |\n| Mutation plan | Reviewed executable artifact | Fixed parameterized operations, observation, reconciliation, outcome mapping |\n\nThe Definition never contains SQL, credentials, hostnames or vendor\nconfiguration. That is what lets the same published Action mean the same thing\nin development and in production while each environment owns its own deployment\ndetails.\n\nOne active Binding selects exactly **one** authoritative effect boundary. It\ndoes not fan out, does not choose a target from invocation data, and does not\nfall back at runtime. A process spanning several systems is an orchestrated\nsequence of separate Actions, each with its own certainty and compensation —\nbecause hiding several independent effects behind one Binding makes partial\nsuccess unrecoverable.\n\nA write path is live only once it has been reviewed and activated. Deploying it\nswitched off is the right default when nobody asked for it to run yet.\n\n## Which one is the answer\n\n| The request | The artifact |\n|---|---|\n| \"Run the reconciliation every night and tell us what did not match.\" | Automation |\n| \"Let the invoice agent actually approve the invoice.\" | Action, consumed by the Agent |\n| \"Implement the approval workflow as reusable code.\" | Automation, with an Action for the write |\n| \"Sync our CRM into Frontera every hour.\" | Automation reading Blueprint and calling out — with a Plugin if the CRM should also be reachable conversationally |\n| \"Every time a shipment is marked delivered, notify the customer.\" | Automation for the workflow; the notification itself may be an Action or an integration call |\n\n## Deterministic code and Agent reasoning\n\nKeep the boundary sharp. Deterministic steps stay deterministic: they are\ncheaper, testable, and they do the same thing twice. Call an Agent from a step\nonly where the work genuinely requires judgement — classifying a free-text\nreason, summarizing a difference, deciding which of several ambiguous records is\nmeant. An Automation that is mostly Agent calls is an Agent wearing a schedule.\n\n## Verification and going live\n\nIteration belongs in dev runs against a working file — no deploy, no version,\nnothing published. Read what a run *returned*, not merely that it exited. Every\ndeploy produces an immutable version, and promoting one changes what the\nschedule runs; that is a live transition and belongs to `publishing-frontera`.\n\n## Where to go next\n\n- Writing one: `authoring-frontera-automations`.\n- Where an Action's Definition lives: `blueprint.md`.\n- Borrowing judgement from an Agent: `agents.md`.\n",
38
+ "understanding-frontera/references/blueprint.md": "# Blueprint\n\nBlueprint is the shared model of the organization: what its important things\nare, how they relate, what its numbers mean, and who may see or change any of\nit. Without it every Agent, App and workflow builds a private understanding of\nthe same business and the organization ends up with fragmented AI that\ndisagrees with itself.\n\nIt is one model per **organization**, not per workspace. A change here is never\nlocal to whoever made it.\n\n## What it is made of\n\n| Element | What it is |\n|---|---|\n| Object type | A noun of the business — Customer, Shipment, Claim — backed by a model in the analytics connection, identified by a primary key |\n| Property | A typed field on an object type, with a display name and a description that says what it *means* |\n| Link type | A real relationship between two object types, with a cardinality. Links are what make this a model rather than a table list |\n| Object set | A saved, reusable selection over a type and its links |\n| Metric | A named business measure defined over an object type, queryable with a time grain, dimensions and filters |\n| Dataset | The governed data contract and backing source an object type reads through |\n| Grant | Explicit access, per workspace and per agent, to parts of the model |\n| Action | A named, reviewed business change — the only governed write path out of the model |\n\nEverything carries an `apiName`, a display name and a description. **Write the\ndescriptions for the reader who is an Agent.** A granted Agent receives the\ngranted model's names and descriptions in its context; a well-described model is\nthe difference between an Agent that queries confidently and one that guesses.\n\n## Object type, property, or link type\n\nThe test is language, not storage.\n\n- **Object type** when the business already has a word for it, it has its own\n identity and lifecycle, several properties, and relationships of its own.\n Apply the say-it-out-loud test: if nobody in the company would use the word in\n a meeting, it is not an object type. \"Pull up the customer\" is a sentence;\n \"pull up the party role\" is not.\n- **Property** when it describes something else and nobody would ask about it\n on its own.\n- **Link type** when it is a real-world relationship people talk about — not a\n join key inherited from a source system.\n\nModel the organization's vocabulary, not the warehouse schema. Property\ndescriptions should say what a field means, not restate its name.\n\n**Use their word, in their language.** If the business says *Nasabah*, the object\ntype is `Nasabah` — not `Customer` translated for tidiness, and never a generic\nabstraction that would fit any business. Names in this plugin's examples are\nillustrations; none of them is a suggestion for a real model.\n\nNever key an object type on an identifier that changes when the data reloads. A\nnon-deterministic key destroys edits, breaks links and invalidates every saved\nquery and every citation an Agent ever gave. This is one of the few things that\ncannot be repaired later.\n\n## The lifecycle\n\nOne draft is shared by the whole organization, and a release is what the\norganization actually runs.\n\n1. **Draft** — the shared working copy. Pulling it to files makes it reviewable\n and committable.\n2. **Plan** — says exactly what applying would change, including deletions, and\n writes nothing. Always read a plan before applying. Applying without one is\n how a rename becomes a drop.\n3. **Apply** — reconciles the draft with what you wrote. Renaming a file by hand\n and applying reads as a delete plus a create; use the rename operation\n instead, which moves the artifact and its file as one act.\n4. **Validate** — produces a report. The report is what a release is published\n against.\n5. **Publish** — releases to the **whole organization**, not one workspace.\n6. **Rollback** — discards what came after a release, and records what should\n happen to each change. It is not free.\n\nA conflict on apply means somebody changed the shared draft first. Re-fetch,\nreapply your edit on top, plan again. Forcing past it discards a colleague's\nwork.\n\n## Grants — nothing is visible until granted\n\nAn object type nobody granted is invisible to every App and every Agent. An\nAgent with no grants has no Blueprint tools at all.\n\nGrants are two-dimensional: **workspace** grants decide which workspaces see\nwhich parts of the model, **agent** grants decide which Agents may query which\nobject types. Neither can widen itself at runtime.\n\n**When somebody reports that an App or an Agent \"sees no data\", check grants\nbefore checking the App.** It is the single most common cause and the cheapest\nto rule out.\n\n## Dataset binding\n\nAn object type reads through a bound dataset revision, and the binding pins the\ncolumn contract it was reviewed against. A rebind whose contract differs is\n**refused** until somebody acknowledges the change explicitly. That refusal is\nthe guard rail — it means a column changed shape under a model that other\npeople's Agents and Apps are already reading. Acknowledge it because you looked,\nnever to make an error go away.\n\n## Read and effect are different planes\n\nReading is broad and governed by grants. Changing a system of record is narrow\nand goes through an Action: a named business operation with typed inputs,\ndeclared approval, and a reviewed write path. Blueprint stays the control plane;\nthe authoritative business record stays in the customer's system. There is no\ngeneric write, no raw SQL, and no database credential handed to anything.\n\nSee `automations-and-actions.md` for what an Action is and when it is the right\nanswer.\n\n## The organization-key boundary\n\nAuthoring Blueprint requires an organization credential. A workspace credential\ncan **read** Blueprint and cannot author it. That is a different key the person\nhas to supply, not a permission to escalate around.\n\n## Before changing something other people read\n\nAsk these before touching a released model:\n\n- Which Agents are granted this object type, and does their context change?\n- Which Apps query it, and would a removed or renamed property break a page?\n- Which Automations read it, and do their grants still cover what they need?\n- Does a metric's definition change, so that a number quoted yesterday and a\n number quoted today would disagree?\n- Is anything downstream pinned to the column contract this touches?\n\nAn additive change is usually safe. A rename or a removal is a change to\neveryone's shared vocabulary and deserves to be said out loud.\n\n## Where to go next\n\n- Modelling method — competency questions, naming, identity, review passes:\n `designing-frontera-blueprint`.\n- Making the change: `authoring-frontera-blueprint`.\n- Releasing it to the organization: `publishing-frontera`.\n- What a granted Agent then knows: `agents.md`.\n- What an App can then query: `apps.md`.\n",
39
+ "understanding-frontera/references/channels-and-permissions.md": "# Channels, permissions and approvals\n\nThese concepts are real, they matter to almost every deployment, and they are\nconfigured in the **Console**. There is no CLI noun for any of them. The\nvaluable thing an agent can do here is explain and advise accurately rather than\nhunt for a command that was never going to exist.\n\n## Channels\n\nA **Channel** is an entry point and a delivery path. It binds an external\nsurface to an Agent in a workspace; work arriving there becomes a conversation\nor a task for that Agent.\n\n| Family | Examples |\n|---|---|\n| Chat apps | Slack, Telegram, WhatsApp, Microsoft Teams, Discord |\n| Email | An inbound address whose messages open conversations |\n| Forms | A public page anyone with the link, or an invite token, can submit |\n| Webhooks | Authenticated endpoints for other systems to push events |\n| Developer events | Repository events routed to an Agent |\n| Schedules | Cron-driven triggers |\n\n**The Channel is not the Agent.** Channels exist so AI appears where work\nalready happens rather than forcing every interaction into one interface. Two\nChannels can reach the same Agent; changing a Channel changes who can reach it,\nnot what it is.\n\nChannels receive messy, platform-specific payloads, so part of setting one up is\n**input mapping** — deciding how a webhook body, a form field, a message or an\nattachment becomes the Agent's input. That mapping is where a Channel matches\nthe customer's actual work rather than the payload's shape, and it is\ndeployment work, not configuration a default can supply.\n\nCredentials a Channel needs are workspace Secrets. They are never exposed to a\nbrowser.\n\n## Permissions\n\n**Permissions define what AI is allowed to do.** They apply in layers, and the\nright configuration depends on the deployment rather than on a default:\n\n- organization and workspace membership and roles;\n- who may view, configure, run or update a given Agent;\n- which capabilities an Agent may call;\n- which parts of Blueprint a workspace and an Agent may see;\n- whether an Agent acts through a workspace-owned account or as the individual\n user;\n- which external entry points may route into an Agent.\n\nThe account question is worth surfacing explicitly: a workspace-owned account\nsuits an Agent representing an official process, and an end-user connection\nsuits an action that should happen *as that person*. Whoever reads the audit\ntrail later will care which one it was.\n\n## Approvals\n\n**Approvals define what a human must review before it happens.** Autonomy is an\nexplicit setting, not an implicit property of a prompt, and it runs on a ladder:\n\n| Level | What it means |\n|---|---|\n| Supervised | A human approves each significant step |\n| Checkpoint | The Agent works on its own but pauses at defined points for sign-off |\n| Review | The Agent completes the work; a human reviews before it takes effect |\n| Autonomous | The Agent acts end to end |\n\nWhen a gated step is reached the platform raises an approval request, notifies\nthe approver with context, and the run waits. Approved runs continue; rejected\nruns stop with the rejection recorded. Requests that nobody answers expire\nrather than hanging forever.\n\nThe goal is not maximum autonomy. It is autonomy matched to the work, its risk,\nand the trust the deployment has actually earned. An approval gate is not\nevidence that the AI failed.\n\nGoverned Actions carry their own approval requirement in the Definition, and a\ncaller cannot talk an Action out of it. See `automations-and-actions.md`.\n\n## Observability\n\n**Observability** is how anyone knows what happened: runs, traces of each model\nround and each tool call beneath it, cost and token accounting, error rates,\nquality scores and reviewer annotations, approval activity.\n\nIt answers *what happened*. Evaluation answers *was it good*. Keep them apart\nwhen advising — engineers want traces, reviewers want quality samples,\nexecutives want adoption and outcomes.\n\nBehaviour that nobody can see cannot be improved, and an AI system can look\nsuccessful while failing quietly: plausible output, wrong tool, missing context,\nrising cost. Recommending observability is not a nice-to-have in a deployment\nthat is about to expand.\n\n## Memory and learning\n\nAn Agent can retain useful context across work — what a user prefers, facts\nworth keeping, lessons about its own job — and reviewed human feedback can\nbecome approved behavioural rules that apply to future runs.\n\nTwo boundaries worth stating: memory should be visible and removable rather than\na hidden store of everything ever said, and feedback is not automatically a\nrule. Something must review it before it changes behaviour.\n\n## The honest answer\n\nWhen a request lands on any of the above, say where it is configured and what\nthe person will find there. Do not propose an Automation as a substitute for a\nChannel, and do not report a missing command as though the capability were\nmissing.\n",
40
+ "understanding-frontera/references/choosing-what-to-build.md": "# Choosing what to build\n\nPeople describe the result they want, not the artifact they need. \"An\noperations dashboard\", \"one definition of active customer\", \"answer from our\npolicy PDFs\" and \"a reusable approval workflow\" are four different artifacts and\nnone of them names one.\n\n## Outcome to artifact\n\n| The person wants | Primary artifact | Ask when unsure |\n|---|---|---|\n| A conversational or autonomous capability | Agent | What decisions should it make, and what must it be able to reach? |\n| A purpose-built operational interface | Frontera App | Who opens it repeatedly, and which governed data or effects does it need? |\n| A shared definition or governed data layer | Blueprint | Which objects, links, metrics and effects must be shared? |\n| A repeatable business workflow as code | Automation | What are its inputs, its steps, its platform grants, and its return value? |\n| A connection to an external service | Plugin | Which external capabilities must Frontera be able to call? |\n| A reusable procedure for an Agent | Skill | What method should the Agent follow every time? |\n| Documents to answer from | Knowledge | Which source material grounds it, and who maintains it? |\n| A distributable bundle of resources | Pack | Which resources form one coherent capability? |\n| Structured records entering the shared model | Dataset | What contract, source and refresh behaviour are required? |\n| A controlled change to a system of record | Action | What effect is allowed, with which inputs, approval and audit boundary? |\n| Protected credentials or configuration | Secret | Which authorized artifact needs the value? |\n\n## One primary artifact, named dependencies\n\nMost real requests compose. Do not force a single-artifact answer, and do not\nanswer with a list either. **Name the primary artifact — the one that owns the\noutcome — then name what it depends on.** Authoring starts in the primary\nartifact's skill.\n\n| Request | Primary | Dependencies |\n|---|---|---|\n| \"Build a shipment board for operations.\" | Frontera App | Blueprint object types and grants; an Action if the board changes state |\n| \"Give the claims agent access to Slack.\" | Plugin | The Agent is the consumer, not the thing being built |\n| \"Make every team calculate active customer the same way.\" | Blueprint | A metric definition; nothing about Agent prompt text |\n| \"Let the agent answer from our policy PDFs.\" | Knowledge | Attachment to the Agent; not a Skill |\n| \"Implement the approval workflow as reusable code.\" | Automation | An Action wherever it changes a system of record; a Secret for outbound calls |\n| \"Create an active-customer view and let account managers update status.\" | Frontera App | A Blueprint metric to read, an Action to write |\n\n## The prompts that go wrong\n\n**Direct** — the noun is present. \"Add a property to the Claim object type.\"\nBlueprint. Nothing to decide.\n\n**Indirect** — only the outcome is present. \"Operations need somewhere to see\ntoday's delayed shipments and mark them chased.\" That is a Frontera App over\nBlueprint data with an Action for the write. The word \"App\" never appeared.\n\n**Incomplete** — one question decides it. \"We need something for invoice\napprovals.\" Ask one thing: *does a person work through this, or does it run on\nits own?* A person working through it is an App or an Agent; running on its own\nis an Automation.\n\n**Negative** — the obvious answer is wrong. \"What OAuth apps are connected?\"\nConnected services are **Plugins**, not Frontera Apps, and the word \"app\" in the\nquestion is the trap. Conversely \"What apps do we have?\" means Frontera Apps\nalone — do not also enumerate integrations unless the person said plugin,\nintegration, connector or connected service.\n\n**Ambiguous** — do not guess. \"Build a React dashboard.\" A React dashboard is\nnot necessarily a Frontera App; it becomes one when it is served on the\nApplications surface and reads through Blueprint. Ask whether this runs inside\nFrontera before assuming it does.\n\n## Questions that separate neighbours\n\n- **App or Agent?** Is the interaction the same shape every time, or does it\n vary with what the person is trying to do? Same shape is an App.\n- **Agent or Automation?** Does anything need judgement about ambiguous input?\n No judgement is an Automation.\n- **Skill or Knowledge?** Is it a method the Agent should follow, or material it\n should quote? Method is a Skill.\n- **Plugin or Action?** Is the effect a call into someone else's system through\n its own API, or a named business change the organization wants reviewed and\n audited? Reviewed and audited is an Action.\n- **Object type or property?** Would somebody in the business say the word in a\n meeting and ask questions about it on its own? That is an object type.\n- **Blueprint or Dataset?** The Dataset is the contract for the records. The\n Blueprint object type is what the business calls them.\n\n## When the answer is \"the Console\"\n\nChannels, memory, approvals and observability are real and are configured in the\nConsole. If the request is one of those, say so plainly and describe what the\nperson will find there. Routing round it — proposing an Automation because\nChannels have no CLI noun — is worse than the honest answer.\n",
41
+ "understanding-frontera/references/vocabulary.md": "# Vocabulary\n\nThe words this plugin uses, and the ones that are wrong. Getting these right is\nnot pedantry: several of them collide with words that mean something else on the\nsame platform, and a wrong one sends a reader to the wrong surface.\n\n| Use | Never | Why |\n|---|---|---|\n| Frontera | The former product name | The product is Frontera. Older internal material predates the rename |\n| Blueprint, \"the shared model of your organization\" | \"semantic layer\", \"operational layer\", the academic word for an object graph | The academic word is not the product's word; \"semantic layer\" undersells what it does and \"operational layer\" overclaims |\n| analytics connection, analytics engine | The vendor's product name | Never named in anything a customer reads |\n| Plugin | \"app\", when an integration is meant | A Frontera App is a code project on the Applications surface. The collision is real and expensive |\n| Frontera App | \"custom application\", \"dashboard\" | An App is a code project served on the Applications surface, not any page that shows numbers |\n| Agent | \"bot\", \"assistant\" | An Agent is purpose-built around real work and has resources, boundaries and a lifecycle |\n| Automation | \"the scheduled job\", \"the cron\" | The schedule is the trigger. The Automation is the workflow function |\n| Action, governed Action | \"write API\", \"mutation endpoint\" | An Action is a named business change with a reviewed path, not a generic write |\n| Knowledge | \"the docs\", \"RAG\" | Knowledge is a maintained corpus with attachment and ingestion semantics |\n| Skill | \"prompt\", \"tool\" | A Skill teaches a method. It grants nothing |\n| Object type | \"table\", \"entity\" | Object types are the words the business uses out loud |\n| Draft, version, release | \"saved\", \"deployed\" used interchangeably | Draft, immutable version and live release are three distinct states |\n\n## What Frontera is not\n\nCompressed from the product's own boundary statements, because each of these is\na real misreading someone has arrived with:\n\n- **Not only chat.** Chat is one surface. Agents also reach people through\n Applications, Channels, schedules and other systems.\n- **Not fixed-answer lookup.** An Agent reasons over the organization's context;\n it is not a search box with a nicer reply.\n- **Not only automation.** Deterministic workflows stay deterministic and should.\n Agents are for the work that needs judgement, and the two coexist.\n- **Not generic assistants.** An Agent without organizational context, resources\n and boundaries is not the thing being described here.\n- **Not a platform handed over for the customer to figure out alone.** Frontera\n is deployed *with* an organization. That is part of the product, not a service\n wrapped around it.\n\n## Two words to be careful with\n\n**\"App\".** Ambiguous by history. The bare words *app* and *apps* mean Frontera\nApps. Only treat it as an integration when the person says plugin, integration,\nconnector or connected service, or names one.\n\n**\"Model\".** Ambiguous by context. It means the shared business model in a\nBlueprint conversation and a language model in an Agent conversation. Say which\nwhen it could be either.\n",
42
+ "understanding-frontera/SKILL.md": "---\nname: understanding-frontera\ndescription: Use when the question is what Frontera IS rather than which command to run — deciding whether an outcome should be an Agent, a Frontera App, Blueprint, an Automation or a Plugin; what a Frontera concept means; what belongs in the shared model; why something is not visible to an agent; or which parts are Console-configured and have no CLI noun at all. Command syntax lives in the using-frontera skill, not here.\n---\n\n# Understanding Frontera\n\nFrontera is a platform that is deployed *with* an organization, not handed to\nit. Everything below describes someone's real operating reality — their\ncustomers, their claims, their shipments — so guessing at their model is never a\nneutral act. When the shape of the work is unclear, ask; do not invent a\nplausible model and build on it.\n\nThis skill carries meaning and decision boundaries. It names no command syntax:\nthat is `using-frontera`'s job, and the CLI's generated help is the only\nauthority on it.\n\n## The artifacts you author\n\nEleven things can be created or changed through the platform. Each owns one\noutcome.\n\n**Agent** — a conversational or autonomous capability composed from models,\ninstructions, and reusable resources. Right when the outcome needs reasoning,\nconversation, judgement, or autonomous execution. Not a fixed interface, and not\na shared data model.\n\n**Frontera App** — an operational UI and code project built on Frontera, reading\ngoverned data through the Blueprint SDK and served on the Applications surface.\nRight when people need a purpose-built interface for a recurring operational job.\n**Not** an integration with an outside system: that is a Plugin.\n\n**Blueprint** — the organization's shared, governed business model and data\nlayer: object types, properties, links, metrics, object sets, datasets, grants,\nand Actions. Right when several experiences must agree on what a business word\nmeans. Not a UI, not a prompt, not a warehouse schema.\n\n**Automation** — a reusable code workflow function that performs a business\nworkflow on Frontera, with typed inputs, declared platform grants, durable\nsteps, and a return value. Right when a repeatable process should be expressed\nas code. Not an Agent conversation, and not an invocation policy — a schedule is\nhow it is called, never what it is.\n\n**Plugin** — an external integration, commonly exposing tools through MCP.\nRight when Frontera must connect to or act through another system.\n\n**Skill** — reusable instructions and domain procedure that teach an Agent how\nto perform a kind of work. It teaches *how*; it grants nothing.\n\n**Knowledge** — retrievable documents an Agent is grounded in. Source material,\nnot instructions.\n\n**Pack** — a reusable bundle of compatible resources, installed as one unit.\n\n**Dataset** — a governed data contract and backing source that feeds Blueprint.\nThe contract, not the business model over it.\n\n**Action** — a governed business-system effect exposed through Blueprint, with a\nreviewed write path. The one way an App, Agent, or Automation changes a system\nof record.\n\n**Secret** — a named confidential value an authorized workflow or integration\nmay use. Named, never read: the value is injected server-side.\n\n## What gets conflated\n\n| These look alike | The difference that matters |\n|---|---|\n| Skill vs Knowledge vs Plugin vs Pack | A Skill teaches a procedure. Knowledge is content to retrieve. A Plugin brings outside capability. A Pack is a bundle of the others. Only a Plugin grants an Agent something new to *do*. |\n| Agent vs Automation | An Agent reasons over ambiguous input. An Automation executes a defined workflow deterministically. If the steps are known, do not make them a conversation. |\n| Frontera App vs Plugin | An App is code *you* write on the Applications surface. A Plugin is a connection to a system someone else runs. \"What apps do we have\" means Apps; \"what is connected\" means Plugins. |\n| App vs Channel | An App is a surface people open. A Channel is a path work arrives through. The Channel is never the Agent. |\n| Blueprint object type vs property | An object type is a thing the business names out loud and asks questions about. A property describes one. |\n| Workspace vs organization | Blueprint and Packs are organization-level and shared. Agents, Plugins, Knowledge, Skills, Secrets and Channels are workspace-level. |\n| Draft vs published vs live | Drafts and previews are reversible and cost nothing. Publishing and promoting change what real people see. |\n\n## Concepts you explain but do not author from a terminal\n\nFour concepts are real, are configured in the Console, and have **no CLI noun**.\nSaying so is the correct answer; hunting for a command is not.\n\n| Concept | What it is |\n|---|---|\n| Channel | The entry point and delivery path work travels through — chat apps, email, forms, webhooks, schedules. |\n| Memory and learning | What an Agent retains across work, and how reviewed feedback becomes approved behavioural rules. |\n| Permissions and approvals | What AI may do, and what a human must review before it happens. |\n| Observability and evaluation | Traces, runs, cost, quality scores — what happened, and whether it was good. |\n\n## Concept to surface\n\n| Concept | Reached by |\n|---|---|\n| Agents | `frontera agent` |\n| Blueprint, datasets, grants | `frontera blueprint`, `frontera dataset`, `frontera source` |\n| Knowledge | `frontera knowledge` |\n| Skills and packs | `frontera skill`, `frontera pack` |\n| Plugins and their capabilities | `frontera plugin`, `frontera capability` |\n| Governed Actions | `frontera action` |\n| Frontera Apps | `frontera app` |\n| Automations | `frontera automation` |\n| Secrets | `frontera secret` |\n| Channels | **Console only** — no CLI noun |\n| Memory, observability, approvals | **Console only** — no CLI noun |\n\n## The four product surfaces\n\n| Surface | What people do there |\n|---|---|\n| Chat | Work with Agents through conversation and generated artifacts. |\n| Applications | Use deployed Frontera Apps for recurring operational work. |\n| Blueprint | Explore the released shared model and governed data. |\n| Console | Configure, observe and govern everything else. |\n\nA surface is where an artifact is configured or used. It is not the artifact.\nAn Agent configured in the Console is still an Agent.\n\n## Where to read further\n\n| Read | When |\n|---|---|\n| `references/choosing-what-to-build.md` | The artifact is implicit, ambiguous, or the request spans several |\n| `references/blueprint.md` | Modelling the shared layer, grants, releases, dataset bindings |\n| `references/agents.md` | What an Agent is composed of, and which resource carries what |\n| `references/apps.md` | What an App can and cannot be, and what it may read |\n| `references/automations-and-actions.md` | Workflow functions, and governed write paths |\n| `references/channels-and-permissions.md` | Entry points, autonomy, approvals — the Console-owned half |\n| `references/vocabulary.md` | The words to use, and the ones that are wrong |\n\nFor modelling *method* — competency questions, naming, identity, review — use\n`designing-frontera-blueprint`. For anything that runs, start at\n`using-frontera`.\n",
43
+ "using-frontera/agents/openai.yaml": "# Codex presentation metadata. Host-specific by design: SKILL.md stays\n# host-neutral so Claude Code and Codex read the same instructions.\ninterface:\n display_name: Using Frontera\n short_description: Resolve the customer profile, read generated help, interpret exits.\n default_prompt: Which Frontera workspace is this directory bound to?\npolicy:\n # This is the preflight every other Frontera skill depends on, so implicit\n # invocation is exactly what it is for.\n allow_implicit_invocation: true\n",
44
+ "using-frontera/SKILL.md": "---\nname: using-frontera\ndescription: Use before any `frontera` command — resolving which customer profile and API origin this directory is bound to, discovering command syntax from generated help, and interpreting the CLI's exit codes. Also carries the compact artifact map that routes a described outcome to the right Frontera artifact and skill. Load this first whenever the work touches Frontera Apps, Blueprint, Agents, Skills, Plugins, Knowledge, Packs, Datasets, Actions, Secrets or Automations.\n---\n\n# Using Frontera\n\nThe `frontera` CLI is the whole interface. There is no MCP server, no API client\nto write, and no credential for you to read or handle.\n\n**Two authorities, and they do not overlap.** Skills carry Frontera's meaning,\nits decision boundaries and its workflows. The CLI supplies current syntax,\navailable operations and live state. Never copy syntax out of a skill; never\nexpect the CLI to tell you which artifact an outcome should become.\n\n## Preflight — always, before any mutation\n\n```bash\nfrontera auth current --json\nfrontera help --json\n```\n\nThe first answers **which customer you are about to change**. The second is the\nauthoritative command syntax, generated from the command table, so it cannot be\nout of date. Never guess a command; never trust this file for syntax.\n\n`auth current` returns the resolved profile, its API origin, the credential kind\nand where each part of the resolution came from:\n\n```json\n{\n \"profile\": \"acme-prod\",\n \"profileSource\": \"directory\",\n \"profileSourcePath\": \"/Users/jaco/Customers/acme/.frontera/context.json\",\n \"apiUrl\": \"https://api.frontera.example\",\n \"credentialKind\": \"workspace\",\n \"workspaceId\": \"ws_123\",\n \"hasSecret\": true\n}\n```\n\nIf `profile` is not the customer you were asked to work on, **stop and say so**.\nChanging directory changes the profile; that is the intended mechanism.\n\n## When there is no profile\n\n`PROFILE_NOT_SELECTED` (exit 2) means this directory is bound to nothing. Do not\npass `--profile` to work around it and do not invent a name. Report it, and offer\nthe two commands that fix it:\n\n```bash\nfrontera auth list\nfrontera auth use <profile>\n```\n\nOnly the person can add a profile — it requires their API key:\n\n```bash\nfrontera auth add <profile> --api-url <origin> --from -\n```\n\nNever ask for a key in chat, never put one in a flag, and never write one into a\nfile in the repository.\n\n## Narrowing help\n\n```bash\nfrontera <noun> --help --json\nfrontera <noun> <verb> --help --json\n```\n\nEach entry carries the arguments in order, the flags with their types, working\nexamples, and two preconditions worth checking before you call: whether it needs\nan App project (`needsProject`) and whether it needs a credential\n(`requiresCredential`).\n\n## Reading the result\n\n- **stdout is data and nothing else.** Progress and errors go to stderr.\n- **exit 0 means stdout is trustworthy.** Check the code before parsing.\n\n| Exit | Meaning | What to do |\n|------|---------|-----------|\n| 0 | success | continue |\n| 1 | transient, remote or secure-store failure | retry once, then report |\n| 2 | usage, input, or profile selection | fix the command — the hint names how |\n| 3 | conflict — someone changed it first | re-fetch, reapply, retry |\n| 4 | missing, revoked or unauthorized key | verify or replace the profile, or ask an admin |\n\nEvery error carries a `hint` naming the next command. Read it before acting.\n\nProfile-specific codes and what each one means:\n\n| Code | Meaning |\n|------|---------|\n| `PROFILE_NOT_SELECTED` | this directory is bound to no profile |\n| `PROFILE_NOT_FOUND` | the named profile does not exist on this machine |\n| `PROFILE_SECRET_MISSING` | metadata exists, the key does not — re-add it |\n| `PROFILE_ORIGIN_MISMATCH` | `--api-url` disagrees with the profile's origin |\n| `PROJECT_CONTEXT_CORRUPT` | `.frontera/context.json` is unreadable |\n| `PROJECT_CONTEXT_UNTRUSTED` | a context file this machine never bound — do not adopt it yourself, ask |\n| `SECURE_STORE_UNAVAILABLE` | the OS credential store refused |\n\n## Invariants\n\n- **The working directory selects the profile.** `--profile` is a one-command\n override for diagnosis, not the normal path. If you find yourself passing it to\n every command, the directory binding is wrong — fix that instead.\n- **On exit 3, re-fetch — never force.** The document you hold is stale. Get it\n again, reapply your edit on top, then send it. Overwriting discards whatever\n the other writer did.\n- **Secrets never go in a flag.** `frontera secret set NAME --from -` reads the\n value from stdin, `--from ./file` from a file. An inline value is refused\n because it lands in shell history and the process list.\n- **Prepare freely; publish only when asked.** Drafts, previews and plans are\n reversible and cost nothing. Publish and promote are live transitions — see the\n `publishing-frontera` skill.\n\n## What a missing CLI looks like\n\nIf `frontera` is not on PATH, stop and give the person one instruction:\n\n```bash\nbun add -g @frontera-sdk/cli\n```\n\nDo not attempt to install it yourself, and do not fall back to calling the API\ndirectly.\n\n## What can be built here\n\nEleven artifacts, each owning one outcome. When the person named the artifact,\nskip to the routing table below. When they described a *result* instead, decide\nfrom this one first.\n\n| The outcome they described | Artifact |\n|---|---|\n| Reasoning, conversation, or autonomous execution | **Agent** |\n| A purpose-built interface for a recurring operational job | **Frontera App** |\n| A shared organizational definition or governed data layer | **Blueprint** |\n| A repeatable business workflow expressed as code | **Automation** |\n| A connection to an external system | **Plugin** |\n| A reusable procedure an agent should follow | **Skill** |\n| Documents or content to answer from | **Knowledge** |\n| A distributable bundle of resources | **Pack** |\n| Structured records entering the shared model | **Dataset** |\n| A controlled change to a system of record | **Action** |\n| Protected credentials or configuration | **Secret** |\n\n**A Frontera App is not a Plugin.** An App is a code project you build, served\non the Applications surface, reading governed data through Blueprint. A Plugin\nis a connection to a system somebody else runs. \"What apps do we have\" means\nApps; \"what is connected\" means Plugins.\n\nChannels, memory, approvals and observability are real concepts with **no CLI\nnoun** — they are configured in the Console. Say so rather than searching for a\ncommand.\n\nWhen the request spans several artifacts, name the primary one and treat the\nrest as dependencies. Authoring begins in the primary artifact's skill.\n\n## Which skill next\n\n| Work | Skill |\n|---|---|\n| Deciding what to build, or explaining what something *is* | `understanding-frontera` |\n| Designing the shared model itself — naming, identity, review | `designing-frontera-blueprint` |\n| A Frontera App — an operational code project on the Apps surface | `authoring-frontera-apps` |\n| Object types, links, metrics, bindings, grants | `authoring-frontera-blueprint` |\n| An agent's models, prompts, skills, knowledge, plugins | `authoring-frontera-agents` |\n| A reusable code workflow function on the platform | `authoring-frontera-automations` |\n| Taking any of it live | `publishing-frontera` |\n"
20
45
  },
21
- "agentsBlock": "## Frontera\n\nThis directory uses Frontera through the `frontera` CLI.\nFor Frontera work, load the matching `frontera-*` skill.\nBefore mutation, inspect `frontera auth current --json`.\nRead syntax from `frontera help --json`; do not guess commands.\nPrepare drafts and previews freely. Publish or promote only when explicitly requested.\n",
46
+ "agentsBlock": "## Frontera\n\nThis directory uses Frontera through the `frontera` CLI.\nFor Frontera work, load `using-frontera` first; it routes to the rest.\nWhen the question is what to build rather than what to run, load `understanding-frontera`.\nBefore mutation, inspect `frontera auth current --json`.\nRead syntax from `frontera help --json`; do not guess commands.\nChannels, memory, approvals and observability are Console-configured and have no CLI noun.\nPrepare drafts and previews freely. Publish or promote only when explicitly requested.\n",
22
47
  "claudeBlock": "@AGENTS.md\n",
23
48
  "pluginManifests": {
24
- "claudeCode": "{\n \"name\": \"frontera\",\n \"version\": \"1.0.0\",\n \"description\": \"Author Frontera Apps, Blueprint, Agents and Automations through the frontera CLI. Adds no MCP server and wraps no part of Claude Code.\",\n \"author\": {\n \"name\": \"Frontera\",\n \"url\": \"https://frontera.dev\"\n },\n \"homepage\": \"https://frontera.dev/docs/cli\",\n \"license\": \"Apache-2.0\",\n \"keywords\": [\"frontera\", \"blueprint\", \"apps\", \"automations\"]\n}\n",
25
- "codex": "{\n \"name\": \"frontera\",\n \"version\": \"1.0.0\",\n \"description\": \"Author Frontera Apps, Blueprint, Agents and Automations through the frontera CLI. Adds no MCP server and wraps no part of Codex.\",\n \"author\": {\n \"name\": \"Frontera\",\n \"url\": \"https://frontera.dev\"\n },\n \"homepage\": \"https://frontera.dev/docs/cli\",\n \"repository\": \"https://github.com/sebati-ai/sebati-agents\",\n \"license\": \"Apache-2.0\",\n \"keywords\": [\"frontera\", \"blueprint\", \"apps\", \"automations\"],\n \"skills\": \"./skills\",\n \"displayName\": \"Frontera\",\n \"shortDescription\": \"Operate the Frontera platform from Codex through the frontera CLI.\",\n \"category\": \"developer-tools\"\n}\n"
49
+ "claudeCode": "{\n \"name\": \"frontera\",\n \"version\": \"1.0.0\",\n \"description\": \"Understand Frontera, then author its Apps, Blueprint, Agents and Automations through the frontera CLI.\",\n \"author\": {\n \"name\": \"Frontera\"\n },\n \"homepage\": \"https://github.com/sebati-ai/sebati-agents\",\n \"license\": \"Apache-2.0\",\n \"keywords\": [\n \"frontera\",\n \"blueprint\",\n \"apps\",\n \"automations\"\n ]\n}\n",
50
+ "codex": "{\n \"name\": \"frontera\",\n \"version\": \"1.0.0\",\n \"description\": \"Understand Frontera, then author its Apps, Blueprint, Agents and Automations through the frontera CLI.\",\n \"author\": {\n \"name\": \"Frontera\"\n },\n \"homepage\": \"https://github.com/sebati-ai/sebati-agents\",\n \"repository\": \"https://github.com/sebati-ai/sebati-agents\",\n \"license\": \"Apache-2.0\",\n \"keywords\": [\n \"frontera\",\n \"blueprint\",\n \"apps\",\n \"automations\"\n ],\n \"skills\": \"./skills\",\n \"displayName\": \"Frontera\",\n \"shortDescription\": \"Operate the Frontera platform from Codex through the frontera CLI.\",\n \"category\": \"developer-tools\",\n \"composerIcon\": \"./assets/icon.png\",\n \"logo\": \"./assets/icon.png\",\n \"brandColor\": \"#006FE6\"\n}\n"
51
+ },
52
+ "pluginAssets": {
53
+ "assets/icon.png": "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",
54
+ "assets/icon.svg": "PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Ik0xMi43MTQ0IDIuODY1ODFDMTIuNzE0NCAyLjIxNzgyIDEyLjAyNzkgMS44MDAwNSAxMS40NTI0IDIuMDk3ODlMNC41MDA3OSA1LjY5NTY0QzIuNjcyNzMgNi41OTk3NyAyLjUzNDQ3IDguNjgwMzEgMi45ODc3NiA5LjgwMjQyQzMuMzA2NTkgMTAuNTkxNyA0LjQ3NjA5IDEyLjAzNjMgNi43ODE0NSAxMi4xMzE0TDguMzgzMTEgMTIuNDYyN0M3LjkyNjY0IDEyLjMyOTIgNy45Mjg2MSAxMS42ODQyIDguMzkwOTIgMTEuNTU2N0M4LjY2NTE3IDExLjQ4MSA4LjkxNDggMTEuNDAxNSA5LjEzOTc5IDExLjMxODJDMTAuMjI5MSAxMC45MTQxIDEwLjc0ODIgMTAuNDAzNCAxMS4xNTYyIDkuMzI4MjZDMTEuMjM1MiA5LjExNTY1IDExLjMwNjMgOC44OTk2NiAxMS4zNjk0IDguNjgwMzFMMTEuMzk2NSA4LjU4NjA0QzExLjUyNDMgOC4xMjI1NSAxMi4xODg3IDguMTIyNTYgMTIuMzE2NSA4LjU4NjA0QzEyLjM4NTcgOC44Mzc1OCAxMi40NjYxIDkuMDg2MDMgMTIuNTU3MiA5LjMzMDYzQzEyLjk2NDMgMTAuNDAzOCAxMy40ODMgMTAuOTE0IDE0LjU3MzIgMTEuMzE4NkMxNC44MTg5IDExLjQwNzkgMTUuMDcwNiAxMS40NzQxIDE1LjMyMjkgMTEuNTQzMkMxNi4xNDIxIDExLjcxNzIgMTguMzA3OCAxMi4xMjcyIDE4Ljg2OTkgMTIuNDkwOEMxOS42ODk0IDEzLjAyMDggMjAuODQ0NyAxMy43NDIxIDIxIDE0LjkxNzlDMjEgMTQuOTE3OSAyMC45OTk4IDEwLjI5NzkgMjEgOS4wODE5M0MyMS4wMDAyIDcuNjQwOTYgMTkuOTk2IDYuNDM1NTggMTkuMDE4OCA2LjE1NDk5QzE4LjA0MjQgNS44NzQ2IDE1LjMzNzMgNS4yMjUwOSAxNS4zMzEyIDUuMjIzODRDMTQuODI3NiA1LjEyMDM1IDE0LjE3OTkgNC45NjA4NiAxMy42NTQ4IDQuODI2MzlDMTMuMDk4NiA0LjY4MzkxIDEyLjcxNDQgNC4xODA0NSAxMi43MTQ0IDMuNjA2MjJDMTIuNzE0NCAzLjQwNzY1IDEyLjcxNDQgMy4xNDIzNyAxMi43MTQ0IDIuODY1ODFaIiBmaWxsPSJ1cmwoI2Zyb250ZXJhLW1hcmstdXBwZXIpIiAvPgogIDxwYXRoIGQ9Ik0xMS4wNTQ4IDIxLjEzNDJDMTEuMDU0OCAyMS43ODIyIDExLjc0MTMgMjIuMiAxMi4zMTY4IDIxLjkwMjJMMTkuMjY4NCAxOC4zMDQ0QzIxLjA5NjQgMTcuNDAwMyAyMS4yMzQ3IDE1LjMxOTcgMjAuNzgxNCAxNC4xOTc2QzIwLjQ2MjYgMTMuNDA4NCAxOS4wOTk0IDEyLjE4MDQgMTYuOTg3NyAxMS44Njg3TDE1LjM4NjEgMTEuNTM3M0MxNS44NDI1IDExLjY3MDggMTUuODQwNiAxMi4zMTU5IDE1LjM3ODIgMTIuNDQzM0MxNS4xMDQgMTIuNTE5MSAxNC44NTQ0IDEyLjU5ODYgMTQuNjI5NCAxMi42ODE5QzEzLjU0MDEgMTMuMDg2IDEzLjAyMSAxMy41OTY3IDEyLjYxMjkgMTQuNjcxOEMxMi41MzQgMTQuODg0NCAxMi40NjI5IDE1LjEwMDQgMTIuMzk5OCAxNS4zMTk3TDEyLjM3MjcgMTUuNDE0QzEyLjI0NDkgMTUuODc3NSAxMS41ODA1IDE1Ljg3NzUgMTEuNDUyNyAxNS40MTRDMTEuMzgzNCAxNS4xNjI1IDExLjMwMzEgMTQuOTE0IDExLjIxMTkgMTQuNjY5NEMxMC44MDQ4IDEzLjU5NjIgMTAuMjg2MiAxMy4wODYgOS4xOTU5OSAxMi42ODE1QzguOTUwMjQgMTIuNTkyMSA4LjY5ODYxIDEyLjUyNTkgOC40NDYyNiAxMi40NTY5QzcuNjI3MDYgMTIuMjgyOCA1LjMxMjUyIDExLjkwMDkgNC43NTAzNSAxMS41MzczQzMuOTMwODggMTEuMDA3MyAyLjkyNDQzIDEwLjI1NzkgMi43NjkxNyA5LjA4MjE1QzIuNzY5MTcgOS4wODIxNSAyLjc2OTMyIDEzLjcwMjIgMi43NjkxNyAxNC45MTgxQzIuNzY4OTkgMTYuMzU5MSAzLjc3MzE2IDE3LjU2NDUgNC43NTAzNSAxNy44NDUxQzUuNzI2ODEgMTguMTI1NCA4LjQzMTg4IDE4Ljc3NSA4LjQzOCAxOC43NzYyQzguOTQxNTMgMTguODc5NyA5LjU4OTI4IDE5LjAzOTIgMTAuMTE0MyAxOS4xNzM3QzEwLjY3MDYgMTkuMzE2MSAxMS4wNTQ4IDE5LjgxOTYgMTEuMDU0OCAyMC4zOTM4QzExLjA1NDggMjAuNTkyNCAxMS4wNTQ4IDIwLjg1NzcgMTEuMDU0OCAyMS4xMzQyWiIgZmlsbD0idXJsKCNmcm9udGVyYS1tYXJrLWxvd2VyKSIgLz4KICA8ZGVmcz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iZnJvbnRlcmEtbWFyay11cHBlciIgeDE9IjIwLjUzNjYiIHkxPSItMC4wODQ4MzE1IiB4Mj0iNC4xNzMwOCIgeTI9IjExLjczMzMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwLjU2ODY4OCIgc3RvcC1jb2xvcj0iIzAwNkZFNiIgLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDAyNjYxIiAvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iZnJvbnRlcmEtbWFyay1sb3dlciIgeDE9IjIuMzU0OSIgeTE9IjIyLjE4NzciIHgyPSIyMS40NDU2IiB5Mj0iOS40NjA1NCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAuNDgwMDg0IiBzdG9wLWNvbG9yPSIjMDA2RkU2IiAvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDI2NjEiIC8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KPC9zdmc+Cg=="
26
55
  },
27
56
  "marketplaceManifests": {
28
57
  "claudeCode": "{\n \"$schema\": \"https://anthropic.com/claude-code/marketplace.schema.json\",\n \"name\": \"frontera\",\n \"description\": \"The Frontera agent-authoring kit — skills that teach a coding host to operate Frontera through the frontera CLI.\",\n \"owner\": {\n \"name\": \"Frontera\",\n \"url\": \"https://frontera.dev\"\n },\n \"plugins\": [\n {\n \"name\": \"frontera\",\n \"description\": \"Author Frontera Apps, Blueprint, Agents and Automations through the frontera CLI. Adds no MCP server and wraps no part of the host.\",\n \"author\": { \"name\": \"Frontera\", \"url\": \"https://frontera.dev\" },\n \"category\": \"development\",\n \"source\": \"./plugin\"\n }\n ]\n}\n",