Command Palette

Search for a command to run...

Arbtr

Command Palette

Search for a command to run...

The Decision Record

Core Concept

A decision in Arbtr represents a choice your team needs to make or has made.

Anatomy of a Decision

Title

A clear, specific statement of what's being decided.

Good: "Use PostgreSQL for user data"
Bad: "Database stuff"

Context

Background information explaining why this decision matters. What problem are you solving? What constraints exist?

"We need a database that supports JSON columns for flexible metadata, has strong consistency guarantees, and can scale to 1M users."

Positions

The options being considered. Each position can have arguments supporting or opposing it.

PostgreSQLMySQLDynamoDB

Arguments

Structured claims supporting or opposing positions. Each argument has a claim and optional evidence.

For PostgreSQL: "Native JSON/JSONB support with indexing"
Against DynamoDB: "Cost model doesn't work for our read-heavy workload"

Status

The current state in the decision lifecycle.

Decision Lifecycle

G

Stub / Proposed (Ghost only)

Used in scenario/branch workflows for what-if planning. Stub is a placeholder; Proposed is ready for merge consideration.

1

Active

Published and open for discussion. Visible to the team.

2

Under Discussion

Active debate happening. Arguments and rebuttals are being added. Automatically triggered when engagement starts.

3a

Approved

Decision concluded with a "yes" outcome. A winning position is selected and rationale is documented.

3b

Rejected

Decision concluded with a "no" outcome. The proposed change was not adopted.

3c

Deferred

We decided not to decide yet. The decision is parked for future consideration.

4

Archived

Soft-deleted. Hidden from normal views but preserved for historical record.

i
Concluded decisions (Approved, Rejected, Deferred) show a final rationale explaining why the outcome was chosen.

Concluding a Decision

When you conclude a decision, you:

  1. Select the outcome (Approved, Rejected, or Deferred)
  2. Choose a winning position (if Approved)
  3. Write the rationale explaining why this outcome was chosen
  4. Add follow-ups (optional) for tasks that result from the decision

Once concluded, the decision is locked. Arguments and votes are preserved as a historical record, but no new ones can be added.

State Machine

Valid state transitions are enforced by the system. Not all transitions are possible—the state machine prevents invalid paths.

┌─────────────────────────────────────────────────────────────────┐
│                    GHOST (Branch) States                        │
│  ┌──────┐    conclude()    ┌──────────┐    merge()    ┌──────┐ │
│  │ Stub │ ───────────────► │ Proposed │ ────────────► │ Live │ │
│  └──────┘                  └──────────┘               └──────┘ │
│     │                           │                               │
│     └───────────────────────────┼── abandon() ──► Deleted       │
└─────────────────────────────────┼───────────────────────────────┘
                                  │
┌─────────────────────────────────▼───────────────────────────────┐
│                       LIVE States                               │
│                                                                 │
│  ┌────────┐   engagement   ┌──────────────────┐                │
│  │ Active │ ─────────────► │ Under Discussion │                │
│  └────────┘                └──────────────────┘                │
│      │                              │                           │
│      │         conclude()           │                           │
│      └──────────────┬───────────────┘                           │
│                     │                                           │
│          ┌──────────┼──────────┐                                │
│          ▼          ▼          ▼                                │
│    ┌──────────┐ ┌──────────┐ ┌──────────┐                      │
│    │ Approved │ │ Rejected │ │ Deferred │                      │
│    └──────────┘ └──────────┘ └──────────┘                      │
│          │          │          │                                │
│          └──────────┼──────────┘                                │
│                     │                                           │
│                     ▼ archive()                                 │
│               ┌──────────┐                                      │
│               │ Archived │                                      │
│               └──────────┘                                      │
└─────────────────────────────────────────────────────────────────┘

Triggers:
• Active → Under Discussion: First argument, vote, or comment added
• Conclude: Owner or delegate explicitly closes with outcome
• Archive: Owner or admin soft-deletes the decision
!
Concluded decisions are locked. You cannot add new arguments, votes, or positions after conclusion. Edit the rationale or reopen requires admin permissions.

Delegation & Ratification

Delegation

The owner can assign a delegateId to another team member. The delegate can conclude the decision on behalf of the owner.

  • Useful when the owner is on vacation or unavailable
  • Delegate has same conclusion powers as owner
  • Delegation can be revoked at any time

Ratification

Teams can require a designated approver (e.g., CTO) to sign off on concluded decisions before they're considered final.

  • pending — Awaiting approver review
  • ratified — Approver confirmed the decision
  • vetoed — Approver rejected with a reason

Enable in Team Settings → Governance. Set the ratification approver to control who has veto power.

Data Model

Complete TypeScript interface from lib/types.ts. Database table: decisions.

lib/types.ts
type DecisionStatus =
  | "Stub"             // Ghost only: Placeholder with just a title
  | "Proposed"         // Ghost only: Ready for merge consideration
  | "Active"           // Live: Freshly created
  | "Under Discussion" // Live: Active debate
  | "Approved"         // Live: Concluded yes
  | "Rejected"         // Live: Concluded no
  | "Deferred"         // Live: Decided not to decide yet
  | "Archived"         // Live: Soft deleted

type DecisionImportanceLevel = "anchor" | "committed" | "standard" | "tentative"
type RatificationStatus = "pending" | "ratified" | "vetoed" | null

interface Decision {
  id: string
  title: string
  slug: string                    // URL-safe identifier
  teamId: string
  teamSlug?: string               // For URL generation
  domainId?: string               // Architectural clustering
  status: DecisionStatus
  context?: string                // Background/problem statement
  tags: string[]
  owner: string                   // Display name
  positions: Position[]

  // Delegation
  delegateId?: string             // User ID who can conclude on owner's behalf
  delegateName?: string           // Delegate display name
  delegateAvatar?: string

  // Conclusion (when status is Approved/Rejected/Deferred)
  winningPositionId?: string      // Selected position ID
  outcomeMatchesVotes?: boolean   // True if matches vote results
  finalRationale?: string         // Why this outcome was chosen
  followUps?: string[]            // Action items resulting from decision
  concludedAt?: Date

  // Ratification (when team requires approval)
  ratificationStatus?: RatificationStatus
  ratifiedAt?: Date
  ratifiedById?: string
  ratifiedByName?: string
  vetoReason?: string

  // Scenario support (what-if branching)
  scenarioId?: string             // NULL = live, UUID = ghost in scenario

  // Provenance (git blame for decisions)
  originScenarioId?: string       // Branch that introduced this
  originScenarioName?: string
  originScenarioColor?: string
  originMergedAt?: Date
  originMergedByName?: string

  // Visibility & Access
  groupIds?: string[]             // Limit visibility to specific groups
  memberIds?: string[]            // Limit visibility to specific members

  // Metadata
  importanceLevel?: DecisionImportanceLevel
  confidence?: number             // 0-100, manually set or calculated
  documentedAsExisting?: boolean  // True if imported via Magic Paste
  sourceContent?: string          // Original text from Magic Paste
  isDraft?: boolean               // Hidden until approved (bulk imports)
  createdAt: Date
  updatedAt: Date
}

interface Position {
  id: string
  label: string                   // Display name (e.g., "PostgreSQL")
  color: string                   // Hex color for visual distinction
  icon?: string                   // Optional emoji
  description?: string            // Explanation of this option
}
i
Related tables: decision_positions, decision_arguments,decision_votes, decision_relationships, decision_audit_log

Previous

Domains
    Decisions | Arbtr Docs