Adoption runbook

Install gantry (Node.js 24+):

Adoption runbook

Product home: https://opengantry.ai · All docs: index.md

This runbook is the operational path for adopters using gantry locally. Product positioning and use cases: README · USE-CASES.md.

Open Source Gantry is vendor-neutral, local-first, git-native — the gantry CLI plus Git hooks and gantry verify over mission YAML (scope + gate_command). Execution never requires a hosted agent dashboard; optional future metadata hub integrations consume digest-only attestation receipts (gantry attest, gantry verify --receipt) — see ADR-0034.

First mission practice: KATA.md (~15 min, headless-friendly).

See also: FEATURES.md · COMPLIANCE-ISO.md · CHANGELOG.md (release history).

First run (onboarding)

Install gantry (Node.js 24+):

npm install -g @jeger-ai/opengantry
# or: npx @jeger-ai/opengantry <cmd>
gantry init --tutorial   # guided loop after scaffold (~3 min)
# or:
gantry init
gantry onboarding      # same strict checks as production
gantry planner set "$(git config user.email)"
gantry doctor
gantry pin .gitagent/missions/example.verify.yaml   # optional; enables verify/scan without --mission
gantry verify                                       # uses pin when set

Standard change loop (review → run → audit)

# 1. Human reviews mission BEFORE executor (Planner commit required)
gantry start "Fix login spinner" --msn MSN-0001 --skill-key ui --gate-command "npm test"
# Planner: review YAML scope/gates, then:
git add .gitagent/missions/MSN-0001.<slug>.yaml
git commit -m "[MSN-0001] legislate mission"

# 2. Pin + executor env (pin optional but recommended for day-one DX)
gantry pin .gitagent/missions/MSN-0001.<slug>.yaml
eval "$(gantry runtime env)"

# 3. Audit evidence: verify + grep
gantry verify --fix
gantry verify --json | jq -r '.error_code // "passed"'
git log --grep='MSN-0001' --oneline
gantry status --json --verbose

Legacy equivalent: gantry legislate "<intent>" --msn MSN-0001 --skill-key ui --gate-command "npm test".

gantry init composes per-tool recipes into docs/INTEGRATIONS.md. Non-interactive: gantry init --yes or gantry init --ides cursor,claude-code --no-ci.

Wire your IDE agent: INTEGRATIONS.md.

Regulated teams (ISO 27001 / ISO 42001)

If auditors ask how AI-assisted coding fits your ISMS or AI management system, see COMPLIANCE-ISO.md for control-to-artifact mapping (SOD, change authorization, trace evidence, enforcement tiers). OpenGantry does not grant certification — it produces the operational records assessors typically request.

Prevent unreviewed edits

Gantry Git hook enforcement (.githooks/pre-commit, .githooks/pre-push, IDE beforeShellExecution) complements the Gantry CLI — hard boundaries live in hooks, gantry verify, and runtime exec, not in a vendor cloud console.

  • Planner-approved mission commit: among recent commits, the newest [MSN-XXXX] from an allowlisted Planner email must modify the mission file passed to --mission.
  • Pre-push handoff: gantry verify --pre-push lets legislative stubs push for remote agent handoff; full verify (gate + trace) is still required before merge.
  • IDE writes are advisory: rules and AGENTS.md guide agents; hooks + gantry runtime exec enforce hard boundaries.

Audit evidence cheatsheet

git log --grep='MSN-' --oneline
# Mission file: .gitagent/missions/<MSN>.<slug>.yaml
# Executor trace: repo-root EXECUTOR_LOG.md (verifier cites verbatim quotes)
gantry verify --mission .gitagent/missions/<file>.yaml

PR CI (this specimen): commits touching .gitagent/, EXECUTOR_LOG.md, hooks, or gxt-validate.yml need [MSN-NNNN] subjects unless the change satisfies a repository-declared trusted_automation rule in .gitagent/config.json (fail-closed when absent).

Trusted automation policy

Low-risk ecosystem bot maintenance can bypass manual mission authoring when all constraints in a committed policy rule pass. Each rule declares exactly one allowed_structural_changes kind (mixing kinds on a single rule is rejected at config load).

