diff --git a/docs/README.md b/docs/README.md index be476c3..7141dcb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,7 +39,7 @@ docs/ │ └── design-system.md │ ├── adr/ # Architecture Decision Records -│ └── 0001-*.md through 0015-*.md +│ └── 0001-*.md through 0016-*.md │ ├── Feature Plans/ # Future feature plans │ ├── claude-plugin-packaging.md diff --git a/docs/SYSTEM_ARCHITECTURE.md b/docs/SYSTEM_ARCHITECTURE.md index 06783d3..12ed4a0 100644 --- a/docs/SYSTEM_ARCHITECTURE.md +++ b/docs/SYSTEM_ARCHITECTURE.md @@ -1,6 +1,6 @@ --- document_id: doc.system-architecture -last_verified: 2026-03-06 +last_verified: 2026-04-20 tokens_estimate: 950 tags: - architecture @@ -37,7 +37,7 @@ ttl_expires_on: null ## Overview -Single-user desktop app. Next.js serves UI + API. Electron wraps it. SQLite stores all state locally. RuVector stores embeddings locally. Anthropic API provides LLM. Build agents run in-process via `@anthropic-ai/claude-agent-sdk`. +Single-user desktop app. Next.js serves UI + API. Electron wraps it. SQLite stores all state locally. RuVector stores embeddings locally. Planning and build both use Claude agent tooling, with a CLI fallback for planning when no extractable credential is available. ``` ┌─────────────────────────────────────────────────────────────┐ @@ -73,7 +73,7 @@ Single-user desktop app. Next.js serves UI + API. Electron wraps it. SQLite stor | UI | React 19 + Tailwind v4 + shadcn/ui | `app/`, `components/` | | API | Next.js App Router (route handlers) | `app/api/` | | Database | SQLite via better-sqlite3 (local, no Supabase) | `lib/db/` | -| Planning LLM | Anthropic Claude (streaming + non-streaming) | `lib/llm/` | +| Planning LLM | Agent SDK `query()`/streaming (credentialed) + Claude CLI fallback | `lib/llm/` | | Build agents | `@anthropic-ai/claude-agent-sdk` `query()` (streaming, in-process) | `lib/orchestration/` | | Agent definitions | agentic-flow registry (system prompts only) | `node_modules/agentic-flow/` | | Embeddings | all-MiniLM-L6-v2 (ONNX WASM, local) | `lib/memory/embedding.ts` | @@ -106,7 +106,7 @@ Full schema details: [data-contracts-reference.md](domains/data-contracts-refere ## Data Flow (Summaries) ### Planning -`User chat → Anthropic streaming API → stream-action-parser → PlanningAction[] → validate → apply → SQLite` +`User chat → planning SDK/CLI execution → stream-action-parser → PlanningAction[] → validate → apply → SQLite` Detail: [planning-reference.md](domains/planning-reference.md) @@ -138,14 +138,14 @@ Two distinct connection patterns exist. | Concern | Planning LLM | Build Agent | |---------|-------------|-------------| -| Auth | `ANTHROPIC_API_KEY` | `ANTHROPIC_API_KEY` | -| SDK | `@anthropic-ai/sdk` (Messages API) | `@anthropic-ai/claude-agent-sdk` | -| Call style | `messages.create` / `messages.stream` | `query()` — async iterator | -| Streaming | Optional (non-streaming for simple calls, streaming for chat) | Always streaming (`for await` over messages) | -| Tools | None (text output only) | Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch | -| CWD | N/A | `worktree_path` (repo clone) | -| Lifecycle | Request-response per chat turn | Fire-and-forget; result via in-process webhook callback | -| Model | `claude-haiku-4-5-20251001` (configurable) | `claude-sonnet-4-5-20250929` (configurable) | +| Auth | Credential from env/config/Claude settings (`ANTHROPIC_API_KEY` or token); CLI fallback when no extractable credential | `ANTHROPIC_API_KEY` | +| SDK/runtime | `@anthropic-ai/claude-agent-sdk` (primary) + `claude -p` fallback | `@anthropic-ai/claude-agent-sdk` | +| Call style | `query()` / async iterator (SDK) or CLI subprocess | `query()` — async iterator | +| Streaming | SDK iterator streaming; CLI `stream-json` fallback | Always streaming (`for await` over messages) | +| Tools | `WebSearch` always; `Read/Glob/Grep` only when repo `cwd` is available | Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch | +| CWD | Optional clone path when repo connected | `worktree_path` (repo clone) | +| Lifecycle | Request-response per chat turn; planner may do multi-turn tool loops before final JSON | Fire-and-forget; result via in-process webhook callback | +| Model | `claude-haiku-4-5-20251001` SDK default; CLI default `claude-sonnet-4-6` (both configurable) | `claude-sonnet-4-5-20250929` (configurable) | --- diff --git a/docs/docs-index.yaml b/docs/docs-index.yaml index fc6899f..3180604 100644 --- a/docs/docs-index.yaml +++ b/docs/docs-index.yaml @@ -12,11 +12,11 @@ docs_index: - id: overview summary: "Self-deployable Next.js app; SQLite + agentic-flow + RuVector" - id: data-flow - summary: "Planning LLM → actions → DbAdapter; Build → orchestration → agents" + summary: "Planning SDK/CLI → actions → DbAdapter; Build → orchestration → agents" - id: endpoints summary: "REST API under /api/projects; map, actions, artifacts, cards" depends_on: [] - last_verified: "2026-02-18" + last_verified: "2026-04-20" - id: doc.data-contracts path: domains/data-contracts-reference.md @@ -76,7 +76,7 @@ docs_index: - id: modes summary: "Scaffold, populate, full; mode selected by map state" depends_on: [doc.system-architecture, doc.data-contracts] - last_verified: "2026-02-18" + last_verified: "2026-04-20" - id: doc.mutation path: domains/mutation-reference.md @@ -110,9 +110,9 @@ docs_index: - id: contract summary: "OrchestrationRun → CardAssignment; checks before approval; PR user-gated" - id: flow - summary: "createRun → assignments → agentic-flow → checks → approval → PR" + summary: "clone/sync → createRun → assignments → agentic-flow → checks → approval → PR" depends_on: [doc.system-architecture, doc.data-contracts] - last_verified: "2026-02-18" + last_verified: "2026-04-20" - id: doc.testing path: testing-reference.md @@ -189,3 +189,13 @@ docs_index: summary: "Desktop installers workflow: manual or on v* tag; download .exe, .deb, .dmg" depends_on: [doc.releases-distribution] last_verified: "2026-03-06" + + - id: doc.adr-0016-planning-auth-paths + path: adr/0016-planning-agent-two-auth-paths.md + tokens_estimate: 500 + tags: [adr, planning, llm, auth] + anchors: + - id: decision + summary: "Planning uses Agent SDK for credentialed users, CLI fallback when no extractable credential exists" + depends_on: [doc.system-architecture, doc.planning] + last_verified: "2026-04-20" diff --git a/docs/domains/orchestration-reference.md b/docs/domains/orchestration-reference.md index 1938655..56bc53c 100644 --- a/docs/domains/orchestration-reference.md +++ b/docs/domains/orchestration-reference.md @@ -1,6 +1,6 @@ --- document_id: doc.orchestration -last_verified: 2026-03-06 +last_verified: 2026-04-20 tokens_estimate: 950 tags: - orchestration @@ -10,7 +10,7 @@ anchors: - id: contract summary: "OrchestrationRun → CardAssignment; checks before approval; PR user-gated" - id: flow - summary: "createRun → assignments → agentic-flow → checks → approval → PR" + summary: "clone/sync → createRun → assignments → agentic-flow → checks → approval → PR" - id: policy summary: "SystemPolicyProfile: required_checks, protected_paths, forbidden_paths" ttl_expires_on: null @@ -38,6 +38,7 @@ ttl_expires_on: null ``` User trigger (card | workflow) → ensureClone (repo to ~/.dossier/repos//) — single-card only for MVP + → optional repo sync (`POST /api/projects/[projectId]/repo/sync`) to fast-forward local base branch from origin → createRun (validate policy, capture snapshots; worktree_root = clone path) → createFeatureBranch per card → createAssignment per card (feature_branch, worktree_path, allowed_paths, forbidden_paths) @@ -75,11 +76,12 @@ dispatch.ts → createAgenticFlowClient() → SDK query() ### Key Files | File | Purpose | |------|---------| -| `lib/orchestration/repo-manager.ts` | ensureClone, createFeatureBranch; clone to ~/.dossier/repos/ | +| `lib/orchestration/repo-manager.ts` | ensureClone, syncMainBranch, createFeatureBranch; clone to ~/.dossier/repos/ | | `lib/orchestration/repo-reader.ts` | getRepoFileTree, getChangedFiles, getFileContent, getFileDiff | | `lib/orchestration/create-run.ts` | createRun; policy validation; snapshot capture | | `lib/orchestration/create-assignment.ts` | CardAssignment per card | | `lib/orchestration/trigger-build.ts` | Entry point; clones repo, creates branch, populates worktree_path | +| `app/api/projects/[projectId]/repo/sync/route.ts` | User-triggered base branch sync endpoint before subsequent builds | | `lib/orchestration/dispatch.ts` | Dispatch to agentic-flow | | `lib/orchestration/execute-checks.ts` | Run required checks | | `lib/orchestration/approval-gates.ts` | Check pass before approval request | diff --git a/docs/domains/planning-reference.md b/docs/domains/planning-reference.md index 34afdf5..494936b 100644 --- a/docs/domains/planning-reference.md +++ b/docs/domains/planning-reference.md @@ -1,6 +1,6 @@ --- document_id: doc.planning -last_verified: 2026-03-06 +last_verified: 2026-04-20 tokens_estimate: 750 tags: - planning @@ -12,7 +12,7 @@ anchors: - id: modes summary: "Scaffold, populate, full; mode selected by map state" - id: flow - summary: "Chat → Claude → stream-action-parser → actions" + summary: "Chat → Planning SDK/CLI → stream-action-parser → actions" ttl_expires_on: null --- # Planning Domain Reference @@ -49,12 +49,20 @@ Mode selected by `lib/llm/planning-prompt.ts` based on map state. ``` User message → POST /chat/stream → buildPlanningSystemPrompt() | buildScaffoldSystemPrompt() | buildPopulateSystemPrompt() | buildFinalizeSystemPrompt() - → Claude API (streaming) + → claude-client (Agent SDK query/stream for credentialed users; CLI fallback when no extractable credential) → stream-action-parser (parse JSON blocks) → PlanningAction[] emitted → POST /actions (validate + apply) ``` +### Auth and execution paths +- Primary path: `runPlanningQuery()` / `streamPlanningQuery()` from `planning-sdk-runner.ts` using `@anthropic-ai/claude-agent-sdk`. +- Credential resolution order: env `ANTHROPIC_API_KEY` → `~/.dossier/config` → `~/.claude/settings.json` (`ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN`). +- CLI fallback: when no extractable credential is available but `claude` CLI is installed/authenticated. +- Planning tool access depends on repo context (`cwd`), not credential type: + - Repo connected: `Read`, `Glob`, `Grep`, `WebSearch` + - No repo connected: `WebSearch` only + ### Per-Card Finalize Flow ``` User clicks "Finalize" on card → POST /cards/[cardId]/finalize @@ -71,8 +79,9 @@ User clicks "Finalize" on card → POST /cards/[cardId]/finalize | `lib/llm/planning-prompt.ts` | System prompts; mode selection | | `lib/llm/stream-action-parser.ts` | Parse streaming JSON → actions | | `lib/llm/build-preview-response.ts` | Preview response before apply | -| `lib/llm/claude-client.ts` | Planning LLM client (Messages API) | -| `lib/llm/planning-credential.ts` | Resolves ANTHROPIC_API_KEY from env or ~/.dossier/config | +| `lib/llm/claude-client.ts` | Planning client orchestrator (SDK primary path + CLI fallback) | +| `lib/llm/planning-sdk-runner.ts` | Agent SDK `query()` / streaming execution and planning tool policy | +| `lib/llm/planning-credential.ts` | Resolves planning credential from env/config/Claude CLI settings | | `app/api/projects/[id]/chat/route.ts` | Non-streaming chat | | `app/api/projects/[id]/chat/stream/route.ts` | Streaming chat (scaffold, populate, finalize) | | `app/api/projects/[id]/cards/[cardId]/finalize/route.ts` | Per-card finalize endpoint | @@ -88,6 +97,7 @@ User clicks "Finalize" on card → POST /cards/[cardId]/finalize - [ ] No action proposes code generation (validate-action rejects) - [ ] Prompt instructs LLM to use existing IDs from context - [ ] User actions follow-up after populate (agent prompts for View Details, Build, etc.) +- [ ] Planning credential routing stays two-path (Agent SDK or CLI fallback); no Messages API routing in planning ## Related - [mutation-reference.md](mutation-reference.md)