Most projects don’t expose their design records. We do. Every decision that shapes the user-facing surface — what an op is, how doctor verdicts are decided, where plugins live, how packages get versioned — was written down as an Architecture Decision Record before a line of code shipped. The records that gate the v2 release are listed here.
The ADRs themselves live alongside the engine source (which is closed) and are mirrored here in summary form. The goal is not transparency for its own sake — it is so that when you ask “why does Tap v2 work this way,” the answer is one clickthrough deep, not a slack DM to a maintainer.
2026-05-03-unified-tap-primitive.mdThe single load-bearing ADR. Defines the v2 schema (5 storage entities — TapId, Plan, Run, Intent, Fingerprint), the 11-op closure, the read/write discriminated union, the 4-arm verdict enum, the 5-arm intent state machine. Source-of-truth file is core/types.ts. Everything else is downstream.
2026-05-04-ecosystem-v2-launch.mdThe cross-repo coordination plan: 5 surfaces flip in one weekend (this docs site, tap-skills repo, plugins, npm packages, brew formula). Decides lockstep release over rolling. Documents the npm deprecate policy, the 30/90/180-day deprecation cadence, and the CI grep gate that catches stale marketing copy.
2026-05-04-plan-versioning.mdWhy the npm packages bumped v0.x → v1.0 and not v0.5. Sequential integer schema versioning at the Plan level; semver-major at the package level. The two are deliberately separate axes.
2026-05-04-distribution-model.mdPer-author namespace (@taprun/<site>/<name> curated; @<author>/<site>/<name> community). Trust tiering between the two. Why community plans require an explicit --trust flag at install. The CI checks that gate the curated subtree.
2026-05-04-plugin-runtime-model.mdIn-process plugin loading is gone. Plugins are MCP sub-servers — ~/.tap/config/plugins/<name>/manifest.json plus an executable speaking JSON-RPC. Locks the boundary so plugins can’t accidentally import private engine code; opens the door to non-Deno plugin authors.
2026-05-04-forge-ai-lifecycle.mdForge as inspect + draft, not “AI generates the whole plan.” Deterministic templates (RSS, JSON-LD, OpenAPI, agents.json, ARIA) cover ~80% of real shapes; AI fills the long tail. Each saved plan carries compiled_by metadata so consumers can distinguish forge AI runs from hand-edits.
2026-05-04-error-handling-philosophy.mdThe two-arm RuntimeResult<T> ({ kind: "ok" } | { kind: "failed" }) and the rule against silent capability degradation. Plans declare requires.runtime; lint rejects mismatches; runtime pre-flights matchCapability before any op fires.
2026-05-04-auth-multi-user.mdWhy license is per-machine, why there is no cloud account, how multi-seat plans avoid a phantom user database. Local-first by architecture means the credential never leaves the machine.
2026-05-04-cross-machine-intent-coord.mdHow write taps deduplicate across machines without a central server. The key CEL expression + intent state machine + per-author namespace combine into a content-addressed, server-free dedup contract.
2026-05-04-followup-plan.mdThe seven §16 follow-up ADRs, sequenced by dependency. What’s done, what’s next, what was deliberately deferred.
2026-05-01-spec-as-artifact.mdWhy @taprun/spec is a derived artifact of core/types.ts, not a separately authored package. The drift-guard test that fires CI on any divergence.
2026-05-02-no-silent-capability-degradation.mdThe earliest ancestor of the v2 error-handling rule. Removed string warnings-as-API; replaced ephemeral fallback with explicit kind: "failed". Set the precedent for v2’s invariant-first approach.
2026-05-01-op-fetch-page-session.mdThe credentials: "deno-host" | "page-session" field on op:fetch. Page-session uses the live browser cookies — credentials never cross a trust boundary. The architectural keystone for “browser automation that runs in your browser.”
2026-05-01-op-grain-fingerprint.mdPlanFingerprint.op_hashes plus the diffPlanFingerprints helper. The substrate for op-grain heal targeting (cache hits become possible at the op level, not just the plan level).
legacy: true on save — 2026-05-01-no-new-legacy-on-save.mdThe drainage terminal state. lintPlan({ isNewSave: true }) rejects plans whose body has legacy: true. Existing legacy taps editing-through still pass; new authoring must compose v2 ops.
A handful of ADRs concern engine internals (heal cache layout, K(Δ) accounting, MCP tool surface budget) and are not user-relevant. They live alongside the source and follow the same naming convention; if you need one cited in a discussion, ping hello@taprun.dev.
ADRs follow a fixed shape: Context (what state the world was in) → Decision (what we picked) → Application (where in the codebase the decision lands) → Risks + mitigations. Most are 200–400 lines. The unified-tap-primitive parent is the longest at ~600 lines because it’s the schema spec; the release-coordination ADR is similar length because it’s a cross-repo plan.
If you find a contradiction between an ADR and the running code, the running code is wrong by definition — file an issue.