Agent Development Environments — Claude, Codex, Grok, Antigravity

Agent Development Environments — Claude, Codex, Grok, Antigravity

This guide is for contributors who want to develop the platform with a dedicated AI coding agent — Claude, Codex, Grok, or Google Antigravity — instead of (or alongside) the in-portal Build Studio. Each agent ships in more than one form, and all of them are valid options:

Agent Available as Notes
Claude Desktop app (Mac/Windows), IDE extension (VS Code / JetBrains), or CLI (Claude Code) Use whichever client you prefer; they share the same ~/.claude config
Codex Desktop / IDE client app or CLI Both read the same ~/.codex/config.toml
Grok CLI only No GUI client yet — the Grok CLI is the only surface today
Antigravity (agy) Agentic IDE + CLI — opt-in install through the bootstrap Google’s Antigravity. The bootstrap can install agy opt-in (--install-antigravity / -InstallAntigravity) and wire the DPF MCP token; agy handles its own Google sign-in (a device-code URL on a headless server). Host contributor surface only — supported for external DPF development, but not as a Build Studio in-sandbox dispatch engine (why). See the Antigravity onboarding runbook.

Whether you run the desktop app or the CLI, the DPF setup is the same: install the dpf-platform plugin (which bundles the skill pack, the DPF MCP server wiring, and the governance hooks), load the AGENTS.md operating doctrine, and adjust a few local client settings so the agent follows the portal’s processes. These agents are the more advanced surface — they let an experienced contributor run multiple concurrent threads of work (one branch and one git worktree per thread) while still adhering to every process the portal establishes.

If you only want the guided experience, use Build Studio and stop here. If you want to drive the platform from a full agent client, read on.

One process, five surfaces. Build Studio, Claude, Codex, Grok, and Antigravity are interchangeable adapters behind one contract wherever each surface’s host capabilities are available: the evidence-gated lifecycle (ideate → plan → build → review → ship), the DPF MCP coordination plane, documentation impact checks, and the worktree/lease isolation model. Governance reads the evidence, never which surface produced it. See the Unified Delivery Surfaces spec and the Antigravity first-class support design.

How the pieces fit together

Every surface — the four external agent clients and Build Studio — plugs into the same coordination plane and the same governed lifecycle. The diagram below is the mental model for the rest of this guide:

flowchart TB
    subgraph surfaces["Development surfaces (interchangeable)"]
        claude["Claude<br/>(app / IDE / CLI)"]
        codex["Codex<br/>(app / CLI)"]
        grok["Grok<br/>(CLI)"]
        antigravity["Antigravity<br/>(IDE / agy CLI)"]
        bs["Build Studio<br/>(in-portal)"]
    end

    subgraph plugin["dpf-platform plugin (per client)"]
        skills["Skills<br/>27 kernel-aware workflows"]
        hooks["Hooks<br/>local governance guards"]
        mcpwire["MCP wiring<br/>dpf connector"]
    end

    mcp["DPF MCP coordination plane<br/>backlog · workrooms · evidence · leases"]
    lifecycle["Evidence-gated lifecycle<br/>ideate → plan → build → review → ship"]
    pr["PR against main<br/>DCO-signed · CI gates"]
    webhook["GitHub webhook<br/>promotion intake"]
    live["Live install<br/>self-upgrade pipeline"]

    claude --- plugin
    codex --- plugin
    grok --- plugin
    antigravity --- plugin
    plugin --> mcp
    bs --> mcp
    mcp --> lifecycle
    lifecycle --> pr
    pr --> webhook
    webhook --> live

Three things are worth calling out up front, because they recur throughout this guide:


Why a dedicated agent client instead of Build Studio?

  Build Studio (in-portal) Agent clients (Claude / Codex / Grok / Antigravity)
Audience Non-technical operators; guided authoring Experienced contributors comfortable with git
Concurrency One guided build at a time per operator Many concurrent threads — one branch + one worktree each
Source access Governed, abstracted Direct source edits, debugging, arbitrary tooling
Same governance? Yes — identical gates, MCP coordination, PR/DCO, evidence Yes — identical gates, MCP coordination, PR/DCO, evidence

The headline advantage is thread management: several worktrees open at once, each on its own branch and its own isolated Docker Compose project, without their working trees, container names, or HEADs colliding. The rest of this guide is mostly about doing that without breaking the processes the portal depends on.


