---
title: Decisions
description: Every architecture decision record of jr2, by number.
---

# Decisions

Each architecture decision record (ADR) says what jr2 decided, why, and what it gave up. An ADR is updated in place: it states the latest decision. The pages of the docs link to the ADR behind a rule; the `ADR-NNNN` in a page is its number here.

| ADR | Title |
| --- | --- |
| 0001 | [Sandboxes are provisioned by a Kubernetes operator via a generic CRD](decisions/0001-operator-owned-generic-sandbox.md) |
| 0002 | [The agent actor is a duplex channel; its control plane is Menu tool calls](decisions/0002-duplex-streaming-actor.md) |
| 0004 | [A Sandbox's workspace is a private local clone of a read-only cache, not a shared worktree](decisions/0004-worktree-provisioning-model.md) |
| 0005 | [The Sandbox pod's containers: Harness, Custodian, an optional User Container, and an optional Sandbox Effector](decisions/0005-sandbox-pod-composition.md) |
| 0006 | [The agent picks from a Machine-defined, schema-backed menu; it does not drive the workflow](decisions/0006-agent-control-surface.md) |
| 0007 | [Durable Machine state: serializable context, live things constructed from input](decisions/0007-durable-machine-state.md) |
| 0008 | [jr2 is a library + CLI; an Orchestrator instance hosts many workflows](decisions/0008-orchestrator-as-deployed-app.md) |
| 0009 | [The `jr2` CLI and instance interface](decisions/0009-cli-and-instance-interface.md) |
| 0010 | [BDD acceptance tests via Cucumber.js (black-box, scenario-isolated)](decisions/0010-bdd-acceptance-tests.md) |
| 0011 | [Control events are workflow-defined and delivered by closure, not routed](decisions/0011-workflow-defined-events.md) |
| 0012 | [`workspace()` wraps a body Machine and owns only Sandbox lifecycle](decisions/0012-workspace-wrapper-machine.md) |
| 0013 | [The Agent reaches its Machine through a container it cannot read](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md) |
| 0014 | [Observation is open; run state and control need the Instance token](decisions/0014-observation-is-open-run-state-is-not.md) |
| 0015 | [Workflows are authored through `jr2Setup`; vocabulary and agent menus derive from the machine](decisions/0015-authoring-surface-absorbs-the-mechanism.md) |
| 0016 | [Agent-turn mechanics are jr2-internal: ambient coordinates, host-side offsets, absorbed retries, fresh sessions](decisions/0016-agent-turn-mechanics-are-internal.md) |
| 0017 | [The run loop is a jr2 `pool` over a generalized source port](decisions/0017-pool-over-a-source-port.md) |
| 0018 | [The instance authors Agent definitions; jr2 assembles the Harness](decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md) |
| 0019 | [The operational surface is one converging command against the current kube context](decisions/0019-one-converging-command-against-the-current-context.md) |
| 0020 | [Private-CA trust is a named concept, not volume plumbing](decisions/0020-private-ca-trust-is-a-named-concept.md) |
| 0021 | [Workspace continuity is watched; the lease asserts](decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md) |
| 0022 | [Observation is a level-triggered feed, and an API before it is a page](decisions/0022-observation-is-a-level-triggered-feed.md) |
| 0023 | [The Harness prints the conversation, and the reasoning is the part that prints](decisions/0023-the-harness-prints-the-conversation.md) |
| 0024 | [An Agent's turn ends with the state that asked for it](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md) |
| 0025 | [CANCEL ends a run; stopping one parks it](decisions/0025-cancel-ends-a-run-stop-parks-it.md) |
| 0026 | [A Turn that is over is never prompted, and only a Turn that is over answers 404](decisions/0026-a-turn-that-is-over-is-never-prompted.md) |
| 0027 | [The Harness is jr2's own server: flue retires, the wire stays](decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md) |
| 0028 | [What an Agent may do to the Workspace is part of its definition](decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md) |
| 0029 | [A Menu is fixed for a conversation, and a Turn is told its Allowed picks](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md) |
| 0030 | [A snapshot names the Machine it was written under](decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md) |
| 0031 | [Menu-only Agents run on the Instance Harness](decisions/0031-menu-only-agents-run-on-the-instance-harness.md) |
| 0032 | [The Console unlocks with the Instance token, and the bands do not move](decisions/0032-the-console-unlocks-with-the-instance-token.md) |
| 0033 | [A Machine declares the input that starts it](decisions/0033-a-machine-declares-the-input-that-starts-it.md) |
| 0034 | [The Console renders with Preact, and the server erases the types](decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md) |
| 0035 | [A runaway turn is ended by the Harness, rerolled once, then a fault](decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md) |
| 0036 | [A turn compacts its own context mid-flight](decisions/0036-a-turn-compacts-its-own-context-mid-flight.md) |
| 0037 | [A Sandbox Image is built or brought; jr2 injects the Harness at pod time](decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md) |
| 0038 | [`jr2 up` builds every image it deploys, except a pinned one](decisions/0038-jr2-up-builds-every-image-it-deploys.md) |
| 0039 | [Image garbage collects by reachability](decisions/0039-image-garbage-collects-by-reachability.md) |
| 0041 | [A build the host already holds is not spent again](decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md) |
| 0042 | [Ready is not routable: the two calls a turn starts with re-ask a Service that has not answered](decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md) |
| 0043 | [The kit is tested as installed: a local registry stands in for npm](decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md) |
| 0044 | [Kit images live at a canonical home; a self-host mirrors it](decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md) |
| 0045 | [The platform joins the image address, and the cluster chooses it](decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md) |
| 0046 | [A converge failure carries its diagnosis](decisions/0046-a-converge-failure-carries-its-diagnosis.md) |
| 0047 | [The git ssh key source is the user's choice](decisions/0047-the-git-ssh-key-source-is-the-users-choice.md) |
| 0048 | [The Orchestrator boots without its repos](decisions/0048-the-orchestrator-boots-without-its-repos.md) |
| 0049 | [A Machine carries its parts and composes by invoke](decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md) |
| 0050 | [What code names, config declares; what the CLI names, discovery finds](decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md) |
| 0051 | [A Repo is a slot on the `workspace()` and a cache on the node](decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md) |
| 0052 | [A Sandbox lands where an ordinary pod lands, and the cache follows it](decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md) |
| 0053 | [A fetch inside the pod asks the node cache, and the cache asks the remote](decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md) |
| 0054 | [The kit ships Machines, and a shipped Machine leaves its parts Open](decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md) |
| 0055 | [A release is a pushed tag, and the publish guard is the credential](decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md) |
| 0056 | [A global `jr2` hands off to the Instance's own, and an Instance has one Kit version](decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md) |
| 0057 | [A Turn is its Frame, its Dials, and whether it continues](decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md) |
| 0058 | [A Harness answers the Orchestrator alone](decisions/0058-a-harness-answers-the-orchestrator-alone.md) |
| 0059 | [A Harness holds stand-ins; the Custodian holds the keys](decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md) |
| 0060 | [A Workspace states its Size, and jr2 reserves all of it](decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md) |
| 0061 | [A memory kill ends the Agent's processes, not the Harness](decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md) |
| 0062 | [jr2 briefs the Agent on its seat, never on its task](decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md) |
| 0063 | [The Orchestrator watches the cluster](decisions/0063-the-orchestrator-watches-the-cluster.md) |
| 0064 | [A Workspace waits for capacity](decisions/0064-a-workspace-waits-for-capacity.md) |
| 0065 | [A persist survives a crash, and history is a week](decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md) |
| 0066 | [A `@model` tier runs a real model, and a change to what the model reads runs the tier](decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md) |
| 0067 | [An Effect is an actor slot, and runs at most once unless marked idempotent](decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md) |
| 0068 | [An Effector holds an Effect's secrets and signs its wire](decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md) |
| 0069 | [The Orchestrator is a Kit image, and an Instance publishes its Assembly](decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md) |
| 0070 | [A Machine lends its parts to a Chart](decisions/0070-a-machine-lends-its-parts-to-a-chart.md) |
| 0071 | [A run starts a run through a `dispatch` Effect](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md) |
| 0072 | [The docs ship inside the Kit, and an Instance's `AGENTS.md` indexes them](decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md) |
| 0073 | [A Machine fails a run with `fail()`, and an uncaught Failure ends it `failed`](decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md) |
| 0074 | [An unrouted mechanism event is refused at load and faults the run](decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md) |
