{
  "pack": "patterns-pack-0.1",
  "version": "0.1",
  "generated_from": "patterns/*.md",
  "patterns": [
    {
      "id": "agent-skill-supply-chain",
      "title": "Agent-skill supply-chain security (#1937)",
      "description": "Inbound supply-chain guidance for skills, plugins, MCP servers, and other agent capability bundles that a directive project installs or exposes to agents. This is the **inbound** complement to Agent Trap Defenses (#480) \u2014 which governs how agents treat externally-ingested content at runtime \u2014 and to outbound disclosure controls (#1700), which govern what an agent may emit about its environment.",
      "triggers": [
        "agent-skill-supply-chain"
      ],
      "path": "patterns/agent-skill-supply-chain.md",
      "body": null
    },
    {
      "id": "code-mode",
      "title": "Code Mode \u2014 compact search + sandboxed execute (#2593)",
      "description": "Pattern for **code-mediated tool use**: the model writes and runs code that orchestrates capabilities, instead of requesting each tool call separately against a large static catalog. The public surface stays tiny (typically `search` / `describe` for progressive discovery and `execute` for sandboxed capability calls); the broader capability graph lives behind that surface in typed code.",
      "triggers": [
        "code-mode"
      ],
      "path": "patterns/code-mode.md",
      "body": null
    },
    {
      "id": "executor-layer-credentials",
      "title": "Executor-layer credentials (#806)",
      "description": "Secrets for privileged operations MUST be bound at the **invocation layer** (the orchestrator, the command definition, the trusted shim that wraps the capability) -- never inside the agent's context window, prompt, filesystem, or globally-inherited environment. The agent receives access to the **capability**, not the **credential**.",
      "triggers": [
        "executor-layer-credentials"
      ],
      "path": "patterns/executor-layer-credentials.md",
      "body": null
    },
    {
      "id": "goal-gate-determinism",
      "title": "Goal-gate determinism (#852)",
      "description": "Skills and agent playbooks MUST be rigid on **goals**, **acceptance criteria**, and **quality gates**. They SHOULD leave the **execution path** flexible.",
      "triggers": [
        "goal-gate-determinism"
      ],
      "path": "patterns/goal-gate-determinism.md",
      "body": null
    },
    {
      "id": "in-band-signaling",
      "title": "No in-band signaling / absence is not a decision (#1695)",
      "description": "Coding-standards pattern: do not overload one field (or its presence/absence) to carry two orthogonal facts. Separate **value** from **decision-provenance**. Triggered by the wipCap onboarding contradiction (#1694).",
      "triggers": [
        "in-band-signaling"
      ],
      "path": "patterns/in-band-signaling.md",
      "body": null
    },
    {
      "id": "install-trust",
      "title": "Install trust \u2014 no naked curl|sh as primary path (#2969)",
      "description": "Install and bootstrap guidance for Directive itself, for docs that teach consumers how to install tools, and for agent-facing install instructions. Industry CTAs still push `curl \u2026 | sh` (and `irm | iex`) as the default. That convenience shape is **not** Directive's blessed primary install path.",
      "triggers": [
        "install-trust"
      ],
      "path": "patterns/install-trust.md",
      "body": null
    },
    {
      "id": "llm-app",
      "title": "LLM application standards (#481)",
      "description": "Architectural standards for projects that call LLM APIs (OpenAI, Anthropic, Cohere, local models, etc.) or that build agentic functionality on top of those calls. These standards are cross-language and cross-interface; they sit alongside `languages/`, `interfaces/`, `platforms/`, and `coding/` and answer the orthogonal question \"how do I architect a system of this type safely?\"",
      "triggers": [
        "llm-app"
      ],
      "path": "patterns/llm-app.md",
      "body": null
    },
    {
      "id": "multi-agent",
      "title": "Multi-agent identity separation pattern (#983)",
      "description": "Status: stable pattern, v1 docs-only. v1 deliberately scopes to a single shared bot/App credential for all workers; per-worker token rotation is deferred to a follow-up. Per #983 non-goals.",
      "triggers": [
        "multi-agent"
      ],
      "path": "patterns/multi-agent.md",
      "body": "# Multi-agent identity separation pattern (#983)\n\n> Status: stable pattern, v1 docs-only. v1 deliberately scopes to a single\n> shared bot/App credential for all workers; per-worker token rotation is\n> deferred to a follow-up. Per #983 non-goals.\n\nThis pattern lays out *whose* GitHub identity dispatched swarm workers\nshould authenticate as, *why* that should not be the maintainer's PAT,\nand *how* operators provision and rotate the worker credential.\n\nIt is the credential-separation track that was carved out of #976\n(`fix(scm,tests): eliminate remaining GraphQL-backed scm.py / live SCM\nsmoke bucket drain after #961`). #976 owns the REST migration; this\npattern owns the orthogonal identity separation. The two tracks are\ncomplementary: REST migration reduces GraphQL demand on the shared\nbucket, identity separation prevents human and machine traffic from\nsharing one bucket in the first place.\n\n## Why this matters\n\nToday, swarm workers and the maintainer share a single GitHub Personal\nAccess Token (PAT). One PAT serves the maintainer's interactive review\nflow AND every worker spawned by `task swarm:*` / `start_agent` /\n`oz agent run`. The operational consequences observed in the\n2026-05-07 multi-agent session and again on 2026-05-08 are concrete:\n\n- **Bucket coupling**: GitHub's GraphQL bucket is **5,000 req/hr per\n  identity**. A swarm of N workers + the maintainer's terminal share\n  one bucket. When workers exhaust it (the documented failure mode for\n  the PR #652 / #561-class merge cascades), the maintainer's\n  `gh issue create` and `gh pr view` start failing with\n  `GraphQL: API rate limit already exceeded` -- the human is rate-\n  limited by their own swarm.\n- **Audit conflation**: every commit, comment, PR open, issue close,\n  and review submission attributes to the same `actor.login`. Forensic\n  separation (\"which action was the maintainer vs. an autonomous\n  worker?\") requires correlating timestamps and dispatch-envelope\n  prompts rather than reading the GitHub event stream directly.\n- **Credential blast radius**: a worker's prompt envelope is by\n  definition reviewable / loggable / inspectable -- prompts leak more\n  readily than secrets. Today a leaked worker prompt acts with the\n  full scope of the maintainer's PAT (issue close, PR merge, release\n  publish, branch protection bypass), not the narrow scope a worker\n  actually needs (issues:write, pulls:write, contents:read).\n\nReducing GraphQL demand (#976 REST migration) only solves bucket\n*pressure*. It does not solve bucket *coupling*, audit conflation, or\nblast radius. Those require partitioning the identity itself.\n\n## The pattern\n\n### Identity model\n\n- ! Workers MUST authenticate as a **distinct GitHub identity** from\n  the maintainer. Two acceptable shapes:\n  1. **GitHub App installation token** (preferred). The deft project\n     installs a GitHub App granting the minimum scopes; workers\n     consume an installation token derived from the App's private key.\n     Tokens are short-lived (~1 hour) and auto-rotated by GitHub.\n  2. **Bot account PAT**. A dedicated GitHub user account (e.g.\n     `deft-swarm-bot`) with its own PAT. Lower setup cost, but tokens\n     are long-lived until manually rotated, and the bot account\n     consumes a real GitHub seat.\n- ! Maintainer PATs MUST be reserved for human-driven work: review,\n  merge, release publication, manual triage. Worker dispatch envelopes\n  MUST NOT inject a maintainer PAT.\n- \u2297 Workers MUST NOT fall back to the host's `gh auth status` token.\n  The dispatch envelope is the contract; an implicit fallback re-\n  introduces the coupling this pattern eliminates.\n\n### Bucket partitioning model\n\n| Bucket               | Owner                | Use                                                |\n|----------------------|----------------------|----------------------------------------------------|\n| Maintainer GraphQL   | Maintainer PAT       | Human review, PR open/merge/ready, manual triage   |\n| Maintainer core REST | Maintainer PAT       | `gh api` reads outside swarm context               |\n| Worker GraphQL       | Bot account / App    | `markPullRequestReadyForReview`, `addPullRequestReview` (the only GraphQL surfaces a worker should hit; see #976 + #961) |\n| Worker core REST     | Bot account / App    | All other reads / mutations via `gh api` REST helpers |\n\nEach bucket is 5,000 req/hr (REST `core` and GraphQL each). With\nidentity separation the maintainer's two buckets are untouched by\nswarm activity, and N workers share *their own* two buckets.\n\nThe bucket partition only delivers value when paired with the #976\nREST migration: workers that still route reads through GraphQL\n(`gh issue view --json`, `gh pr view --json`, `gh pr ready`) will\nexhaust their own GraphQL bucket within minutes under N concurrent\npoll loops. REST-by-default per `templates/agent-prompt-preamble.md`\nS5 keeps the worker GraphQL bucket reserved for the unavoidable PR\nstate-mutation operations.\n\n### Dispatch-envelope credential rule\n\nThe canonical preamble at `templates/agent-prompt-preamble.md` carries\nthis rule verbatim alongside the existing REST-default,\nmax-1-Draft-toggle, and rate-limit-throttle rules:\n\n> Workers MUST consume the GitHub credential injected by the dispatcher\n> (typically `GH_TOKEN` in the prompt-supplied env). Workers MUST NOT\n> fall back to the host's `gh auth status` token. If `GH_TOKEN` is\n> unset and no other dispatcher-supplied credential is present, the\n> worker MUST fail loud with a clear error rather than silently\n> running under the host identity.\n\nThe rule is enforced at two points:\n\n1. **Dispatch time** (orchestrator side). The orchestrator (swarm\n   skill, monitor agent, scheduled run) injects the worker\n   credential into the dispatch envelope -- usually as `GH_TOKEN` in\n   the env, with the maintainer's `gh auth` state untouched. Workers\n   inherit this env at spawn time.\n2. **Worker side**. The worker's first action (after AGENTS.md read)\n   verifies `GH_TOKEN` is set and matches the expected bot/App\n   identity (e.g. `gh api user --jq .login` returns the bot login).\n   Mismatch is a hard refusal: stop the tool loop, send `BLOCKED:\n   identity mismatch` to the parent.\n\nThe two-sided enforcement means a missing/malformed credential surfaces\nat the earliest possible point rather than mid-dispatch when the worker\nhas already started writing files.\n\n### Permission scoping\n\n! The worker credential MUST be scoped down to the minimum needed:\n\n- `issues:write` -- open / close / comment / label\n- `pulls:write` -- open / merge / review / comment\n- `contents:read` -- read repo contents (for diff context)\n- `metadata:read` -- standard for any GitHub App\n- \u2297 `contents:write` -- workers MUST NOT push commits directly under\n  the worker identity. Pushes happen via the maintainer (interactive\n  review of the worker's diff) or via the GitHub App's restricted\n  contents:write scope on a specific bot-owned ref pattern.\n- \u2297 `admin:*` / `repo` (broad) -- workers MUST NOT have admin scopes.\n  Branch protection bypass, label/milestone management, secret\n  rotation -- all maintainer-only.\n\nThe maintainer PAT keeps the broader scope it has today (`repo`,\n`workflow`, etc.). The narrowness of the worker scope is half the\nblast-radius mitigation; the other half is short-lived credentials\n(GitHub App installation tokens auto-rotate ~1 hour; bot PATs MUST be\nrotated quarterly per the runbook below).\n\n## Operator runbook\n\n### Provisioning a worker identity\n\n#### Option A: GitHub App (preferred)\n\n1. Create a new GitHub App at\n   `https://github.com/organizations/<org>/settings/apps/new`\n   (account-level path: `https://github.com/settings/apps/new`).\n2. Grant the **minimum** permissions enumerated in\n   \"Permission scoping\" above. Decline every other permission.\n3. Subscribe to no events (workers consume the API; they do not need\n   webhook delivery).\n4. Generate and download a private key (`.pem`). Store it in\n   `secrets/swarm-app.pem` outside the repo (the deft `secrets/`\n   convention is `.gitignore`d by default per the repo conventions).\n5. Install the App on the deft repository.\n6. Note the App ID and Installation ID; both are required to mint\n   installation tokens at dispatch time.\n7. The dispatcher mints an installation token via\n   `POST /app/installations/<installation-id>/access_tokens` (the\n   private-key-signed JWT flow). Each minted token lives ~1 hour;\n   spawn-burst refreshes are cheap.\n\n#### Option B: bot account PAT\n\n1. Create a new GitHub user account (e.g. `deft-swarm-bot`). Email\n   address can be a `+swarmbot` alias on the maintainer's account.\n2. Add the bot account as a repository collaborator with **Write**\n   access (NOT Maintain or Admin).\n3. Generate a fine-grained PAT under the bot account with the scopes\n   enumerated in \"Permission scoping\". Set expiry to 90 days.\n4. Store the PAT in `secrets/swarm-bot.env` as\n   `SWARM_GH_TOKEN=<value>`. Reference from dispatcher via\n   `Get-Content secrets/swarm-bot.env` or equivalent at dispatch\n   time; never paste inline.\n\n### Wiring the dispatcher\n\nThe orchestrator (swarm skill, monitor agent, `start_agent`/`oz`\ninvocation, scheduled run) loads the worker credential and injects it\ninto the worker's env:\n\n```pwsh path=null start=null\n# Option A (GitHub App): mint installation token at dispatch time.\n$jwt = <operator-supplied GitHub App JWT>  # Directive does not ship a mint helper in v1 (#983)\n$inst_token = (gh api -X POST \"/app/installations/$env:DEFT_SWARM_INSTALLATION_ID/access_tokens\" -H \"Authorization: Bearer $jwt\" --jq .token)\nstart_agent ... -e GH_TOKEN=$inst_token\n\n# Option B (bot PAT): inject from secrets/swarm-bot.env.\n$bot_token = (Get-Content secrets/swarm-bot.env | Where-Object { $_ -like 'SWARM_GH_TOKEN=*' }) -replace '^SWARM_GH_TOKEN=', ''\nstart_agent ... -e GH_TOKEN=$bot_token\n```\n\nToken-mint plumbing is intentionally not\nshipped in v1 -- the runbook above is operator-facing guidance, not\ndeft-supplied automation. v1 is documentation-only per #983 non-goals.\nOperators MAY automate token minting in their own dispatcher; the\ncontract this pattern pins is the env-var injection.\n\n### Rotation and recovery\n\n#### Routine rotation\n\n- **GitHub App tokens**: auto-rotate ~1 hour. No operator action\n  needed unless the App's private key is compromised.\n- **Bot PAT**: quarterly rotation. Update `secrets/swarm-bot.env`\n  and revoke the prior PAT. Verify the new token via\n  `gh api user --jq .login` returns the bot login.\n\n#### Compromise recovery (leaked worker token)\n\n1. Immediately revoke the leaked credential:\n   - GitHub App: rotate the private key (Settings -> Apps -> Your\n     deft-swarm App -> Generate a new private key, then delete the\n     compromised key).\n   - Bot PAT: revoke at\n     `https://github.com/settings/tokens` under the bot account.\n2. Audit the bot's recent activity: `gh api\n   /users/<bot-login>/events/public --jq\n   '.[] | {repo, type, created_at}'`. Investigate any action outside\n   the expected swarm workflow.\n3. Provision a replacement credential per the provisioning steps\n   above and update the dispatcher.\n4. File an incident vBRIEF in `vbrief/proposed/` documenting the\n   compromise, scope of activity, and remediation. The vBRIEF\n   becomes the audit artifact.\n\nThe maintainer PAT MUST NOT be used as a fallback during the\ncompromise window -- doing so re-couples the buckets and re-introduces\nthe blast-radius problem this pattern solves.\n\n## Cross-references\n\n- #976 -- remaining GraphQL drain in `task scm:body` + smoke (the\n  REST-migration track this pattern complements; this pattern was\n  carved out of #976's \"Complementary mitigation\" section)\n- #588 -- agent identity pattern (distinct attestable identity per\n  agent; the conceptual frame this pattern operationalises)\n- #806 -- executor-layer-credentials (secrets bound at invocation\n  layer, not in agent context; the architectural pattern this\n  pattern lands)\n- #585 -- credential hygiene standard for cloud agent dispatch\n  (overlapping with v1, but #585 covers the broader cloud-agent\n  surface; this pattern scopes specifically to swarm workers)\n- #519 -- rate limiting as a first-class architectural constraint\n  for multi-agent guidance (the \"shared bucket is the bottleneck\"\n  framing that motivates partitioning by identity)\n- #520 -- multi-provider routing as the production solution for\n  large-scale swarms (the LLM-side analogue of this pattern -- LLM\n  providers also rate-limit per identity, and the same partitioning\n  argument applies upstream)\n- #954 / #966 -- canonical orchestrator preamble; the\n  `templates/agent-prompt-preamble.md` rule enforcing the\n  dispatch-envelope credential contract is part of #954's preamble\n  surface and is updated by this issue (#983)\n- AGENTS.md `## Multi-agent orchestration discipline (#954)` -- the\n  REST-default / no-Draft-retoggle / rate-limit-throttle rules this\n  pattern complements\n\n## Non-goals (per #983)\n\n- Per-worker token rotation infrastructure -- a single shared\n  bot/App credential for all workers is acceptable in v1; per-worker\n  identities are deferred to a follow-up.\n- Cross-provider identity (Anthropic, OpenAI, etc.) -- this pattern\n  is GitHub-specific; the LLM-side analogue is #520.\n- Replacing the SCM/REST migration -- #976 owns that track; this\n  pattern is complementary, not a substitute.\n"
    },
    {
      "id": "operator-log-hygiene",
      "title": "Operator-log hygiene \u2014 structured operator-facing logs (#1940)",
      "description": "Guidance for consumer services that humans operate. Declare and keep structured, operator-facing logs so outages are diagnosable without a week of reactive firefighting.",
      "triggers": [
        "operator-log-hygiene"
      ],
      "path": "patterns/operator-log-hygiene.md",
      "body": null
    },
    {
      "id": "prompt-assembly-layer-ordering",
      "title": "Prompt assembly layer ordering (#836)",
      "description": "Architectural standard for agents that issue multi-turn LLM API calls (OpenAI, Anthropic, Cohere, local models, etc.). It pins the contract between the **cached system prefix** (assembled once at session start, stable for the session) and the **ephemeral per-turn injections** (rebuilt on every API call, never cached). Mixing these two layers collapses prefix-cache effectiveness and silently multiplies token cost by the number of turns.",
      "triggers": [
        "prompt-assembly-layer-ordering"
      ],
      "path": "patterns/prompt-assembly-layer-ordering.md",
      "body": null
    },
    {
      "id": "role-as-overlay",
      "title": "Role as overlay (#816)",
      "description": "Architectural standard for how persona and role instructions are applied to LLM calls in directive's skills, agents, and downstream consumers. Role instructions MUST be implemented as **call-scoped system-prompt overlays**, never injected into the persisted message history.",
      "triggers": [
        "role-as-overlay"
      ],
      "path": "patterns/role-as-overlay.md",
      "body": null
    },
    {
      "id": "tool-call-taxonomy",
      "title": "Tool-call taxonomy \u2014 explore / commit / verify (#2967)",
      "description": "Deterministic activity buckets for swarm and review-cycle operators. Use this taxonomy when skimming tool logs, monitor status lines, or batch briefs so \u201cran N tools\u201d becomes a structured mix.",
      "triggers": [
        "tool-call-taxonomy"
      ],
      "path": "patterns/tool-call-taxonomy.md",
      "body": null
    }
  ]
}