Prerequisites

You need the base developer environment first — see Developer Setup (pnpm + Docker sidecars) or the Dev Container Setup. Then install at least one agent client:

Agent Where to get it
Claude (desktop app, IDE extension, or Claude Code CLI) code.claude.com/docs
Codex (desktop/IDE app or CLI) developers.openai.com/codex
Grok (CLI — no GUI yet) xAI Grok Build CLI (grok)
Google Antigravity (IDE and agy CLI) antigravity.google

You do not have to install all four, or pick one form over another. The setup is symmetric: install whatever you like, run the bootstrap, and add more later by re-running it.


Step 1 — Wire MCP, the plugin, and AGENTS.md (one command)

From the repo root, run the agent toolchain bootstrap. It is the single, client-agnostic entry point that connects every installed client — desktop app or CLI — to DPF in one pass:

# macOS / Linux
bash scripts/dpf-bootstrap-agent-toolchain.sh

# Windows (PowerShell)
.\scripts\dpf-bootstrap-agent-toolchain.ps1

The bootstrap is idempotent (re-running on a converged install is a no-op) and writes the shared client configuration that both the desktop app and the CLI read (~/.claude, ~/.codex/config.toml, ~/.grok/config.toml, and the Antigravity MCP config it can detect/write). It:

  1. Detects which of Claude / Codex / Grok / Antigravity are installed — resolving GUI-app and non-PATH install locations, not just which.
  2. Mints and persists a legacy DPF MCP token if one isn’t present (a client that speaks the browser flow no longer needs this — see How a client authenticates) (issued inside the portal container, persisted to ~/.dpf/agent-toolchain.env and your shell profile, never logged). Default scope is write so the agent can use side-effecting MCP tools (backlog, evidence, Build Studio handoff). On macOS it also injects the token via launchctl so GUI-launched apps — which don’t read your shell profile — still pick it up.
  3. Connects the DPF MCP server in each client (.mcp.json / .vscode/mcp.json for Claude, [mcp_servers.dpf] in Codex/Grok config, and Antigravity’s mcpServers.dpf config when available), all referencing ${DPF_MCP_BEARER_TOKEN}.
  4. Installs the dpf-platform plugin for each client from its local marketplace/registry — this is the single package that carries the shared skill pack and the cross-client hook/MCP contracts (see The plugin below). For Codex, the bootstrap registers and verifies the qualified plugin key dpf-platform@personal; copying plugin files alone is not considered installed.
  5. Seeds kernel-tier memory so the agent is kernel-aware from the first turn, before any MCP retrieval round-trip.
  6. Runs read-only MCP + kernel smoke probes, checks whether the DPF-native process-spine replacement skills are installed and visible to the current session, and prints a single readiness banner. On Grok, this check is verified (grok plugin list --json, run automatically by the bootstrap before the health check) rather than merely inferred from install state; Codex and Antigravity have no non-interactive way to list actively loaded skills yet, so their exposure stays unknown until their CLIs expose one — see the process-spine skill exposure health design.

After it finishes, restart the client (desktop app or CLI) so it reloads the MCP connection and the plugin.

AGENTS.md is already in the repo. AGENTS.md at the repo root is the canonical rulebook, and the tool-specific pointer files (CLAUDE.md, .cursor/rules/, .clinerules/, .github/copilot-instructions.md, CONVENTIONS.md, .continue/rules/) already point to it — they’re checked in. You don’t author these; you just make sure your client loads project instructions (most do automatically from the repo root). Don’t duplicate rules into the pointer files — they are pointers, not copies.

Reading the readiness banner

State Meaning Next action
ready Client(s) wired, MCP reachable, kernel principle fired Start working
partial One client is ready; another needs setup Repair toolchain (re-run bootstrap)
missing_cli No supported agent detected Install Claude / Codex / Grok / Antigravity
missing_token No DPF MCP token Issue a development token (Admin → Platform Development → MCP)
needs_refresh Token exists but the running client hasn’t picked it up Restart the client / refresh the binding
failed_smoke Installed but did not apply a kernel principle View evidence under --show-substrate

Re-run with --show-substrate for plugin/config/memory detail, or --dry-run to preview writes. See docs/operations/install.md for what each state means in depth.

