Skip to content
GitHub
Decisions

ADR-103: Decision-authority positioning and the alpha product vocabulary

Context

A live exploratory-testing pass over the shipped portal redesign (2026-06-13, both portals, the full author → review → publish → deploy → customer loop) surfaced 47 findings and a cluster of cross-cutting design/positioning questions the redesign refinement had not settled. A founder design/positioning session that day resolved nine decisions (RD-1..RD-9). They were implemented as the SPEC-649 deliverable epic (D1–D8, all merged + closed) and two ADR amendments; this ADR is their durable home — the why, lifted out of the exploratory planning log before that planning folder is swept at milestone close.

The findings clustered around three problems the redesign’s “speak human” rename did not reach:

  1. The customer-facing copy overclaimed enforcement. Surfaces said “every action your agents take is checked before it happens” / “the agent must obey it” / “Spectral sits between your agents and the actions.” Spectral cannot intercept or block a customer’s agent — it offers a decision capability the agent calls and is expected to honor. The copy promised a capability the architecture does not have, and that gap is a positioning liability, not just a wording nit.
  2. The vocabulary leaked internal concepts and overloaded terms. “World” (an internal code/schema concept) surfaced across the UI; “domain” (the tenant unit) collides with DNS/web “domain” and the internal bounded-context “domain”; decision-outcome verbs (Proceed/Hold/Blocked) were reused as lifecycle status; the determinism / “no LLM” claim repeated at per-rule and per-decision granularity where it read as noise.
  3. Two authoring-loop behaviors did not match how an operator reasons. Rule logic was shown as raw generated predicate code rather than the natural-language intent that drives it; compile + test “checks” were deferred until after approval (so an operator approved with no validation evidence); and “publish to production” did not actually deploy — publish (a worlds-side version mint) and deploy (platform routing) are distinct, and the cockpit exposed only publish, so a “published” ruleset kept serving the prior version to customers.

These are customer-facing positioning and product-vocabulary decisions plus two authoring-workflow decisions. They shape more than one epic (the whole SPEC-649 epic, plus the ADR-082 / ADR-100 amendments and a customer-facing-copy sweep that extends into the Codex), so they warrant an ADR.

Decision

D1 — Positioning anchor: Spectral decides; every decision is provable (RD-1)

Spectral owns the decision — authoritative, deterministic, reproducible, recorded. The customer’s agent owns the action: it consults Spectral before acting and is expected to honor the decision. Agency sits with the customer’s agent; authority and proof sit with Spectral. The product is a decision-authority capability, not an enforcement boundary.

This leaves room to add real enforcement later (an SDK/proxy that mediates the action) as an additive direction, not a correction — but the alpha makes no enforcement claim. Customer-facing copy retires the enforcement framing across both portals and the Codex:

RetireUse
”every action…is checked before it happens""your agent checks with Spectral before it acts"
"the agent must obey it""your agent is expected to honor the decision"
"Spectral sits between your agents and the actions""Spectral decides; your agent acts on the decision"
"goes live to every customer immediately""makes v_N the authoritative ruleset for new decisions"
"enforced / we ensure""adjudicated against your policy, and recorded”

D2 — Tenant + policy vocabulary: Workspace, Ruleset; “world” is internal-only (RD-2)

  • Workspace is the customer tenant scope — the display rename of “domain.” Code, schema, and URLs keep domain for now; display-decoupling the label from the identifier is a deferred follow-on (see Consequences).
  • Ruleset is the policy (rules + their versions) — the shared term across both portals: the operator authors a Ruleset, the customer views it.
  • Relationship: a Workspace is governed by a Ruleset. This is 1:1 today (per ADR-098) but is modeled and named as two distinct concepts for forward-compatibility — do not collapse them on the alpha 1:1.
  • Consequence: “world” is internal-only (code/schema) and retired from every UI surface. This forces the surface renames in D4 (World Agent, World Model Card, WORLD ·xxxx badges).

D3 — Display label + status vocabulary; determinism claim placement (RD-4, RD-9)

  • Tab/page “The rules” → Rules; a duplicate in-page section heading → Active rules.
  • Stop reusing decision outcomes (Proceed/Hold/Blocked) as lifecycle status. Versions: Live / Superseded. Rules: Live / Under review / Retired. Decision outcomes stay Proceed/Hold/Blocked — the four-state decision vocabulary is for decisions, not lifecycle.
  • Keep the rule importance tier (Standard / Important) but give it a defining tooltip; on the decision detail, relabel the outcome-driving rule “Important” → Determining rule, so “Important” is not double-duty.
  • The determinism / “no LLM in decision path” claim lives at the Trust / System Card level only. Remove its per-rule and per-decision repetition, where it reads as noise.

D4 — Surface naming and the Assistant topology (RD-3, RD-8)

The canonical naming decision is enshrined in ADR-082: World Agent → Assistant (full “Ruleset Assistant,” short “Assistant”); World Model Card → Ruleset Card (pairs with “System Card”; avoids “Model,” which would imply an ML model and undercut the no-LLM positioning); the masked IdRef kind label becomes RULESET ·xxxx (not WORLD ·xxxx). Rationale recorded here because it drove the rename: “Agent” collides with the customer’s governed agents — the one place naming must stay crisp.

The Assistant topology is decided here: the Assistant is a dedicated, ruleset-scoped page (centered chat with a right-rail of proposed rules), not a right-side dock/slide-over. The command surface is a single ⌘K palette — the separate ⌘J is dropped. The composer is unified: paste a link inline and drag-drop a file onto the chat input rather than dedicated “Attach document” / “Add link” controls; assistant messages render as markdown.

