Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ agon conquer "..." --push # on success, commit + push
- **Cesar consults on forks.** When the builder hits a genuine fork it emits `CONQUER_ASK: <question>`; Cesar classifies it and convenes the _cheapest sufficient_ panel — `nero` (quick), `tribunal` (a choice), `brainstorm` (open), `council` (high-stakes) — then feeds back a compact verdict. A normal agent loop re-prompts itself with the same blind spots; conquer brings the whole heterogeneous panel to bear.
- **A layered done-oracle, not a self-claim.** On `CONQUER_DONE: <claim>` the cheap deterministic layers run first — the `--gate` command (L0), a diff acceptance-drift check that blocks weakened/rewritten existing tests (L1), and an empty-claim guard (L2). Only when those pass does the **evidence-based falsifier** run (L4/L5): a _tool-enabled_ critic clones the working tree into a throwaway sandbox, reads the real code and runs commands to hunt a counterexample, then Cesar **mechanically re-runs** that counterexample in the sandbox and blocks "done" _only_ when it actually reproduces a failure — never on a bare opinion or confidence score. The adversary's findings are surfaced to your merge gate whether or not they blocked. A red gate, a weakened/tampered test, or a _verified_ counterexample blocks "done."
- **Runs in an isolated worktree.** conquer creates a persistent `conquer/*` branch and worktree from `HEAD`, so the builder never edits your source checkout and uncommitted source changes are not silently included. The final summary prints both locations and the cleanup command.
- **Stops at a human merge gate.** conquer never auto-merges to main. By default it leaves the isolated branch and worktree for you to review; `--push` commits + pushes that branch, then prints an **engine-written PR title/body** (from the real branch diff) and a **prefilled GitHub PR link** (`…/compare/…?quick_pull=1&title=…&body=…`) — click it, the form is already filled, review + merge. No `gh` CLI or token needed. The done-oracle is irreducible for open-ended work, so the human merge gate is load-bearing — it holds the original product intent no automated layer can reconstruct.
- **Stops at a human merge gate.** conquer never auto-merges to main. By default it leaves the isolated branch and worktree for you to review; `--push` commits + pushes that branch, then prints an **engine-written PR title/body** (from the real branch diff) and a **prefilled GitHub PR link** (`…/compare/…?quick_pull=1&title=…&body=…`) — click it, the form is already filled, review + merge. No `gh` CLI or token needed. `--push` additionally **refuses protected branches** (`main`/`master` by default; override with `protectedPushBranches` in config) — if the worktree HEAD somehow resolves to one, the work stays committed locally for a human push. The done-oracle is irreducible for open-ended work, so the human merge gate is load-bearing — it holds the original product intent no automated layer can reconstruct.

Also available as interactive `/conquer` in the REPL and `agon call conquer` for external CLIs.
Also available as interactive `/conquer` in the REPL (with full CLI flag parity: `--max-turns`, `--gate-timeout`, `--max-hours`, `--timeout`) and `agon call conquer` for external CLIs.

## Interactive REPL