The readiness record is committed through the same locked, compare-and-swap install-state transaction used by the installer and self-upgrade promoter. A failed state write now stops the bootstrap with an explicit error instead of reporting a misleading ready banner.

The banner reports DPF-native replacement skills installed separately from DPF-native replacement skills loaded/exposed in this session. That distinction matters: a client can have the dpf-platform plugin on disk but still be running with stale skill exposure until restart. If a retired generic process skill such as superpowers:brainstorming is visible while its DPF replacement is absent, stop before project work, restart the client, and re-run the bootstrap. Codex may safely disable known competitive plugins through its native config adapter; other clients warn until their native plugin surfaces support the same reconciliation.


The plugin: skills, hooks, and MCP in one package

The bootstrap doesn’t rely on loose skill files — it installs one plugin, dpf-platform, into each client. The shared package owns the skills plus the cross-client hook and MCP contracts. Each client adapter then uses the host’s supported registration surfaces. Claude can consume those declarations from its plugin manifest; Codex receives skills through the qualified dpf-platform@personal registry entry while the bootstrap wires Codex hooks and MCP in its global config.

flowchart LR
    subgraph pkg["packages/dpf-skill-pack"]
        manifest[".claude-plugin/plugin.json<br/>(+ .codex-plugin / .grok-plugin / .antigravity-plugin)"]
        sk["skills/<br/>27 SKILL.md workflows"]
        hk["hooks/hooks.json<br/>governance guards"]
        mc["claude.mcp.json<br/>dpf connector contract"]
    end

    market["Repo-local marketplace<br/>.claude-plugin/marketplace.json"]
    client["Your client<br/>Claude / Codex / Grok / Antigravity"]

    manifest --> market
    market -->|bootstrap installs| client
    sk --> client
    hk --> client
    mc --> client

The surface manifest (plugin.json) ties the package to each host. Manifests declare only capabilities that host supports; the bootstrap adapter owns any remaining global wiring. Codex, Grok, and Antigravity get parallel manifests (.codex-plugin/plugin.json, .grok-plugin/plugin.json, .antigravity-plugin/plugin.json) so the same source of truth installs on every surface without pretending their plugin schemas are identical.

One file per skill, two surfaces. Each skill’s SKILL.md is a superset that feeds both the external agent client (as the dpf-platform:* plugin namespace) and the in-portal coworker (seeded as a SkillDefinition row). You never maintain two copies.

Skills — the kernel-aware workflows

Skills are the reusable procedures that encode DPF’s non-negotiable process into steps an agent can follow. They fire in two ways: you invoke one explicitly (dpf-platform:dpf-file-backlog-item), or the agent auto-selects one when your request matches its trigger description. There are 27 in the pack; the ones you’ll reach for most:

Skill Use it when
dpf-worktree-per-session Starting or auditing a concurrent session that touches the working tree
dpf-verify-substrate-first Tempted to add a new table / type / enum / tool — check it doesn’t already exist
dpf-file-backlog-item New work needs to enter the backlog before a plan is written
dpf-writing-plans A filed BI needs a phased implementation plan
dpf-decision-via-kernel An open question has 2+ architecturally-distinct options
dpf-evidence-before-diagnosis Diagnosing a failure — gather signals before proposing a cause
dpf-tdd / dpf-systematic-debugging Test-first implementation; disciplined bug hunts
dpf-local-merge-ci-before-push About to push — converge and run CI locally first
dpf-pr-with-dco Opening a PR (branch from origin/main, sign every commit)
dpf-verify-on-live-install Runtime-bound verification against the canonical install
dpf-promote-to-build-studio Handing a triaged BI to the Build Studio pipeline
dpf-route-learning-to-commons A durable learning needs to reach every agent and install

The full set spans architecture review, data-architecture stewardship, decision capture, UX-fit review, and the SysML architecture substrate. Because they enforce the same kernel principles that AGENTS.md documents, using the skill is how you comply by construction rather than remembering every rule by hand.

Hooks — local guardrails (not to be confused with webhooks)

The plugin also ships hooks: local, deterministic guards the client runs before a tool call, defined in hooks/hooks.json. They are how the platform stays safe even when an agent moves fast. Distinguish them from webhooks (GitHub → portal HTTP callbacks) covered later — hooks run on your machine, inside the client; webhooks run server-side, across machines.

