diff --git a/docs/research.md b/docs/research.md index 66867f5..5b675d9 100644 --- a/docs/research.md +++ b/docs/research.md @@ -266,6 +266,20 @@ Autonomy contracts are not set-and-forget. The agent should re-confirm autonomy Beyond per-product autonomy settings, Anthropic positions its own model behavior on a "disposition dial" ranging from _fully corrigible_ (does whatever instructed) to _fully autonomous_ (acts on its own values). Current Claude models sit closer to the corrigible end — a deliberate safety choice with direct UX implications: agents defer to the principal hierarchy (Anthropic → operator → user) rather than override it. The autonomy contract a product designs sits on top of this model-level disposition. +### 4.5 Levels are analysis vocabulary, not Send-time UI (July 2026 reframe) + +> **Position (ratified 2026-07-05).** The level ladder in §4.1 is how we _analyze_ autonomy. It is not what the user sees at Send. At the dispatch moment the user sees a **behavioral posture badge** plus **verification defensibility gaps** — and, for complex tasks, a **plan→execute gate** that picks execution posture after plan review. + +The July 2026 web audits (`audits/`, 2026-07-03 series) converged on three findings that reshape how §4 applies to composer UI: + +1. **No product ships L0–L5 as a numbered control at Send** ([`audits/dispatch-moment-ui-web-2026-07-03.md`](../audits/dispatch-moment-ui-web-2026-07-03.md)). Mode, model, and placement are visible; Run Mode, sandbox, allowlists, and stopping conditions stay hidden. Where level surfaces at all, it works as behavior language, not a number. +2. **The strongest pre-dispatch gap is defensibility** ([`audits/verification-defensibility-web-2026-07-03.md`](../audits/verification-defensibility-web-2026-07-03.md)). Nothing on the market answers "is this autonomy level defensible for _this_ task?" before Send. The eight-field run contract (Addy Osmani, July 2026) is one safeguard among many — not the organizing UI concept; its fields ship shredded across products ([`audits/contract-field-reality-2026-07-03.md`](../audits/contract-field-reality-2026-07-03.md)). +3. **Plan gates that also pick execution posture are the strongest shipping pattern** — Claude Code's plan-approval options, Factory's Spec approval. The plan review moment is where autonomy gets renegotiated, not a settings page. + +**Canonical Send-time vocabulary.** agentic-craft ships posture as three behavioral badges — **"Asks first"** (pauses before edits and external actions), **"Edits freely"** (applies file edits without per-step approval), **"On its own"** (runs until done or a gate fires) — roughly the behavior of L2/L3/L4 in §4.1's terms. Before Send, the composer surfaces five defensibility gaps: **stopping condition, verification method, scope boundary, spend cap, risky actions**. Source of truth: `src/views/patterns/dispatch-moment-data.ts`; reference sketch: `/patterns/dispatch-moment`. + +**How this composes with the rest of §4.** The matrix view (§4.2) and renegotiation (§4.3) still hold — the badge is the compressed, legible face of the effective policy, and the plan→execute gate is a renegotiation moment. What changes is the UI claim: the ladder informs design analysis and this document's taxonomy; the badge, the gap checklist, and the plan gate are what earn pixels at Send. + ## 5. Trust through provenance > **Position.** Trust in agentic systems is not earned through confident prose. It is earned through _provenance_ — visible links between every claim and its source. An agent that says less but cites everything beats an agent that says more without sources. diff --git a/sessions/2026-07-03-eve-chat-composer-autonomy.md b/sessions/2026-07-03-eve-chat-composer-autonomy.md index 51e79a5..670436e 100644 --- a/sessions/2026-07-03-eve-chat-composer-autonomy.md +++ b/sessions/2026-07-03-eve-chat-composer-autonomy.md @@ -36,15 +36,25 @@ The Claude Code exploration may have been **solving the wrong problem well**: po --- -## Open composer questions (pick one to pursue) +## Composer direction — decided 2026-07-05 -| ID | Question | Research signal | -|----|----------|-----------------| -| **A** | Level selection legibility at Send | No product ships L0–L5 as a numbered control; level works better as behavioral badge | -| **B** | Verification defensibility before dispatch | Strongest gap — nothing answers "is this autonomy level defensible for *this* task?" pre-Send | -| **C** | Plan→execute transition | Strongest pre-dispatch patterns: Claude Code 5-option plan approval, Factory Spec approval, Plan→Implement | +**Decision: pursue B + C.** Verification defensibility before dispatch plus +the plan→execute transition are the composer problems agentic-craft works on. +Contract read-back is no longer the main problem. -Research points strongest at **B + C**, with level as behavioral badge rather than ladder UI. +| ID | Question | Resolution | +|----|----------|------------| +| **A** | Level selection legibility at Send | **Resolved as design position** — level ships as a behavioral badge ("Asks first" / "Edits freely" / "On its own"), never a numbered L0–L5 control | +| **B** | Verification defensibility before dispatch | **Chosen** — surface missing proof, unclear stopping conditions, missing scope, cost/budget ambiguity, and risky actions before Send | +| **C** | Plan→execute transition | **Chosen** — complex tasks gate on plan review, then explicitly pick execution posture | + +Canonical vocabulary (three postures, five defensibility gaps) lives in +`src/views/patterns/dispatch-moment-data.ts`; the pattern page at +[`/patterns/dispatch-moment`](../app/(reference)/patterns/dispatch-moment/page.tsx) +is the reference sketch. `docs/research.md` §4.5 carries the reframe. + +**Bare/B/C/D stay retired** unless B+C work surfaces a concrete need for a +contract-variant comparison. --- @@ -130,9 +140,9 @@ Fixture ask: *"migrate session-chat-page to the shared adapter — don't touch d --- -## Suggested next steps in agentic-craft +## Next steps in agentic-craft -1. Choose composer problem **A**, **B**, or **C** (recommend B + C) — **started:** [`/patterns/dispatch-moment`](../app/(reference)/patterns/dispatch-moment/page.tsx) sketches B+C on the registry composer +1. ~~Choose composer problem **A**, **B**, or **C**~~ — **done 2026-07-05:** B + C chosen (see decision record above); [`/patterns/dispatch-moment`](../app/(reference)/patterns/dispatch-moment/page.tsx) sketches B+C on the registry composer 2. Sketch against registry composer demos and/or compound-composer slots — not contract read-back -3. Cross-check [`docs/research.md`](../docs/research.md) §4 "Autonomy as a contract" — may need revision to match reframe -4. If promoting compound composer into the site, wire a playground route under agentic-craft (don't fork registry composer) +3. ~~Cross-check [`docs/research.md`](../docs/research.md) §4~~ — **done 2026-07-05:** §4.5 carries the reframe (behavioral badge, defensibility at Send) +4. Wire the compound-composer playground at `/playground/compound-composer` (URL-only lab; don't fork registry composer) — icons injectable per consumer shadcn config, `attachment` added via CLI diff --git a/src/components/DispatchMomentDemo.tsx b/src/components/DispatchMomentDemo.tsx index 4d522a0..c341603 100644 --- a/src/components/DispatchMomentDemo.tsx +++ b/src/components/DispatchMomentDemo.tsx @@ -16,7 +16,6 @@ import { ComposerPlan, ComposerDoneWhen, ComposerReceipt, - type ComposerDoneWhenItem, type ComposerTask, } from "@/components/ui/composer" import { @@ -31,9 +30,13 @@ import { HumanGateTitle, } from "@/components/ui/human-gate" import { cn } from "@/lib/utils" - -const FIXTURE_PROMPT = - "Migrate session-chat-page to the shared adapter — don't touch deps, stop when tests pass, keep it under $5" +import { + AUTONOMY_POSTURES, + FIXTURE_PROMPT, + evaluateDefensibility, + parseDispatchPrompt, + type AutonomyPosture, +} from "@/views/patterns/dispatch-moment-data" type ExecutionPosture = | "auto-review" @@ -41,30 +44,6 @@ type ExecutionPosture = | "review-each" | "keep-planning" -type AutonomyPosture = { - id: string - label: string - description: string -} - -const AUTONOMY_POSTURES: AutonomyPosture[] = [ - { - id: "asks-first", - label: "Asks first", - description: "Pauses before edits and external actions.", - }, - { - id: "edits-freely", - label: "Edits freely", - description: "Applies file edits without per-step approval.", - }, - { - id: "on-its-own", - label: "On its own", - description: "Runs until done or a gate fires.", - }, -] - const EXECUTION_OPTIONS: { id: ExecutionPosture label: string @@ -111,103 +90,6 @@ const PLAN_TASKS: ComposerTask[] = [ }, ] -type ParsedDispatch = { - summary: string - doneWhen: ComposerDoneWhenItem[] - exclusions: string[] - budget?: string - needsPlanGate: boolean -} - -function parseDispatchPrompt(text: string): ParsedDispatch { - const trimmed = text.trim() - const lower = trimmed.toLowerCase() - - const doneWhen: ComposerDoneWhenItem[] = [] - const exclusions: string[] = [] - let budget: string | undefined - - const stopMatch = lower.match( - /(?:stop|done)\s+when\s+([^—–.;]+(?:pass|green|complete)[^—–.;]*)/i - ) - if (stopMatch) { - doneWhen.push({ - id: "stop", - label: stopMatch[1].trim(), - }) - } - - const budgetMatch = trimmed.match( - /(?:under|below|keep\s+it\s+under)\s+\$?\d+/i - ) - if (budgetMatch) { - budget = budgetMatch[0].replace(/^keep it /i, "") - doneWhen.push({ id: "budget", label: budget }) - } - - const dontTouchMatch = trimmed.match(/don't touch\s+([^—–.;]+)/i) - if (dontTouchMatch) { - exclusions.push(dontTouchMatch[1].trim()) - doneWhen.push({ - id: "exclude", - label: `${dontTouchMatch[1].trim()} locked`, - }) - } - - const summary = - trimmed.length > 72 ? `${trimmed.slice(0, 69).trim()}…` : trimmed || "…" - - const needsPlanGate = - /migrate|refactor|implement|across|shared adapter/i.test(trimmed) && - trimmed.length > 40 - - return { - summary, - doneWhen, - exclusions, - budget, - needsPlanGate, - } -} - -type VerificationGap = { - id: string - label: string - met: boolean -} - -function buildVerificationGaps( - parsed: ParsedDispatch, - fullText: string -): VerificationGap[] { - const hasStop = parsed.doneWhen.some((item) => item.id === "stop") - const hasBudget = Boolean(parsed.budget) - const hasScope = parsed.exclusions.length > 0 - - return [ - { - id: "stop", - label: "Stopping condition", - met: hasStop, - }, - { - id: "proof", - label: "Verification method", - met: hasStop && /test|check|pass|green|ci/i.test(fullText), - }, - { - id: "scope", - label: "Scope boundary", - met: hasScope, - }, - { - id: "budget", - label: "Spend cap", - met: hasBudget, - }, - ] -} - function DispatchMomentDemo() { const [draft, setDraft] = React.useState("") const [postureIndex, setPostureIndex] = React.useState(0) @@ -222,7 +104,7 @@ function DispatchMomentDemo() { const parsed = React.useMemo(() => parseDispatchPrompt(draft), [draft]) const verificationGaps = React.useMemo( - () => buildVerificationGaps(parsed, draft), + () => evaluateDefensibility(parsed, draft), [parsed, draft] ) const missingVerification = verificationGaps.filter((gap) => !gap.met) @@ -466,4 +348,4 @@ function DispatchMomentDemo() { ) } -export { DispatchMomentDemo, FIXTURE_PROMPT, parseDispatchPrompt } +export { DispatchMomentDemo } diff --git a/src/views/patterns/dispatch-moment-content.tsx b/src/views/patterns/dispatch-moment-content.tsx index b40b680..af41dbb 100644 --- a/src/views/patterns/dispatch-moment-content.tsx +++ b/src/views/patterns/dispatch-moment-content.tsx @@ -7,12 +7,17 @@ import { PatternDemo } from "@/components/reference/pattern-demo" import { PatternPage } from "@/components/reference/pattern-page" import { PatternSection } from "@/components/reference/pattern-section" import { PatternSpecTable } from "@/components/reference/pattern-spec-table" +import { + AUTONOMY_POSTURES, + DEFENSIBILITY_GAPS, +} from "@/views/patterns/dispatch-moment-data" const PRINCIPLES = [ { title: "Behavioral badge, not a ladder", - description: - "Ship posture as language users recognize — asks first, edits freely — not L0–L5 numbers.", + description: `Ship posture as language users recognize — ${AUTONOMY_POSTURES.map( + (posture) => posture.label.toLowerCase() + ).join(", ")} — not L0–L5 numbers.`, }, { title: "Verification before posture", @@ -62,13 +67,13 @@ function DispatchMomentContent() { className="mb-10 grid scroll-mt-20 gap-4 border-y border-border/60 py-5 lg:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)]" >
Reframe
+Direction — ratified 2026-07-05
Verification defensibility + plan→execute — not contract read-back.
Open questions pursued
+Questions chosen
- Continues the July 3 composer/autonomy session handoff in{" "}
+ Decision recorded in{" "}
sessions/2026-07-03-eve-chat-composer-autonomy.md
- . Supersedes the Bare/B/C/D contract-variant framing until the
- problem is reframed.
+ . Question A resolves as behavioral badge, not ladder UI; the
+ Bare/B/C/D contract-variant framing is retired unless B+C work
+ surfaces a concrete need for it.
Posture badge
+Defensibility checklist
+docs/research.md §4
- against the agency×orchestration reframe (behavioral badge vs
- numbered ladder).
+ docs/research.md §4.5 now carries
+ the reframe: levels are analysis vocabulary; Send shows a behavioral
+ badge plus defensibility gaps.
references/eve-chat/ only where
- they strengthen B+C — not contract document UI.
+ Compound-composer lab at{" "}
+ /playground/compound-composer —
+ slot compositions, fixture controls, and the same B+C ideas on the
+ eve-chat compound API for comparison against this registry-composer
+ sketch.