D5 — Rule logic representation and verify-at-review (RD-5)

  • The rule’s natural-language intent (applies_when_source) is the canonical representation in the UI. The generated predicate code is demoted to a collapsible “view generated implementation” — a derived artifact, not the headline.
  • Add a “Generate & run checks” action to the candidate evidence bundle: codegen + per-rule tests run on demand at review against sample/simulated inputs, surfacing compile/test results as approval evidence before the approve action. This replaces “checks deferred to go-live,” where an operator approved with no validation.
  • Generate-once-persist-reuse: review-time generation must produce the same artifact deploy consumes — generate once, persist on the candidate, reuse verbatim at enshrine/deploy; never double-generate divergently. (A revised candidate is a new row and regenerates.)

D6 — Publish-and-deploy model (RD-6)

  • Publish deploys to bound domains by default, with a “publish only (stage)” override to hold rollout. Publish (the worlds-side version mint) and deploy (platform routing to customer domains) stay distinct under the hood — forward-compatible with staged / per-domain rollout.
  • Expose deploy in the cockpit (previously absent): deploy status, and the ability to deploy a published-but-undeployed version or deploy to specific workspaces.
  • Deployments derive from / stay consistent with world_model_versions so the version registry and platform routing cannot disagree on what “vN” is. The live session hit exactly this divergence — a seed deployed a platform version with no worlds-side version row, so Publish minted a colliding “v1” and crashed on a UNIQUE violation. A published version’s content is immutable; the two paths must not be able to define the same label differently.

D7 — Origin provenance for Assistant-drafted rules (RD-7)

The canonical provenance decision is enshrined in ADR-100: a new assistant_drafted (operator-directed) source family. Recorded here because it resolves a finding: an Assistant-drafted candidate showed “No recorded origin / 0 cited sources,” but an operator directing the Assistant to draft a rule is an origin (operator + Assistant + the chat prompt), even when no external source is cited. Capture that origin instead of “No recorded origin,” and make the tier ↔ cited-sources relationship legible (a “distilled” tier does not guarantee external citations — surface the taxonomy rather than implying a contradiction).

Alternatives considered

  • Enforcement positioning (Direction B). Position Spectral as an enforcement boundary backed by an SDK/proxy that mediates the agent’s action. Rejected for alpha — the architecture does not mediate the action, so the claim would be false; deferred as an additive future direction, not a correction of D1.
  • “domain” rename candidates. application / environment / policy area were weighed against Workspace. Workspace won — it reads as a tenant scope without the DNS/web/bounded-context collisions of “domain” and without implying a deployment environment or a narrow policy slice.
  • Collapsing Domain and Ruleset on the 1:1. Rejected — modeling them as one concept bakes in the alpha 1:1 cardinality and blocks forward-compatible per-domain rollout (D6) and multi-domain rulesets.
  • Keeping generated code as the canonical rule representation. Rejected (D5) — operators reason in intent, not predicate source; the code is a derived artifact.
  • Checks deferred to go-live. The shipped behavior before this session. Rejected (D5) — validation evidence must precede the approval it supports.
  • Publish implies deploy with no override vs publish and deploy fully separate in the UI. Rejected the extremes in favor of publish-and-deploy-by-default with a stage override (D6) — the common case is one action, the staged case stays expressible.

Consequences

  • Implemented end-to-end as SPEC-649 (D1–D8, merged + closed): the copy/positioning sweep (both portals + Codex + the lockstep ADR-082 amendment), the Assistant page + unified ⌘K, NL-first rule detail + verify-at-review, publish-and-deploy + the cockpit deploy affordance, the assistant_drafted provenance family + origin capture, and the runtime-bug fixes the session surfaced.
  • Display is decoupled from identity only for the labels renamed here. Code, schema, and URLs keep domain and world; the UI renames are display-layer. Fully decoupling the domain identifier from the “Workspace” label (and world from internal naming) is a deferred follow-on, not done here.
  • The four-state decision vocabulary (Proceed/Hold/Blocked/No action needed) is now reserved for decision outcomes; lifecycle uses its own labels (D3). Any future surface must not reuse decision verbs for status.
  • Verify-at-review (D5) makes the review-time artifact the deploy artifact (generate-once-persist-reuse); the enshrine-site codegen and deploy must consume that persisted artifact, never regenerate divergently.
  • Deployments deriving from world_model_versions (D6) is a standing integrity invariant: the seed/authoring path and the platform deployment registry cannot define the same version label with different content.
  • This ADR is the customer-facing-positioning why; the Codex (what) and the SPEC-649 issues (when) carry the surface detail. D4’s naming and D7’s provenance remain owned by ADR-082 and ADR-100 respectively — this ADR records their rationale and session lineage without restating their decision content.

References

  • Implementation: Linear epic SPEC-649 (D1–D8) and its sub-issues SPEC-650–657; the ADR-082 amendment (SPEC-650) and the ADR-100 amendment (SPEC-654).
  • Enshrined elsewhere: ADR-082 (D4 naming), ADR-100 (D7 assistant_drafted family).
  • Adjacent decisions: ADR-089 D2 (the per-action attribute contract), ADR-090 D3 (operator-mediated review), ADR-098 (domain↔world 1:1 cardinality D2 reframes as Workspace↔Ruleset).
  • Design corpus: docs/design/ (the 0003 redesign specs this session evolved).