Hook Fires on What it prevents
lease-guard Bash Ungoverned dev-server launches (pnpm/npm/yarn dev, next dev, turbo dev) against a shared runtime without a lease
root-clone-guard Bash Mutating the shared root clone from a session that should be in a worktree
compose-guard Bash Ad-hoc docker compose / docker run against shared singletons
ux-fit-precheck Write / Edit Shipping a UI-impacting change without a UX-fit pass
spec-plan-doc-precheck Write / Edit Code landing ahead of its spec / plan / doc
tool-economy-precheck Write / Edit Adding tool surface that blows the context budget
worktree-create WorktreeCreate A new worktree starting life un-seeded (no MCP, no isolated compose project)

Don’t loosen these. There is one narrow, documented escape hatch — the lease guard only — for a genuine local emergency: prefix the command with DPF_ALLOW_UNGATED_SERVER=1. Everything else is meant to hold.

Codex, Grok, and Antigravity inherit the same guard contract. The dpf-platform plugin ships hooks/hooks.json and surface manifests for the external clients. Where a client’s hook plane is not yet proven to enforce a guard, comply by construction: claim a lease before launching any shared runtime, claim a Workroom before you start, record evidence as you go.


Step 2 — Adjust local client settings to match DPF’s processes

The bootstrap wires the connection, but a few client-local settings are not DPF’s to set for you. Check these so your agent’s defaults don’t fight the portal’s processes:

Turn off “open PRs as draft”

This is the important one. Some clients open pull requests as drafts by default — Codex’s GitHub/cloud integration is known to do this. DPF does not use draft PRs. Per AGENTS.md §4, a PR means ready to merge — there is no draft→final review process to graduate through. A pushed branch is the in-flight handoff artifact; the PR is opened only when the branch is green and ready for merge automation.

In your client’s GitHub / PR settings, disable any “create pull requests as draft” default so your PRs open ready for review. If a PR is opened as a draft by mistake, mark it ready for review immediately (or close it and keep the branch).

Confirm the DPF MCP server is connected

After restarting, verify the dpf connector is present:

If it’s missing, the token probably isn’t in the running client’s environment yet — restart the client (GUI apps need a full restart to pick up a freshly minted token), or re-run the bootstrap.

Let the client load project instructions

Make sure your client reads repo-root project instructions (AGENTS.md via its pointer file). Desktop apps and CLIs generally do this automatically when opened at the repo root; if your client has a “project rules / instructions” setting, point it at the repo root rather than copying rules elsewhere.

Be deliberate about auto-run / auto-approve

DPF relies on local guardrails — the pre-commit secret scan + typecheck hook (git config core.hooksPath .githooks, auto-set on new clones), and the plugin’s PreToolUse hooks (above). Don’t loosen these. If a hook blocks you, the fix is almost always to claim a lease or move into a worktree, not to bypass the guard.


Per-agent specifics

Claude

Codex

Grok

Antigravity


How a client authenticates (all clients)

Point the client at the MCP URL and approve it once in your browser. The client gets a 401 that tells it where to look, discovers this installation’s authorization server, and runs the standard OAuth flow. A portal page opens naming the client, this installation, and what it is asking to do; you approve, and the client refreshes its own access from then on. No environment variable, no copy-paste, no client restart.

Headless callers (CI, cron, containers)

Anything with no browser cannot approve a screen, so an operator grants its permissions once, up front: create a client in Admin → Platform Development, choose its scopes, and give it the client id and secret. It exchanges those for short-lived access at the same endpoint every other client uses. Same permissions vocabulary, same revocation, same audit trail — a different way in, not a different system.

The legacy dpfmcp_ token

Older clients authenticate with a DPF_MCP_BEARER_TOKEN environment variable, referenced (never inlined) from each client’s config. This still works and nothing breaks. It is being retired: new tokens stop being issued when the operator closes issuance, and existing ones keep working until the operator sets a horizon. Prefer connecting a client over the browser flow instead.

.mcp.json and .vscode/mcp.json remain gitignored credential files — never commit them. A client connected over the browser flow stores its own credential and needs neither file for authentication.


Marketplaces — two different catalogs

“Marketplace” means two distinct things in DPF. Keep them straight:

  Plugin marketplace (client-side) Tool / skill marketplace (in-portal)
