feat: implement CI (Continuous Intelligence) autonomous engineering harness

Implements the full PRD for CI - a fully autonomous AI-driven software
engineering harness derived from Learnship's architecture.

Core components:
- CI Orchestrator agent with autonomous pipeline (SPECIFY → CLARIFY →
  RESEARCH → PLAN → EXECUTE → VERIFY → COMPLETE)
- Decision Engine with confidence thresholds (high/medium/low)
- Clarify Phase with question budget and default acceptance
- Escalation Protocol with timeout auto-proceed
- Audit Trail system (.ci/audit/) for post-hoc review
- Error Recovery with retry, plan revision, and rollback

18 agents (all Learnship agents + Orchestrator):
- Autonomous behavioral modifications per PRD §7.1
- Agent registry with factory pattern

11 CLI commands:
- ci init, ci run, ci quick, ci debug, ci verify
- ci review, ci status, ci audit, ci clarify
- ci rollback, ci ship

4-layer verification system:
- Structural, Behavioral, Security, Code Quality

3 autonomy levels: full, supervised, guided
Compatible with Learnship artifact schemas (.planning/)
This commit is contained in:
CI
2026-05-28 23:24:42 +00:00
commit 9cf5c000d9
57 changed files with 7336 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
import * as crypto from "node:crypto";
import { Decision, DecisionCategory, Alternative, confidenceToLevel } from "../types/decisions.js";
import { CIConfig } from "../types/config.js";
import { logDecision } from "./audit.js";
export interface DecisionInput {
decision: string;
rationale: string;
confidence: number;
category: DecisionCategory;
alternatives_considered: Alternative[];
learnship_equivalent: string;
phase?: string;
task?: string;
}
export interface DecisionResult {
decision: Decision;
escalated: boolean;
reason?: string;
}
export class DecisionEngine {
private config: CIConfig;
private projectPath: string;
private currentPhase: number;
private decisionCounter: number;
constructor(config: CIConfig, projectPath: string) {
this.config = config;
this.projectPath = projectPath;
this.currentPhase = 0;
this.decisionCounter = 0;
}
setPhase(phase: number): void {
this.currentPhase = phase;
}
makeDecision(input: DecisionInput): DecisionResult {
const id = `D-${String(++this.decisionCounter).padStart(3, "0")}`;
const threshold = this.config.autonomy.decision_confidence_threshold;
const decision: Decision = {
id,
timestamp: new Date().toISOString(),
decision: input.decision,
rationale: input.rationale,
confidence: input.confidence,
category: input.category,
alternatives_considered: input.alternatives_considered,
learnship_equivalent: input.learnship_equivalent,
human_override: null,
phase: input.phase,
task: input.task,
};
logDecision(this.projectPath, this.currentPhase, decision);
const confidenceLevel = confidenceToLevel(input.confidence);
if (input.confidence < threshold) {
return {
decision,
escalated: true,
reason: `Confidence ${input.confidence.toFixed(2)} below threshold ${threshold} (${confidenceLevel})`,
};
}
return { decision, escalated: false };
}
makeHighConfidenceDecision(
decision: string,
rationale: string,
category: DecisionCategory,
alternatives: Alternative[] = [],
learnship_equivalent: string = ""
): DecisionResult {
return this.makeDecision({
decision,
rationale,
confidence: 0.95,
category,
alternatives_considered: alternatives,
learnship_equivalent,
});
}
makeMediumConfidenceDecision(
decision: string,
rationale: string,
category: DecisionCategory,
alternatives: Alternative[] = [],
learnship_equivalent: string = ""
): DecisionResult {
return this.makeDecision({
decision,
rationale,
confidence: 0.7,
category,
alternatives_considered: alternatives,
learnship_equivalent,
});
}
shouldAutoDecide(confidence: number): boolean {
return confidence >= this.config.autonomy.decision_confidence_threshold;
}
isIrreversibleAction(action: string): boolean {
return this.config.autonomy.escalation_hooks.some((hook) =>
action.toLowerCase().includes(hook.toLowerCase())
);
}
}