Expand Down Expand Up @@ -596,6 +596,14 @@ If you want manual control, you can easily override Cesar's routing:
/cesar agy
```

### Delegation reflex

When a prompt is explicitly list-shaped (three or more numbered/bulleted items) with no sequential-dependency, shared-artifact, or small-task markers, Cesar receives a structural note that the work may decompose into parallel subtasks — it can then offer an agent team (worktree-isolated, running under the delegated permission floor). Detection is veto-first and advisory-only: nothing ever spawns without your confirmation, and prose or ordered work never triggers it. Disable with `cesarDelegationReflex false`.

### Experience precedent

Cesar learns from its own history beyond ratings: when your prompt resembles past runs, the matching episodes are injected into the turn as **advisory precedent** — `"fix the CSV parser crash" — mode=forge → codex, succeeded, 4m`. It's framed as evidence, never authority: nothing is shown unless at least `cesarExperienceMinEpisodes` (default 3) past runs clear the similarity gate, matching is purely lexical (no model or sidecar on the hot path), and any failure injects nothing. Disable with `cesarExperience false`; tune with `cesarExperienceMinSimilarity`, `cesarExperienceTopK`, and `cesarExperienceWindow`. Episodes accumulate from run telemetry as you use agon — older records without an intent summary are simply skipped.

## Configuration

Global configuration, engine selection, model preferences, and telemetry settings are managed via your personal config file located at `~/.agon/AGON.md`. Project-specific settings can be defined in a local `AGON.md` within your repository.
Expand Down
43 changes: 39 additions & 4 deletions packages/cli/src/generated/cesar/brain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ import { buildRoutingContext, deriveRoutingHints, shouldSpeculate } from './rout

import { shouldGroundInput, buildGroundingBlock } from './grounding.js';

import { episodesFromRunRecords, retrieveExperience, buildExperienceBlock, experienceRetrievalOptions } from './experience.js';

import { assessDelegationShape, buildDelegationAdvisory } from './delegation-reflex.js';

import { recentRunRecords, currentProjectKey } from '../../telemetry/index.js';

import { readCesarToolReliability, formatCesarReliabilityLine, shouldDowngradeCesarToolWork, buildWhatHappenedSummary } from './reliability.js';

import { applyCesarSelfTurnApproval } from './self-turn-approval.js';
Expand All @@ -58,7 +64,7 @@ import { consumeCesarPlanControlSignals } from './plan-control-signals.js';

import { hostNowIso, hostWaitForInteractiveChoice } from '../lib/kern-host.js';

// @kern-source: brain:31
// @kern-source: brain:34
export async function commitTurnAndDelegate(pendingDel: PendingDelegation, input: string, response: string, cesarEngineId: string, streaming: boolean, dispatch: Dispatch, ctx: HandlerContext, telemetry?: Record<string,unknown>, turnAlreadyCommitted?: boolean): Promise<CesarTurnOutcome> {
// streaming-end commits a real stream OR (when only a speculative preview
// draft sits on the pane) drops the draft without committing — safe no-op when
Expand Down Expand Up @@ -91,7 +97,7 @@ export async function commitTurnAndDelegate(pendingDel: PendingDelegation, input
return { delegated: false, responded: true, decisionReason: 'delegation-cancelled', ...telemetry ?? {} };
}

// @kern-source: brain:58
// @kern-source: brain:61
export async function commitTurnAndSuggest(suggestion: {action:string, rest?:string, hardened?:boolean, tribunalMode?:string, team?:boolean}, input: string, response: string, cesarEngineId: string, color: number, streaming: boolean, dispatch: Dispatch, ctx: HandlerContext, telemetry?: Record<string,unknown>): Promise<CesarTurnOutcome> {
// streaming-end commits a real stream OR drops a lingering speculative preview
// draft without committing — safe no-op when there's no entry at all.
Expand Down Expand Up @@ -122,10 +128,10 @@ export async function commitTurnAndSuggest(suggestion: {action:string, rest?:str
return { delegated: false, responded: true, decisionReason: 'suggestion-cancelled', ...telemetry ?? {} };
}

// @kern-source: brain:83
// @kern-source: brain:86
export const _noBriefNudged: WeakMap<object, boolean> = new WeakMap<object, boolean>();

// @kern-source: brain:85
// @kern-source: brain:88
export async function handleCesarBrain(input: string, dispatch: Dispatch, ctx: HandlerContext, images?: ImageAttachment[]): Promise<CesarTurnOutcome> {
const abort = new AbortController();
const _turnStart = Date.now();
Expand Down Expand Up @@ -904,6 +910,35 @@ export async function handleCesarBrain(input: string, dispatch: Dispatch, ctx: H
} catch { /* grounding is best-effort */ }
}

// ── Experience precedent (advisory, default-on: config.cesarExperience) ──
// RAG roadmap 1b: similar PAST RUN episodes (mode/winner/outcome) injected
// as evidence, never authority. Purely lexical (no sidecar spawn on the hot
// path), gated on min-N qualifying matches + a similarity floor, and
// fail-open — any error injects nothing. Reuses shouldGroundInput so slash
// commands and trivial prompts never retrieve.
if ((config as any).cesarExperience !== false && shouldGroundInput(input)) {
try {
const _expOpts = experienceRetrievalOptions(config);
// Scoped to THIS project: global telemetry must never leak another
// repo's task text into this turn (review blocker: codex).
const _expEpisodes = episodesFromRunRecords(recentRunRecords(_expOpts.window), currentProjectKey());
const _expBlock = buildExperienceBlock(retrieveExperience(input, _expEpisodes, _expOpts));
if (_expBlock) enrichedInput = `${_expBlock}\n\n${enrichedInput}`;
} catch { /* experience is best-effort */ }
}

// ── Delegation reflex (advisory-only: config.cesarDelegationReflex) ──
// Structural fan-out detection (explicit ≥3-item lists, veto-first). The
// advisory rides the prompt; surfacing stays with Cesar's existing
// [SUGGEST:agent-team] → promptDelegation flow, so the user always
// confirms and nothing auto-spawns. Fail-open like its siblings.
if ((config as any).cesarDelegationReflex !== false && shouldGroundInput(input)) {
try {
const _delAdvisory = buildDelegationAdvisory(assessDelegationShape(input));
if (_delAdvisory) enrichedInput = `${_delAdvisory}\n\n${enrichedInput}`;
} catch { /* delegation reflex is best-effort */ }
}

// ── Sequential-thinking scaffold (opt-in: config.cesarThinkFirst) ──
// The in-loop, dispatch-free form of `agon think`: when enabled, scaffold
// structured decomposition into the prompt so Cesar reasons before acting
Expand Down
68 changes: 68 additions & 0 deletions packages/cli/src/generated/cesar/delegation-reflex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// @generated by kern v4.5.0 — DO NOT EDIT. Source: src/kern/cesar/delegation-reflex.kern

// @kern-source: delegation-reflex:11
export interface DelegationShape {
decision: 'none' | 'suggest';
items: string[];
reasons: string[];
vetoes: string[];
}

/**
* Sequential-dependency markers: ordered work must never be pitched as parallel. The first…then pair is windowed to one sentence-ish span so unrelated mentions across a long prompt don't over-veto (review: kimi).
*/
// @kern-source: delegation-reflex:17
export const DELEGATION_SEQUENTIAL_RE: RegExp = /\b(?:then|after (?:that|this|which)|once (?:that|this|it)|depends on|followed by|first\b[^\n.]{0,120}\bthen)\b/i;

/**
* The user saying the work is small is a hard veto — spawning a team for a typo fix burns money.
*/
// @kern-source: delegation-reflex:20
export const DELEGATION_SMALL_RE: RegExp = /\b(?:quick(?:ly)?|just|tiny|small|simple|typo|one[- ]liner|minor)\b/i;

/**
* Shared-artifact mentions: list-shaped prompts whose items converge on one artifact look parallel but are not.
*/
// @kern-source: delegation-reflex:23
export const DELEGATION_SHARED_STATE_RE: RegExp = /\b(?:lockfiles?|package\.json|package-lock|migrations?|schemas?|generated|shared (?:types?|modules?|configs?|state)|same files?)\b/i;

/**
* Explicit list items only (numbered or bulleted lines). Deliberately strict for the first slice: comma-series and 'for each X' phrasings under-trigger rather than over-trigger.
*/
// @kern-source: delegation-reflex:26
export const DELEGATION_ITEM_RE: RegExp = /^\s*(?:\d+[.)]\s+|[-*•]\s+)(.+)$/gm;

/**
* Pure fan-out-shape assessment of a user prompt. Suggests ONLY when: ≥3 explicit list items, every item clears a 20-char size floor, and NO veto fires (sequential markers, small-task language, shared-artifact mentions, prompt too short overall). Vetoes are reported so the advisory can be debugged; the caller decides how to surface the result.
*/
// @kern-source: delegation-reflex:29
export function assessDelegationShape(input: string): DelegationShape {
const text = String(input ?? '');
const vetoes: string[] = [];
const reasons: string[] = [];
const items: string[] = [];
const re = new RegExp(DELEGATION_ITEM_RE.source, 'gm');
for (const m of text.matchAll(re)) {
const item = (m[1] ?? '').trim();
if (item) items.push(item.length > 120 ? item.slice(0, 119).trimEnd() + '…' : item);
}
if (text.trim().length < 80) vetoes.push('prompt-too-short');
if (items.length < 3) vetoes.push('fewer-than-3-items');
if (items.some((i) => i.length < 20)) vetoes.push('item-below-size-floor');
if (DELEGATION_SEQUENTIAL_RE.test(text)) vetoes.push('sequential-markers');
if (DELEGATION_SMALL_RE.test(text)) vetoes.push('small-task-language');
if (DELEGATION_SHARED_STATE_RE.test(text)) vetoes.push('shared-artifact-mention');
if (vetoes.length > 0) return { decision: 'none', items, reasons, vetoes };
reasons.push(`${items.length} explicit list items`);
reasons.push('no sequential/shared-state/small-task markers');
return { decision: 'suggest', items, reasons, vetoes };
}

/**
* The in-prompt advisory injected ahead of the user message when the shape suggests fan-out. Deliberately framed as a structural observation Cesar may reject: the model owns the judgment, the existing [SUGGEST:agent-team] → user-confirm flow owns the UX, and nothing spawns without the user saying yes.
*/
// @kern-source: delegation-reflex:53
export function buildDelegationAdvisory(shape: DelegationShape): string | null {
if (shape.decision !== 'suggest' || shape.items.length < 3) return null;
return `[DELEGATION SHAPE] This request contains ${shape.items.length} explicit list items with no sequential or shared-state markers — it MAY decompose into independent parallel subtasks. If, after reading them, you judge them genuinely independent (disjoint files, no ordering), you can offer parallel execution via [SUGGEST:team-agent] (worktree-isolated agent team; the user confirms before anything spawns) or background jobs. If they share state or order matters, ignore this note entirely — do not mention it.`;
}
Loading