{"id":48192983,"url":"https://github.com/clay-good/codelicious","last_synced_at":"2026-04-04T17:56:29.554Z","repository":{"id":345165494,"uuid":"1082000092","full_name":"clay-good/codelicious","owner":"clay-good","description":"Codelicious is a headless autonomous developer CLI that transforms markdown specifications into production-ready Pull Requests with zero human intervention. It orchestrates a dual-engine architecture powered by Claude Code and Hugging Face (DeepSeek for reasoning and Qwen for Coding).   Specs -\u003e Code -\u003e Commits","archived":false,"fork":false,"pushed_at":"2026-03-26T00:37:48.000Z","size":41942,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T21:52:23.988Z","etag":null,"topics":["ai-developer-agent","autonomous-coding","claude-code","deepseek","devops-automation","github-automation","gitlab-automation","headless-cli","llm-tools","markdown-to-code","software-engineering"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clay-good.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-23T15:33:50.000Z","updated_at":"2026-03-26T00:37:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/clay-good/codelicious","commit_stats":null,"previous_names":["clay-good/codelicious"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/clay-good/codelicious","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clay-good%2Fcodelicious","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clay-good%2Fcodelicious/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clay-good%2Fcodelicious/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clay-good%2Fcodelicious/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clay-good","download_url":"https://codeload.github.com/clay-good/codelicious/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clay-good%2Fcodelicious/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31407655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-developer-agent","autonomous-coding","claude-code","deepseek","devops-automation","github-automation","gitlab-automation","headless-cli","llm-tools","markdown-to-code","software-engineering"],"created_at":"2026-04-04T17:56:29.460Z","updated_at":"2026-04-04T17:56:29.537Z","avatar_url":"https://github.com/clay-good.png","language":"Python","readme":"# Codelicious\n\n**Outcome as a Service.** Write specs. Run `codelicious /path/to/repo`. Get a green, review-ready Pull Request.\n\nCodelicious is a headless, autonomous developer CLI that transforms markdown specifications into production-ready Pull Requests with zero human intervention. It orchestrates a dual-engine architecture powered by Claude Code and HuggingFace (DeepSeek for reasoning, Qwen for coding).\n\n```\nSpec -\u003e Code -\u003e Test -\u003e Commit -\u003e PR\n```\n\n---\n\n## Quick Start\n\n```bash\n# 1. Clone and install (includes dev tools: pytest, ruff, bandit, pip-audit)\ngit clone https://github.com/clay-good/codelicious.git\ncd codelicious\npip install -e \".[dev]\"\n# Or minimal install without dev tools: pip install -e .\n\n# 2. Run against your repo\ncodelicious /path/to/your/repo\n```\n\n### Engine Options\n\n```bash\n# Claude Code CLI (requires `claude` binary installed + API credits)\ncodelicious /path/to/your/repo\n\n# HuggingFace engine (free, no API costs)\nexport HF_TOKEN=hf_your_token_here  # https://huggingface.co/settings/tokens\ncodelicious /path/to/your/repo --engine huggingface\n```\n\n### Development Setup\n\n```bash\npip install -e \".[dev]\"    # Install with dev dependencies (pytest, ruff, bandit, pip-audit)\npytest                      # Run tests\nruff check src/ tests/      # Lint\nbandit -r src/              # Security scan\npip-audit                   # Dependency vulnerability check\n```\n\n---\n\n## How Git, Commits, and PRs Work\n\nThis is the part you need to understand. Codelicious works **inside a git repo you provide**. Here's the full workflow:\n\n### Prerequisites\n\nYour target repo must:\n1. **Be a git repository** (has a `.git/` folder)\n2. **Have a remote named `origin`** pointing to GitHub or GitLab\n3. **Have `gh` CLI installed and authenticated** (for GitHub PRs) or `glab` for GitLab MRs\n\n### Step-by-Step Workflow\n\n```bash\n# 1. Navigate to your project repo\ncd /path/to/your/repo\n\n# 2. Make sure you're on main and up to date\ngit checkout main\ngit pull origin main\n\n# 3. Run codelicious with --push-pr to get the full pipeline\ncodelicious /path/to/your/repo --push-pr\n```\n\n**What happens automatically:**\n\n1. Codelicious detects you're on `main` and creates a feature branch: `codelicious/auto-build`\n2. It reads your specs from `docs/specs/*.md`\n3. It implements the code, runs tests, verifies\n4. It commits changes to the feature branch\n5. With `--push-pr`, it pushes the branch and creates a **Draft PR** via `gh pr create --draft`\n6. When all verification passes, it marks the PR as **Ready for Review**\n\n### Manual Git Push (if you skip --push-pr)\n\nIf you run without `--push-pr`, codelicious still commits locally but does NOT push. You handle it:\n\n```bash\n# After codelicious finishes:\ncd /path/to/your/repo\ngit log --oneline -5           # See what codelicious committed\ngit push -u origin HEAD        # Push the feature branch\n\n# Create the PR yourself:\ngh pr create --title \"feat: autonomous implementation\" --body \"Built by Codelicious\"\n# Or for GitLab:\nglab mr create --title \"feat: autonomous implementation\" --description \"Built by Codelicious\"\n```\n\n### Recommended Workflow for Iterative Builds\n\n```bash\n# First run — builds and creates draft PR\ncodelicious /path/to/your/repo --push-pr\n\n# Subsequent runs — appends commits to the same branch/PR\ncodelicious /path/to/your/repo --push-pr\n\n# When you're happy, the PR is already open — just review and merge\n```\n\n### Summary of Commands\n\n| Step | Command | When |\n|------|---------|------|\n| Install | `pip install -e .` | Once |\n| Build + auto PR | `codelicious /path/to/repo --push-pr` | Each build cycle |\n| Build only (no push) | `codelicious /path/to/repo` | When you want to review locally first |\n| Push manually | `git push -u origin HEAD` | After a no-push build |\n| Create PR (GitHub) | `gh pr create --draft` | After manual push |\n| Create MR (GitLab) | `glab mr create` | After manual push |\n\n---\n\n## Dual Engine Architecture\n\nCodelicious auto-detects the best available engine at startup:\n\n| Engine | Backend | How It Works |\n|--------|---------|--------------|\n| **Claude Code CLI** | `claude` binary | Spawns Claude Code as subprocess. 6-phase lifecycle: scaffold, build, verify, reflect, commit, PR. |\n| **HuggingFace** | DeepSeek-V3 + Qwen3-235B | Free HTTP API via SambaNova. DeepSeek plans, Qwen codes. 50-iteration agentic loop. No API costs. |\n\nAuto-detection priority: Claude Code CLI \u003e HuggingFace \u003e error with setup instructions.\n\n\u003e **Note:** Engine selection happens at startup, not mid-build. If you hit Claude token limits, re-run with `--engine huggingface` to use the free HuggingFace backend. The HuggingFace engine is a fully independent code path — not a degraded mode.\n\n---\n\n## CLI Reference\n\n```\ncodelicious \u003crepo_path\u003e [options]\n\nOptions:\n  --engine {auto,claude,huggingface}  Build engine (default: auto)\n  --model MODEL                       Model override (e.g. claude-sonnet-4-6)\n  --agent-timeout SECONDS             Claude engine timeout (default: 1800)\n  --resume SESSION_ID                 Resume a previous Claude session\n  --verify-passes N                   Verification passes (default: 3)\n  --no-reflect                        Skip quality review phase\n  --push-pr                           Push and create/update PR\n  --max-iterations N                  HF engine max iterations (default: 50)\n  --dry-run                           Log phases without executing\n  --spec PATH                         Target a specific spec file\n```\n\n## Claude Code Engine Phases\n\nWhen using the Claude Code engine, codelicious runs a 6-phase lifecycle:\n\n1. **SCAFFOLD** — writes `CLAUDE.md` and `.claude/` directory (agents, skills, rules, settings) into the target project\n2. **BUILD** — spawns Claude Code CLI with an autonomous build prompt. Claude reads specs, implements code, runs tests, commits.\n3. **VERIFY** — runs deterministic verification: Python syntax check, test suite, security pattern scan\n4. **REFLECT** — optional read-only quality review by Claude (can skip with `--no-reflect`)\n5. **GIT** — commits all changes to the feature branch\n6. **PR** — pushes and creates/updates a draft PR (requires `--push-pr`)\n\n---\n\n## Writing Specs\n\nPlace markdown specs in `docs/specs/` in your target repo. Codelicious will find and build them in order.\n\n```markdown\n# Feature: User Authentication\n\n## Requirements\n- [ ] Add login endpoint at POST /api/auth/login\n- [ ] Add JWT token generation\n- [ ] Add middleware for protected routes\n- [ ] Write tests for all auth flows\n\n## Acceptance Criteria\n- All tests pass\n- No hardcoded secrets\n- Rate limiting on login endpoint\n```\n\n---\n\n## Security Model\n\nCodelicious enforces defense-in-depth security, all hardcoded in Python (not configurable by the LLM):\n\n- **Command denylist** — 39 dangerous commands blocked (`rm`, `sudo`, `dd`, `kill`, `curl`, etc.)\n- **Shell injection prevention** — `shell=False` + metacharacter blocking (`|`, `\u0026`, `;`, `$`, etc.)\n- **File write protection** — LLM cannot modify its own tool source code or security config\n- **File extension allowlist** — only safe file types can be written\n- **Path traversal defense** — null byte detection, `..` rejection, symlink resolution\n- **Security scanning** — pre-commit scan for `eval()`, `exec()`, `shell=True`, hardcoded secrets\n\n---\n\n## Project Structure\n\n```\nsrc/codelicious/\n  cli.py                    # Entry point with engine selection\n  engines/\n    __init__.py             # select_engine() auto-detection\n    base.py                 # BuildEngine ABC + BuildResult\n    claude_engine.py        # Claude Code CLI 6-phase engine\n    huggingface_engine.py   # HuggingFace tool-dispatch engine\n  agent_runner.py           # Claude subprocess management\n  scaffolder.py             # CLAUDE.md + .claude/ generation\n  prompts.py                # All agent prompt templates\n  verifier.py               # Deterministic verification pipeline\n  tools/\n    registry.py             # Tool name -\u003e function dispatch\n    fs_tools.py             # Sandboxed file operations\n    command_runner.py        # Denylist command execution\n    audit_logger.py         # Security event logging\n  git/\n    git_orchestrator.py     # Branch safety + PR management\n  context/\n    cache_engine.py         # State persistence\n    rag_engine.py           # SQLite vector search\n  errors.py                 # Typed exceptions\n  config.py                 # Environment + file config loading\n```\n\n## Runtime Files\n\nCodelicious creates a `.codelicious/` directory in the target repo (gitignored):\n\n| File | Purpose |\n|------|---------|\n| `state.json` | Task progress and memory |\n| `cache.json` | File hash index |\n| `db.sqlite3` | Vector embeddings for RAG |\n| `audit.log` | Full agent interaction log |\n| `security.log` | Security events only |\n| `STATE.md` | Human-readable build status |\n| `BUILD_COMPLETE` | Sentinel file (contains \"DONE\" when finished) |\n\n---\n\n## Architecture\n\n### Build Lifecycle\n\n```mermaid\nflowchart TB\n    User[\"Developer runs: codelicious /path/to/repo\"]\n    EngineSelect{\"Engine\\nSelection\"}\n    Claude[\"Claude Code CLI Engine\"]\n    HF[\"HuggingFace Engine\"]\n\n    subgraph Claude_Lifecycle[\"Claude Code 6-Phase Lifecycle\"]\n        C1[\"1. SCAFFOLD\\nWrite CLAUDE.md + .claude/\"]\n        C2[\"2. ANALYZE\\nExplore codebase\"]\n        C3[\"3. BUILD\\nImplement specs\"]\n        C4[\"4. VERIFY\\nSyntax + Tests + Security\"]\n        C5[\"5. REFLECT\\nQuality review\"]\n        C6[\"6. PR\\nCommit + Push + PR\"]\n        C1 --\u003e C2 --\u003e C3 --\u003e C4 --\u003e C5 --\u003e C6\n    end\n\n    subgraph HF_Lifecycle[\"HuggingFace Agentic Loop\"]\n        H1[\"System prompt\\nwith tool schemas\"]\n        H2[\"LLM generates\\ntool calls\"]\n        H3[\"Tool dispatch\\n(read/write/run)\"]\n        H4[\"Result appended\\nto history\"]\n        H5{\"Iteration\\nlimit?\"}\n        H1 --\u003e H2 --\u003e H3 --\u003e H4 --\u003e H5\n        H5 --\u003e|No| H2\n        H5 --\u003e|Yes| H6[\"Return result\"]\n    end\n\n    User --\u003e EngineSelect\n    EngineSelect --\u003e|\"claude binary found\"| Claude\n    EngineSelect --\u003e|\"HF_TOKEN set\"| HF\n    Claude --\u003e Claude_Lifecycle\n    HF --\u003e HF_Lifecycle\n\n    C6 --\u003e Done[\"Review-ready PR\"]\n    H6 --\u003e Done\n```\n\n### Security Architecture\n\n```mermaid\nflowchart TB\n    LLM[\"LLM Agent\\n(Claude or DeepSeek/Qwen)\"]\n\n    subgraph Security_Layers[\"Defense-in-Depth Layers\"]\n        direction TB\n        L1[\"Command Denylist\\n39 dangerous commands blocked\"]\n        L2[\"Metacharacter Filter\\nShell injection chars blocked\"]\n        L3[\"shell=False\\nNo shell interpretation\"]\n        L4[\"Extension Allowlist\\n32 safe file types only\"]\n        L5[\"Path Validation\\nNull bytes, .., symlinks\"]\n        L6[\"Protected Paths\\nSecurity-critical files immutable\"]\n        L7[\"Size/Count Limits\\n1MB per file, 200 files per session\"]\n        L8[\"Security Scanner\\neval/exec/secrets detection\"]\n        L9[\"Audit Logging\\nAll operations logged\"]\n    end\n\n    LLM --\u003e L1 --\u003e L2 --\u003e L3\n    L3 --\u003e L4 --\u003e L5 --\u003e L6 --\u003e L7\n    L7 --\u003e L8 --\u003e L9\n    L9 --\u003e FS[\"Filesystem\\n(safe writes only)\"]\n```\n\n---\n\n## Security Findings Resolution\n\n```mermaid\npie title Security Findings Resolution (Spec-07 through Spec-14)\n    \"Resolved by Spec-07 (sandbox)\" : 16\n    \"Resolved by Spec-08 (reliability)\" : 2\n    \"Resolved by Spec-13 (bulletproof)\" : 42\n    \"Resolved by Spec-14 (hardening v2)\" : 20\n```\n\n### Spec-15 Parallel Execution Architecture\n\n```mermaid\nflowchart TB\n    CLI[\"codelicious /repo --parallel 4\"]\n    Engine[\"HuggingFaceEngine.run_build_cycle()\"]\n    PE[\"ParallelExecutor(max_workers=4)\"]\n\n    subgraph Workers[\"ThreadPoolExecutor\"]\n        W1[\"LoopWorker loop-001\\nspec: 01_feature_cli.md\"]\n        W2[\"LoopWorker loop-002\\nspec: 02_feature_agent.md\"]\n        W3[\"LoopWorker loop-003\\nspec: 03_feature_git.md\"]\n        W4[\"LoopWorker loop-004\\nspec: 04_feature_ext.md\"]\n    end\n\n    subgraph Shared[\"Shared Resources (Thread-Safe)\"]\n        LLM[\"LLMClient\\n(stateless)\"]\n        SB[\"Sandbox\\n(Lock)\"]\n        AL[\"AuditLogger\\n(Lock)\"]\n        CM[\"CacheManager\\n(Lock)\"]\n        SL[\"StructuredLogger\\n(Lock)\"]\n    end\n\n    subgraph PerLoop[\"Per-Loop Resources (No Sharing)\"]\n        TR[\"ToolRegistry\\n(per instance)\"]\n        MH[\"Message History\\n(per list)\"]\n    end\n\n    CLI --\u003e Engine --\u003e PE\n    PE --\u003e Workers\n    W1 \u0026 W2 \u0026 W3 \u0026 W4 --\u003e Shared\n    W1 \u0026 W2 \u0026 W3 \u0026 W4 --\u003e PerLoop\n    Workers --\u003e Result[\"BuildResult\\n(aggregated)\"]\n\n    style Shared fill:#228B22,color:#fff\n    style PerLoop fill:#4169E1,color:#fff\n```\n\n### Structured Logging Flow (Spec-15)\n\n```mermaid\nflowchart LR\n    subgraph Loops[\"Concurrent Agentic Loops\"]\n        L1[\"loop-001\"]\n        L2[\"loop-002\"]\n        L3[\"loop-003\"]\n        L4[\"loop-004\"]\n    end\n\n    SL[\"StructuredLogger\\n(thread-safe)\"]\n\n    subgraph Output[\"Dual Output Streams\"]\n        File[\"build.log\\nJSON Lines\\n(machine-readable)\"]\n        Term[\"Terminal\\n[loop-id] formatted\\n(human-readable)\"]\n    end\n\n    L1 \u0026 L2 \u0026 L3 \u0026 L4 --\u003e SL\n    SL --\u003e File\n    SL --\u003e Term\n```\n\n### Thread Safety Model (Spec-15)\n\n```mermaid\nflowchart TB\n    subgraph Global[\"Global Resources (Lock-Protected)\"]\n        direction LR\n        S1[\"Sandbox\\nFile count: global 200 limit\\nLock: full validate-write cycle\"]\n        S2[\"AuditLogger\\nLock: per file write\\naudit.log + security.log\"]\n        S3[\"CacheManager\\nLock: load-modify-flush\\ncache.json + state.json\"]\n        S4[\"StructuredLogger\\nLock: per JSON line write\\nbuild.log\"]\n    end\n\n    subgraph Stateless[\"Stateless (No Lock Needed)\"]\n        direction LR\n        S5[\"LLMClient\\nImmutable config after init\\nurllib creates new conn per call\"]\n    end\n\n    subgraph Isolated[\"Per-Loop Instances (No Sharing)\"]\n        direction LR\n        S6[\"ToolRegistry\\nOwn tool schema + dispatch\"]\n        S7[\"Message History\\nOwn list per loop\"]\n        S8[\"Iteration Counter\\nOwn int per loop\"]\n    end\n\n    style Global fill:#DAA520,color:#000\n    style Stateless fill:#228B22,color:#fff\n    style Isolated fill:#4169E1,color:#fff\n```\n\n### Spec-15 Throughput Scaling Projection\n\n```mermaid\nxychart-beta\n    title \"Estimated Tokens Per Second by Parallelism Level\"\n    x-axis [\"1 loop\", \"2 loops\", \"4 loops\", \"8 loops\"]\n    y-axis \"Tokens/Second (SambaNova via HF Router)\" 0 --\u003e 1800\n    bar [125, 250, 500, 1000]\n```\n\n### Spec-16 CI Quality Gate Pipeline\n\n```mermaid\nflowchart LR\n    A[Push / PR] --\u003e B[Lint\\nruff check]\n    B --\u003e C[Format\\nruff format]\n    C --\u003e D[Tests\\npytest]\n    D --\u003e E[Coverage\\n90% minimum]\n    E --\u003e F[Security\\nbandit]\n    F --\u003e G[Audit\\npip-audit]\n    G --\u003e H{All Pass?}\n    H --\u003e|Yes| I[Merge Ready]\n    H --\u003e|No| J[Block Merge]\n\n    style I fill:#228B22,color:#fff\n    style J fill:#DC143C,color:#fff\n```\n\n### Spec-16 Security Defense Layers\n\n```mermaid\nflowchart TB\n    subgraph L1[\"Layer 1: Input Validation\"]\n        A1[\"Command denylist\\n39 blocked commands\"]\n        A2[\"Shell metacharacter filter\\n12 blocked chars\"]\n        A3[\"Path traversal defense\\niterative decode + sandbox\"]\n    end\n\n    subgraph L2[\"Layer 2: Execution Safety\"]\n        B1[\"shell=False enforcement\"]\n        B2[\"Process group timeout\"]\n        B3[\"Prompt sanitization\"]\n    end\n\n    subgraph L3[\"Layer 3: Output Protection\"]\n        C1[\"File extension allowlist\"]\n        C2[\"File count/size limits\"]\n        C3[\"Atomic writes + symlink check\"]\n    end\n\n    subgraph L4[\"Layer 4: Audit and Detection\"]\n        D1[\"Security event logging\"]\n        D2[\"Credential sanitization\"]\n        D3[\"Secret pattern scanning\"]\n    end\n\n    L1 --\u003e L2 --\u003e L3 --\u003e L4\n\n    style L1 fill:#DAA520,color:#000\n    style L2 fill:#4169E1,color:#fff\n    style L3 fill:#228B22,color:#fff\n    style L4 fill:#8B008B,color:#fff\n```\n\n### Spec-16 Module Test Coverage Map\n\n```mermaid\nblock-beta\n    columns 5\n    sandbox[\"sandbox.py\\n50+ tests\"]:1\n    verifier[\"verifier.py\\n60+ tests\"]:1\n    executor[\"executor.py\\n45+ tests\"]:1\n    cmd_runner[\"command_runner\\n30+ tests\"]:1\n    parser[\"parser.py\\n31 tests\"]:1\n    context_mgr[\"context_mgr\\n35+ tests\"]:1\n    fs_tools[\"fs_tools.py\\n20+ tests\"]:1\n    security[\"security_audit\\n35+ tests\"]:1\n    llm_client[\"llm_client\\n17 tests\"]:1\n    cache[\"cache_engine\\n16 tests\"]:1\n    cli[\"cli.py\\nNEW\"]:1\n    agent_runner[\"agent_runner\\nNEW\"]:1\n    planner[\"planner.py\\nNEW\"]:1\n    config[\"config.py\\nNEW\"]:1\n    budget[\"budget_guard\\nNEW\"]:1\n\n    style sandbox fill:#228B22,color:#fff\n    style verifier fill:#228B22,color:#fff\n    style executor fill:#228B22,color:#fff\n    style cmd_runner fill:#228B22,color:#fff\n    style parser fill:#228B22,color:#fff\n    style context_mgr fill:#228B22,color:#fff\n    style fs_tools fill:#228B22,color:#fff\n    style security fill:#228B22,color:#fff\n    style llm_client fill:#228B22,color:#fff\n    style cache fill:#228B22,color:#fff\n    style cli fill:#4169E1,color:#fff\n    style agent_runner fill:#4169E1,color:#fff\n    style planner fill:#4169E1,color:#fff\n    style config fill:#4169E1,color:#fff\n    style budget fill:#4169E1,color:#fff\n```\n\nGreen = existing coverage, Blue = new in spec-16\n\n### Spec-17 Security Finding Resolution Flow\n\n```mermaid\nflowchart TB\n    subgraph P1[\"P1 Critical (6 Findings)\"]\n        P14[\"P1-4: File count race\"]\n        P15[\"P1-5: Overwrite count bug\"]\n        P16[\"P1-6: Symlink TOCTOU\"]\n        P18[\"P1-8: Silent exception\"]\n        P19[\"P1-9: JSON deser DoS\"]\n        P111[\"P1-11: Prompt injection\"]\n    end\n\n    subgraph P2[\"P2 Important (11 Findings)\"]\n        P25[\"P2-5: Dir listing DoS\"]\n        P26[\"P2-6: mkdir race\"]\n        P27[\"P2-7: Silent chmod\"]\n        P28[\"P2-8: Verifier injection\"]\n        P29[\"P2-9: Secret detection gaps\"]\n        P210[\"P2-10: Timeout overrun\"]\n        P211[\"P2-11: Regex backtrack\"]\n        P212[\"P2-12: Log file perms\"]\n        P213[\"P2-13: Incomplete redaction\"]\n        P2N1[\"P2-NEW-1: Git push timeout\"]\n        P2N2[\"P2-NEW-2: Verifier proc group\"]\n    end\n\n    subgraph Phases[\"Implementation Phases\"]\n        Ph1[\"Phase 1: cli.py\"]\n        Ph2[\"Phase 2: sandbox count\"]\n        Ph3[\"Phase 3: sandbox symlink\"]\n        Ph4[\"Phase 4: JSON limits\"]\n        Ph5[\"Phase 5: prompt sanitize\"]\n        Ph6[\"Phase 6: dir limits\"]\n        Ph7[\"Phase 7: race fixes\"]\n        Ph8[\"Phase 8: verifier + git\"]\n        Ph9[\"Phase 9: credentials\"]\n        Ph10[\"Phase 10: regex fix\"]\n        Ph11[\"Phase 11: timeout fix\"]\n    end\n\n    P18 --\u003e Ph1\n    P14 --\u003e Ph2\n    P15 --\u003e Ph2\n    P16 --\u003e Ph3\n    P19 --\u003e Ph4\n    P111 --\u003e Ph5\n    P25 --\u003e Ph6\n    P26 --\u003e Ph7\n    P27 --\u003e Ph7\n    P212 --\u003e Ph7\n    P28 --\u003e Ph8\n    P2N1 --\u003e Ph8\n    P2N2 --\u003e Ph8\n    P29 --\u003e Ph9\n    P213 --\u003e Ph9\n    P211 --\u003e Ph10\n    P210 --\u003e Ph11\n\n    Ph1 \u0026 Ph2 \u0026 Ph3 \u0026 Ph4 \u0026 Ph5 \u0026 Ph6 \u0026 Ph7 \u0026 Ph8 \u0026 Ph9 \u0026 Ph10 \u0026 Ph11 --\u003e ZeroFindings[\"Zero Open Findings\"]\n\n    style P1 fill:#DC143C,color:#fff\n    style P2 fill:#DAA520,color:#000\n    style ZeroFindings fill:#228B22,color:#fff\n```\n\n### Spec-17 Atomic File Write Sequence (Post-Fix)\n\n```mermaid\nsequenceDiagram\n    participant Thread as Worker Thread\n    participant Lock as Sandbox Lock\n    participant Set as Written Paths Set\n    participant Counter as File Counter\n    participant FS as Filesystem\n    participant Check as Post-Write Check\n\n    Thread-\u003e\u003eLock: acquire()\n    Lock--\u003e\u003eThread: granted\n\n    Thread-\u003e\u003eSet: path in _written_paths?\n    alt New file\n        Set--\u003e\u003eThread: No (new file)\n        Thread-\u003e\u003eCounter: count \u003c max_files?\n        alt Under limit\n            Counter--\u003e\u003eThread: Yes\n            Counter-\u003e\u003eCounter: increment\n            Set-\u003e\u003eSet: add(path)\n            Thread-\u003e\u003eFS: tempfile.write(content)\n            Thread-\u003e\u003eFS: os.replace(temp, target)\n            alt Write fails\n                FS--\u003e\u003eThread: OSError\n                Counter-\u003e\u003eCounter: decrement\n                Set-\u003e\u003eSet: remove(path)\n                Thread-\u003e\u003eLock: release()\n                Thread--\u003e\u003eThread: raise FileWriteError\n            else Write succeeds\n                FS--\u003e\u003eThread: OK\n                Thread-\u003e\u003eCheck: os.lstat(target)\n                alt Symlink detected\n                    Check--\u003e\u003eThread: is_symlink=True\n                    Thread-\u003e\u003eFS: os.unlink(target)\n                    Counter-\u003e\u003eCounter: decrement\n                    Set-\u003e\u003eSet: remove(path)\n                    Thread-\u003e\u003eLock: release()\n                    Thread--\u003e\u003eThread: raise SandboxViolationError\n                else Normal file\n                    Check--\u003e\u003eThread: is_symlink=False\n                    Thread-\u003e\u003eLock: release()\n                    Thread--\u003e\u003eThread: return success\n                end\n            end\n        else Over limit\n            Counter--\u003e\u003eThread: No (at max)\n            Thread-\u003e\u003eLock: release()\n            Thread--\u003e\u003eThread: raise FileCountLimitError\n        end\n    else Existing file (overwrite)\n        Set--\u003e\u003eThread: Yes (overwrite)\n        Thread-\u003e\u003eFS: tempfile.write(content)\n        Thread-\u003e\u003eFS: os.replace(temp, target)\n        Thread-\u003e\u003eCheck: os.lstat(target)\n        Check--\u003e\u003eThread: is_symlink=False\n        Thread-\u003e\u003eLock: release()\n        Thread--\u003e\u003eThread: return success\n    end\n```\n\n### Spec-17 Credential Redaction Coverage\n\n```mermaid\nflowchart LR\n    subgraph Existing[\"Existing Patterns (Pre-Spec-17)\"]\n        E1[\"OpenAI (sk-)\"]\n        E2[\"GitHub (ghp_, gho_, ghu_, ghs_, ghr_)\"]\n        E3[\"AWS (AKIA, ABIA, ACCA, ASIA)\"]\n        E4[\"Anthropic (sk-ant-)\"]\n        E5[\"JWT (eyJ...)\"]\n        E6[\"Database URLs\"]\n        E7[\"Bearer tokens\"]\n        E8[\"Azure credentials\"]\n        E9[\"GCP service accounts\"]\n        E10[\"HuggingFace (hf_)\"]\n    end\n\n    subgraph New[\"New Patterns (Spec-17 Phase 9)\"]\n        N1[\"SSH Private Keys\"]\n        N2[\"NPM Tokens (npm_)\"]\n        N3[\"Slack (xoxb-, xoxp-, xoxs-, xoxa-)\"]\n        N4[\"Stripe (sk_live_, pk_live_, rk_live_)\"]\n        N5[\"Twilio (AC, SK + 32 hex)\"]\n        N6[\"Webhook URLs with tokens\"]\n    end\n\n    Existing --\u003e Redactor[\"sanitize_message()\"]\n    New --\u003e Redactor\n    Redactor --\u003e Safe[\"Safe Log Output\\n(all credentials replaced\\nwith REDACTED)\"]\n\n    style Existing fill:#228B22,color:#fff\n    style New fill:#4169E1,color:#fff\n    style Safe fill:#228B22,color:#fff\n```\n\n### Spec-18 LLM API Retry Flow\n\n```mermaid\nflowchart TB\n    Call[\"LLM API Call\"]\n    Check{\"Response\\nStatus?\"}\n    Success[\"Return Result\"]\n    Transient{\"Transient?\\n429/500/502/503/504\\nURLError/Timeout\"}\n    Fatal[\"Raise Immediately\\n401/403/ValueError\"]\n    Retry{\"Retries\\nRemaining?\"}\n    Backoff[\"Sleep: base * 2^attempt + jitter\"]\n    Fail[\"Raise After Retries\\nInclude retry count\"]\n\n    Call --\u003e Check\n    Check --\u003e|200 OK| Success\n    Check --\u003e|Error| Transient\n    Transient --\u003e|Yes| Retry\n    Transient --\u003e|No| Fatal\n    Retry --\u003e|Yes| Backoff\n    Retry --\u003e|No| Fail\n    Backoff --\u003e Call\n\n    style Success fill:#228B22,color:#fff\n    style Fatal fill:#DC143C,color:#fff\n    style Fail fill:#DC143C,color:#fff\n    style Backoff fill:#DAA520,color:#000\n```\n\n### Spec-18 Startup Validation Flow\n\n```mermaid\nflowchart TB\n    Start[\"codelicious /path/to/repo\"]\n    Git{\"git on PATH?\"}\n    GitErr[\"Error: git not found\\nexit 1\"]\n    Engine{\"Engine\\nSelection?\"}\n    Claude{\"claude on PATH?\"}\n    ClaudeErr[\"Error: claude not found\\nexit 1\"]\n    HF{\"HF_TOKEN set?\"}\n    HFErr[\"Error: HF_TOKEN required\\nexit 1\"]\n    HTTPS{\"Endpoint HTTPS?\"}\n    HTTPSErr[\"Error: HTTPS required\\nexit 1\"]\n    Ready[\"Dependencies Validated\\nStart Build\"]\n\n    Start --\u003e Git\n    Git --\u003e|No| GitErr\n    Git --\u003e|Yes| Engine\n    Engine --\u003e|claude| Claude\n    Engine --\u003e|huggingface| HF\n    Engine --\u003e|auto| Claude\n    Claude --\u003e|Yes| Ready\n    Claude --\u003e|No, explicit| ClaudeErr\n    Claude --\u003e|No, auto| HF\n    HF --\u003e|Yes| HTTPS\n    HF --\u003e|No| HFErr\n    HTTPS --\u003e|Yes| Ready\n    HTTPS --\u003e|No| HTTPSErr\n\n    style Ready fill:#228B22,color:#fff\n    style GitErr fill:#DC143C,color:#fff\n    style ClaudeErr fill:#DC143C,color:#fff\n    style HFErr fill:#DC143C,color:#fff\n    style HTTPSErr fill:#DC143C,color:#fff\n```\n\n### Spec-18 Graceful Shutdown Sequence\n\n```mermaid\nsequenceDiagram\n    participant OS as Orchestrator (Docker/K8s)\n    participant CLI as cli.py (main)\n    participant Handler as SIGTERM Handler\n    participant Progress as ProgressReporter\n    participant RAG as RagEngine\n    participant Exit as atexit hooks\n\n    OS-\u003e\u003eCLI: SIGTERM (signal 15)\n    CLI-\u003e\u003eHandler: _handle_sigterm()\n    Handler-\u003e\u003eHandler: Set _shutdown_requested = True\n    Handler-\u003e\u003eHandler: Log WARNING \"Received SIGTERM\"\n    Handler-\u003e\u003eCLI: Raise SystemExit(143)\n    CLI-\u003e\u003eExit: atexit hooks triggered\n    Exit-\u003e\u003eProgress: close()\n    Progress-\u003e\u003eProgress: Flush progress file\n    Progress-\u003e\u003eProgress: Set _closed = True\n    Exit-\u003e\u003eRAG: close()\n    RAG-\u003e\u003eRAG: Flush SQLite WAL\n    RAG-\u003e\u003eRAG: Close connection\n    RAG-\u003e\u003eRAG: Set _closed = True\n    Exit-\u003e\u003eOS: Exit code 143\n```\n\n### Spec-18 Cumulative Build Timeout Enforcement\n\n```mermaid\nflowchart LR\n    Start[\"Build Start\\ndeadline = now + max_build_time\"]\n    P1[\"Phase: Scaffold\"]\n    P2[\"Phase: Build\"]\n    P3[\"Phase: Verify (1)\"]\n    P4[\"Phase: Verify (2)\"]\n    P5[\"Phase: Verify (3)\"]\n    P6[\"Phase: Reflect\"]\n    P7[\"Phase: Commit\"]\n    Check1{\"now \u003e\\ndeadline?\"}\n    Check2{\"now \u003e\\ndeadline?\"}\n    Check3{\"now \u003e\\ndeadline?\"}\n    Timeout[\"BuildTimeoutError\\nReport elapsed time\\nand current phase\"]\n    Done[\"Build Complete\"]\n\n    Start --\u003e P1 --\u003e P2 --\u003e Check1\n    Check1 --\u003e|No| P3 --\u003e Check2\n    Check1 --\u003e|Yes| Timeout\n    Check2 --\u003e|No| P4 --\u003e Check3\n    Check2 --\u003e|Yes| Timeout\n    Check3 --\u003e|No| P5 --\u003e P6 --\u003e P7 --\u003e Done\n    Check3 --\u003e|Yes| Timeout\n\n    style Done fill:#228B22,color:#fff\n    style Timeout fill:#DC143C,color:#fff\n```\n\n### Spec-18 Plan Validation Pipeline\n\n```mermaid\nflowchart TB\n    LLM[\"LLM Generates Plan JSON\"]\n    Parse[\"json.loads()\"]\n    Schema[\"Schema Validation\\n- Is dict?\\n- Has 'tasks' list?\\n- Each task has title, description?\"]\n    Cycle[\"Cycle Detection\\n- Build adjacency graph\\n- DFS with gray/black sets\\n- Report cycle path\"]\n    Valid[\"Valid Plan\\nProceed to execution\"]\n    Invalid[\"InvalidPlanError\\nSpecific message\\n(missing key, cycle path)\"]\n\n    LLM --\u003e Parse --\u003e Schema\n    Schema --\u003e|Pass| Cycle\n    Schema --\u003e|Fail| Invalid\n    Cycle --\u003e|No cycles| Valid\n    Cycle --\u003e|Cycle found| Invalid\n\n    style Valid fill:#228B22,color:#fff\n    style Invalid fill:#DC143C,color:#fff\n```\n\n### Spec-19 Code Quality Improvement Areas\n\n```mermaid\nflowchart TB\n    subgraph T1[\"Tier 1: Foundation (Sequential)\"]\n        P1[\"Phase 1\\nConfig Constants\\nEnv Var Overrides\"]\n        P2[\"Phase 2\\nError Message\\nQuality\"]\n        P3[\"Phase 3\\nResource Cleanup\\nFile Handle Leaks\"]\n        P4[\"Phase 4\\nEdge Case\\nClosure\"]\n        P1 --\u003e P2 --\u003e P3 --\u003e P4\n    end\n\n    subgraph T2[\"Tier 2: Docs and Testing (Parallel)\"]\n        P5[\"Phase 5\\nREADME-CLI\\nAccuracy\"]\n        P6[\"Phase 6\\nTest Fixture\\nExpansion\"]\n        P7[\"Phase 7\\nDependency\\nPinning\"]\n        P8[\"Phase 8\\nCI Workflow\\nHardening\"]\n    end\n\n    subgraph T3[\"Tier 3: Code Quality (Parallel)\"]\n        P9[\"Phase 9\\nShared Utility\\nExtraction\"]\n        P10[\"Phase 10\\nType Safety\\nHints\"]\n        P11[\"Phase 11\\nPrompt Template\\nSafety\"]\n        P12[\"Phase 12\\nDry-Run\\nPurity\"]\n    end\n\n    subgraph T4[\"Tier 4: Hardening (Sequential)\"]\n        P13[\"Phase 13\\nConfig Validation\\nat Startup\"]\n        P14[\"Phase 14\\nLogger Permission\\nFixes\"]\n        P15[\"Phase 15\\nError Handling\\nConsistency\"]\n        P13 --\u003e P14 --\u003e P15\n    end\n\n    T1 --\u003e T2\n    T1 --\u003e T3\n    T2 --\u003e T4\n    T3 --\u003e T4\n    T4 --\u003e Done[\"47 Gaps Closed\\n650+ Tests\\nZero Quality Findings\"]\n\n    style T1 fill:#4169E1,color:#fff\n    style T2 fill:#228B22,color:#fff\n    style T3 fill:#DAA520,color:#000\n    style T4 fill:#8B008B,color:#fff\n    style Done fill:#228B22,color:#fff\n```\n\n### Spec-19 Finding Distribution by Category\n\n```mermaid\npie title Code Quality Findings by Category (47 Total)\n    \"Configuration Hardening\" : 4\n    \"Error Messages\" : 5\n    \"Resource Cleanup\" : 3\n    \"Edge Cases\" : 4\n    \"Documentation Drift\" : 6\n    \"Test Fixtures\" : 4\n    \"Dependency Pinning\" : 4\n    \"CI Workflow\" : 5\n    \"Code Duplication\" : 3\n    \"Type Safety\" : 5\n    \"Template Safety\" : 2\n    \"Dry-Run Purity\" : 3\n    \"Config Validation\" : 3\n    \"Logger Fixes\" : 2\n    \"Error Handling\" : 3\n```\n\n### Spec-19 Configuration Override Flow\n\n```mermaid\nflowchart LR\n    Env[\"Environment Variable\\nCODELICIOUS_TIMEOUT_TEST=120\"]\n    Parse[\"_env.parse_env_int()\\nValidate: \u003e 0\\nLog: DEBUG override active\"]\n    Default[\"Hardcoded Default\\n_TIMEOUT_TEST = 60\"]\n    Module[\"verifier.py\\nUses effective value\"]\n\n    Env --\u003e|Set and valid| Parse --\u003e Module\n    Env --\u003e|Not set| Default --\u003e Module\n    Env --\u003e|Invalid value| Parse\n    Parse --\u003e|\"WARNING: invalid, using default\"| Default\n\n    style Env fill:#4169E1,color:#fff\n    style Default fill:#DAA520,color:#000\n    style Module fill:#228B22,color:#fff\n```\n\n### Spec-19 Dry-Run Fix: Before and After\n\n```mermaid\nsequenceDiagram\n    participant User as User\n    participant CLI as cli.py\n    participant SB as Sandbox (dry_run=True)\n    participant FS as Filesystem\n\n    Note over User,FS: BEFORE (Bug): mkdir runs even in dry-run\n    User-\u003e\u003eCLI: codelicious /repo --dry-run\n    CLI-\u003e\u003eSB: write_file(\"src/app.py\", content)\n    SB-\u003e\u003eFS: parent.mkdir(parents=True)\n    Note right of FS: Directory created (BUG)\n    SB-\u003e\u003eSB: if self.dry_run: return\n    SB--\u003e\u003eCLI: (returned early but dir exists)\n\n    Note over User,FS: AFTER (Fixed): no filesystem changes\n    User-\u003e\u003eCLI: codelicious /repo --dry-run\n    CLI-\u003e\u003eSB: write_file(\"src/app.py\", content)\n    SB-\u003e\u003eSB: if self.dry_run: log and return\n    Note right of SB: No mkdir, no temp file, no writes\n    SB--\u003e\u003eCLI: (returned early, FS untouched)\n```\n\n### Spec-19 Logic Breakdown Progression\n\n```mermaid\nxychart-beta\n    title \"Codebase Composition by Spec Phase (Estimated Lines)\"\n    x-axis [\"Post-16\", \"Post-17\", \"Post-18\", \"Post-19\"]\n    y-axis \"Source Lines\" 0 --\u003e 10000\n    bar [3800, 3900, 4100, 4200]\n    bar [4050, 3600, 3600, 3600]\n    bar [1350, 1300, 1500, 1600]\n```\n\n### Spec-20 Security Finding Resolution Flow\n\n```mermaid\nflowchart TB\n    subgraph P1[\"S20-P1 Critical (5 Findings)\"]\n        S1[\"S20-P1-1\\nSSRF via\\nLLM endpoint\"]\n        S2[\"S20-P1-2\\ngit add .\\nstages secrets\"]\n        S3[\"S20-P1-3\\n--dangerously-\\nskip-permissions\"]\n        S4[\"S20-P1-4\\nPrompt injection\\nvia spec_filter\"]\n        S5[\"S20-P1-5\\nSQLite DB\\nworld-readable\"]\n    end\n\n    subgraph P2[\"S20-P2 Important (11 Findings)\"]\n        S6[\"S20-P2-1: Newline filename\"]\n        S7[\"S20-P2-2: os.walk escape\"]\n        S8[\"S20-P2-3: Denylist bypass\"]\n        S9[\"S20-P2-4: No backoff\"]\n        S10[\"S20-P2-5: BudgetGuard race\"]\n        S11[\"S20-P2-6: retry_after ignored\"]\n        S12[\"S20-P2-7: Duplicate check\"]\n        S13[\"S20-P2-8: String tracker\"]\n        S14[\"S20-P2-9: Symlink rmtree\"]\n        S15[\"S20-P2-10: atomic_write\"]\n        S16[\"S20-P2-11: Audit log race\"]\n    end\n\n    subgraph Phases[\"Implementation Phases\"]\n        Ph1[\"Phase 1: SSRF\"]\n        Ph2[\"Phase 2: Git staging\"]\n        Ph3[\"Phase 3: CLI perms\"]\n        Ph4[\"Phase 4: Prompt sanitize\"]\n        Ph5[\"Phase 5: SQLite perms\"]\n        Ph6[\"Phase 6-12: P2 fixes\"]\n        Ph7[\"Phase 13-18: P3 fixes\"]\n    end\n\n    S1 --\u003e Ph1\n    S2 --\u003e Ph2\n    S3 --\u003e Ph3\n    S4 --\u003e Ph4\n    S5 --\u003e Ph5\n    S6 \u0026 S7 \u0026 S8 \u0026 S9 \u0026 S10 \u0026 S11 \u0026 S12 \u0026 S13 \u0026 S14 \u0026 S15 \u0026 S16 --\u003e Ph6\n    Ph1 \u0026 Ph2 \u0026 Ph3 \u0026 Ph4 \u0026 Ph5 \u0026 Ph6 \u0026 Ph7 --\u003e Zero[\"Zero S20 Findings\\n720+ Tests\"]\n\n    style P1 fill:#DC143C,color:#fff\n    style P2 fill:#DAA520,color:#000\n    style Zero fill:#228B22,color:#fff\n```\n\n### Spec-20 Git Staging Safety (Before and After)\n\n```mermaid\nsequenceDiagram\n    participant Dev as Developer\n    participant GO as GitOrchestrator\n    participant Git as git CLI\n    participant Check as Sensitive File Check\n\n    Note over Dev,Check: BEFORE (Unsafe): git add . with warning-only guard\n    Dev-\u003e\u003eGO: commit_verified_changes(files=None)\n    GO-\u003e\u003eGit: git add .\n    Git--\u003e\u003eGO: staged everything (including .env)\n    GO-\u003e\u003eCheck: _check_staged_files()\n    Check--\u003e\u003eGO: WARNING: .env detected\n    Note right of GO: Warning logged but commit proceeds\n    GO-\u003e\u003eGit: git commit -m \"...\"\n    Git--\u003e\u003eGO: committed (with secrets)\n\n    Note over Dev,Check: AFTER (Safe): explicit staging with hard abort\n    Dev-\u003e\u003eGO: commit_verified_changes(files=None)\n    GO-\u003e\u003eGit: git add -u\n    Git--\u003e\u003eGO: staged tracked files only\n    GO-\u003e\u003eCheck: _check_staged_files()\n    Check--\u003e\u003eGO: ERROR: .env detected\n    Note right of GO: GitOperationError raised, commit aborted\n    GO--\u003e\u003eDev: Error: Refusing to commit sensitive file\n```\n\n### Spec-20 LLM Endpoint Validation Pipeline\n\n```mermaid\nflowchart TB\n    Input[\"LLM_ENDPOINT env var\"]\n    Parse[\"urllib.parse.urlparse()\"]\n    Scheme{\"Scheme\\n== https?\"}\n    SchemeErr[\"ConfigurationError:\\nOnly HTTPS permitted\"]\n    DNS[\"socket.getaddrinfo()\\nResolve hostname\"]\n    DNSErr[\"ConfigurationError:\\nCannot resolve hostname\"]\n    IP[\"ipaddress.ip_address()\"]\n    Private{\"is_private?\\nis_loopback?\\nis_link_local?\"}\n    PrivateErr[\"ConfigurationError:\\nPrivate/loopback IP rejected\"]\n    Accept[\"Validated endpoint URL\\nStored in LLMClient\"]\n\n    Input --\u003e Parse --\u003e Scheme\n    Scheme --\u003e|No| SchemeErr\n    Scheme --\u003e|Yes| DNS\n    DNS --\u003e|Fail| DNSErr\n    DNS --\u003e|OK| IP --\u003e Private\n    Private --\u003e|Yes| PrivateErr\n    Private --\u003e|No| Accept\n\n    style Accept fill:#228B22,color:#fff\n    style SchemeErr fill:#DC143C,color:#fff\n    style DNSErr fill:#DC143C,color:#fff\n    style PrivateErr fill:#DC143C,color:#fff\n```\n\n### Spec-20 Thread Safety Model (Updated)\n\n```mermaid\nflowchart TB\n    subgraph Global[\"Global Resources (Lock-Protected)\"]\n        direction LR\n        S1[\"Sandbox\\nFile count: global 200 limit\\nLock: full validate-write cycle\"]\n        S2[\"AuditLogger\\nLock: per file write\\naudit.log + security.log\"]\n        S3[\"CacheManager\\nLock: load-modify-flush\\ncache.json + state.json\"]\n        S4[\"StructuredLogger\\nLock: per JSON line write\\nbuild.log\"]\n        S5[\"BudgetGuard\\nLock: record() + check()\\ncalls + cost counters\"]\n    end\n\n    subgraph Stateless[\"Stateless (No Lock Needed)\"]\n        direction LR\n        S6[\"LLMClient\\nImmutable config after init\\nEndpoint validated at construction\"]\n    end\n\n    subgraph Isolated[\"Per-Loop Instances (No Sharing)\"]\n        direction LR\n        S7[\"ToolRegistry\\nOwn tool schema + dispatch\"]\n        S8[\"Message History\\nOwn list per loop\"]\n        S9[\"Iteration Counter\\nOwn int per loop\"]\n    end\n\n    style Global fill:#DAA520,color:#000\n    style Stateless fill:#228B22,color:#fff\n    style Isolated fill:#4169E1,color:#fff\n```\n\n### Spec-20 Credential Redaction Pipeline (Updated)\n\n```mermaid\nflowchart LR\n    subgraph Stage1[\"Stage 1: Individual Sanitization\"]\n        Msg[\"record.msg\"]\n        Args[\"record.args\"]\n        SanMsg[\"sanitize_message(msg)\"]\n        SanArgs[\"sanitize_message(str(arg))\"]\n        Msg --\u003e SanMsg\n        Args --\u003e SanArgs\n    end\n\n    subgraph Stage2[\"Stage 2: Formatted Message Sanitization\"]\n        Format[\"record.getMessage()\\nmsg % args\"]\n        SanFinal[\"sanitize_message(formatted)\"]\n        Format --\u003e SanFinal\n    end\n\n    subgraph Output[\"Safe Output\"]\n        Final[\"record.msg = sanitized\\nrecord.args = None\\nAll secrets REDACTED\"]\n    end\n\n    Stage1 --\u003e Stage2 --\u003e Output\n\n    style Stage1 fill:#4169E1,color:#fff\n    style Stage2 fill:#DAA520,color:#000\n    style Output fill:#228B22,color:#fff\n```\n\n### Spec-20 Codebase Composition Progression\n\n```mermaid\nxychart-beta\n    title \"Codebase Composition by Spec Phase (Estimated Lines)\"\n    x-axis [\"Post-16\", \"Post-17\", \"Post-18\", \"Post-19\", \"Post-20\"]\n    y-axis \"Source Lines\" 0 --\u003e 10000\n    bar [3800, 3900, 4100, 4200, 4500]\n    bar [4050, 3600, 3600, 3600, 3600]\n    bar [1350, 1300, 1500, 1600, 1500]\n```\n\n### Spec-21 Coverage Gap Analysis\n\n```mermaid\nflowchart TB\n    subgraph Zero[\"0% Coverage (No Tests)\"]\n        Z1[\"budget_guard.py\\n134 lines\"]\n        Z2[\"config.py\\n455 lines\"]\n        Z3[\"orchestrator.py\\n709 lines\"]\n        Z4[\"huggingface_engine.py\\n166 lines\"]\n        Z5[\"__main__.py\\n9 lines\"]\n    end\n\n    subgraph Low[\"Below 50% Coverage\"]\n        L1[\"engines/__init__.py\\n30%\"]\n        L2[\"planner.py\\n29%\"]\n        L3[\"registry.py\\n33%\"]\n        L4[\"claude_engine.py\\n34%\"]\n        L5[\"git_orchestrator.py\\n36%\"]\n        L6[\"logger.py\\n39%\"]\n        L7[\"prompts.py\\n47%\"]\n        L8[\"loop_controller.py\\n50%\"]\n    end\n\n    subgraph Good[\"Above 80% Coverage\"]\n        G1[\"sandbox.py 91%\"]\n        G2[\"executor.py 96%\"]\n        G3[\"command_runner.py 97%\"]\n        G4[\"context_manager.py 95%\"]\n        G5[\"cli.py 94%\"]\n        G6[\"parser.py 93%\"]\n        G7[\"llm_client.py 93%\"]\n        G8[\"scaffolder.py 92%\"]\n    end\n\n    Zero --\u003e|\"Spec-21 Target: 80%+\"| Good\n    Low --\u003e|\"Spec-21 Target: 60%+\"| Good\n\n    style Zero fill:#DC143C,color:#fff\n    style Low fill:#DAA520,color:#000\n    style Good fill:#228B22,color:#fff\n```\n\n### Spec-21 Deterministic vs Probabilistic Logic\n\n```mermaid\npie title Codebase Logic Distribution (9,842 lines)\n    \"Deterministic (56%): CLI, config, parser, sandbox, verifier, fs_tools, command_runner, git, logger, security, errors\" : 5500\n    \"Probabilistic (44%): executor, planner, llm_client, loop_controller, orchestrator, engines, agent_runner, rag, prompts\" : 4300\n```\n\n### Spec-21 Security Finding Closure\n\n```mermaid\nflowchart TB\n    subgraph Original[\"Original P2 (3 Open)\"]\n        O1[\"P2-12: Build logger\\nfile creation race\"]\n        O2[\"P2-NEW-1: Git push\\nmissing timeout\"]\n        O3[\"P2-NEW-2: Verifier\\nno process group\"]\n    end\n\n    subgraph REV1[\"REV-P1 (5 Open)\"]\n        R1[\"REV-P1-1: Assertions\\nin threaded code\"]\n        R2[\"REV-P1-2: Executor\\nReDoS\"]\n        R3[\"REV-P1-3: Sandbox\\nTOCTOU\"]\n        R4[\"REV-P1-4: JSON\\ndepth limits\"]\n        R5[\"REV-P1-5: Verifier\\nSIGKILL\"]\n    end\n\n    subgraph REV2[\"REV-P2 (5 Open)\"]\n        R6[\"REV-P2-1: Thread\\nlifecycle race\"]\n        R7[\"REV-P2-2: Dead code\\nCommandDeniedError\"]\n        R8[\"REV-P2-3: mkdir\\nsymlink\"]\n        R9[\"REV-P2-4: Secret\\npatterns\"]\n        R10[\"REV-P2-5: Timing\\nside-channel\"]\n    end\n\n    subgraph New[\"S21 New (3 P2)\"]\n        N1[\"S21-P2-1: Logger\\nReDoS\"]\n        N2[\"S21-P2-2: Backoff\\nclamping\"]\n        N3[\"S21-P2-3: Bare\\nBaseException\"]\n    end\n\n    Original --\u003e Closed[\"All Findings Closed\\n16 fixes across 22 phases\"]\n    REV1 --\u003e Closed\n    REV2 --\u003e Closed\n    New --\u003e Closed\n\n    style Original fill:#DAA520,color:#000\n    style REV1 fill:#DC143C,color:#fff\n    style REV2 fill:#DAA520,color:#000\n    style New fill:#4169E1,color:#fff\n    style Closed fill:#228B22,color:#fff\n```\n\n### Spec-21 Implementation Phase Dependencies\n\n```mermaid\nflowchart LR\n    subgraph Security[\"Security Fixes (Phases 1-11)\"]\n        P1[\"P1: Logger\\nfile race\"]\n        P2[\"P2: Git\\ntimeout\"]\n        P3[\"P3: Verifier\\nproc group\"]\n        P4[\"P4: Assert\\nreplacement\"]\n        P5[\"P5: Executor\\nReDoS\"]\n        P6[\"P6: Sandbox\\nTOCTOU\"]\n        P7[\"P7: JSON\\ndepth\"]\n        P8[\"P8: Verifier\\nSIGKILL\"]\n        P9[\"P9: REV-P2\\nclosure\"]\n        P10[\"P10: Logger\\nReDoS\"]\n        P11[\"P11: Backoff\\nclamp\"]\n    end\n\n    subgraph Coverage[\"Coverage Expansion (Phases 12-16)\"]\n        P12[\"P12: budget_guard\\n0% to 80%+\"]\n        P13[\"P13: config\\n0% to 80%+\"]\n        P14[\"P14: orchestrator\\n0% to 60%+\"]\n        P15[\"P15: hf_engine\\n0% to 70%+\"]\n        P16[\"P16: Low-coverage\\nmodules 60%+\"]\n    end\n\n    subgraph Docs[\"Documentation (Phases 17-22)\"]\n        P17[\"P17: README\\nnumber fixes\"]\n        P18[\"P18: CI\\npipeline\"]\n        P19[\"P19: Exception\\nhardening\"]\n        P20[\"P20: Test\\nfixtures\"]\n        P21[\"P21: STATE.md\\nupdate\"]\n        P22[\"P22: Mermaid\\ndiagrams\"]\n    end\n\n    Security --\u003e Coverage --\u003e Docs\n\n    style Security fill:#DC143C,color:#fff\n    style Coverage fill:#4169E1,color:#fff\n    style Docs fill:#228B22,color:#fff\n```\n\n### Spec-21 CI Quality Gate Pipeline (Updated)\n\n```mermaid\nflowchart LR\n    A[Push / PR] --\u003e B[Install\\npip install -e .[dev]]\n    B --\u003e B2[Verify Install\\nimport codelicious]\n    B2 --\u003e C[Lint\\nruff check]\n    C --\u003e D[Format\\nruff format]\n    D --\u003e E[Tests + Coverage\\npytest --cov-fail-under=75]\n    E --\u003e F[Security\\nbandit]\n    F --\u003e G[Audit\\npip-audit]\n    G --\u003e H{All Pass?}\n    H --\u003e|Yes| I[Merge Ready]\n    H --\u003e|No| J[Block Merge]\n\n    style I fill:#228B22,color:#fff\n    style J fill:#DC143C,color:#fff\n    style B2 fill:#4169E1,color:#fff\n```\n\n---\n\n### Spec-22 Spec-as-PR Lifecycle\n\n```mermaid\nflowchart TD\n    A[\"User runs: codelicious /path/to/repo --push-pr\"] --\u003e B[\"CLI parses args\"]\n    B --\u003e C[\"Engine selection: Claude or HuggingFace\"]\n    C --\u003e D[\"GitManager.assert_safe_branch with spec_id\"]\n    D --\u003e E{\"On forbidden branch?\"}\n    E --\u003e|Yes| F[\"Create/checkout codelicious/spec-N\"]\n    E --\u003e|No| G[\"Continue on current branch\"]\n    F --\u003e H[\"Scaffold: write CLAUDE.md + .claude/\"]\n    G --\u003e H\n    H --\u003e I[\"Build: spawn agent with spec prompt\"]\n    I --\u003e J[\"Verify: syntax + tests + security scan\"]\n    J --\u003e|Fail| K[\"Fix agent: re-run with error context\"]\n    K --\u003e J\n    J --\u003e|Pass| L[\"Commit: git add specific-files + commit\"]\n    L --\u003e M[\"Push: git push to spec branch\"]\n    M --\u003e N{\"Push succeeded?\"}\n    N --\u003e|No| O[\"Log error, skip PR\"]\n    N --\u003e|Yes| P[\"ensure_draft_pr_exists with spec_id\"]\n    P --\u003e Q{\"PR with spec-N prefix exists?\"}\n    Q --\u003e|Yes| R[\"Log: PR already exists, commits appended\"]\n    Q --\u003e|No| S[\"gh pr create --draft with spec-N title\"]\n    R --\u003e T{\"Verify passed?\"}\n    S --\u003e T\n    T --\u003e|Yes| U[\"transition_pr_to_review\"]\n    T --\u003e|No| V[\"PR stays as draft\"]\n\n    style F fill:#4169E1,color:#fff\n    style R fill:#228B22,color:#fff\n    style S fill:#DAA520,color:#000\n    style U fill:#228B22,color:#fff\n    style O fill:#DC143C,color:#fff\n```\n\n### Spec-22 Duplicate PR Prevention\n\n```mermaid\nflowchart LR\n    A[\"ensure_draft_pr_exists called\"] --\u003e B[\"gh pr list --state open --json\"]\n    B --\u003e C{\"Parse JSON response\"}\n    C --\u003e|Success| D{\"Any PR title starts\\nwith [spec-N]?\"}\n    C --\u003e|Failure| E[\"Log warning, return None\"]\n    D --\u003e|\"Found PR #X\"| F[\"Return PR number X\\n(commits auto-appended)\"]\n    D --\u003e|Not found| G[\"gh pr create --draft\\ntitle: [spec-N] summary\"]\n    G --\u003e H{\"Create succeeded?\"}\n    H --\u003e|Yes| I[\"Return new PR number\"]\n    H --\u003e|No| J[\"Log error, return None\"]\n\n    style F fill:#228B22,color:#fff\n    style I fill:#228B22,color:#fff\n    style E fill:#DC143C,color:#fff\n    style J fill:#DC143C,color:#fff\n```\n\n### Spec-22 Finding Resolution by Phase\n\n```mermaid\nflowchart TB\n    subgraph P1_Fixes[\"P1 Critical (4 Findings)\"]\n        F1[\"S22-P1-1\\nTypeError in\\nensure_draft_pr_exists\"]\n        F2[\"S22-P1-2\\nDuplicate PR\\ncreation\"]\n        F3[\"S22-P1-3\\nPush failure\\nsilently swallowed\"]\n        F4[\"S22-P1-4\\nbuild_logger\\ncleanup never runs\"]\n    end\n\n    subgraph P2_Fixes[\"P2 Important (20 Findings)\"]\n        G1[\"Thread safety\\naudit_logger\\nbudget_guard\\nprogress\"]\n        G2[\"Token budget\\nbypass in\\ncontext_manager\"]\n        G3[\"TOCTOU race\\nin parser\"]\n        G4[\"Denylist gaps\\ngit, java, go\\ncargo, dotnet\"]\n        G5[\"Agent prompt\\nstages secrets\\ncreates PRs\"]\n    end\n\n    subgraph Phases[\"Implementation Phases\"]\n        Ph1[\"Phase 1: Branch mapping\"]\n        Ph2[\"Phase 2: PR dedup\"]\n        Ph3[\"Phase 3: Prompt cleanup\"]\n        Ph4[\"Phase 4: Full lifecycle\"]\n        Ph5[\"Phase 5: Build logger\"]\n        Ph6[\"Phase 6: Thread safety\"]\n        Ph7[\"Phase 7: Budget + TOCTOU\"]\n        Ph8[\"Phase 8: Denylist + cache\"]\n        Ph9[\"Phase 9: Test coverage\"]\n        Ph10[\"Phase 10: Documentation\"]\n    end\n\n    F1 --\u003e Ph2\n    F2 --\u003e Ph2\n    F3 --\u003e Ph2\n    F4 --\u003e Ph5\n    G1 --\u003e Ph6\n    G2 --\u003e Ph7\n    G3 --\u003e Ph7\n    G4 --\u003e Ph8\n    G5 --\u003e Ph3\n\n    Ph1 \u0026 Ph2 \u0026 Ph3 \u0026 Ph4 \u0026 Ph5 \u0026 Ph6 \u0026 Ph7 \u0026 Ph8 \u0026 Ph9 \u0026 Ph10 --\u003e Zero[\"Zero Duplicate PRs\\nZero P1 Findings\\n760+ Tests\"]\n\n    style P1_Fixes fill:#DC143C,color:#fff\n    style P2_Fixes fill:#DAA520,color:#000\n    style Zero fill:#228B22,color:#fff\n```\n\n### Spec-22 Deterministic vs Probabilistic Logic\n\n```mermaid\npie title Codebase Logic Breakdown (9,893 lines)\n    \"Deterministic Safety Harness (56%)\" : 5500\n    \"Probabilistic LLM-Driven (44%)\" : 4400\n```\n\n---\n\n## Zero Dependencies\n\nThe core engine uses only Python standard library (`urllib`, `json`, `sqlite3`, `subprocess`). No pip packages required at runtime.\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclay-good%2Fcodelicious","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclay-good%2Fcodelicious","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclay-good%2Fcodelicious/lists"}