What it distributes The dpf-platform plugin (skills + hooks + MCP wiring) Governed MCP tools and skills an agent or coworker can adopt
Where it lives .claude-plugin/marketplace.json in the repo (dpf-platform-local) The portal catalog, reached via MCP (search_tool_marketplace) and the in-portal UI
Who installs from it The bootstrap, into your Claude / Codex / Grok / Antigravity client An agent requesting a capability it doesn’t yet have granted
When you touch it Once, at setup (the bootstrap does it for you) When a thread needs a tool/skill that isn’t in its current grant

The plugin marketplace is repo-local and boring by design — a single JSON manifest that names one plugin (dpf-platform) and points at packages/dpf-skill-pack. The bootstrap runs the equivalent of claude plugin install dpf-platform@dpf-platform-local --scope local; you rarely interact with it directly.

The tool marketplace is the interesting one for day-to-day work: it’s the governed catalog through which an agent discovers and requests additional capabilities rather than reaching for ungoverned tooling. Requests flow through the same evidence/coordination plane — a capability is granted, not self-installed — which is what keeps the tool surface auditable. See the Agent Tool Marketplace spec and the AI Coworker Skills Marketplace spec.


Managing multiple threads

This is where the agent clients go beyond Build Studio. The model is simple and strict:

One thread = one branch = one git worktree. Never share a working tree across sessions — that causes index/HEAD collisions and cross-thread file sweeps.

flowchart TB
    root["Root clone (~/dpf or d:/DPF)<br/>SHARED · merge / release / inspect only"]
    root -. "based on origin/main" .-> wtA
    root -.-> wtB
    root -.-> wtC

    subgraph threads["Concurrent threads — isolated"]
        wtA["worktree: feat/alpha<br/>branch + COMPOSE_PROJECT_NAME=dpf-alpha"]
        wtB["worktree: fix/beta<br/>branch + COMPOSE_PROJECT_NAME=dpf-beta"]
        wtC["worktree: feat/gamma<br/>branch + COMPOSE_PROJECT_NAME=dpf-gamma"]
    end

    wtA --> prA["PR → main (DCO)"]
    wtB --> prB["PR → main (DCO)"]
    wtC --> prC["PR → main (DCO)"]

Each worktree is its own branch, its own isolated Docker Compose project, and its own seeded MCP config — so containers, volumes, and HEADs never collide. The root clone is the only shared thing, and you keep it out of the way.

Never work in the root clone

The root clone (~/dpf on macOS/Linux, d:\DPF on Windows) is shared mutable state. The self-upgrade loop and other concurrent sessions rewrite its working tree and HEAD without coordinating with your editor — they will roll back or discard work that lives only there. Treat the root clone as merge / release / inspection only. See the Collision-Free Dev Workflow for the full failure analysis.

Spin up an isolated thread

# macOS / Linux — off the freshest origin/main, MCP + toolchain seeded automatically
./scripts/new-dev-worktree.sh <slug> [branch-prefix]   # default prefix: feat
cd ~/dpf-worktrees/<slug>

new-dev-worktree.sh resolves the true root clone, bases the new branch on origin/main, places the worktree at the canonical sibling base (~/dpf-worktrees/<slug> / D:/DPF-worktrees/<topic>), and runs the MCP + toolchain seed so the dpf connector and an isolated Docker Compose stack work immediately. Each worktree gets its own COMPOSE_PROJECT_NAME=dpf-<topic> so its containers and volumes can’t join the root dpf project.

.mcp.json does not travel with a worktree — it’s gitignored (it carries your local token). The seed step copies it in. If you create a worktree by hand, run scripts/dpf-bootstrap-agent-toolchain.sh from inside it, then restart the client.

Commit and push fast

The durability boundary is the remote, not your disk. Commit and push after every logical step, DCO-signed (-s) — the DCO bot blocks merge otherwise:

git add -A && git commit -s -m "…" && git push -u origin <prefix>/<slug>

Worktrees are source-control isolation, not runtime isolation

A worktree keeps your code changes off the root clone’s HEAD. It is not a second DPF install. Runtime-bound verification (production build, UX against the served portal, migration apply) does not run inside the worktree — route it through the shared local-CI convergence sandbox by claiming a lease:

claim_nonprod_environment_lease(environmentKey="local-integration-ci")

