Files
ci/opencode/ci/references/decision-engine.md
T

3.9 KiB
Raw Blame History

<decision_engine>

How CI makes decisions and commits them as git artifacts. The DecisionEngine uses bounded rationality with confidence thresholds to auto-decide or escalate.


Confidence Thresholds

Level Range Action
High > 0.85 Auto-decide, commit with minimal logging
Medium 0.600.85 Auto-decide, commit with assumption logging
Low < 0.60 Escalate to human

The threshold is configurable via config.autonomy.decision_confidence_threshold (default: 0.60).

Decision Flow

Input: decision + rationale + confidence + alternatives
  │
  ├─ confidence >= threshold → Auto-decide
  │   ├─ High confidence: commit with type `decision`
  │   └─ Medium confidence: commit with type `decision`, log assumptions
  │
  └─ confidence < threshold → Escalate
      └─ Generate escalation commit, pause for human input

DecisionRecord in Commits

Every decision is recorded in a ---ci--- block:

decisions:
  - id: D-001
    decision: "Use YAML blocks in commit messages for project state"
    rationale: "Git log is queryable, diffable, and survives repo transfers"
    confidence: 0.92
    alternatives: [JSON sidecar files, .ci/audit/ directory, database]

DecisionEngine API

Method Returns Purpose
makeDecision(input) DecisionResult Full decision flow with confidence check
makeHighConfidenceDecision(...) DecisionResult Shortcut for confidence = 0.95
makeMediumConfidenceDecision(...) DecisionResult Shortcut for confidence = 0.70
shouldAutoDecide(confidence) boolean Check threshold without making decision
isIrreversibleAction(action) boolean Check against escalation hooks
commitDecision(commitMessage) boolean Execute git commit
setPhase(phase) void Update current phase
setMilestone(milestone) void Update current milestone

DecisionResult

interface DecisionResult {
  decision: Decision;
  escalated: boolean;
  reason?: string;         // set when escalated
  commitMessage?: string;  // set when git.auto_commit is true
}

Decision Categories

Category When Used
architecture System structure, component boundaries
technology Library, framework, tool choices
implementation Algorithm, data structure, approach
prioritization Feature ordering, scope decisions
security Threat disposition, auth approach
testing Test strategy, coverage targets
performance Optimization decisions, caching strategy

Irreversible Actions

The isIrreversibleAction() method checks against config.autonomy.escalation_hooks. Default hooks include patterns like delete, drop, force, reset --hard, and any custom patterns.

Even with high confidence, irreversible actions are flagged for additional scrutiny.

Decision Retrieval

Decisions are retrieved from the git log, not from files:

const gitContext = new GitContext(projectPath);
const allDecisions = gitContext.getDecisions();        // All phases
const phaseDecisions = gitContext.getDecisions(3);     // Phase 3 only
const commitDecisions = gitContext.getDecisionsFromCommits(commits, 3);

Project-Scoped Decisions

Decisions can be project-scoped via the project field in ---ci--- blocks. When in multi-project mode, include the project slug so that GitContext.getDecisions() can filter decisions by project. Project-scoped decisions only apply to the specified project and do not affect other projects in the same repository.

Anti-Patterns

  • Never write decisions to a .ci/audit/ file — commit them
  • Never skip recording a decision, even high-confidence ones
  • Never make a decision without listing alternatives
  • Never override the confidence threshold without explicit configuration
  • Never store the decision counter in a file — it's ephemeral per session

</decision_engine>