ConstraintMeaning
allowed_actorsCommit author email (git log -1 --format=%ae) must match an entry you legislated — no hardcoded vendor strings in the engine
allowed_pathsEvery MSN-enforced changed file must match a glob in the rule
allowed_structural_changesStructural kind — see table below (one kind per rule)
max_net_locTotal diff churn (additions + deletions) per evaluation; must be ≤ the hard cap for that kind
KindUse caseHard max_net_loc capStructural checks
workflow_version_pinDependabot workflow uses: version bumps5YAML structure unchanged; only existing uses: version segments may differ
bounded_contentSecurity autofix bots (code scanning, Snyk, similar)100Content changes allowed inside allowed_paths; engine hard-rejects any touch under .gitagent/** or MANIFEST perimeter_protected even if listed in allowed_paths

Example — workflow pins (this specimen repo):

{
  "trusted_automation": {
    "rules": [
      {
        "id": "workflow-dependency-bumps",
        "allowed_actors": ["dependabot[bot]@users.noreply.github.com"],
        "allowed_paths": [".github/workflows/**"],
        "allowed_structural_changes": ["workflow_version_pin"],
        "max_net_loc": 5
      }
    ]
  }
}

Ecosystem autofix bots

GitHub code scanning agentic autofix, Copilot SWE agent, Snyk fix PRs, and similar tools commit application-source changes without a [MSN-NNNN] subject. To let those PRs pass MSN CI without break-glass, add a separate bounded_content rule — opt-in per repository:

{
  "id": "security-autofix-bots",
  "allowed_actors": [
    "223556219+Copilot@users.noreply.github.com",
    "snyk-bot@snyk.io"
  ],
  "allowed_paths": ["src/**", "package.json", "package-lock.json"],
  "allowed_structural_changes": ["bounded_content"],
  "max_net_loc": 80
}

Actor discovery: when CI fails MSN check on a bot PR, inspect the commit author on the failing commit (git log -1 --format=%ae <sha>) and add that exact email to allowed_actors. GitHub noreply formats vary by account; Snyk private-repo fix PRs may be opened on behalf of a human collaborator — those commits will not match snyk-bot@snyk.io unless you configure Snyk’s fixed GitHub account or add the collaborator email explicitly.

Not for break-glass: routine autofixes belong in trusted_automation. Reserve gantry verify --break-glass for production emergencies only (secret-gated, Planner post-incident review).

Evaluation is git-derived only (gxt-manifest-lib.mjs eval-commit / eval-range) — not CI environment variables. Missing or invalid config → full MSN/mission workflow remains enforced.

Role-based CLI output

gantry --audience executor start "…"      # constraint-forward next steps
gantry --audience planner verify      # copyable git / mission hints
gantry --audience verifier verify     # silence unless [GXT_*] errors (CI)
export GXT_AUDIENCE=verifier            # same as global --audience

Verify troubleshooting

gantry verify auto-resolves formatter line drift in EXECUTOR_LOG.md. Use --strict-trace only when you need exact line numbers. Pre-push: gantry verify --pre-push for legislative stub handoff.

Stale trace evidence

After gate + trace quote mapping, full verify binds each committed PASS quote line in EXECUTOR_LOG.md to the mission skill’s full tmvc_roots:

  1. Resolve the quote line (numeric anchor, fuzzy drift, or freeform anchor + quote).
  2. git blame --porcelain on that line → attestation commit (skip when blame is all-zeros — uncommitted line; trace and code co-evolve in the working tree).
  3. git diff --name-only <attestationCommit> -- <tmvc_roots…> vs working tree — any path listed → Trace STALE (GXT_TRACE_STALE).

Re-run the gate, append a fresh unique trace line to EXECUTOR_LOG.md, update mission trace_quote, commit, and verify again. After interactive rebase/squash, historical attestation may be invalidated — expect to refresh traces.

Formatter guard (recommended): Add EXECUTOR_LOG.md to .prettierignore (Prettier) or an equivalent ignore for your formatter (Biome files.ignore, ESLint ignore, editor format-on-save exclude). Numeric anchors and stale-evidence git blame bind to committed line numbers; auto-formatting the log causes avoidable drift (verify can fuzzy-resolve, but prevention is cheaper). gantry init and gantry upgrade apply merge this entry automatically; existing repos should add it once manually or re-run upgrade.

Migration escape hatch: gantry verify --skip-stale-evidence (also skip_stale_evidence on MCP gxt_verify). Do not hash working-tree files in Node for this check — Git’s diff engine handles CRLF and .gitattributes correctly on all platforms.

MCP verify envelope

gxt_verify / handleVerify returns a flat VerifyResultPayload — same shape as gantry verify --json:

  • Success: { "status": "passed", "phase": "full" | "pre_push_stub" | "break_glass", "exit_code": 0, … }
  • Failure: { "status": "failed", "phase": "<phase>", "error_code": "GXT_*", "fix_hints": [], "next_actions": [], "exit_code": N, … }

Init and parse failures use status: "failed", phase: "init" — not legacy { "status": "error" }. Other MCP tools (gxt_runtime_env, gxt_runtime_exec) still use { "status": "error" } until a future unification.

gantry verify --json and --fix are mutually exclusive; combining them returns GXT_INVALID_ARGUMENT (exit_code: 2).

Enforcement boundary

IDE Agent Write/Edit is advisory TMVC; hard boundaries live in runtime exec, gantry verify, and hooks.

TierMechanismEnterprise control
Process-boundarygantry runtime execForbidden-zone scan + subprocess TMVC envelope
Deterministic hookCursor beforeShellExecution, pre-push verifyGovernance path writes require mission + verify
AdvisoryIDE rules, AGENTS.md, sessionStart contextIDE suggestions alone do not count as approval

Per-tool closed-loop recipes: INTEGRATIONS.md.

Hooks (fast, scoped)

git config core.hooksPath .githooks
  • post-checkout: creates EXECUTOR_LOG.md on feature branches when missing.
  • pre-commit: gantry tmvc guard — advisory TMVC path warnings for staged files (stderr; exit 0). Skips when no pinned mission. Set GXT_TMVC_GUARD_STRICT=1 or pass --strict to block.
  • pre-push: gantry verify --pre-push for mission files changed on branch — ensures Planner review before remote handoff; full gate+trace still required to merge.

Record out-of-TMVC expansion before editing: gantry context-request --path <p…> --reason <text> (optional --stage-worker-log).

Break-glass (emergency only)

Emergency bypass for verify when production is down — not a substitute for mission review. Authorization requires GXT_BYPASS_SECRET matching .gitagent/foreman/BYPASS.sha256 (never commit the plaintext secret). Audit trail: refs/notes/gxt-bypass or --audit-commit.

Technical setup

printf '%s' 'your-team-secret' | sha256sum | awk '{print $1}' > .gitagent/foreman/BYPASS.sha256
export GXT_BYPASS_SECRET='your-team-secret'
gantry verify --break-glass --reason "Production auth down: hotfix session cookie" \
  --mission .gitagent/missions/MSN-0001.<slug>.yaml
git push origin refs/notes/gxt-bypass

gantry doctor tests whether GXT_BYPASS_SECRET matches the anchor when set.

Substrate version drift: gantry doctor compares on-disk .gitagent/foreman/SUBSTRATE.version.json to the opengantry_version bundled with your installed gantry (same source as gantry upgrade). When behind, doctor emits a warn (exit 0) and suggests gantry upgrade after updating the npm package. Warnings do not fail gates that only check exit code.

Agent errors (machine vs human)

On runtime exec failure, a one-line human summary goes to stdout; full JSON goes to stderr and .gitagent/history/.ignored-last-error.json. Orchestrators read GXT_LAST_ERROR_FILE from gantry runtime env.

Metrics

gantry metrics
gantry metrics --json --ref main

Git-native only (single streamed git log pass). No local event ledger.

Routing proxy caveat: legislative_commits vs worker_trace_commits are path-touch heuristics, not historical gantry triage replay. JSON exposes this explicitly via gxt_extension_metadata (see below).

Metrics JSON envelope

gantry metrics --json includes a namespaced extension block so strict top-level parsers that only read primitive counters remain compatible:

{
  "legislative_commits": 12,
  "worker_trace_commits": 4,
  "gxt_extension_metadata": {
    "classification_mode": "PATH_TOUCH_PROXY",
    "schema_version": 1
  }
}

Classification rules (PATH_TOUCH_PROXY):

  • legislative_commits: commit touches .gitagent/missions/* with MSN-NNNN in the filename, subject starts with [MSN-NNNN], author is in GANTRY_PLANNER_EMAILS (non-empty allowlist entries only).
  • worker_trace_commits: commit touches EXECUTOR_LOG.md and does not qualify as legislative (mutually exclusive; dual-touch legislative commits never increment worker-trace).
  • Human stdout labels (proxy) on the counters; JSON uses gxt_extension_metadata.classification_mode instead of suffixing field names.