Harness friction inside a worktree (missing pnpm on PATH, cross-workspace symlinks, missing Prisma client) is a harness limitation, not a product defect — verify via the lease. Cheap source-local checks (targeted vitest, pnpm --filter <pkg> typecheck) are fine in the worktree.

Heavy local commands use a shared host-resource lane

Full TypeScript and Vitest runs, Next builds, Docker builds, previews, local inference, and semantic review can each retain several gigabytes of memory. The repository routes these commands through a governed host-resource runner. It measures available memory, preserves operating-system and resident-inference reserves, and admits only the work that fits. Inference is always single-flight.

When capacity is unavailable, the command records its queue position and exits with code 75 instead of leaving a waiting Node process alive. Retry after the active heavyweight command releases its lease. Do not start duplicate copies to race the queue, and do not kill processes based only on a familiar executable name; the runner supervises only the child whose PID and process-start identity it owns.

If memory cannot be measured, heavyweight admission fails closed. Cheap repository guards still run without claiming the lane. For current resource classes, memory floors, queue inspection, and recovery, see Local CI and host-resource lanes.

Clean up when merged

git -C ~/dpf worktree remove ~/dpf-worktrees/<slug>

Webhooks — closing the promotion loop

Everything above gets your change into a pushed branch and a PR. The last leg — how that pushed work re-enters the governed promotion pipeline — runs on a webhook, server-side, and it’s the same regardless of which agent produced the branch.

A GitHub webhook posts repository events to the portal at POST /api/platform/git/updates. The portal verifies the HMAC signature (x-hub-signature-256 against DPF_GIT_WEBHOOK_SECRET), records a git promotion candidate, and — for a push to the default branch — queues it for sandbox verification ahead of the self-upgrade pipeline. Deliveries are idempotent (deduplicated on the GitHub delivery id), and events that don’t qualify (non-default branch, deleted ref, missing SHA) are recorded as ignored rather than acted on.

sequenceDiagram
    participant A as Agent client
    participant GH as GitHub
    participant WH as Portal /api/platform/git/updates
    participant P as Promotion pipeline
    participant L as Live install

    A->>GH: push branch / open PR (DCO-signed)
    GH->>WH: webhook event (HMAC-signed)
    WH->>WH: verify signature, dedupe delivery id
    WH->>P: record promotion candidate → queue sandbox verify
    P->>P: sandbox build + gate evidence
    P->>L: self-upgrade advances live install

Two things follow from this design:

Don’t confuse this server-side webhook with the client-side hooks — hooks guard tool calls on your machine; the webhook carries git events between GitHub and the portal.


Adhering to the portal’s processes

The agent surfaces are powerful precisely because they don’t get a governance discount. Hold these whichever client you drive:

The full operating contract is AGENTS.md — read it before any work. The skill pack enforces the same kernel principles it documents.


Troubleshooting

Symptom Fix
/mcp (or the client’s MCP panel) doesn’t list dpf Restart the client in the repo root; GUI apps need a full restart to pick up a new token; re-run the bootstrap if still missing
Banner shows missing_token Issue a write token in Admin → Platform Development → MCP, then re-run the bootstrap
Banner shows needs_refresh Restart the client; if rotated, POST /api/mcp/token/refresh with the new token
Skills / plugin not showing up Re-run the bootstrap and inspect --show-substrate; on Codex, confirm the qualified dpf-platform@personal registry entry is installed and enabled, then restart the client
Retired generic process skills are visible but DPF replacements are missing Stop before project work, restart the client, and re-run the bootstrap; the readiness banner distinguishes plugin files installed from replacement skills loaded in the active session
PRs keep opening as drafts Disable the “create PRs as draft” default in your client’s GitHub settings (DPF uses ready-for-review PRs only)
Tool returns insufficient_token_scope Issue a scoped token, refresh, retry — do not bypass with direct DB edits
New worktree has no dpf connector Run scripts/dpf-bootstrap-agent-toolchain.sh inside the worktree, then restart
Dev-server launch refused (a hook blocked it) Use a lease for the shared runtime, or run in an isolated worktree compose stack
Pushed branch isn’t triggering promotion That’s the server-side webhook — confirm the GitHub repo webhook and DPF_GIT_WEBHOOK_SECRET are configured (operator task), not a per-session step
Codex/Grok/Antigravity missing a hook guard Expected on some surfaces — comply by construction: claim the lease before launching