diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..3c78088 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,50 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: [main] + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + # Build study plan (root) + - run: npm ci + - run: npm run build + + # Build quiz engine (quiz/) + - run: cd quiz && npm ci && npm run build + + # Merge both builds into one output + - run: | + mkdir -p dist/quiz + cp -r quiz/dist/* dist/quiz/ + + - uses: actions/upload-pages-artifact@v3 + with: + path: dist + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 92c3d63..f62d724 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,20 @@ A week-by-week battle plan covering all 5 exam domains, organized into 4 phases: ### Features -- **5 tabs**: Weekly Plan, Concepts (31 nodes), Projects, Decision Rules (11 rules), Cheat Sheet +- **6 tabs**: Weekly Plan, **Brain Map**, Concepts (30 nodes), Projects, Decision Rules (11 rules), Cheat Sheet +- **Theme toggle** (top-right): cycle dark → grey → light; choice persists in localStorage - **Daily KPIs** with measurable targets for each study day - **Daily closure assessments** linking to specific quiz engine modes - **Progress tracking** with localStorage-persisted checkboxes on tasks and concepts - **Completion percentages** per tab displayed in the header -### The 5 tabs +### The 6 tabs **Weekly Plan** -- Expand any week, then individual days. Each day lists what to study, a KPI, and a closure quiz reference. Colored borders indicate the domain. -**Concepts** -- 31 testable concepts organized by domain with weight percentages. Your self-test: explain any leaf node from memory. +**Brain Map** -- Radial SVG view of all 30 concepts across 5 domains with cross-domain connection arcs. Click any concept to see why it matters in production, related concepts across domains, curated learning resources, common failure modes, and exam distractor-trap phrases. Designed for scenario questions that span multiple domains. + +**Concepts** -- 30 testable concepts organized by domain with weight percentages. Your self-test: explain any leaf node from memory. **Projects** -- 4 production-style apps mapped to exam scenarios. diff --git a/quiz/vite.config.js b/quiz/vite.config.js index 9ffcc67..f729314 100644 --- a/quiz/vite.config.js +++ b/quiz/vite.config.js @@ -3,4 +3,5 @@ import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], + base: '/cca-study-plan/quiz/', }) diff --git a/src/App.jsx b/src/App.jsx index 03822c3..13ad360 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,11 +2,49 @@ import { useState, useEffect, useMemo } from "react"; /* ─── localStorage progress tracking ─── */ const STORAGE_KEY = "cca-study-progress"; +const THEME_KEY = "cca-theme"; function loadProgress() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY)) || {}; } catch { return {}; } } function saveProgress(p) { localStorage.setItem(STORAGE_KEY, JSON.stringify(p)); } +function loadTheme() { + try { return localStorage.getItem(THEME_KEY) || "dark"; } + catch { return "dark"; } +} +function saveTheme(t) { try { localStorage.setItem(THEME_KEY, t); } catch {} } + +/* ─── THEMES: three palettes (dark / grey / light) driving CSS variables ─── */ +const THEMES = { + dark: { + bgRoot: "#0c0c10", bgPanel: "var(--bg-panel)", bgPanelAlt: "var(--bg-panel-alt)", + border: "#1c1c28", borderSoft: "var(--border-soft)", borderMed: "var(--border-med)", + textPrimary: "var(--text-primary)", textBody: "var(--text-body)", textSoft: "var(--text-soft)", + textMuted: "var(--text-muted)", textFaint: "var(--text-faint)", textDim: "var(--text-dim)", + }, + grey: { + bgRoot: "#1f2026", bgPanel: "#272830", bgPanelAlt: "#2e2f38", + border: "#363742", borderSoft: "#323340", borderMed: "#3e3f4c", + textPrimary: "#f5f5f7", textBody: "#d8d8dd", textSoft: "#a8a8b0", + textMuted: "#888892", textFaint: "#666670", textDim: "#4a4a55", + }, + light: { + bgRoot: "#fafafa", bgPanel: "#ffffff", bgPanelAlt: "#f2f2f4", + border: "#d8d8dd", borderSoft: "#e4e4e8", borderMed: "var(--text-body)", + textPrimary: "#0c0c10", textBody: "#2a2a32", textSoft: "#4a4a55", + textMuted: "#6a6a75", textFaint: "#8a8a95", textDim: "#b0b0b8", + }, +}; + +function themeVars(theme) { + const t = THEMES[theme] || THEMES.dark; + return { + "--bg-root": t.bgRoot, "--bg-panel": t.bgPanel, "--bg-panel-alt": t.bgPanelAlt, + "--border": t.border, "--border-soft": t.borderSoft, "--border-med": t.borderMed, + "--text-primary": t.textPrimary, "--text-body": t.textBody, "--text-soft": t.textSoft, + "--text-muted": t.textMuted, "--text-faint": t.textFaint, "--text-dim": t.textDim, + }; +} /* ─── WEEKS ─── */ const WEEKS = [ @@ -14,7 +52,7 @@ const WEEKS = [ id: 1, title: "Foundation Sprint", subtitle: "Core mental models + baseline diagnostic", - theme: "Build the skeleton — understand HOW Claude thinks", + theme: "Build the skeleton — understand HOW the system thinks", days: [ { day: "Days 1–2", @@ -35,7 +73,7 @@ const WEEKS = [ focus: "Tool Design + MCP Foundations", domain: "D2", tasks: [ - "Study tool descriptions as THE mechanism for LLM tool selection", + "Study tool descriptions as THE mechanism for tool selection", "Learn tool splitting: generic → purpose-specific (analyze_document → extract_data_points + summarize_content + verify_claim)", "MCP: tools (actions) vs resources (content catalogs) — resources reduce exploratory calls", "Config: .mcp.json (project/shared) vs ~/.claude.json (user/personal), env var expansion ${TOKEN}", @@ -311,7 +349,7 @@ const CONCEPT_TREE = [ weight: "18%", accent: "#d35400", concepts: [ - { name: "Tool Interface Design", children: ["descriptions drive LLM tool selection", "include input formats, examples, edge cases, boundaries", "rename + update descriptions to eliminate overlap", "splitting generic → purpose-specific tools"] }, + { name: "Tool Interface Design", children: ["descriptions drive tool selection", "include input formats, examples, edge cases, boundaries", "rename + update descriptions to eliminate overlap", "splitting generic → purpose-specific tools"] }, { name: "Structured Error Responses", children: ["errorCategory: transient/validation/permission", "isRetryable boolean prevents wasted retries", "isError flag in MCP for tool failures", "access failure vs valid empty result distinction"] }, { name: "Tool Distribution & tool_choice", children: ["4-5 tools per agent; 18 degrades selection", "scoped cross-role tools for high-frequency needs", "tool_choice: auto / any / forced selection", "forced tool for sequencing (extract before enrich)"] }, { name: "MCP Integration", children: [".mcp.json (project) vs ~/.claude.json (user)", "env var expansion ${TOKEN} for credentials", "community servers over custom for standard integrations", "resources = content catalogs; tools = actions"] }, @@ -327,7 +365,7 @@ const CONCEPT_TREE = [ { name: "Commands & Skills", children: [".claude/commands/ (project) vs ~/.claude/commands/ (personal)", ".claude/skills/ + SKILL.md with frontmatter config", "context: fork isolates verbose skill output", "allowed-tools + argument-hint in frontmatter"] }, { name: "Path-Specific Rules", children: [".claude/rules/ with YAML frontmatter glob patterns", "paths: ['src/api/**/*'] for conditional loading", "glob patterns span directories (e.g., **/*.test.tsx)", "path rules > directory CLAUDE.md for cross-directory conventions"] }, { name: "Plan vs Direct Execution", children: ["plan mode: large-scale, multiple approaches, architectural", "direct: well-scoped single-file changes", "Explore subagent isolates verbose discovery", "combine: plan for investigation, direct for implementation"] }, - { name: "Iterative Refinement", children: ["concrete input/output examples > prose descriptions", "test-driven: write tests first, share failures to iterate", "interview pattern: Claude asks questions before implementing", "single message for interacting issues; sequential for independent"] }, + { name: "Iterative Refinement", children: ["concrete input/output examples > prose descriptions", "test-driven: write tests first, share failures to iterate", "interview pattern: agent asks questions before implementing", "single message for interacting issues; sequential for independent"] }, { name: "CLI for CI/CD", children: ["-p / --print: non-interactive mode", "--output-format json + --json-schema", "CLAUDE.md provides project context to CI-invoked Claude", "session isolation: separate instance for review vs generation"] }, ], }, @@ -359,6 +397,361 @@ const CONCEPT_TREE = [ }, ]; +/* ─── ENRICHED_CONCEPTS: brain-map metadata (why/production/links/failures/signals) ─── */ +const ENRICHED_CONCEPTS = [ + // ═══════════════════════════════════════════════════════════ + // D1 — Agentic Architecture (7 concepts, 27% weight) + // ═══════════════════════════════════════════════════════════ + { + id: "d1-agentic-loop", name: "Agentic Loop", domain: "D1", task: "1.1", + whyItMatters: "The loop is the core execution model. Check text content instead of stop_reason and your agent stops mid-workflow — claims don't get approved, support tickets sit half-resolved, extraction pipelines go silent. Tested heavily because it breaks quietly in prod.", + productionExamples: ["Customer support ticket resolution", "Insurance claims processing (retrieve → assess → approve)", "Document extraction pipelines"], + relatedConcepts: ["d2-structured-errors", "d4-structured-output", "d5-error-propagation"], + resources: [ + { label: "Building with the API (Skilljar Course)", url: "https://anthropic.skilljar.com", type: "course" }, + { label: "SDK Overview", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["Checking text content for termination → stops before tools finish", "NL parsing of tool results → brittle, unreliable routing", "Iteration cap without monitoring → silent task truncation"], + examSignals: ["agent stops mid-workflow", "reliability issue", "loop termination", "not calling expected tool"], + }, + { + id: "d1-multi-agent", name: "Multi-Agent Orchestration", domain: "D1", task: "1.2", + whyItMatters: "Complex work exceeds one agent's context and tool budget. Hub-and-spoke — a coordinator delegating to specialized subagents — scales to research, investigation, and cross-source synthesis. Overly narrow decomposition recreates the problem: fragmented context, no one can synthesize.", + productionExamples: ["Research systems querying multiple sources", "Codebase-wide refactors (per-file + cross-file passes)", "Compliance sweeps across heterogeneous datastores"], + relatedConcepts: ["d1-subagent-mgmt", "d1-task-decomp", "d5-context-mgmt"], + resources: [ + { label: "Subagent Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + { label: "Full Stack Guide (alexop.dev)", url: "https://alexop.dev/posts/understanding-claude-code-full-stack/", type: "blog" }, + ], + failureModes: ["Too-narrow subagents → fragmented context, no synthesis possible", "Coordinator doing execution work instead of delegating", "Bypassing the coordinator for inter-subagent chat"], + examSignals: ["hub-and-spoke", "coordinator", "subagent selection", "complex investigation"], + }, + { + id: "d1-subagent-mgmt", name: "Subagent Management", domain: "D1", task: "1.3", + whyItMatters: "Subagents don't inherit parent context. If you don't pass complete findings explicitly in the subagent's prompt, the synthesis step sees half a story. This is the #1 multi-agent bug: the synthesis agent has no idea what was already found.", + productionExamples: ["Parallel codebase investigations", "Cross-department research (legal + finance + ops)", "Per-file review + cross-file integration review"], + relatedConcepts: ["d1-multi-agent", "d5-context-mgmt", "d5-provenance"], + resources: [ + { label: "Task Tool Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["Assuming context inheritance → synthesis agent lacks info", "Sequential Task calls when they could run in parallel", "Over-broad allowedTools → subagent drifts out of scope"], + examSignals: ["subagent", "context passing", "synthesis agent lacks info", "parallel Task"], + }, + { + id: "d1-workflow-enforce", name: "Workflow Enforcement", domain: "D1", task: "1.4", + whyItMatters: "For financial ops, identity verification, or policy rules, prompts like 'always check X first' have non-zero failure rates. Hooks and programmatic prerequisites enforce these deterministically. The exam loves this distractor: 'occasionally fails' means you need a hook, not better wording.", + productionExamples: ["KYC checks before account creation", "Policy validation before refund", "PII redaction before logging"], + relatedConcepts: ["d1-hooks", "d2-tool-design", "d3-claude-md"], + resources: [ + { label: "Hooks Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["Relying on prompts for compliance → 5% failure rate compounds", "Hook runs after the tool, not before → irreversible damage done", "Redundant prompt-and-hook instructions → confusion, not safety"], + examSignals: ["reliability issue", "occasionally", "non-zero failure rate", "compliance must be guaranteed"], + }, + { + id: "d1-hooks", name: "Agent SDK Hooks", domain: "D1", task: "1.5", + whyItMatters: "Hooks (PostToolUse, PreToolUse) run deterministic code around every tool call. They're how you intercept, normalize, enforce, and redirect — without relying on the model. The desktop app can't do this; the Agent SDK can.", + productionExamples: ["PII scrubbing on every file read", "Audit logging every DB write", "Blocking writes to protected paths"], + relatedConcepts: ["d1-workflow-enforce", "d3-claude-md", "d2-tool-design"], + resources: [ + { label: "Hooks Reference", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + { label: "Features Explained (Medium)", url: "https://muneebsa.medium.com/claude-code-extensions-explained-skills-mcp-hooks-subagents-agent-teams-plugins-9294907e84ff", type: "blog" }, + ], + failureModes: ["Using prompts to enforce what hooks should enforce", "Hooks with side effects + retries → double writes", "Forgetting hooks run in subagents too"], + examSignals: ["policy enforcement", "deterministic compliance", "tool call interception", "data normalization"], + }, + { + id: "d1-task-decomp", name: "Task Decomposition", domain: "D1", task: "1.6", + whyItMatters: "Fixed prompt chains work for predictable flows; adaptive decomposition (map structure → identify high-impact → prioritized plan) works for open-ended tasks. Choosing wrong costs tokens and time, or worse, misses the high-impact issues entirely.", + productionExamples: ["Codebase security audits (adaptive)", "ETL pipelines (fixed chain)", "Incident investigations (adaptive)"], + relatedConcepts: ["d1-multi-agent", "d3-plan-vs-direct", "d4-multi-pass-review"], + resources: [ + { label: "Prompt Chaining Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Fixed chain on open-ended task → misses the point", "Adaptive decomposition on a deterministic pipeline → wasted planning", "Per-file only (no cross-file pass) → integration bugs missed"], + examSignals: ["adaptive decomposition", "per-file + cross-file", "prompt chaining", "map structure first"], + }, + { + id: "d1-session-state", name: "Session State & Forking", domain: "D1", task: "1.7", + whyItMatters: "Long sessions degrade — answers get vague, context fills up. `fork_session` lets you explore alternatives from a shared baseline. `--resume` vs fresh + summary is a real tradeoff: resume keeps reasoning but compounds degradation; fresh loses nuance but starts clean.", + productionExamples: ["Architecture exploration (fork for alternatives)", "Long debugging sessions", "A/B comparing refactors from a checkpoint"], + relatedConcepts: ["d5-context-mgmt", "d5-codebase-exploration", "d3-iterative-refinement"], + resources: [ + { label: "Resume Sessions Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Always resuming → context degrades permanently", "Always starting fresh → losing valuable context repeatedly", "Forking without informing about diverged changes"], + examSignals: ["--resume", "fork_session", "divergent exploration", "session merging"], + }, + // ═══════════════════════════════════════════════════════════ + // D2 — Tool Design & MCP (5 concepts, 18% weight) + // ═══════════════════════════════════════════════════════════ + { + id: "d2-tool-design", name: "Tool Interface Design", domain: "D2", task: "2.1", + whyItMatters: "Tools are selected based on DESCRIPTIONS, not names. If two tools have overlapping descriptions, selection becomes unreliable and wrong tools fire. Splitting a generic tool into purpose-specific ones (with boundaries spelled out) fixes this.", + productionExamples: ["Billing API with separate refund/adjustment/dispute endpoints", "Knowledge base tools split by authoritativeness", "Split read-only vs write-allowed file tools"], + relatedConcepts: ["d2-tool-distribution", "d2-structured-errors", "d1-hooks"], + resources: [ + { label: "Tool Design Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["Overlapping tool descriptions → wrong tool called", "Ghost associations from system prompt keywords", "Generic tools used in specialized contexts → incorrect operations"], + examSignals: ["wrong tool called", "tool selection unreliable", "descriptions drive selection", "tool boundaries"], + }, + { + id: "d2-structured-errors", name: "Structured Error Responses", domain: "D2", task: "2.2", + whyItMatters: "`errorCategory + isRetryable + description` lets the coordinator decide: retry, fall back, or escalate. Generic 'unavailable' hides information. The big one: access failure vs valid empty result — if the agent can't distinguish 'DB down' from 'no matching rows', it reports all-clear on broken infra.", + productionExamples: ["Compliance monitoring (empty ≠ access failure)", "Retry logic with exponential backoff", "Escalation routing by error category"], + relatedConcepts: ["d5-error-propagation", "d1-agentic-loop", "d5-escalation"], + resources: [ + { label: "Error Handling Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["Access failure reported as 'no results' → false all-clear", "isRetryable=true on deterministic failures → infinite loops", "Generic errors → coordinator makes blind decisions"], + examSignals: ["error handling", "recovery", "coordinator decisions", "access failure vs empty"], + }, + { + id: "d2-tool-distribution", name: "Tool Distribution & tool_choice", domain: "D2", task: "2.3", + whyItMatters: "4-5 tools per agent works; 18 degrades selection reliability. Scope tools to the agent's role. `tool_choice` (auto/any/forced) controls when a call is required — forced tool is how you sequence (extract before enrich, verify before act).", + productionExamples: ["Customer support agent (5 tools)", "Research agent (7 scoped tools)", "Forced 'verify_identity' before 'process_refund'"], + relatedConcepts: ["d2-tool-design", "d4-structured-output", "d1-subagent-mgmt"], + resources: [ + { label: "tool_choice Docs", url: "https://platform.claude.com/docs/en/agent-sdk/overview", type: "docs" }, + ], + failureModes: ["18+ tools per agent → selection unreliable", "tool_choice='any' when you need 'forced'", "Cross-role tools everywhere → drift from role"], + examSignals: ["too many tools", "tool selection unreliable", "wrong tool called", "forced tool sequencing"], + }, + { + id: "d2-mcp", name: "MCP Integration", domain: "D2", task: "2.4", + whyItMatters: "`.mcp.json` (project-level, version-controlled) vs `~/.claude.json` (user-level, private). Env var expansion `${TOKEN}` keeps credentials out of config. Key distinction: MCP **tools** perform actions; MCP **resources** expose content catalogs — resources reduce exploratory tool calls.", + productionExamples: ["Shared team MCP servers (via .mcp.json)", "Personal tokens in ~/.claude.json", "Doc catalog exposed as MCP resources (no tool call needed to list)"], + relatedConcepts: ["d2-tool-design", "d3-claude-md", "d2-builtin-tools"], + resources: [ + { label: "Model Context Protocol Docs", url: "https://modelcontextprotocol.io/docs", type: "docs" }, + { label: "MCP: Universal Connectivity (ZenML)", url: "https://www.zenml.io/llmops-database/model-context-protocol-mcp-building-universal-connectivity-for-llms-in-production", type: "blog" }, + ], + failureModes: ["Credentials in .mcp.json committed to git", "Custom MCP server for standard integration → maintenance burden", "Using tools when resources would work better"], + examSignals: ["content catalog", "reduce tool calls", "give visibility", "project vs user config"], + }, + { + id: "d2-builtin-tools", name: "Built-in Tools", domain: "D2", task: "2.5", + whyItMatters: "Grep for content search, Glob for paths, Read/Write/Edit for files. Edit fails → fall back to Read + Write. Incremental Grep → Read tracing beats loading whole directories. Knowing the fallback patterns keeps sessions efficient.", + productionExamples: ["Codebase search workflows", "Large-file editing via surgical Edits", "Tracing symbol usage via Grep chains"], + relatedConcepts: ["d2-tool-distribution", "d3-plan-vs-direct", "d5-codebase-exploration"], + resources: [ + { label: "Built-in Tools Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Reading whole files instead of Grep → context waste", "Edit when string not unique → silent failure, use Read+Write", "Glob for content search (wrong tool)"], + examSignals: ["Grep", "Glob", "Edit fails", "fallback pattern", "incremental tracing"], + }, + // ═══════════════════════════════════════════════════════════ + // D3 — Config & Workflows (6 concepts, 20% weight) + // ═══════════════════════════════════════════════════════════ + { + id: "d3-claude-md", name: "CLAUDE.md Hierarchy", domain: "D3", task: "3.1", + whyItMatters: "User (~/.claude/) → project (.claude/) → directory CLAUDE.md files merge into working context. User-level is NOT version-controlled (private, per-dev). Project-level is team-shared. Get this wrong and teammates diverge silently.", + productionExamples: ["60-person team with shared .claude/ rules", "Personal tool preferences in ~/.claude/", "Directory-scoped rules for legacy code"], + relatedConcepts: ["d3-path-rules", "d3-commands-skills", "d1-workflow-enforce"], + resources: [ + { label: "CLAUDE.md Reference", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Committing ~/.claude/ config to git", "Relying on user-level for team standards", "Monolithic CLAUDE.md when modular @imports would be cleaner"], + examSignals: ["CLAUDE.md hierarchy", "version control", "team-shared rules", "merging behavior"], + }, + { + id: "d3-commands-skills", name: "Commands & Skills", domain: "D3", task: "3.2", + whyItMatters: ".claude/commands/ holds reusable slash commands; .claude/skills/ holds skills with SKILL.md frontmatter. `context: fork` isolates verbose skill output so it doesn't pollute the parent conversation. Project-level vs user-level matters for team sharing.", + productionExamples: ["Custom /commit slash command", "A /review-pr skill forked to avoid context bloat", "Personal ~/.claude/commands/ for solo workflows"], + relatedConcepts: ["d3-claude-md", "d3-cli-cicd", "d1-subagent-mgmt"], + resources: [ + { label: "Skills & Commands Docs", url: "https://code.claude.com/docs", type: "docs" }, + { label: "Extensions Explained (Medium)", url: "https://muneebsa.medium.com/claude-code-extensions-explained-skills-mcp-hooks-subagents-agent-teams-plugins-9294907e84ff", type: "blog" }, + ], + failureModes: ["Verbose skill without context: fork → parent conversation drowns", "Personal commands committed to project repo", "Missing allowed-tools frontmatter → permission errors"], + examSignals: ["context: fork", "allowed-tools", "argument-hint", "SKILL.md"], + }, + { + id: "d3-path-rules", name: "Path-Specific Rules", domain: "D3", task: "3.3", + whyItMatters: ".claude/rules/ files with YAML frontmatter glob patterns conditionally load rules based on which file is being touched. Cross-directory conventions (e.g., all **/*.test.tsx) work here better than scattered directory-level CLAUDE.md files.", + productionExamples: ["Test-file conventions across entire repo", "API-layer rules for src/api/**/*", "Security rules only for auth code"], + relatedConcepts: ["d3-claude-md", "d3-commands-skills", "d1-workflow-enforce"], + resources: [ + { label: "Path-Specific Rules Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Monolithic CLAUDE.md with rules for every path → noise", "Globs too broad → rules fire in wrong contexts", "Directory CLAUDE.md duplicates path-rule content"], + examSignals: ["glob patterns", "path-scoped", "cross-directory conventions", "conditional loading"], + }, + { + id: "d3-plan-vs-direct", name: "Plan vs Direct Execution", domain: "D3", task: "3.4", + whyItMatters: "Plan mode is for architecture and multi-file changes where you need alignment before coding. Direct mode is for well-scoped single-file fixes. The Explore subagent isolates verbose discovery from the main conversation.", + productionExamples: ["Architecture refactor → plan mode", "Typo fix → direct", "Research task → Explore subagent, then plan"], + relatedConcepts: ["d1-task-decomp", "d3-iterative-refinement", "d1-subagent-mgmt"], + resources: [ + { label: "Planning Mode Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Plan mode for trivial fixes → overhead", "Direct mode for architectural changes → half-done work", "Skipping Explore → verbose output pollutes plan context"], + examSignals: ["plan mode", "direct execution", "architectural", "single-file change", "Explore subagent"], + }, + { + id: "d3-iterative-refinement", name: "Iterative Refinement", domain: "D3", task: "3.5", + whyItMatters: "Concrete input/output examples beat prose descriptions. Test-driven iteration (write tests first, share failures) makes ambiguity visible. Interview pattern (agent asks clarifying questions before implementing) avoids wrong assumptions. Independent issues → sequential messages; interacting issues → one combined message.", + productionExamples: ["TDD loops with agents writing to pass your tests", "Interview pattern for underspecified tickets", "Concrete JSON examples over prose schema descriptions"], + relatedConcepts: ["d4-explicit-criteria", "d4-few-shot", "d3-plan-vs-direct"], + resources: [ + { label: "Best Practices Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["Prose descriptions when examples would clarify", "Skipping interview → wrong assumptions baked in", "Batched independent issues → tangled fixes"], + examSignals: ["input/output examples", "test-driven", "interview pattern", "sequential vs single message"], + }, + { + id: "d3-cli-cicd", name: "CLI for CI/CD", domain: "D3", task: "3.6", + whyItMatters: "`-p` / `--print` runs the CLI non-interactively. `--output-format json` + `--json-schema` makes output machine-parseable. CLAUDE.md still applies. Session isolation matters: separate instance for generation vs review prevents self-confirmation bias.", + productionExamples: ["PR review bot", "Release notes generator", "Automated test-failure triage"], + relatedConcepts: ["d4-multi-pass-review", "d4-structured-output", "d3-claude-md"], + resources: [ + { label: "CLI Reference Docs", url: "https://code.claude.com/docs", type: "docs" }, + { label: "Deployment Patterns (AWS Blog)", url: "https://aws.amazon.com/blogs/machine-learning/claude-code-deployment-patterns-and-best-practices-with-amazon-bedrock/", type: "blog" }, + ], + failureModes: ["Same session for generate + review → biased review", "No --output-format json → unparseable output in CI", "Forgetting CLAUDE.md still loads in -p mode"], + examSignals: ["-p", "--print", "non-interactive", "--output-format json", "CI/CD integration"], + }, + // ═══════════════════════════════════════════════════════════ + // D4 — Prompt Engineering & Structured Output (6 concepts, 20% weight) + // ═══════════════════════════════════════════════════════════ + { + id: "d4-explicit-criteria", name: "Explicit Criteria", domain: "D4", task: "4.1", + whyItMatters: "Specific categorical criteria ('flag only when claimed behavior directly contradicts actual behavior') beats vague ones ('be conservative'). False positives destroy developer trust — a 5% FP rate in code review means 100 spurious warnings/week nobody reads.", + productionExamples: ["Static analysis rules", "Content moderation thresholds", "Code review linters"], + relatedConcepts: ["d4-few-shot", "d4-schema-design", "d5-confidence-review"], + resources: [ + { label: "Prompt Engineering Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Vague 'be careful' instructions → inconsistent output", "High FP rate destroys trust even at high recall", "Disabling whole categories instead of tightening criteria"], + examSignals: ["improve precision", "reduce false positives", "developer trust", "vague instructions"], + }, + { + id: "d4-few-shot", name: "Few-Shot Prompting", domain: "D4", task: "4.2", + whyItMatters: "2-4 examples targeting AMBIGUOUS scenarios teach generalization. Show WHY one action beats alternatives — demonstrate reasoning, not just format. This is how you handle edge cases you can't pre-enumerate.", + productionExamples: ["Classification with unusual edge cases", "Format demonstrations for custom output", "Reasoning patterns for judgment calls"], + relatedConcepts: ["d4-explicit-criteria", "d4-schema-design", "d3-iterative-refinement"], + resources: [ + { label: "Few-Shot Prompting Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Examples only showing easy cases → fails on hard ones", "Examples showing output without reasoning → no generalization", "Too many examples (20+) → context bloat + overfitting"], + examSignals: ["ambiguous cases", "show reasoning", "demonstrate format", "generalize to novel patterns"], + }, + { + id: "d4-structured-output", name: "Structured Output", domain: "D4", task: "4.3", + whyItMatters: "`tool_use` + JSON schema guarantees schema compliance (eliminates SYNTAX errors). Semantic errors persist — the field will be present but the value may be wrong. Nullable/optional fields prevent fabrication when source data is absent.", + productionExamples: ["Document extraction to structured DBs", "API-response normalization", "Invoice field extraction"], + relatedConcepts: ["d4-schema-design", "d2-tool-distribution", "d4-batch-validation"], + resources: [ + { label: "Tool Use & Structured Outputs Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Required fields on optional data → fabricated values", "Trusting schema compliance for semantic correctness", "tool_choice='auto' when you need 'any' or 'forced'"], + examSignals: ["JSON schema", "tool_use", "guaranteed compliance", "semantic errors persist"], + }, + { + id: "d4-schema-design", name: "Schema Design", domain: "D4", task: "4.4", + whyItMatters: "Required vs optional fields matter: required fields on absent data force fabrication. Enum + 'other' + detail string keeps categories extensible. Pydantic (or similar) adds semantic validation the JSON schema can't.", + productionExamples: ["Extensible categorization (enum + other + free text)", "Nullable fields for optional source data", "Pydantic models for cross-field validation"], + relatedConcepts: ["d4-structured-output", "d4-batch-validation", "d5-error-propagation"], + resources: [ + { label: "Pydantic Docs", url: "https://docs.pydantic.dev", type: "docs" }, + ], + failureModes: ["Locked enums → categorization fails on novel cases", "All-required schemas → hallucination on absent data", "Schema without semantic validation → invalid data accepted"], + examSignals: ["nullable fields", "enum + other", "required vs optional", "semantic validation"], + }, + { + id: "d4-batch-validation", name: "Batch & Validation", domain: "D4", task: "4.5", + whyItMatters: "Message Batches API: 50% cost savings, up to 24-hour window, no latency SLA. Perfect for overnight reports, WRONG for pre-merge checks where devs wait. `custom_id` correlates requests to responses. Validation-retry loops need the document + failed extraction + specific error — not just 'try again'.", + productionExamples: ["Overnight batch classification of tickets", "Pre-merge blocking checks (sync, not batch)", "Validation-retry on failed extractions"], + relatedConcepts: ["d4-structured-output", "d4-schema-design", "d2-structured-errors"], + resources: [ + { label: "Message Batches API Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Batch for blocking checks → devs wait 24hr", "Generic 'try again' retry → same failure", "Missing custom_id → can't correlate"], + examSignals: ["cost savings", "pre-merge", "overnight", "batch processing", "validation-retry"], + }, + { + id: "d4-multi-pass-review", name: "Multi-Pass Review", domain: "D4", task: "4.6", + whyItMatters: "The generator retains its reasoning context — it's biased toward its own work. An independent review instance (without that context) catches what the generator missed. Per-file passes catch local issues; a cross-file pass catches integration bugs.", + productionExamples: ["Code review with a separate instance", "Per-file linting + cross-file consistency", "Confidence-based routing to human review"], + relatedConcepts: ["d1-task-decomp", "d3-cli-cicd", "d5-confidence-review"], + resources: [ + { label: "Self-Review Limitations Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Self-review in same session → confirms own reasoning", "Per-file only → integration bugs slip through", "No confidence routing → low-confidence outputs auto-accepted"], + examSignals: ["review quality", "same session", "independent instance", "per-file + cross-file", "confidence routing"], + }, + // ═══════════════════════════════════════════════════════════ + // D5 — Context & Reliability (6 concepts, 15% weight) + // ═══════════════════════════════════════════════════════════ + { + id: "d5-context-mgmt", name: "Context Management", domain: "D5", task: "5.1", + whyItMatters: "Progressive summarization drops facts. Key facts (amounts, dates, IDs) belong in a case-facts block EXCLUDED from summarization. Trim verbose tool outputs BEFORE accumulation. Lost-in-the-middle: put findings at START and END of long inputs — the middle gets underweighted.", + productionExamples: ["Support tickets with preserved case facts", "Long debugging sessions with distilled findings", "Multi-issue conversations with structured layers"], + relatedConcepts: ["d5-codebase-exploration", "d5-provenance", "d1-session-state"], + resources: [ + { label: "Long Context Handling Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Progressive summarization → refund amounts go vague", "Accumulating verbose tool output → token bloat", "Key findings buried in middle → ignored"], + examSignals: ["case facts block", "lost-in-the-middle", "progressive summarization", "trim before accumulate"], + }, + { + id: "d5-escalation", name: "Escalation Patterns", domain: "D5", task: "5.2", + whyItMatters: "Honor explicit human requests immediately. Escalate on policy gaps and when stuck. Do NOT escalate on sentiment (angry customer ≠ needs human) — that's an anti-pattern. On ambiguous matches, ask for the identifier; don't heuristic-guess.", + productionExamples: ["Support agents with clear escalation triggers", "Claims systems escalating on policy gaps", "Identity systems asking for specific IDs on collision"], + relatedConcepts: ["d5-error-propagation", "d2-structured-errors", "d4-explicit-criteria"], + resources: [ + { label: "Escalation Patterns Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Sentiment-based escalation → unreliable", "Heuristic-matching on ambiguous identifiers → wrong records", "Not honoring explicit human requests immediately"], + examSignals: ["escalation triggers", "customer demands human", "policy gaps", "sentiment-based anti-pattern"], + }, + { + id: "d5-error-propagation", name: "Error Propagation", domain: "D5", task: "5.3", + whyItMatters: "Structured errors (failure_type + attempted_query + partial_results + alternatives) let coordinators decide. Generic errors hide everything. Recover transients locally; propagate unresolvables with coverage annotations — 'this finding was well-supported, this one came from unavailable sources'.", + productionExamples: ["Research pipelines with coverage annotations", "Local retry + propagated-failure patterns", "Contested-findings sections in reports"], + relatedConcepts: ["d2-structured-errors", "d5-provenance", "d1-agentic-loop"], + resources: [ + { label: "Error Handling Patterns Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Generic 'failed' error → coordinator blind", "Propagating recoverable errors → unnecessary escalation", "No coverage annotations → findings indistinguishable from gaps"], + examSignals: ["structured errors", "access failure vs empty", "local recovery", "coverage annotations"], + }, + { + id: "d5-codebase-exploration", name: "Codebase Exploration Context", domain: "D5", task: "5.4", + whyItMatters: "Long exploration sessions degrade: answers start referencing 'typical patterns' instead of actual findings. Scratchpad files persist key findings across context boundaries. `/compact` reduces context mid-session. State manifests enable crash recovery.", + productionExamples: ["Large codebase audits with scratchpads", "Long investigations using /compact", "Crash-recovery manifests for agent state"], + relatedConcepts: ["d5-context-mgmt", "d1-session-state", "d2-builtin-tools"], + resources: [ + { label: "Managing Context Docs", url: "https://code.claude.com/docs", type: "docs" }, + ], + failureModes: ["No scratchpad → findings evaporate after /compact", "Inconsistent answers in extended sessions", "No crash recovery → restart from scratch"], + examSignals: ["inconsistent answers", "typical patterns", "context degradation", "extended session", "scratchpad"], + }, + { + id: "d5-confidence-review", name: "Confidence & Review", domain: "D5", task: "5.5", + whyItMatters: "Aggregate 97% accuracy can hide terrible performance on specific doc types. Stratified sampling by doc type measures true error rate. Field-level confidence needs calibration against labeled validation — not self-reported scores alone.", + productionExamples: ["Stratified random sampling of extractions", "Per-doc-type accuracy dashboards", "Human review routing by confidence threshold"], + relatedConcepts: ["d4-multi-pass-review", "d5-provenance", "d4-explicit-criteria"], + resources: [ + { label: "Evaluating Outputs Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Aggregate accuracy hides per-type failures", "Trusting self-reported confidence without calibration", "No stratified sampling → systemic errors invisible"], + examSignals: ["aggregate accuracy", "stratified sampling", "field-level confidence", "calibration"], + }, + { + id: "d5-provenance", name: "Provenance", domain: "D5", task: "5.6", + whyItMatters: "Claim-source mappings must be preserved through synthesis. Temporal data needs publication/collection dates. Conflicts need source attribution — don't arbitrarily pick one. Structured reports separate well-supported from contested findings explicitly.", + productionExamples: ["Research reports with citation tracking", "Temporal-sensitive analysis with dates", "Contested-findings sections for disputed claims"], + relatedConcepts: ["d5-error-propagation", "d5-confidence-review", "d1-subagent-mgmt"], + resources: [ + { label: "Provenance & Citations Docs", url: "https://platform.claude.com/docs", type: "docs" }, + ], + failureModes: ["Synthesis drops source attribution → unverifiable claims", "Arbitrary conflict resolution → silent bias", "No temporal data → stale findings presented as current"], + examSignals: ["claim-source mappings", "temporal data", "conflict annotation", "contested findings"], + }, +]; + /* ─── DECISION RULES ─── */ const RULES = [ { @@ -394,7 +787,7 @@ const RULES = [ { num: 6, rule: "Nullable Prevents Hallucination", - detail: "Make schema fields optional/nullable when the source may not contain the info. Required fields on absent data forces the model to fabricate values to satisfy the schema.", + detail: "Make schema fields optional/nullable when the source may not contain the info. Required fields on absent data forces fabrication to satisfy the schema.", signal: "Look for: 'fabricated values', 'hallucination', 'missing information'", }, { @@ -412,7 +805,7 @@ const RULES = [ { num: 9, rule: "Independent Review > Self-Review", - detail: "A model retains reasoning context from generation, making it less likely to question its own decisions. A separate Claude instance (without prior reasoning) catches issues the generator misses.", + detail: "The generator retains reasoning context, making it less likely to question its own decisions. A separate instance (without prior reasoning) catches issues the generator misses.", signal: "Look for: 'review quality', 'same session', 'missed issues', 'inconsistent feedback'", }, { @@ -456,11 +849,11 @@ const PROJECTS = [ name: "CI/CD Code Review Pipeline", scenario: "Scenario 5", domains: "D3 + D4", - desc: "Claude Code in non-interactive CI mode with structured output, explicit review criteria, and multi-pass architecture", + desc: "Non-interactive CI mode with structured output, explicit review criteria, and multi-pass architecture", skills: ["-p flag non-interactive mode", "--output-format json", "Explicit review criteria", "Multi-pass: per-file + cross-file", "False positive category management"], }, { - name: "Claude Code Team Workflow", + name: "Team Workflow", scenario: "Scenario 2", domains: "D3 + D5", desc: "Configure CLAUDE.md hierarchy, path-scoped rules, custom skills with context: fork, MCP server integration, and iterative refinement patterns", @@ -484,7 +877,7 @@ const CHEAT_SHEET = [ { category: "Tool Design Decisions", items: [ - "Generic tool confusing the model → split into purpose-specific tools with distinct descriptions", + "Generic tool causing confusion → split into purpose-specific tools with distinct descriptions", "Similar tools misrouted → rename + expand descriptions with boundaries and examples", "Agent has 18 tools → scope to 4-5 per role; add cross-role tools for high-frequency needs only", "MCP tools = actions (create, update, query); MCP resources = content catalogs (browse without calling)", @@ -584,6 +977,9 @@ export default function App() { const [openDomain, setOpenDomain] = useState(0); const [openDay, setOpenDay] = useState(null); const [progress, setProgress] = useState(loadProgress); + const [theme, setTheme] = useState(loadTheme); + useEffect(() => { saveTheme(theme); }, [theme]); + const cycleTheme = () => setTheme(t => t === "dark" ? "grey" : t === "grey" ? "light" : "dark"); const toggleProgress = (key) => { setProgress(prev => { @@ -600,6 +996,7 @@ export default function App() { const tabs = [ { id: "plan", label: "Weekly Plan" }, + { id: "brain", label: "Brain Map" }, { id: "tree", label: "Concepts" }, { id: "builds", label: "Projects" }, { id: "rules", label: "Decision Rules" }, @@ -609,51 +1006,55 @@ export default function App() { const s = { root: { fontFamily: "'IBM Plex Mono', 'Menlo', 'Consolas', monospace", - background: "#0c0c10", - color: "#c8c8d0", + background: "var(--bg-root)", + color: "var(--text-body)", minHeight: "100vh", - maxWidth: 520, + maxWidth: 860, margin: "0 auto", + padding: "0 24px", + ...themeVars(theme), }, header: { - padding: "20px 16px 12px", - borderBottom: "1px solid #1c1c28", + padding: "28px 0 16px", + borderBottom: "1px solid var(--border)", + position: "relative", }, tag: { display: "inline-block", - fontSize: 9, + fontSize: 11, letterSpacing: 2.5, color: "#c0392b", textTransform: "uppercase", fontWeight: 600, - marginBottom: 6, + marginBottom: 8, }, h1: { - fontSize: 18, + fontSize: 24, fontWeight: 700, - color: "#f0f0f0", + color: "var(--text-primary)", margin: 0, lineHeight: 1.3, }, sub: { - fontSize: 11, - color: "#555", - marginTop: 4, + fontSize: 15, + color: "var(--text-faint)", + marginTop: 6, }, tabs: { display: "flex", - borderBottom: "1px solid #1c1c28", - padding: "0 4px", + borderBottom: "1px solid var(--border)", + padding: "0 0", overflowX: "auto", + gap: 4, }, tabBtn: (active) => ({ flex: 1, - padding: "10px 4px", - fontSize: 9, + padding: "12px 8px", + fontSize: 12, fontFamily: "inherit", fontWeight: active ? 600 : 400, background: "none", - color: active ? "#f0f0f0" : "#4a4a58", + color: active ? "var(--text-primary)" : "var(--text-faint)", border: "none", borderBottom: active ? "2px solid #c0392b" : "2px solid transparent", cursor: "pointer", @@ -662,14 +1063,30 @@ export default function App() { whiteSpace: "nowrap", }), content: { - padding: "12px 16px 24px", + padding: "20px 0 32px", }, progressBar: { - height: 3, - background: "#1a1a26", + height: 4, + background: "var(--border-soft)", borderRadius: 2, overflow: "hidden", - marginTop: 8, + marginTop: 10, + }, + themeBtn: { + position: "absolute", + top: 24, + right: 0, + padding: "6px 12px", + fontSize: 11, + fontFamily: "inherit", + letterSpacing: 1, + textTransform: "uppercase", + fontWeight: 600, + background: "var(--bg-panel)", + color: "var(--text-soft)", + border: "1px solid var(--border)", + borderRadius: 4, + cursor: "pointer", }, }; @@ -680,13 +1097,21 @@ export default function App() { return (
Scaled 100–1000 / 720 pass / 60 questions / 4 random scenarios