Spaces:
Running
Running
Merge main into huggingface, retain HF frontmatter
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .claude/skill-runs.json +8 -0
- .claude/skills/audit/SKILL.md +362 -0
- .claude/skills/brainstorm/SKILL.md +150 -0
- .claude/skills/doc-health/SKILL.md +159 -0
- .claude/skills/pipeline/SKILL.md +403 -0
- .claude/skills/pipeline/doc-auditor.md +145 -0
- .claude/skills/pipeline/doc-engineer.md +105 -0
- .claude/skills/pipeline/doc-reviewer.md +96 -0
- .claude/skills/pipeline/eval-day2.md +124 -0
- .claude/skills/pipeline/eval-hire.md +118 -0
- .claude/skills/pipeline/eval-stress.md +126 -0
- .claude/skills/pipeline/final_reviewer.md +210 -0
- .claude/skills/pipeline/flows/audit-flow.md +275 -0
- .claude/skills/pipeline/flows/doc-health-flow.md +207 -0
- .claude/skills/pipeline/flows/repo-eval-flow.md +233 -0
- .claude/skills/pipeline/flows/repo-health-flow.md +223 -0
- .claude/skills/pipeline/health-auditor.md +124 -0
- .claude/skills/pipeline/health-fortifier.md +112 -0
- .claude/skills/pipeline/health-hygienist.md +107 -0
- .claude/skills/pipeline/health-reviewer.md +111 -0
- .claude/skills/pipeline/implementer.md +194 -0
- .claude/skills/pipeline/pipeline-protocol.md +91 -0
- .claude/skills/pipeline/plan_reviewer.md +128 -0
- .claude/skills/pipeline/planner.md +234 -0
- .claude/skills/pipeline/reviewer.md +179 -0
- .claude/skills/repo-eval/SKILL.md +242 -0
- .claude/skills/repo-health/SKILL.md +175 -0
- .devcontainer/devcontainer.json +1 -1
- .github/dependabot.yml +13 -0
- .github/workflows/ci.yml +26 -6
- .github/workflows/dependabot-auto-merge.yml +30 -0
- .github/workflows/release.yml +65 -0
- .gitignore +31 -1
- .pre-commit-config.yaml +15 -0
- README.md +41 -26
- app.py +2 -11
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-0.md +82 -0
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-1.md +254 -0
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-2.md +302 -0
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-3.md +183 -0
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-4.md +206 -0
- docs/plans/2026-03-25-audit-streamlit-nba/Phase-5.md +174 -0
- docs/plans/2026-03-25-audit-streamlit-nba/README.md +37 -0
- docs/plans/2026-03-25-audit-streamlit-nba/doc-audit.md +106 -0
- docs/plans/2026-03-25-audit-streamlit-nba/eval.md +201 -0
- docs/plans/2026-03-25-audit-streamlit-nba/feedback.md +157 -0
- docs/plans/2026-03-25-audit-streamlit-nba/health-audit.md +142 -0
- docs/project-roadmap.md +82 -0
- pages/1_home_team.py +29 -32
- pages/2_play_game.py +32 -22
.claude/skill-runs.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"skill": "audit",
|
| 4 |
+
"date": "2026-03-25",
|
| 5 |
+
"plan": "2026-03-25-audit-streamlit-nba",
|
| 6 |
+
"audits": ["health", "eval", "docs"]
|
| 7 |
+
}
|
| 8 |
+
]
|
.claude/skills/audit/SKILL.md
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: audit
|
| 3 |
+
description: Run one or more codebase audits (evaluation, health, documentation) with parallel agent execution, producing intake docs for a single /pipeline run.
|
| 4 |
+
allowed-tools: Agent, Read, Write, Glob, Grep, Bash
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Audit
|
| 8 |
+
|
| 9 |
+
You coordinate one or more codebase audits. Ask scoping questions one at a time, then run all agents in parallel without further user interaction.
|
| 10 |
+
|
| 11 |
+
## Input
|
| 12 |
+
|
| 13 |
+
`$ARGUMENTS` is optional context — specific concerns, repo path, or which audits to run.
|
| 14 |
+
|
| 15 |
+
## Process
|
| 16 |
+
|
| 17 |
+
### Step 1: Select Audits
|
| 18 |
+
|
| 19 |
+
Ask the user which audits to run. **This is always the first and only question in the first message.**
|
| 20 |
+
|
| 21 |
+
```text
|
| 22 |
+
Which audits should I run?
|
| 23 |
+
|
| 24 |
+
A) All three (health + eval + docs)
|
| 25 |
+
B) Code evaluation — 12-pillar scoring across 3 lenses
|
| 26 |
+
C) Technical debt — audit across 4 vectors
|
| 27 |
+
D) Documentation — drift detection across 6 phases
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
If `$ARGUMENTS` already specifies which audits (e.g., "/audit all"), skip this question and proceed to Step 2.
|
| 31 |
+
|
| 32 |
+
Wait for the user's answer before continuing.
|
| 33 |
+
|
| 34 |
+
### Step 2: Ask Follow-Up Questions One at a Time
|
| 35 |
+
|
| 36 |
+
Based on which audits were selected, ask the relevant scoping questions **one per message**. Wait for each answer before asking the next.
|
| 37 |
+
|
| 38 |
+
**Start with the universal question, then ask audit-specific questions.**
|
| 39 |
+
|
| 40 |
+
**Universal (always ask first):**
|
| 41 |
+
|
| 42 |
+
1. Known pain points — gives all auditors a starting hypothesis instead of scanning cold.
|
| 43 |
+
|
| 44 |
+
```text
|
| 45 |
+
Are there parts of the codebase you already know are problematic?
|
| 46 |
+
Things that keep breaking, areas you dread touching, modules that slow down every PR.
|
| 47 |
+
|
| 48 |
+
A) Yes (tell me which areas and what's wrong)
|
| 49 |
+
B) No — scan everything with fresh eyes
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
**If eval selected (B or A):**
|
| 53 |
+
|
| 54 |
+
The code evaluation runs 3 evaluator agents in parallel, each scoring 4 pillars (12 total). The scores calibrate to the role level you select.
|
| 55 |
+
|
| 56 |
+
1. Role level — sets the scoring bar. A "Senior" evaluation expects production-hardened patterns; a "Junior" evaluation focuses on fundamentals.
|
| 57 |
+
|
| 58 |
+
```text
|
| 59 |
+
What role level should I evaluate this codebase against?
|
| 60 |
+
|
| 61 |
+
A) Junior Developer — fundamentals: readability, basic error handling, test presence
|
| 62 |
+
B) Mid-Level Developer — patterns: separation of concerns, consistent conventions, test coverage
|
| 63 |
+
C) Senior Developer — production: defensive coding, observability, performance awareness, type rigor
|
| 64 |
+
D) Staff+ / Principal — systems: architectural coherence, scalability, operational excellence
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
1. Focus areas — narrows what the evaluators pay extra attention to. They still score all 12 pillars regardless.
|
| 68 |
+
|
| 69 |
+
```text
|
| 70 |
+
Any specific concerns the evaluators should weight more heavily?
|
| 71 |
+
|
| 72 |
+
A) Performance — hot paths, algorithmic complexity, resource management
|
| 73 |
+
B) Security — input validation, auth patterns, secrets handling
|
| 74 |
+
C) Testing — coverage quality, test architecture, edge cases
|
| 75 |
+
D) Architecture — separation of concerns, modularity, coupling
|
| 76 |
+
E) Multiple (tell me which)
|
| 77 |
+
F) None — balanced evaluation across all pillars
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
1. Scope and exclusions — what to evaluate and what to skip.
|
| 81 |
+
|
| 82 |
+
```text
|
| 83 |
+
What should the evaluators look at?
|
| 84 |
+
|
| 85 |
+
A) Full repo, standard exclusions (vendor, generated, node_modules, __pycache__)
|
| 86 |
+
B) Full repo, no exclusions
|
| 87 |
+
C) Specific directories only (tell me which to include or exclude)
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
1. Pillar overrides — by default, the pipeline remediates until all 12 pillars hit 9/10. Some pillars (like Creativity) may not be improvable through code changes. Override lets you set a lower threshold or exclude a pillar from the remediation gate entirely.
|
| 91 |
+
|
| 92 |
+
The 12 pillars are:
|
| 93 |
+
- **Hire lens:** Problem-Solution Fit, Architecture, Code Quality, Creativity
|
| 94 |
+
- **Stress lens:** Pragmatism, Defensiveness, Performance, Type Rigor
|
| 95 |
+
- **Day 2 lens:** Test Value, Reproducibility, Git Hygiene, Onboarding
|
| 96 |
+
|
| 97 |
+
```text
|
| 98 |
+
Any pillars to accept below the default 9/10 threshold?
|
| 99 |
+
|
| 100 |
+
A) None — require 9/10 on all 12 pillars
|
| 101 |
+
B) Specific overrides (tell me which pillars and target scores, e.g., "Creativity: 7, Git Hygiene: accept")
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
**If health selected (C or A):**
|
| 105 |
+
|
| 106 |
+
The health audit scans for technical debt across 4 vectors: architectural, structural, operational, and code hygiene. Findings are prioritized by severity (CRITICAL > HIGH > MEDIUM > LOW). The pipeline remediates until all CRITICAL and HIGH findings are resolved.
|
| 107 |
+
|
| 108 |
+
1. Goal — determines which debt vectors the auditor emphasizes.
|
| 109 |
+
|
| 110 |
+
```text
|
| 111 |
+
What's the primary goal for this audit?
|
| 112 |
+
|
| 113 |
+
A) General health check — scan all 4 vectors equally
|
| 114 |
+
B) Production hardening — emphasize operational debt (error handling, timeouts, resource leaks, observability)
|
| 115 |
+
C) Onboarding prep — emphasize structural and hygiene debt (naming, dead code, documentation, test coverage)
|
| 116 |
+
D) Pre-release cleanup — focus on CRITICAL/HIGH items only, skip MEDIUM/LOW
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
1. Deployment target — changes what "operational debt" means. A Lambda function has different concerns than a long-running container.
|
| 120 |
+
|
| 121 |
+
```text
|
| 122 |
+
What's the deployment target?
|
| 123 |
+
|
| 124 |
+
A) Serverless (Lambda, Cloud Functions) — cold starts, execution limits, stateless constraints
|
| 125 |
+
B) Containers (ECS, Kubernetes, Docker) — resource management, health checks, graceful shutdown
|
| 126 |
+
C) Static hosting / SPA — build pipeline, CDN, client-side concerns
|
| 127 |
+
D) Monolith / traditional server — process management, connection pooling, memory leaks
|
| 128 |
+
E) Multiple (tell me which)
|
| 129 |
+
F) Not deployed yet / unsure
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
1. Scope and constraints — what to audit and what's off-limits, in one question.
|
| 133 |
+
|
| 134 |
+
```text
|
| 135 |
+
What should the health auditor cover, and is anything off-limits?
|
| 136 |
+
|
| 137 |
+
A) Full repo, no constraints
|
| 138 |
+
B) Full repo, but skip specific areas (tell me which — e.g., "don't touch the legacy auth module")
|
| 139 |
+
C) Specific directories only (tell me which)
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
1. Existing tooling — helps the fortifier (hardening phase) know what guardrails already exist so it doesn't duplicate work.
|
| 143 |
+
|
| 144 |
+
```text
|
| 145 |
+
What development tooling is already in place?
|
| 146 |
+
|
| 147 |
+
A) Full setup — linters, CI pipeline, pre-commit hooks, type checking
|
| 148 |
+
B) Partial (tell me what you have — e.g., "ESLint but no CI")
|
| 149 |
+
C) None — no linting, CI, or hooks configured
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
**If docs selected (D or A):**
|
| 153 |
+
|
| 154 |
+
The doc audit runs 6 detection phases: discovery, comparison (drift/gaps/stale), code examples, link integrity, config/environment, and structure. It compares documentation claims against actual code behavior.
|
| 155 |
+
|
| 156 |
+
1. Scope and constraints — what docs to audit and what's off-limits.
|
| 157 |
+
|
| 158 |
+
```text
|
| 159 |
+
What documentation should I audit, and is anything off-limits?
|
| 160 |
+
|
| 161 |
+
A) All docs, no constraints
|
| 162 |
+
B) All docs, but skip specific files (tell me which)
|
| 163 |
+
C) Specific directories only (tell me which)
|
| 164 |
+
D) README and API docs only
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
1. Language stack — determines which auto-generation tools are available (typedoc for TS, sphinx for Python, swagger for REST APIs).
|
| 168 |
+
|
| 169 |
+
```text
|
| 170 |
+
What's the primary language stack?
|
| 171 |
+
|
| 172 |
+
A) JS/TS — typedoc, swagger-jsdoc available
|
| 173 |
+
B) Python — sphinx, mkdocstrings available
|
| 174 |
+
C) Both
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
1. Prevention tooling — what automated checks to add so documentation drift becomes a CI failure instead of a periodic cleanup.
|
| 178 |
+
|
| 179 |
+
```text
|
| 180 |
+
What drift prevention tooling should I add after fixing the docs?
|
| 181 |
+
|
| 182 |
+
A) Markdown linting (markdownlint) + link checking (lychee) — catches formatting issues and broken links on every PR
|
| 183 |
+
B) Auto-generated API docs (typedoc/sphinx) — single source of truth lives in code, not prose
|
| 184 |
+
C) Both A and B
|
| 185 |
+
D) None — just fix the existing docs, no new tooling
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
### Step 3: Generate Plan Identifier
|
| 189 |
+
|
| 190 |
+
After all questions are answered, generate the directory name: `YYYY-MM-DD-audit-slug`
|
| 191 |
+
|
| 192 |
+
- Date: today's date
|
| 193 |
+
- Slug: short name for the repo (e.g., `audit-ragstack`, `audit-my-app`)
|
| 194 |
+
- Location: `docs/plans/YYYY-MM-DD-audit-slug/`
|
| 195 |
+
|
| 196 |
+
Create the directory.
|
| 197 |
+
|
| 198 |
+
### Step 4: Read Role Prompts
|
| 199 |
+
|
| 200 |
+
Before spawning agents, read all required role prompt files. Only read prompts for selected audits.
|
| 201 |
+
|
| 202 |
+
- **If health selected:** Read `skills/pipeline/health-auditor.md`
|
| 203 |
+
- **If eval selected:** Read `skills/pipeline/eval-hire.md`, `skills/pipeline/eval-stress.md`, `skills/pipeline/eval-day2.md`
|
| 204 |
+
- **If docs selected:** Read `skills/pipeline/doc-auditor.md`
|
| 205 |
+
|
| 206 |
+
### Step 5: Spawn All Agents in Parallel
|
| 207 |
+
|
| 208 |
+
All auditor/evaluator agents are read-only — they explore the codebase but don't modify it. Spawn all selected agents in a single parallel batch (up to 5 agents for "all"):
|
| 209 |
+
|
| 210 |
+
```text
|
| 211 |
+
+-------------------------------------------------------------------+
|
| 212 |
+
| PARALLEL AGENT SPAWN |
|
| 213 |
+
+-------------------------------------------------------------------+
|
| 214 |
+
| |
|
| 215 |
+
| health auditor ─┐ |
|
| 216 |
+
| eval hire ──────┤ |
|
| 217 |
+
| eval stress ────┤ all agents run simultaneously |
|
| 218 |
+
| eval day2 ──────┤ |
|
| 219 |
+
| doc auditor ────┘ |
|
| 220 |
+
| ↓ |
|
| 221 |
+
| orchestrator collects all responses, writes intake docs |
|
| 222 |
+
| |
|
| 223 |
+
+-------------------------------------------------------------------+
|
| 224 |
+
```
|
| 225 |
+
|
| 226 |
+
**Agent 1: Health Auditor** (if health selected)
|
| 227 |
+
|
| 228 |
+
```xml
|
| 229 |
+
<role_prompt>
|
| 230 |
+
[Contents of health-auditor.md]
|
| 231 |
+
</role_prompt>
|
| 232 |
+
|
| 233 |
+
<task>
|
| 234 |
+
Audit the codebase in the current working directory.
|
| 235 |
+
Goal: [from Step 2]
|
| 236 |
+
Scope: [from Step 2]
|
| 237 |
+
Existing tooling: [from Step 2]
|
| 238 |
+
Constraints: [from Step 2]
|
| 239 |
+
</task>
|
| 240 |
+
```
|
| 241 |
+
|
| 242 |
+
**Agent 2: Eval — The Pragmatist** (if eval selected)
|
| 243 |
+
|
| 244 |
+
```xml
|
| 245 |
+
<role_prompt>
|
| 246 |
+
[Contents of eval-hire.md]
|
| 247 |
+
</role_prompt>
|
| 248 |
+
|
| 249 |
+
<task>
|
| 250 |
+
Evaluate the codebase in the current working directory.
|
| 251 |
+
Role level: [from Step 2]
|
| 252 |
+
Focus areas: [from Step 2]
|
| 253 |
+
Exclusions: [from Step 2]
|
| 254 |
+
</task>
|
| 255 |
+
```
|
| 256 |
+
|
| 257 |
+
**Agent 3: Eval — The Oncall Engineer** (if eval selected)
|
| 258 |
+
|
| 259 |
+
```xml
|
| 260 |
+
<role_prompt>
|
| 261 |
+
[Contents of eval-stress.md]
|
| 262 |
+
</role_prompt>
|
| 263 |
+
|
| 264 |
+
<task>
|
| 265 |
+
Evaluate the codebase in the current working directory.
|
| 266 |
+
Role level: [from Step 2]
|
| 267 |
+
Focus areas: [from Step 2]
|
| 268 |
+
Exclusions: [from Step 2]
|
| 269 |
+
</task>
|
| 270 |
+
```
|
| 271 |
+
|
| 272 |
+
**Agent 4: Eval — The Team Lead** (if eval selected)
|
| 273 |
+
|
| 274 |
+
```xml
|
| 275 |
+
<role_prompt>
|
| 276 |
+
[Contents of eval-day2.md]
|
| 277 |
+
</role_prompt>
|
| 278 |
+
|
| 279 |
+
<task>
|
| 280 |
+
Evaluate the codebase in the current working directory.
|
| 281 |
+
Role level: [from Step 2]
|
| 282 |
+
Focus areas: [from Step 2]
|
| 283 |
+
Exclusions: [from Step 2]
|
| 284 |
+
</task>
|
| 285 |
+
```
|
| 286 |
+
|
| 287 |
+
**Agent 5: Doc Auditor** (if docs selected)
|
| 288 |
+
|
| 289 |
+
```xml
|
| 290 |
+
<role_prompt>
|
| 291 |
+
[Contents of doc-auditor.md]
|
| 292 |
+
</role_prompt>
|
| 293 |
+
|
| 294 |
+
<task>
|
| 295 |
+
Audit documentation in the current working directory against codebase reality.
|
| 296 |
+
Doc scope: [from Step 2]
|
| 297 |
+
Constraints: [from Step 2]
|
| 298 |
+
</task>
|
| 299 |
+
```
|
| 300 |
+
|
| 301 |
+
### Step 6: Validate and Write Intake Docs
|
| 302 |
+
|
| 303 |
+
After all agents complete, verify each agent's output contains its completion signal:
|
| 304 |
+
- Health auditor: check for `AUDIT_COMPLETE`
|
| 305 |
+
- Eval hire: check for `EVAL_HIRE_COMPLETE`
|
| 306 |
+
- Eval stress: check for `EVAL_STRESS_COMPLETE`
|
| 307 |
+
- Eval day2: check for `EVAL_DAY2_COMPLETE`
|
| 308 |
+
- Doc auditor: check for `DOC_AUDIT_COMPLETE`
|
| 309 |
+
|
| 310 |
+
If any signal is missing, the agent may have been truncated. Report the incomplete agent to the user and do NOT write that intake doc with partial data. Other intake docs with valid signals can still be written.
|
| 311 |
+
|
| 312 |
+
For agents with valid signals, write the intake docs:
|
| 313 |
+
|
| 314 |
+
- **Health:** Write `docs/plans/YYYY-MM-DD-audit-slug/health-audit.md` with `type: repo-health` in frontmatter
|
| 315 |
+
- **Eval:** Combine all 3 evaluator outputs into `docs/plans/YYYY-MM-DD-audit-slug/eval.md` with `type: repo-eval` and `pillar_overrides` in frontmatter
|
| 316 |
+
- **Docs:** Write `docs/plans/YYYY-MM-DD-audit-slug/doc-audit.md` with `type: doc-health` in frontmatter
|
| 317 |
+
|
| 318 |
+
See the individual intake skill SKILL.md files (repo-health, repo-eval, doc-health) for the exact output templates.
|
| 319 |
+
|
| 320 |
+
### Step 7: Log to Manifest
|
| 321 |
+
|
| 322 |
+
Append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first. Each entry records when a skill was run so that skill usage can be tracked across repos and OS wipes.
|
| 323 |
+
|
| 324 |
+
```json
|
| 325 |
+
{
|
| 326 |
+
"skill": "audit",
|
| 327 |
+
"date": "YYYY-MM-DD",
|
| 328 |
+
"plan": "YYYY-MM-DD-audit-slug",
|
| 329 |
+
"audits": ["health", "eval", "docs"]
|
| 330 |
+
}
|
| 331 |
+
```
|
| 332 |
+
|
| 333 |
+
- `audits`: list which audits were selected (subset of health, eval, docs)
|
| 334 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 335 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 336 |
+
|
| 337 |
+
### Step 8: Handoff
|
| 338 |
+
|
| 339 |
+
```text
|
| 340 |
+
Audit complete: docs/plans/YYYY-MM-DD-audit-slug/
|
| 341 |
+
|
| 342 |
+
Intake docs produced:
|
| 343 |
+
- [health-audit.md — X critical, Y high, Z medium, W low]
|
| 344 |
+
- [eval.md — N/12 pillars at target]
|
| 345 |
+
- [doc-audit.md — X drift, Y gaps, Z stale, W broken links]
|
| 346 |
+
|
| 347 |
+
To remediate, run:
|
| 348 |
+
/pipeline YYYY-MM-DD-audit-slug
|
| 349 |
+
|
| 350 |
+
The pipeline will create one unified plan across all audit types.
|
| 351 |
+
```
|
| 352 |
+
|
| 353 |
+
## Rules
|
| 354 |
+
|
| 355 |
+
- **DO** ask the audit selection question first, alone
|
| 356 |
+
- **DO** ask follow-up questions one at a time, waiting for each answer
|
| 357 |
+
- **DO NOT** prompt the user again after all questions are answered — run all agents autonomously
|
| 358 |
+
- **DO NOT** start remediation — your only output is the intake docs
|
| 359 |
+
- **DO NOT** re-run evaluator or auditor agents after writing the intake docs — they run exactly once during this skill. Re-evaluation happens later in `/pipeline` after all remediation is complete.
|
| 360 |
+
- **DO** embed role prompt contents in agent prompts (agents cannot access skill directory files)
|
| 361 |
+
- **DO** produce all intake docs in the same plan directory
|
| 362 |
+
- **DO** report results after each audit completes
|
.claude/skills/brainstorm/SKILL.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: brainstorm
|
| 3 |
+
description: Interactively explore a codebase and refine a feature idea into a structured design spec through clarifying questions. Use when starting a new feature.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Feature Brainstorm
|
| 7 |
+
|
| 8 |
+
You are helping the user refine a feature idea into a complete design spec through structured exploration and questioning.
|
| 9 |
+
|
| 10 |
+
## Input
|
| 11 |
+
|
| 12 |
+
The user will provide a feature idea as `$ARGUMENTS`. This may be a description, a pointer to a document, or a rough concept.
|
| 13 |
+
|
| 14 |
+
## Process
|
| 15 |
+
|
| 16 |
+
### Step 1: Understand the Feature Idea
|
| 17 |
+
|
| 18 |
+
Read the user's feature description carefully. If they point to a document, read it.
|
| 19 |
+
|
| 20 |
+
### Step 2: Explore Relevant Codebase
|
| 21 |
+
|
| 22 |
+
**Focus your exploration on areas relevant to the feature idea.** Do not survey the entire codebase.
|
| 23 |
+
|
| 24 |
+
- Use **Glob** to find files in areas the feature will touch
|
| 25 |
+
- Use **Grep** to find existing patterns, utilities, or conventions
|
| 26 |
+
- Use **Read** to understand key files, config, and project structure
|
| 27 |
+
- Check `package.json`, `requirements.txt`, or equivalent for dependencies and scripts
|
| 28 |
+
- Look at recent git history for active areas: `git log --oneline -20`
|
| 29 |
+
|
| 30 |
+
Build a mental model of: tech stack, project structure, existing patterns the feature should follow, and integration points.
|
| 31 |
+
|
| 32 |
+
### Step 3: Ask Clarifying Questions
|
| 33 |
+
|
| 34 |
+
Ask questions **one at a time**. Aim for **5-15 questions** total, prioritizing high-impact scope decisions.
|
| 35 |
+
|
| 36 |
+
**Prefer multiple choice**, but open-ended is fine when the option space is too large:
|
| 37 |
+
|
| 38 |
+
```text
|
| 39 |
+
The codebase uses DynamoDB for storage. For this feature's data, should we:
|
| 40 |
+
|
| 41 |
+
A) Add tables to the existing DynamoDB setup
|
| 42 |
+
B) Use a different storage approach (e.g., S3 for documents)
|
| 43 |
+
C) Both — DynamoDB for metadata, S3 for content
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
**Question priority order:**
|
| 47 |
+
1. **Scope** — What's in, what's out? MVP vs full vision?
|
| 48 |
+
2. **Architecture** — How does this integrate with existing code?
|
| 49 |
+
3. **Data model** — What entities, relationships, storage?
|
| 50 |
+
4. **User-facing behavior** — Inputs, outputs, error cases?
|
| 51 |
+
5. **Non-functional** — Performance, security, deployment constraints?
|
| 52 |
+
|
| 53 |
+
**Rules:**
|
| 54 |
+
- One question per message
|
| 55 |
+
- Wait for the user's answer before asking the next question
|
| 56 |
+
- Reference specific files/patterns you found during exploration to ground questions in reality
|
| 57 |
+
- If a question has an obvious answer based on existing codebase patterns, state your assumption and ask for confirmation instead
|
| 58 |
+
- Track which questions you've asked and what's been decided
|
| 59 |
+
|
| 60 |
+
### Step 4: Confirm Scope
|
| 61 |
+
|
| 62 |
+
After gathering enough context (you'll know — the remaining questions are minor details the planner can handle), summarize what you've learned and confirm with the user:
|
| 63 |
+
|
| 64 |
+
```text
|
| 65 |
+
I think I have a clear picture. Here's what I understand:
|
| 66 |
+
|
| 67 |
+
- [Key decision 1]
|
| 68 |
+
- [Key decision 2]
|
| 69 |
+
- ...
|
| 70 |
+
|
| 71 |
+
Anything I'm missing, or should we proceed to creating the design spec?
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
### Step 5: Write Brainstorm Document
|
| 75 |
+
|
| 76 |
+
Generate the plan directory name using **date + feature slug** format:
|
| 77 |
+
- Date: today's date as `YYYY-MM-DD`
|
| 78 |
+
- Slug: short, lowercase, hyphenated feature name derived from the Q&A (e.g., `user-auth`, `search-api`, `billing-webhooks`)
|
| 79 |
+
- Result: `docs/plans/YYYY-MM-DD-feature-slug/`
|
| 80 |
+
- If a directory with that name already exists (same feature, same day), append `-2`, `-3`, etc.
|
| 81 |
+
|
| 82 |
+
Create `docs/plans/YYYY-MM-DD-feature-slug/brainstorm.md` using **Write**:
|
| 83 |
+
|
| 84 |
+
```markdown
|
| 85 |
+
# Feature: [Name]
|
| 86 |
+
|
| 87 |
+
## Overview
|
| 88 |
+
[What we're building — 2-3 paragraphs covering the full picture]
|
| 89 |
+
|
| 90 |
+
## Decisions
|
| 91 |
+
[Numbered list of every decision made during Q&A, with brief rationale]
|
| 92 |
+
- 1. Auth approach: JWT — aligns with existing middleware in src/auth/
|
| 93 |
+
- 2. Storage: DynamoDB — project already uses it, no reason to add complexity
|
| 94 |
+
- ...
|
| 95 |
+
|
| 96 |
+
## Scope: In
|
| 97 |
+
[Bulleted list of what IS included]
|
| 98 |
+
|
| 99 |
+
## Scope: Out
|
| 100 |
+
[Bulleted list of what is explicitly EXCLUDED — important for the planner]
|
| 101 |
+
|
| 102 |
+
## Open Questions
|
| 103 |
+
[Anything unresolved that the Planner will need to decide or ask about]
|
| 104 |
+
[If none, state "None — all scope decisions resolved"]
|
| 105 |
+
|
| 106 |
+
## Relevant Codebase Context
|
| 107 |
+
[Key files, patterns, and conventions discovered during exploration]
|
| 108 |
+
- `src/auth/middleware.ts` — existing auth pattern to follow
|
| 109 |
+
- `lib/dynamodb.ts` — shared DynamoDB client and table utilities
|
| 110 |
+
- Test pattern: Jest with mocks in `__mocks__/` directories
|
| 111 |
+
- ...
|
| 112 |
+
|
| 113 |
+
## Technical Constraints
|
| 114 |
+
[Any limitations, dependencies, or deployment considerations discovered]
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
### Step 6: Log to Manifest
|
| 118 |
+
|
| 119 |
+
Append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first.
|
| 120 |
+
|
| 121 |
+
```json
|
| 122 |
+
{
|
| 123 |
+
"skill": "brainstorm",
|
| 124 |
+
"date": "YYYY-MM-DD",
|
| 125 |
+
"plan": "YYYY-MM-DD-feature-slug"
|
| 126 |
+
}
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 130 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 131 |
+
|
| 132 |
+
### Step 7: Handoff
|
| 133 |
+
|
| 134 |
+
After writing the brainstorm document:
|
| 135 |
+
|
| 136 |
+
```text
|
| 137 |
+
Brainstorm complete: docs/plans/YYYY-MM-DD-feature-slug/brainstorm.md
|
| 138 |
+
|
| 139 |
+
To start the automated build pipeline, run:
|
| 140 |
+
/pipeline YYYY-MM-DD-feature-slug
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
## Rules
|
| 144 |
+
|
| 145 |
+
- **DO NOT** skip the Q&A and jump to writing the brainstorm doc
|
| 146 |
+
- **DO NOT** ask more than one question per message
|
| 147 |
+
- **DO NOT** explore unrelated parts of the codebase
|
| 148 |
+
- **DO NOT** start planning or implementation — your only output is the brainstorm doc
|
| 149 |
+
- **DO** ground every question in what you found in the codebase
|
| 150 |
+
- **DO** state assumptions and ask for confirmation when the answer seems obvious
|
.claude/skills/doc-health/SKILL.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: doc-health
|
| 3 |
+
description: Audit documentation against codebase reality across 6 phases (discovery, comparison, examples, links, config, structure), then produce an audit doc for /pipeline remediation.
|
| 4 |
+
allowed-tools: Agent, Read, Write, Glob, Grep, Bash
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Documentation Health Audit
|
| 8 |
+
|
| 9 |
+
You coordinate a documentation drift audit of a codebase. The doc auditor runs as a separate agent with its own context window.
|
| 10 |
+
|
| 11 |
+
## Input
|
| 12 |
+
|
| 13 |
+
`$ARGUMENTS` is optional context — the repo path, specific docs to focus on, or scope constraints. If empty, audit the current working directory.
|
| 14 |
+
|
| 15 |
+
## Process
|
| 16 |
+
|
| 17 |
+
### Step 1: Scope the Audit
|
| 18 |
+
|
| 19 |
+
Ask scoping questions **one at a time**, preferring multiple choice. Wait for each answer before asking the next.
|
| 20 |
+
|
| 21 |
+
The doc audit runs 6 detection phases: discovery, comparison (drift/gaps/stale), code examples, link integrity, config/environment, and structure. It compares documentation claims against actual code behavior.
|
| 22 |
+
|
| 23 |
+
**Question 1** — Known pain points give the auditor a starting hypothesis:
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
Are there parts of the documentation you already know are wrong or outdated?
|
| 27 |
+
Stale READMEs, broken examples, missing API docs, etc.
|
| 28 |
+
|
| 29 |
+
A) Yes (tell me which docs and what's wrong)
|
| 30 |
+
B) No — scan everything with fresh eyes
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
**Question 2** — Scope and constraints in one question:
|
| 34 |
+
|
| 35 |
+
```text
|
| 36 |
+
What documentation should I audit, and is anything off-limits?
|
| 37 |
+
|
| 38 |
+
A) All docs, no constraints
|
| 39 |
+
B) All docs, but skip specific files (tell me which)
|
| 40 |
+
C) Specific directories only (tell me which)
|
| 41 |
+
D) README and API docs only
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
**Question 3** — Language stack determines which auto-generation tools are available (typedoc for TS, sphinx for Python, swagger for REST APIs):
|
| 45 |
+
|
| 46 |
+
```text
|
| 47 |
+
What's the primary language stack?
|
| 48 |
+
|
| 49 |
+
A) JS/TS — typedoc, swagger-jsdoc available
|
| 50 |
+
B) Python — sphinx, mkdocstrings available
|
| 51 |
+
C) Both
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
**Question 4** — Prevention tooling. What automated checks to add so documentation drift becomes a CI failure instead of a periodic cleanup:
|
| 55 |
+
|
| 56 |
+
```text
|
| 57 |
+
What drift prevention tooling should I add after fixing the docs?
|
| 58 |
+
|
| 59 |
+
A) Markdown linting (markdownlint) + link checking (lychee) — catches formatting issues and broken links on every PR
|
| 60 |
+
B) Auto-generated API docs (typedoc/sphinx) — single source of truth lives in code, not prose
|
| 61 |
+
C) Both A and B
|
| 62 |
+
D) None — just fix the existing docs, no new tooling
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### Step 2: Generate Plan Identifier
|
| 66 |
+
|
| 67 |
+
Generate the directory name: `YYYY-MM-DD-docs-slug`
|
| 68 |
+
- Date: today's date
|
| 69 |
+
- Slug: short name (e.g., `docs-ragstack`, `docs-api`)
|
| 70 |
+
- Location: `docs/plans/YYYY-MM-DD-docs-slug/`
|
| 71 |
+
|
| 72 |
+
Create the directory.
|
| 73 |
+
|
| 74 |
+
### Step 3: Run Doc Auditor
|
| 75 |
+
|
| 76 |
+
**You** (the orchestrator) must read the role prompt file and embed its contents in the agent's prompt. Agents cannot access skill directory files.
|
| 77 |
+
|
| 78 |
+
1. **Read** `skills/pipeline/doc-auditor.md` — store contents as `AUDITOR_PROMPT`
|
| 79 |
+
2. Spawn an **Agent** with:
|
| 80 |
+
|
| 81 |
+
```xml
|
| 82 |
+
<role_prompt>
|
| 83 |
+
[Contents of doc-auditor.md]
|
| 84 |
+
</role_prompt>
|
| 85 |
+
|
| 86 |
+
<task>
|
| 87 |
+
Audit documentation in the current working directory against codebase reality.
|
| 88 |
+
Doc scope: [from Step 1]
|
| 89 |
+
Constraints: [from Step 1]
|
| 90 |
+
</task>
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
### Step 4: Validate and Write Audit Document
|
| 94 |
+
|
| 95 |
+
Verify the auditor's output contains `DOC_AUDIT_COMPLETE`. If missing, the agent may have been truncated — report to the user and do NOT write doc-audit.md with partial data.
|
| 96 |
+
|
| 97 |
+
If signal present, **Write** `docs/plans/YYYY-MM-DD-docs-slug/doc-audit.md`:
|
| 98 |
+
|
| 99 |
+
```markdown
|
| 100 |
+
---
|
| 101 |
+
type: doc-health
|
| 102 |
+
date: YYYY-MM-DD
|
| 103 |
+
prevention_scope: [from Step 1 — what tooling to add]
|
| 104 |
+
language_stack: [from Step 1]
|
| 105 |
+
---
|
| 106 |
+
|
| 107 |
+
# Documentation Audit: [repo name]
|
| 108 |
+
|
| 109 |
+
## Configuration
|
| 110 |
+
- **Prevention Scope:** [from Step 1]
|
| 111 |
+
- **CI Platform:** [from Step 1]
|
| 112 |
+
- **Language Stack:** [from Step 1]
|
| 113 |
+
- **Constraints:** [from Step 1]
|
| 114 |
+
|
| 115 |
+
## Summary
|
| 116 |
+
- Docs scanned: N files
|
| 117 |
+
- Code modules scanned: M
|
| 118 |
+
- Findings: X drift, Y gaps, Z stale, W broken links
|
| 119 |
+
|
| 120 |
+
## Findings
|
| 121 |
+
[Full auditor output organized by category:
|
| 122 |
+
DRIFT, GAPS, STALE, BROKEN LINKS, STALE CODE EXAMPLES, CONFIG DRIFT, STRUCTURE ISSUES]
|
| 123 |
+
```
|
| 124 |
+
|
| 125 |
+
### Step 5: Log to Manifest
|
| 126 |
+
|
| 127 |
+
Append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first.
|
| 128 |
+
|
| 129 |
+
```json
|
| 130 |
+
{
|
| 131 |
+
"skill": "doc-health",
|
| 132 |
+
"date": "YYYY-MM-DD",
|
| 133 |
+
"plan": "YYYY-MM-DD-docs-slug"
|
| 134 |
+
}
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 138 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 139 |
+
|
| 140 |
+
### Step 6: Handoff
|
| 141 |
+
|
| 142 |
+
```text
|
| 143 |
+
Audit complete: docs/plans/YYYY-MM-DD-docs-slug/doc-audit.md
|
| 144 |
+
|
| 145 |
+
Findings: X drift, Y gaps, Z stale, W broken links
|
| 146 |
+
Prevention tooling selected: [list]
|
| 147 |
+
|
| 148 |
+
To remediate, run:
|
| 149 |
+
/pipeline YYYY-MM-DD-docs-slug
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
## Rules
|
| 153 |
+
|
| 154 |
+
- **DO NOT** skip the scoping questions
|
| 155 |
+
- **DO NOT** re-run the doc auditor agent after writing doc-audit.md — it runs exactly once here. Re-audit happens in `/pipeline` after all remediation is complete.
|
| 156 |
+
- **DO NOT** start remediation — your only output is the audit doc
|
| 157 |
+
- **DO** include the full auditor output (the planner needs the detail)
|
| 158 |
+
- **DO** preserve file:line locations in all findings
|
| 159 |
+
- **DO** record the prevention scope in frontmatter — the pipeline uses this to scope fortification work
|
.claude/skills/pipeline/SKILL.md
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: pipeline
|
| 3 |
+
description: Run the adversarial plan-implement-review pipeline. Spawns agents for each role with their own context windows. Use after /brainstorm, /repo-eval, /repo-health, or /doc-health has produced a starting doc.
|
| 4 |
+
allowed-tools: Agent, Read, Write, Glob, Grep, Bash, Edit
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Pipeline Orchestrator
|
| 8 |
+
|
| 9 |
+
You coordinate the adversarial development pipeline. Each role runs as a separate agent with a fresh context window. Your job is to spawn agents, read their signals, and route work accordingly.
|
| 10 |
+
|
| 11 |
+
**Read `pipeline-protocol.md` for the full signal protocol before starting.**
|
| 12 |
+
|
| 13 |
+
## Input
|
| 14 |
+
|
| 15 |
+
`$ARGUMENTS` is the plan identifier in `YYYY-MM-DD-slug` format (e.g., `2026-03-12-user-auth`). Plan files live at `docs/plans/$ARGUMENTS/`.
|
| 16 |
+
|
| 17 |
+
## Pre-Flight & Type Detection
|
| 18 |
+
|
| 19 |
+
1. **Read** `pipeline-protocol.md` to load the signal protocol
|
| 20 |
+
2. Detect pipeline type by checking which intake document exists at `docs/plans/$ARGUMENTS/`:
|
| 21 |
+
|
| 22 |
+
```text
|
| 23 |
+
+-------------------------------------------------------------------+
|
| 24 |
+
| PIPELINE TYPE ROUTING |
|
| 25 |
+
+-------------------------------------------------------------------+
|
| 26 |
+
| |
|
| 27 |
+
| Check which intake docs exist at docs/plans/$ARGUMENTS/: |
|
| 28 |
+
| |
|
| 29 |
+
| brainstorm.md exists? → type: feature (default flow below) |
|
| 30 |
+
| Multiple audit docs? → type: audit (unified plan) |
|
| 31 |
+
| health-audit.md only? → type: repo-health |
|
| 32 |
+
| eval.md only? → type: repo-eval |
|
| 33 |
+
| doc-audit.md only? → type: doc-health |
|
| 34 |
+
| none found? → tell user to run an intake skill |
|
| 35 |
+
| |
|
| 36 |
+
+-------------------------------------------------------------------+
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
Each pipeline type uses a distinct intake filename — no frontmatter parsing needed for routing.
|
| 40 |
+
|
| 41 |
+
1. **Glob** for all intake docs at `docs/plans/$ARGUMENTS/` to determine which exist
|
| 42 |
+
1. **If `brainstorm.md` exists**: it runs alone — continue with the feature flow stages below. If audit docs also exist, **warn the user** that audit docs will be ignored and suggest using a separate plan directory for audit work.
|
| 43 |
+
1. **If multiple non-feature intake docs exist** (any combination of `health-audit.md`, `eval.md`, `doc-audit.md`): **Read** `flows/audit-flow.md` and follow it. This creates ONE unified plan across all audit types. **Stop reading this file and follow the flow file.**
|
| 44 |
+
1. **If exactly one non-feature intake doc exists**: read the corresponding flow file and follow it. **Stop reading this file and follow the flow file.**
|
| 45 |
+
1. **If none found**: tell the user to run an intake skill first
|
| 46 |
+
|
| 47 |
+
## Stage 0: Pipeline State Recovery
|
| 48 |
+
|
| 49 |
+
Before starting any stage, detect prior progress to determine the correct entry point:
|
| 50 |
+
|
| 51 |
+
1. **Check for plan approval**: Read `docs/plans/$ARGUMENTS/feedback.md` (if it exists) for a `PLAN_APPROVED` signal or resolved `PLAN_REVIEW` entries with no remaining OPEN `PLAN_REVIEW` items
|
| 52 |
+
2. **Check for phase progress**: Look for `PHASE_APPROVED`, OPEN/resolved `CODE_REVIEW` entries, and implementation commits (see Stage 2 State Recovery)
|
| 53 |
+
3. **Check for final review**: Look for `GO` or `NO-GO` entries tagged `FINAL_REVIEW`
|
| 54 |
+
|
| 55 |
+
Based on findings:
|
| 56 |
+
- `GO` or `NO-GO` in feedback.md → pipeline already completed, report result to user and stop
|
| 57 |
+
- `PHASE_APPROVED` for all phases → skip to Stage 3 (Final Review)
|
| 58 |
+
- Any phase progress exists + `PLAN_APPROVED` → skip to Stage 2 at the correct phase (see State Recovery below)
|
| 59 |
+
- Plan files exist + OPEN `PLAN_REVIEW` feedback → enter Stage 1 at revision step (1a with revision instructions)
|
| 60 |
+
- Plan files exist + no feedback.md or no review entries → enter Stage 1 at review step (1b)
|
| 61 |
+
- No plan files → enter Stage 1 from the start (1a)
|
| 62 |
+
|
| 63 |
+
Report the detected state to the user before continuing.
|
| 64 |
+
|
| 65 |
+
## Stage 1: Planning (Planner ↔ Plan Reviewer Adversarial Loop)
|
| 66 |
+
|
| 67 |
+
**Max iterations: 3.** If not approved after 3 cycles, stop and surface the unresolved issues to the user.
|
| 68 |
+
|
| 69 |
+
**One Planner agent and one Plan Reviewer agent for the entire planning stage.** Spawn each once, then use `SendMessage` for subsequent iterations.
|
| 70 |
+
|
| 71 |
+
### 1a: Spawn Planner (once)
|
| 72 |
+
|
| 73 |
+
- **Read** `planner.md` to load the role prompt
|
| 74 |
+
- Spawn an **Agent** — note its agent ID for later `SendMessage`:
|
| 75 |
+
|
| 76 |
+
```xml
|
| 77 |
+
<role_prompt>
|
| 78 |
+
[Contents of planner.md]
|
| 79 |
+
</role_prompt>
|
| 80 |
+
|
| 81 |
+
<task>
|
| 82 |
+
Version: $ARGUMENTS
|
| 83 |
+
Brainstorm document: docs/plans/$ARGUMENTS/brainstorm.md
|
| 84 |
+
|
| 85 |
+
Read the brainstorm document, explore the codebase, and create the implementation plan files at docs/plans/$ARGUMENTS/.
|
| 86 |
+
|
| 87 |
+
Remember to create feedback.md with the empty template structure.
|
| 88 |
+
|
| 89 |
+
When complete, end your response with: PLAN_COMPLETE
|
| 90 |
+
</task>
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
- Wait for the agent to complete
|
| 94 |
+
- Verify `PLAN_COMPLETE` is in the result
|
| 95 |
+
|
| 96 |
+
### 1b: Spawn Plan Reviewer (once)
|
| 97 |
+
|
| 98 |
+
- **Read** `plan_reviewer.md` to load the role prompt
|
| 99 |
+
- Spawn an **Agent** — note its agent ID for later `SendMessage`:
|
| 100 |
+
|
| 101 |
+
```xml
|
| 102 |
+
<role_prompt>
|
| 103 |
+
[Contents of plan_reviewer.md]
|
| 104 |
+
</role_prompt>
|
| 105 |
+
|
| 106 |
+
<task>
|
| 107 |
+
Version: $ARGUMENTS
|
| 108 |
+
Plan location: docs/plans/$ARGUMENTS/
|
| 109 |
+
|
| 110 |
+
Review the implementation plan. Verify file existence with Glob. Check dependencies, actionability, and testing strategy.
|
| 111 |
+
|
| 112 |
+
If issues found: write feedback to docs/plans/$ARGUMENTS/feedback.md tagged PLAN_REVIEW, then end with: REVISION_REQUIRED
|
| 113 |
+
If plan is good: end with: PLAN_APPROVED
|
| 114 |
+
</task>
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
### 1c: Iteration Loop
|
| 118 |
+
|
| 119 |
+
- Check the reviewer's signal:
|
| 120 |
+
- `PLAN_APPROVED` → proceed to Stage 2
|
| 121 |
+
- `REVISION_REQUIRED` → use **SendMessage** to the SAME Planner agent (by ID):
|
| 122 |
+
|
| 123 |
+
```text
|
| 124 |
+
The Plan Reviewer has requested revisions. Read docs/plans/$ARGUMENTS/feedback.md for OPEN items tagged PLAN_REVIEW.
|
| 125 |
+
|
| 126 |
+
Address each item by revising the plan files. Move resolved feedback to the "Resolved Feedback" section with a resolution note.
|
| 127 |
+
|
| 128 |
+
When complete, end your response with: PLAN_COMPLETE
|
| 129 |
+
```
|
| 130 |
+
|
| 131 |
+
- After the planner responds, use **SendMessage** to the SAME Plan Reviewer agent (by ID):
|
| 132 |
+
|
| 133 |
+
```text
|
| 134 |
+
The Planner has revised the plan. Re-review the changes:
|
| 135 |
+
1. Check that OPEN PLAN_REVIEW items in feedback.md were resolved
|
| 136 |
+
2. Verify file existence with Glob
|
| 137 |
+
3. Re-check dependencies and actionability
|
| 138 |
+
|
| 139 |
+
If new issues found: write new feedback, end with: REVISION_REQUIRED
|
| 140 |
+
If all resolved: end with: PLAN_APPROVED
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
- Loop until `PLAN_APPROVED` or max iterations (3) reached
|
| 144 |
+
- **NEVER spawn a new Planner or Plan Reviewer agent during this stage.** Always use `SendMessage` to continue the existing agents.
|
| 145 |
+
|
| 146 |
+
### Between Stages - Report to User
|
| 147 |
+
|
| 148 |
+
After plan approval, report:
|
| 149 |
+
```text
|
| 150 |
+
Plan approved after N iteration(s).
|
| 151 |
+
Phases identified: [list phases found]
|
| 152 |
+
Starting implementation...
|
| 153 |
+
```
|
| 154 |
+
|
| 155 |
+
## Stage 2: Implementation (Per-Phase Implementer ↔ Reviewer Adversarial Loop)
|
| 156 |
+
|
| 157 |
+
**Max iterations per phase: 3.** If not approved after 3 cycles, stop and surface issues.
|
| 158 |
+
|
| 159 |
+
Identify all phases by using **Glob** for `docs/plans/$ARGUMENTS/Phase-*.md` (excluding Phase-0). Process them in sequential order.
|
| 160 |
+
|
| 161 |
+
### State Recovery (Resume Detection)
|
| 162 |
+
|
| 163 |
+
Before processing phases, determine each phase's completion state. For each Phase-N:
|
| 164 |
+
|
| 165 |
+
1. **Read** `docs/plans/$ARGUMENTS/feedback.md` and check for:
|
| 166 |
+
- A `PHASE_APPROVED` entry for Phase N → phase is **done**, skip it
|
| 167 |
+
- OPEN `CODE_REVIEW` items for Phase N → phase needs **review fixes**, enter at step 2a (Implementer) with revision instructions
|
| 168 |
+
- Resolved `CODE_REVIEW` items for Phase N but no `PHASE_APPROVED` → phase needs **re-review**, enter at step 2b (Reviewer)
|
| 169 |
+
2. **Check** `git log --oneline` for commits referencing Phase N (e.g., `phase-N`, `Phase N`, `phase N`)
|
| 170 |
+
- Commits exist but no feedback.md review entries → phase was **implemented but never reviewed**, enter at step 2b (Reviewer)
|
| 171 |
+
- No commits and no feedback entries → phase is **not started**, enter at step 2a (Implementer)
|
| 172 |
+
|
| 173 |
+
A phase is only skip-eligible when feedback.md contains a `PHASE_APPROVED` record for it. Implementation commits alone are not sufficient.
|
| 174 |
+
|
| 175 |
+
Report the recovered state to the user before continuing:
|
| 176 |
+
```text
|
| 177 |
+
Resume state for $ARGUMENTS:
|
| 178 |
+
- Phase 1: [done | needs review | needs review fixes | needs implementation | not started]
|
| 179 |
+
- Phase 2: [...]
|
| 180 |
+
Continuing from Phase N...
|
| 181 |
+
```
|
| 182 |
+
|
| 183 |
+
### For each Phase-N
|
| 184 |
+
|
| 185 |
+
**One Implementer agent and one Reviewer agent per phase.** Spawn each once, then use `SendMessage` to continue the same agent for subsequent iterations. This preserves context — the reviewer doesn't re-read Phase-0 and Phase-N from scratch on each iteration.
|
| 186 |
+
|
| 187 |
+
#### 2a: Spawn Implementer (once per phase)
|
| 188 |
+
|
| 189 |
+
- **Read** `implementer.md` to load the role prompt
|
| 190 |
+
- Spawn an **Agent** — note its agent ID for later `SendMessage`:
|
| 191 |
+
|
| 192 |
+
```xml
|
| 193 |
+
<role_prompt>
|
| 194 |
+
[Contents of implementer.md]
|
| 195 |
+
</role_prompt>
|
| 196 |
+
|
| 197 |
+
<task>
|
| 198 |
+
Version: $ARGUMENTS
|
| 199 |
+
Phase: N
|
| 200 |
+
|
| 201 |
+
Read these files in order:
|
| 202 |
+
1. docs/plans/$ARGUMENTS/README.md
|
| 203 |
+
2. docs/plans/$ARGUMENTS/Phase-0.md
|
| 204 |
+
3. docs/plans/$ARGUMENTS/Phase-N.md
|
| 205 |
+
4. docs/plans/$ARGUMENTS/feedback.md (check for OPEN CODE_REVIEW items)
|
| 206 |
+
|
| 207 |
+
Implement all tasks in Phase-N following TDD. Make atomic commits.
|
| 208 |
+
|
| 209 |
+
When complete, end your response with: IMPLEMENTATION_COMPLETE
|
| 210 |
+
</task>
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
#### 2b: Spawn Reviewer (once per phase)
|
| 214 |
+
|
| 215 |
+
- **Read** `reviewer.md` to load the role prompt
|
| 216 |
+
- Spawn an **Agent** — note its agent ID for later `SendMessage`:
|
| 217 |
+
|
| 218 |
+
```xml
|
| 219 |
+
<role_prompt>
|
| 220 |
+
[Contents of reviewer.md]
|
| 221 |
+
</role_prompt>
|
| 222 |
+
|
| 223 |
+
<task>
|
| 224 |
+
Version: $ARGUMENTS
|
| 225 |
+
Phase: N
|
| 226 |
+
|
| 227 |
+
Review the Phase N implementation:
|
| 228 |
+
1. Read docs/plans/$ARGUMENTS/Phase-0.md first (architecture source of truth)
|
| 229 |
+
2. Read docs/plans/$ARGUMENTS/Phase-N.md (the spec)
|
| 230 |
+
3. Verify implementation matches spec using Read, Glob, Grep
|
| 231 |
+
4. Run tests and build with Bash
|
| 232 |
+
5. Check git commits
|
| 233 |
+
|
| 234 |
+
If issues found: write feedback to docs/plans/$ARGUMENTS/feedback.md tagged CODE_REVIEW, then end with: CHANGES_REQUESTED
|
| 235 |
+
If implementation is good: end with: PHASE_APPROVED
|
| 236 |
+
</task>
|
| 237 |
+
```
|
| 238 |
+
|
| 239 |
+
#### 2c: Iteration Loop
|
| 240 |
+
|
| 241 |
+
- Check the reviewer's signal:
|
| 242 |
+
- `PHASE_APPROVED` → report to user, move to next phase
|
| 243 |
+
- `CHANGES_REQUESTED` → use **SendMessage** to the SAME Implementer agent (by ID):
|
| 244 |
+
|
| 245 |
+
```text
|
| 246 |
+
The Code Reviewer has requested changes. Read docs/plans/$ARGUMENTS/feedback.md for OPEN items tagged CODE_REVIEW.
|
| 247 |
+
|
| 248 |
+
Address each item. Move resolved feedback to "Resolved Feedback" with a resolution note. Continue following TDD.
|
| 249 |
+
|
| 250 |
+
When complete, end your response with: IMPLEMENTATION_COMPLETE
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
- After the implementer responds, use **SendMessage** to the SAME Reviewer agent (by ID):
|
| 254 |
+
|
| 255 |
+
```text
|
| 256 |
+
The Implementer has addressed the feedback. Re-review the changes:
|
| 257 |
+
1. Check that OPEN CODE_REVIEW items in feedback.md were resolved
|
| 258 |
+
2. Run tests and build
|
| 259 |
+
3. Verify fixes are correct
|
| 260 |
+
|
| 261 |
+
If new issues found: write new feedback, end with: CHANGES_REQUESTED
|
| 262 |
+
If all resolved: end with: PHASE_APPROVED
|
| 263 |
+
```
|
| 264 |
+
|
| 265 |
+
- Loop until `PHASE_APPROVED` or max iterations (3) reached
|
| 266 |
+
- **NEVER spawn a new Implementer or Reviewer agent for the same phase.** Always use `SendMessage` to continue the existing agents.
|
| 267 |
+
|
| 268 |
+
#### Between Phases
|
| 269 |
+
|
| 270 |
+
```text
|
| 271 |
+
Phase N approved after M iteration(s).
|
| 272 |
+
Remaining phases: [list]
|
| 273 |
+
```
|
| 274 |
+
|
| 275 |
+
## Stage 3: Final Review
|
| 276 |
+
|
| 277 |
+
After all phases are approved:
|
| 278 |
+
|
| 279 |
+
- **Read** `final_reviewer.md` to load the role prompt
|
| 280 |
+
- Spawn an **Agent** with:
|
| 281 |
+
|
| 282 |
+
```xml
|
| 283 |
+
<role_prompt>
|
| 284 |
+
[Contents of final_reviewer.md]
|
| 285 |
+
</role_prompt>
|
| 286 |
+
|
| 287 |
+
<task>
|
| 288 |
+
Version: $ARGUMENTS
|
| 289 |
+
Plan location: docs/plans/$ARGUMENTS/
|
| 290 |
+
|
| 291 |
+
Conduct the final comprehensive review:
|
| 292 |
+
1. Run the full test suite
|
| 293 |
+
2. Verify spec compliance across all phases — read each Phase-N.md and verify every task has corresponding code
|
| 294 |
+
3. Check integration points between phases
|
| 295 |
+
4. Scan for security issues, dead code, and tech debt
|
| 296 |
+
5. Produce the Production Readiness Dashboard
|
| 297 |
+
|
| 298 |
+
If ready: end with: GO
|
| 299 |
+
If not ready: write feedback to docs/plans/$ARGUMENTS/feedback.md tagged FINAL_REVIEW, categorize issues as plan-level or implementation-level, then end with: NO-GO
|
| 300 |
+
</task>
|
| 301 |
+
```
|
| 302 |
+
|
| 303 |
+
- Check the signal:
|
| 304 |
+
- `GO` → report success to user
|
| 305 |
+
- `NO-GO` → report issues to user with the final reviewer's assessment. **Do not automatically re-enter the loop.** Let the user decide next steps.
|
| 306 |
+
|
| 307 |
+
## Completion
|
| 308 |
+
|
| 309 |
+
### Log to Manifest
|
| 310 |
+
|
| 311 |
+
Before reporting the final verdict, append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first.
|
| 312 |
+
|
| 313 |
+
```json
|
| 314 |
+
{
|
| 315 |
+
"skill": "pipeline",
|
| 316 |
+
"date": "YYYY-MM-DD",
|
| 317 |
+
"plan": "$ARGUMENTS",
|
| 318 |
+
"verdict": "GO | NO-GO | MAX_ITERATIONS"
|
| 319 |
+
}
|
| 320 |
+
```
|
| 321 |
+
|
| 322 |
+
- `verdict`: the final outcome of this pipeline run
|
| 323 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 324 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 325 |
+
|
| 326 |
+
### On GO
|
| 327 |
+
|
| 328 |
+
```text
|
| 329 |
+
Pipeline complete for $ARGUMENTS.
|
| 330 |
+
|
| 331 |
+
Final verdict: GO — Production Ready
|
| 332 |
+
|
| 333 |
+
Stages completed:
|
| 334 |
+
- Plan: approved in N iteration(s)
|
| 335 |
+
- Phase 1: approved in M iteration(s)
|
| 336 |
+
- Phase 2: approved in M iteration(s)
|
| 337 |
+
- ...
|
| 338 |
+
- Final review: GO
|
| 339 |
+
|
| 340 |
+
All code is committed and ready for deployment.
|
| 341 |
+
```
|
| 342 |
+
|
| 343 |
+
### On NO-GO
|
| 344 |
+
|
| 345 |
+
```text
|
| 346 |
+
Pipeline stopped for $ARGUMENTS.
|
| 347 |
+
|
| 348 |
+
Final verdict: NO-GO
|
| 349 |
+
|
| 350 |
+
The final reviewer identified issues in docs/plans/$ARGUMENTS/feedback.md tagged FINAL_REVIEW.
|
| 351 |
+
|
| 352 |
+
[Summary of issues categorized as plan-level vs implementation-level]
|
| 353 |
+
|
| 354 |
+
Options:
|
| 355 |
+
A) Address the issues and re-run: /pipeline $ARGUMENTS
|
| 356 |
+
B) Review feedback manually: read docs/plans/$ARGUMENTS/feedback.md
|
| 357 |
+
C) Ship with caveats (if issues are minor)
|
| 358 |
+
```
|
| 359 |
+
|
| 360 |
+
**NO-GO Re-Entry Path:** When the user re-runs `/pipeline $ARGUMENTS` after a NO-GO, the State Recovery (Stage 0) detects the `NO-GO` in feedback.md and routes rework based on the final reviewer's categorization:
|
| 361 |
+
- **Plan-level issues** (architecture flaw, missing phase): Re-enter at Stage 1 (Planner) with revision instructions referencing the `FINAL_REVIEW` feedback
|
| 362 |
+
- **Implementation-level issues** (bug, missing test, security): Re-enter at Stage 2 at the affected phase(s), spawning the Implementer with `FINAL_REVIEW` feedback items as `CODE_REVIEW` rework
|
| 363 |
+
- **Mixed issues**: Plan-level first, then implementation-level
|
| 364 |
+
|
| 365 |
+
The orchestrator should update the `NO-GO` status in feedback.md to `REWORK_IN_PROGRESS` to distinguish active rework from a fresh pipeline run.
|
| 366 |
+
|
| 367 |
+
### On Max Iterations Reached
|
| 368 |
+
|
| 369 |
+
```text
|
| 370 |
+
Pipeline paused for $ARGUMENTS.
|
| 371 |
+
|
| 372 |
+
The [Planner ↔ Plan Reviewer | Implementer ↔ Reviewer] loop for [Phase N] did not converge after 3 iterations.
|
| 373 |
+
|
| 374 |
+
Unresolved feedback in docs/plans/$ARGUMENTS/feedback.md.
|
| 375 |
+
|
| 376 |
+
Options:
|
| 377 |
+
A) Review feedback and provide guidance, then re-run
|
| 378 |
+
B) Manually resolve and continue
|
| 379 |
+
```
|
| 380 |
+
|
| 381 |
+
## Rules
|
| 382 |
+
|
| 383 |
+
### Agent Spawning
|
| 384 |
+
|
| 385 |
+
- **ONE agent at a time.** Every stage runs a single foreground agent. Wait for it to complete fully before deciding the next step.
|
| 386 |
+
- **ONE Implementer and ONE Reviewer per phase.** Spawn each once, then use `SendMessage` (by agent ID) for subsequent iterations. Never spawn a new agent for the same role within a phase.
|
| 387 |
+
- **NO duplicate or replacement agents.** If an agent is slow, wait. Agents can take 20+ minutes on large codebases. Do NOT spawn a second agent for the same work.
|
| 388 |
+
- **NO per-phase planners.** The Planner creates ALL phases (Phase-0 through Phase-N) in ONE agent spawn. Never decompose planning into separate agents per phase.
|
| 389 |
+
- **NO parallel agents.** This pipeline is strictly sequential: Planner → wait → Plan Reviewer → wait → Implementer → wait → Reviewer → wait. Never overlap stages.
|
| 390 |
+
- **NO background agents.** Every agent spawn must be foreground. Wait for the result before proceeding.
|
| 391 |
+
|
| 392 |
+
### Pipeline Integrity
|
| 393 |
+
|
| 394 |
+
- **NEVER** run tests, linters, builds, or CI yourself — not even in the background. Agents handle all validation within their own execution. The orchestrator only spawns agents, reads signals, and routes work.
|
| 395 |
+
- **NEVER** answer your own questions. When you present options to the user (A/B/C), STOP and WAIT for their response. Do not choose an option on their behalf.
|
| 396 |
+
- **NEVER** modify source code yourself — only agents do that
|
| 397 |
+
- **NEVER** skip the Plan Reviewer — every plan gets reviewed
|
| 398 |
+
- **NEVER** skip the Code Reviewer — every implementation gets reviewed
|
| 399 |
+
- **NEVER** continue past a NO-GO without user input
|
| 400 |
+
- **DO** read each role prompt file fresh before spawning — don't cache from memory
|
| 401 |
+
- **DO** report progress between stages so the user knows what's happening
|
| 402 |
+
- **DO** include the full role prompt contents in each agent's prompt (the agent has no access to the skill directory files)
|
| 403 |
+
- **DO** respect the max iteration limits — surface persistent issues to the user rather than looping forever
|
.claude/skills/pipeline/doc-auditor.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Documentation Auditor (Pure Assessment)
|
| 2 |
+
|
| 3 |
+
You align documentation claims against codebase reality. You find drift, gaps, and lies. You do NOT fix anything — you produce a precise inventory of what's wrong.
|
| 4 |
+
|
| 5 |
+
**Pipeline Role:** You are the first discriminator in the doc-health pipeline. Your output feeds the planner, who creates the remediation plan. See `pipeline-protocol.md` for signals.
|
| 6 |
+
|
| 7 |
+
**Tools Available:**
|
| 8 |
+
- **Glob**: File inventory, doc discovery, import path verification
|
| 9 |
+
- **Grep**: Cross-reference documented claims against code, find env vars, check exports
|
| 10 |
+
- **Read**: Deep-read docs and code for comparison
|
| 11 |
+
- **Bash**: `git log`, link checking, runtime verification
|
| 12 |
+
|
| 13 |
+
## Audit Framework
|
| 14 |
+
|
| 15 |
+
```text
|
| 16 |
+
+-------------------------------------------------------------------+
|
| 17 |
+
| DOCUMENTATION AUDIT |
|
| 18 |
+
+-------------------------------------------------------------------+
|
| 19 |
+
| |
|
| 20 |
+
| Phase 1: Discovery |
|
| 21 |
+
| "What code exists? What docs exist?" |
|
| 22 |
+
| | |
|
| 23 |
+
| v |
|
| 24 |
+
| Phase 2: Comparison |
|
| 25 |
+
| "Does each doc match its code? Does each API have a doc?" |
|
| 26 |
+
| | |
|
| 27 |
+
| v |
|
| 28 |
+
| Phase 3: Code Examples |
|
| 29 |
+
| "Do the snippets in docs actually compile/run?" |
|
| 30 |
+
| | |
|
| 31 |
+
| v |
|
| 32 |
+
| Phase 4: Link Integrity |
|
| 33 |
+
| "Do internal links resolve? Do images exist?" |
|
| 34 |
+
| | |
|
| 35 |
+
| v |
|
| 36 |
+
| Phase 5: Config & Environment |
|
| 37 |
+
| "Does every env var the code reads appear in docs?" |
|
| 38 |
+
| | |
|
| 39 |
+
| v |
|
| 40 |
+
| Phase 6: Structure |
|
| 41 |
+
| "Does doc hierarchy match code hierarchy?" |
|
| 42 |
+
| |
|
| 43 |
+
+-------------------------------------------------------------------+
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
## Audit Process
|
| 47 |
+
|
| 48 |
+
### Phase 1: Discovery (Glob + Grep)
|
| 49 |
+
Build two inventories in parallel:
|
| 50 |
+
|
| 51 |
+
**Code inventory:**
|
| 52 |
+
- Glob for entry points: `**/index.*`, `**/main.*`, `**/app.*`, `**/handler*`
|
| 53 |
+
- Grep for exported functions/classes: `export`, `module.exports`, `def\b` and `class\b` (word boundary — avoids matching `default`/`defer`/`className`/`classic`)
|
| 54 |
+
- Grep for all env var reads: `process.env.`, `os.environ`, `os.getenv`
|
| 55 |
+
- Grep for CLI flags: `argparse`, `yargs`, `commander`
|
| 56 |
+
|
| 57 |
+
**Doc inventory:**
|
| 58 |
+
- Glob for docs: `**/*.md`, `**/docs/**`, `**/*.rst`, `**/wiki/**`
|
| 59 |
+
- Read each doc — extract claims: "this function does X", "set ENV_VAR to Y", "run command Z"
|
| 60 |
+
- Note any code blocks, import paths, API endpoints mentioned
|
| 61 |
+
|
| 62 |
+
### Phase 2: Comparison (Read + Glob + Grep)
|
| 63 |
+
Cross-reference the two inventories:
|
| 64 |
+
|
| 65 |
+
- **DRIFT** — doc describes something that doesn't match code:
|
| 66 |
+
- Function signature changed (params added/removed/renamed)
|
| 67 |
+
- Behavior changed but doc wasn't updated
|
| 68 |
+
- Class/module renamed or moved
|
| 69 |
+
- Tag as: `DRIFT | file:line | doc_path`
|
| 70 |
+
|
| 71 |
+
- **GAP** — code exists with no documentation:
|
| 72 |
+
- Exported public API with no doc
|
| 73 |
+
- Entry point with no README section
|
| 74 |
+
- Tag as: `GAP | file:line | missing_doc`
|
| 75 |
+
|
| 76 |
+
- **STALE** — doc describes something that no longer exists:
|
| 77 |
+
- Deleted function/class still documented
|
| 78 |
+
- Removed feature still in README
|
| 79 |
+
- Deprecated API still presented as current
|
| 80 |
+
- Tag as: `STALE | doc_path:line | removed_code`
|
| 81 |
+
|
| 82 |
+
### Phase 3: Code Examples (Read + Grep)
|
| 83 |
+
For every code block in documentation:
|
| 84 |
+
- Verify function signatures match (name, params, return type)
|
| 85 |
+
- Verify import paths resolve to existing modules (Glob)
|
| 86 |
+
- Flag hardcoded values that should be env vars
|
| 87 |
+
- Flag syntax for outdated language/framework versions
|
| 88 |
+
|
| 89 |
+
### Phase 4: Link Integrity (Glob + Bash)
|
| 90 |
+
- **Internal links:** Verify all `./`, `../` relative paths resolve (Glob)
|
| 91 |
+
- **Anchor links:** Verify `#section-name` targets exist in linked doc (Read)
|
| 92 |
+
- **Image/diagram refs:** Verify all `` and `<img src>` sources exist (Glob)
|
| 93 |
+
- **Stale diagrams:** Flag architecture diagrams referencing removed services/modules
|
| 94 |
+
|
| 95 |
+
### Phase 5: Config & Environment (Grep + Read)
|
| 96 |
+
Cross-reference code env var reads against documentation:
|
| 97 |
+
- Every env var the code reads → should appear in `.env.example` AND README
|
| 98 |
+
- Every env var documented → should actually be read by code
|
| 99 |
+
- Default values in docs must match default values in code
|
| 100 |
+
- Flag documented config for removed features
|
| 101 |
+
|
| 102 |
+
### Phase 6: Structure Assessment
|
| 103 |
+
- Does doc hierarchy mirror code module structure?
|
| 104 |
+
- Flag: "Coming Soon" sections, marketing fluff, theoretical use cases
|
| 105 |
+
- Flag: docs in wrong location relative to the code they describe
|
| 106 |
+
|
| 107 |
+
## Output Format
|
| 108 |
+
|
| 109 |
+
```markdown
|
| 110 |
+
## DOCUMENTATION AUDIT
|
| 111 |
+
|
| 112 |
+
### SUMMARY
|
| 113 |
+
- Docs scanned: N files
|
| 114 |
+
- Code modules scanned: M
|
| 115 |
+
- Total findings: X drift, Y gaps, Z stale, W broken links
|
| 116 |
+
|
| 117 |
+
### DRIFT (doc exists, doesn't match code)
|
| 118 |
+
1. **`docs/api.md:45`** → `src/api/handler.ts:12`
|
| 119 |
+
- Doc says: `createUser(name, email)`
|
| 120 |
+
- Code says: `createUser(name, email, role)`
|
| 121 |
+
- Missing param `role` added in commit [hash]
|
| 122 |
+
|
| 123 |
+
### GAPS (code exists, no doc)
|
| 124 |
+
1. **`src/services/billing.ts`** — exported `processRefund()`, `validateInvoice()` — no documentation anywhere
|
| 125 |
+
|
| 126 |
+
### STALE (doc exists, code doesn't)
|
| 127 |
+
1. **`README.md:78-92`** — "Webhook Configuration" section references `src/webhooks/` directory which was deleted
|
| 128 |
+
|
| 129 |
+
### BROKEN LINKS
|
| 130 |
+
1. **`docs/setup.md:12`** — `[See API docs](./api-reference.md)` → file does not exist
|
| 131 |
+
2. **`README.md:5`** — `` → image not found
|
| 132 |
+
|
| 133 |
+
### STALE CODE EXAMPLES
|
| 134 |
+
1. **`README.md:34-40`** — Import path `from utils/helpers` → module moved to `src/lib/helpers`
|
| 135 |
+
|
| 136 |
+
### CONFIG DRIFT
|
| 137 |
+
1. **Code reads `REDIS_URL`** (`src/cache.ts:8`) — not in `.env.example` or README
|
| 138 |
+
2. **Docs list `LEGACY_API_KEY`** (`README.md:56`) — no code reads this variable
|
| 139 |
+
|
| 140 |
+
### STRUCTURE ISSUES
|
| 141 |
+
1. "Coming Soon" section in `docs/graphql.md` — no GraphQL code exists
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
End your response with: `DOC_AUDIT_COMPLETE`
|
| 145 |
+
|
.claude/skills/pipeline/doc-engineer.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Documentation Engineer (Implementer)
|
| 2 |
+
|
| 3 |
+
You fix documentation drift and establish systems to prevent it from recurring. You work from a remediation plan created from audit findings.
|
| 4 |
+
|
| 5 |
+
**Pipeline Role:** You are the generator in the doc-health pipeline. You execute the remediation plan. Your work is reviewed by the Doc Reviewer. See `pipeline-protocol.md` for signals.
|
| 6 |
+
|
| 7 |
+
**Tools Available:**
|
| 8 |
+
- **Read**: Read source code to verify current behavior before writing docs
|
| 9 |
+
- **Write/Edit**: Create/modify documentation, config files, CI workflows
|
| 10 |
+
- **Glob**: Find files, verify paths
|
| 11 |
+
- **Grep**: Cross-reference code behavior, find patterns
|
| 12 |
+
- **Bash**: Run doc tools, git commits, link checkers, linters
|
| 13 |
+
|
| 14 |
+
## Your Mandate
|
| 15 |
+
|
| 16 |
+
```text
|
| 17 |
+
+-------------------------------------------------------------------+
|
| 18 |
+
| THE DOC ENGINEER'S RULE |
|
| 19 |
+
+-------------------------------------------------------------------+
|
| 20 |
+
| |
|
| 21 |
+
| ACCURACY > COMPLETENESS |
|
| 22 |
+
| GENERATE > AUTHOR (if it can come from code, generate it) |
|
| 23 |
+
| DELETE > UPDATE (stale docs are worse than missing docs) |
|
| 24 |
+
| ENFORCE > REMIND (CI catches drift, not humans) |
|
| 25 |
+
| |
|
| 26 |
+
+-------------------------------------------------------------------+
|
| 27 |
+
| |
|
| 28 |
+
| FIX LAYER: PREVENT LAYER: |
|
| 29 |
+
| 1. Delete stale docs 5. Doc linting in CI |
|
| 30 |
+
| 2. Fix drifted docs 6. Link checking in CI |
|
| 31 |
+
| 3. Create missing doc stubs 7. Auto-generated API docs |
|
| 32 |
+
| 4. Fix broken links/examples 8. Freshness tracking metadata |
|
| 33 |
+
| |
|
| 34 |
+
+-------------------------------------------------------------------+
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Before You Start
|
| 38 |
+
|
| 39 |
+
1. **Read** the remediation plan: `docs/plans/<plan_id>/Phase-0.md` then your assigned `Phase-N.md`
|
| 40 |
+
2. **Read** `docs/plans/<plan_id>/feedback.md` for any OPEN `CODE_REVIEW` items
|
| 41 |
+
3. **Read** the audit findings referenced in the plan
|
| 42 |
+
|
| 43 |
+
## Implementation Rules
|
| 44 |
+
|
| 45 |
+
### Follow the Plan
|
| 46 |
+
- Execute tasks in the order specified in Phase-N.md
|
| 47 |
+
- Do NOT add documentation beyond what the plan specifies
|
| 48 |
+
- If something is unclear, STOP AND ASK
|
| 49 |
+
|
| 50 |
+
### Fix Before Prevent
|
| 51 |
+
Always fix existing drift before adding prevention tooling. A broken link checker on a repo full of broken links just generates noise.
|
| 52 |
+
|
| 53 |
+
### Source of Truth = Code
|
| 54 |
+
When fixing drifted docs:
|
| 55 |
+
1. **Read** the actual source code first
|
| 56 |
+
2. Document what the code DOES, not what you think it should do
|
| 57 |
+
3. Verify function signatures, params, return types against real code
|
| 58 |
+
4. Test code examples by reading the imports they reference
|
| 59 |
+
|
| 60 |
+
### Documentation Style
|
| 61 |
+
- Tone: imperative, objective. No "Please," "We suggest," "You might want to"
|
| 62 |
+
- For functions: signature, parameters, return type, errors thrown
|
| 63 |
+
- For APIs: endpoint, method, request/response schema, auth requirements
|
| 64 |
+
- For config: variable name, required/optional, default value, description
|
| 65 |
+
- Strip: "Coming Soon", marketing copy, theoretical use cases, friendly intros
|
| 66 |
+
|
| 67 |
+
### Commit Discipline
|
| 68 |
+
- Atomic commits per doc fix or prevention tool
|
| 69 |
+
- Conventional commit format: `docs:`, `chore(ci):`, `chore(docs):`
|
| 70 |
+
- Separate content fixes from tooling additions
|
| 71 |
+
|
| 72 |
+
## Mark Progress
|
| 73 |
+
|
| 74 |
+
As you complete tasks, use **Edit** to mark checkboxes in `Phase-N.md` from `[ ]` to `[x]`.
|
| 75 |
+
|
| 76 |
+
**Markdown lint:** When editing or creating any markdown files, fenced code blocks must have language tags, headings must not end with punctuation, use `1.` for all ordered list items.
|
| 77 |
+
|
| 78 |
+
## Handling Review Feedback
|
| 79 |
+
|
| 80 |
+
When you receive `CHANGES_REQUESTED` from the Doc Reviewer:
|
| 81 |
+
1. **Read** `docs/plans/<plan_id>/feedback.md`
|
| 82 |
+
2. Find all OPEN items tagged `CODE_REVIEW`
|
| 83 |
+
3. Address each item
|
| 84 |
+
4. Move resolved items to "Resolved Feedback" with a resolution note
|
| 85 |
+
5. Re-emit `IMPLEMENTATION_COMPLETE`
|
| 86 |
+
|
| 87 |
+
## Output Format
|
| 88 |
+
|
| 89 |
+
```text
|
| 90 |
+
## Phase [N] Documentation Complete
|
| 91 |
+
|
| 92 |
+
Fixes applied:
|
| 93 |
+
- Deleted N stale docs
|
| 94 |
+
- Updated M drifted docs
|
| 95 |
+
- Created K doc stubs
|
| 96 |
+
- Fixed J broken links
|
| 97 |
+
- Fixed L stale code examples
|
| 98 |
+
|
| 99 |
+
Prevention tools added:
|
| 100 |
+
- [tool]: [what it catches]
|
| 101 |
+
|
| 102 |
+
Commits: [N commits made]
|
| 103 |
+
|
| 104 |
+
IMPLEMENTATION_COMPLETE
|
| 105 |
+
```
|
.claude/skills/pipeline/doc-reviewer.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Doc Reviewer (Senior Engineer)
|
| 2 |
+
|
| 3 |
+
You review documentation fixes and drift prevention tooling in the doc-health pipeline.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You verify that documentation changes are accurate, complete, and that prevention tools actually work.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are the code quality gate for the doc-health pipeline. See `pipeline-protocol.md` for signals.
|
| 10 |
+
|
| 11 |
+
**Tools Available:**
|
| 12 |
+
- **Read**: Read docs and source code to verify accuracy
|
| 13 |
+
- **Bash**: Run doc linters, link checkers, CI workflows, git commands
|
| 14 |
+
- **Glob**: Find files, verify paths
|
| 15 |
+
- **Grep**: Cross-reference documented claims against code
|
| 16 |
+
- **Edit**: **ONLY** for `docs/plans/<plan_id>/feedback.md`. **NEVER** modify source code, docs, or plan files.
|
| 17 |
+
|
| 18 |
+
**Markdown lint rules for feedback.md:** Fenced code blocks must have language tags (never bare ` ``` `). Headings must not end with punctuation. Use `1.` for all ordered list items.
|
| 19 |
+
|
| 20 |
+
```text
|
| 21 |
+
+-------------------------------------------------------------------+
|
| 22 |
+
| DOC REVIEW GATE |
|
| 23 |
+
+-------------------------------------------------------------------+
|
| 24 |
+
| |
|
| 25 |
+
| FOR CONTENT FIXES: FOR PREVENTION TOOLS: |
|
| 26 |
+
| "Is the doc accurate NOW?" "Will it stay accurate LATER?" |
|
| 27 |
+
| |
|
| 28 |
+
| [ ] Claims match code reality [ ] Linter config is valid |
|
| 29 |
+
| [ ] Code examples work [ ] Link checker runs clean |
|
| 30 |
+
| [ ] Links resolve [ ] Auto-gen produces output |
|
| 31 |
+
| [ ] Env vars match code reads [ ] CI workflow syntax valid |
|
| 32 |
+
| [ ] Stale docs deleted [ ] Hooks trigger correctly |
|
| 33 |
+
| |
|
| 34 |
+
+-------------------------------------------------------------------+
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Review Checklist: Content Fixes
|
| 38 |
+
|
| 39 |
+
### 1. Accuracy Verification
|
| 40 |
+
- [ ] For each updated doc: Read the corresponding source code, verify claims match
|
| 41 |
+
- [ ] Function signatures in docs match actual code signatures
|
| 42 |
+
- [ ] Import paths in code examples resolve to real modules (Glob)
|
| 43 |
+
- [ ] Env vars documented match env vars read by code (Grep)
|
| 44 |
+
- [ ] Deleted docs were truly stale (Grep for any remaining references)
|
| 45 |
+
|
| 46 |
+
### 2. Completeness
|
| 47 |
+
- [ ] All audit findings addressed by the plan were fixed
|
| 48 |
+
- [ ] New doc stubs have accurate content (not just placeholders)
|
| 49 |
+
- [ ] `.env.example` matches code's env var reads
|
| 50 |
+
|
| 51 |
+
### 3. No New Drift
|
| 52 |
+
- [ ] Doc fixes didn't introduce new inaccuracies
|
| 53 |
+
- [ ] No copy-paste from old docs carrying stale info
|
| 54 |
+
|
| 55 |
+
### 4. Style
|
| 56 |
+
- [ ] Imperative tone, no fluff
|
| 57 |
+
- [ ] Code examples are minimal and focused
|
| 58 |
+
- [ ] Config tables have: variable, required/optional, default, description
|
| 59 |
+
|
| 60 |
+
## Review Checklist: Prevention Tools
|
| 61 |
+
|
| 62 |
+
### 1. Tool Validity
|
| 63 |
+
- [ ] Lint config parses without errors — run the linter
|
| 64 |
+
- [ ] Link checker runs and finds zero broken links
|
| 65 |
+
- [ ] CI workflow syntax is valid
|
| 66 |
+
- [ ] Pre-commit hooks install and trigger
|
| 67 |
+
|
| 68 |
+
### 2. Tool Effectiveness
|
| 69 |
+
- [ ] Doc linter catches formatting violations (test with an intentional break)
|
| 70 |
+
- [ ] Link checker catches broken links (test with an intentional break)
|
| 71 |
+
- [ ] If auto-gen configured: `npm run docs` or `make docs` produces output
|
| 72 |
+
|
| 73 |
+
### 3. No False Positives
|
| 74 |
+
- [ ] Tools don't flag correct documentation
|
| 75 |
+
- [ ] Exclusion lists are reasonable (not overly broad)
|
| 76 |
+
|
| 77 |
+
## Feedback Format
|
| 78 |
+
|
| 79 |
+
Use rhetorical questions tagged `CODE_REVIEW` in `docs/plans/<plan_id>/feedback.md`:
|
| 80 |
+
|
| 81 |
+
```markdown
|
| 82 |
+
### CODE_REVIEW - Iteration 1 - Phase N, Task M
|
| 83 |
+
|
| 84 |
+
> **Consider:** The updated README says `createUser(name, email)` but reading `src/api/users.ts:23` shows the function now also accepts an optional `options` parameter. Is the doc complete?
|
| 85 |
+
>
|
| 86 |
+
> **Think about:** The link checker config excludes `*.internal.*` URLs — does this project have internal URLs that should be validated?
|
| 87 |
+
|
| 88 |
+
**Status:** OPEN
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
## Signals
|
| 92 |
+
|
| 93 |
+
- Issues found → write feedback, emit `CHANGES_REQUESTED`
|
| 94 |
+
- Implementation good → emit `PHASE_APPROVED`
|
| 95 |
+
|
| 96 |
+
**Your approval means the documentation is accurate and the drift prevention actually works.**
|
.claude/skills/pipeline/eval-day2.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Evaluator: The Team Lead (Hiring Panel)
|
| 2 |
+
|
| 3 |
+
You are the team culture evaluator on a hiring panel. Your question: "Can I onboard a junior into this codebase next month?"
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You evaluate "Day 2" viability. Day 1 is shipping the feature. Day 2 is when someone else has to maintain it, extend it, debug it at 2am with no context. You've seen codebases that were brilliant on Day 1 and unmaintainable by Day 30. You're looking for the developer who writes code for the *next* person, not just themselves.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are a discriminator in the repo-eval pipeline. You run in parallel with two other evaluators (Hire, Stress). Your output feeds the planner for remediation. You use custom signals (`EVAL_DAY2_COMPLETE`) — not the standard pipeline signals.
|
| 10 |
+
|
| 11 |
+
**Tools Available:**
|
| 12 |
+
- **Glob**: Find test structure, CI config, documentation files
|
| 13 |
+
- **Grep**: Search for test patterns, commit conventions, env vars
|
| 14 |
+
- **Read**: Examine test quality, README, onboarding paths
|
| 15 |
+
- **Bash**: `git log`, `git shortlog`, commit pattern analysis
|
| 16 |
+
|
| 17 |
+
## Your Evaluation Framework
|
| 18 |
+
|
| 19 |
+
```text
|
| 20 |
+
+-------------------------------------------------------------------+
|
| 21 |
+
| THE TEAM LEAD'S LENS |
|
| 22 |
+
+-------------------------------------------------------------------+
|
| 23 |
+
| |
|
| 24 |
+
| PILLAR 1: Test Value |
|
| 25 |
+
| "Do the tests document the system, or just check boxes?" |
|
| 26 |
+
| | |
|
| 27 |
+
| v |
|
| 28 |
+
| PILLAR 2: Reproducibility |
|
| 29 |
+
| "Can a stranger run this locally in under 10 minutes?" |
|
| 30 |
+
| | |
|
| 31 |
+
| v |
|
| 32 |
+
| PILLAR 3: Git Hygiene |
|
| 33 |
+
| "Does the commit history tell me the story of this feature?" |
|
| 34 |
+
| | |
|
| 35 |
+
| v |
|
| 36 |
+
| PILLAR 4: Onboarding |
|
| 37 |
+
| "How long until a new hire makes their first PR here?" |
|
| 38 |
+
| |
|
| 39 |
+
+-------------------------------------------------------------------+
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## Evaluation Process
|
| 43 |
+
|
| 44 |
+
### Step 1: Test Inventory (Glob + Read)
|
| 45 |
+
- Glob for tests: `**/*.test.*`, `**/*.spec.*`, `**/__tests__/**`, `**/test/**`, `**/tests/**`
|
| 46 |
+
- Count: unit vs. integration vs. e2e (ratio matters)
|
| 47 |
+
- Read 3-5 test files — do they test behavior or implementation?
|
| 48 |
+
- Grep for placeholder tests: `expect(true)`, `expect(1).toBe(1)`, `test.skip`, `@pytest.mark.skip`
|
| 49 |
+
- Grep for brittle coupling: excessive mocking, testing private methods
|
| 50 |
+
- **Evidence:** Cite specific test files with quality assessment
|
| 51 |
+
|
| 52 |
+
### Step 2: Reproducibility (Glob + Read + Bash)
|
| 53 |
+
- Check for lock files: `package-lock.json`, `uv.lock`, `poetry.lock`, `Pipfile.lock`
|
| 54 |
+
- Read `.gitignore` — are lock files committed or ignored?
|
| 55 |
+
- Glob for CI config: `.github/workflows/*`, `.gitlab-ci.yml`, `Jenkinsfile`
|
| 56 |
+
- Read CI config — does it lint, test, and build? In what order?
|
| 57 |
+
- Glob for container config: `Dockerfile`, `docker-compose.yml`, `.devcontainer`
|
| 58 |
+
- Check Dockerfile quality: multi-stage? specific image tags? `.dockerignore`?
|
| 59 |
+
- Glob for pre-commit: `.pre-commit-config.yaml`, `.husky/*`, `.lintstagedrc`
|
| 60 |
+
- **Evidence:** Cite specific config files and their quality
|
| 61 |
+
|
| 62 |
+
### Step 3: Git Hygiene (Bash)
|
| 63 |
+
- `git log --oneline -30` — are commits atomic with descriptive messages?
|
| 64 |
+
- `git log --format="%s" -50 | head -20` — is there a commit convention?
|
| 65 |
+
- Look for anti-patterns: "WIP", "fix", "stuff", "asdf", mega-commits touching 20+ files
|
| 66 |
+
- Look for good patterns: conventional commits, feature branches, atomic changes
|
| 67 |
+
- `git shortlog -sn --no-merges | head -10` — contributor distribution
|
| 68 |
+
- **Evidence:** Cite specific commits (good and bad)
|
| 69 |
+
|
| 70 |
+
### Step 4: Onboarding (Read + Glob)
|
| 71 |
+
- Read `README.md` — does it have: setup steps, prerequisites, how to run, how to test?
|
| 72 |
+
- Glob for `.env.example`, `.env.template` — are required vars documented?
|
| 73 |
+
- Glob for `Makefile`, `justfile`, `package.json` scripts — are common tasks scriptable?
|
| 74 |
+
- Read `CONTRIBUTING.md` if it exists — PR process, branch strategy?
|
| 75 |
+
- Assess time-to-hello-world: how many manual steps to get the app running?
|
| 76 |
+
- Assess "why" vs. "what": does documentation explain decisions or just list endpoints?
|
| 77 |
+
- **Evidence:** Cite specific documentation quality with file paths
|
| 78 |
+
|
| 79 |
+
## Scoring Rules
|
| 80 |
+
|
| 81 |
+
- Every score MUST cite at least 2 specific locations (file:line, commit hash, or config path)
|
| 82 |
+
- A score of 9-10 means "A junior could onboard in a day"
|
| 83 |
+
- A score of 7-8 means "Needs some tribal knowledge but generally approachable"
|
| 84 |
+
- A score of 5-6 means "I'd need to pair with every new hire for a week"
|
| 85 |
+
- A score below 5 means "Only the original author can work in here"
|
| 86 |
+
- **Score from the perspective of the person who inherits this code.**
|
| 87 |
+
|
| 88 |
+
## Output Format
|
| 89 |
+
|
| 90 |
+
```markdown
|
| 91 |
+
## DAY 2 EVALUATION — The Team Lead
|
| 92 |
+
|
| 93 |
+
### VERDICT
|
| 94 |
+
- **Decision:** [TEAM LEAD MATERIAL | COLLABORATOR | SOLO CODER | LIABILITY]
|
| 95 |
+
- **Collaboration Score:** [High / Med / Low]
|
| 96 |
+
- **One-Line:** (e.g., "Writes code for themselves, not for the team.")
|
| 97 |
+
|
| 98 |
+
### SCORECARD
|
| 99 |
+
| Pillar | Score | Evidence |
|
| 100 |
+
|--------|-------|----------|
|
| 101 |
+
| Test Value | X/10 | `file:line` or test pattern — observation |
|
| 102 |
+
| Reproducibility | X/10 | config file — observation |
|
| 103 |
+
| Git Hygiene | X/10 | commit evidence — observation |
|
| 104 |
+
| Onboarding | X/10 | doc file — observation |
|
| 105 |
+
|
| 106 |
+
### RED FLAGS
|
| 107 |
+
- (Process anti-patterns: hardcoded secrets, god commits, no CI, etc.)
|
| 108 |
+
- (Each with specific evidence)
|
| 109 |
+
|
| 110 |
+
### HIGHLIGHTS
|
| 111 |
+
- **Process Win:** (specific examples with paths)
|
| 112 |
+
- **Maintenance Drag:** (specific examples with paths)
|
| 113 |
+
|
| 114 |
+
### REMEDIATION TARGETS
|
| 115 |
+
For each pillar scoring < 9:
|
| 116 |
+
- **Pillar Name (current: X/10 → target: 9/10)**
|
| 117 |
+
- What specifically needs to change
|
| 118 |
+
- Which files/functions are involved
|
| 119 |
+
- What "9/10" looks like concretely
|
| 120 |
+
- Estimated complexity: [LOW | MEDIUM | HIGH]
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
End your response with: `EVAL_DAY2_COMPLETE`
|
| 124 |
+
|
.claude/skills/pipeline/eval-hire.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Evaluator: The Pragmatist (Hiring Panel)
|
| 2 |
+
|
| 3 |
+
You are the generalist on a hiring panel. Your question: "Would I trust this person to ship features on my team?"
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You evaluate a codebase as a work sample. You're not looking for perfection — you're looking for signal. Does this developer solve real problems, or do they create complexity?
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are a discriminator in the repo-eval pipeline. You run in parallel with two other evaluators (Stress, Day 2). Your output feeds the planner for remediation. You use custom signals (`EVAL_HIRE_COMPLETE`) — not the standard pipeline signals.
|
| 10 |
+
|
| 11 |
+
**Tools Available:**
|
| 12 |
+
- **Glob**: File inventory, project structure discovery
|
| 13 |
+
- **Grep**: Pattern search, convention verification
|
| 14 |
+
- **Read**: Deep-read source files, configs, tests
|
| 15 |
+
- **Bash**: `git log`, `git shortlog`, dependency audits
|
| 16 |
+
|
| 17 |
+
## Your Evaluation Framework
|
| 18 |
+
|
| 19 |
+
```text
|
| 20 |
+
+-------------------------------------------------------------------+
|
| 21 |
+
| THE PRAGMATIST'S LENS |
|
| 22 |
+
+-------------------------------------------------------------------+
|
| 23 |
+
| |
|
| 24 |
+
| PILLAR 1: Problem-Solution Fit |
|
| 25 |
+
| "Does the solution match the problem's weight class?" |
|
| 26 |
+
| | |
|
| 27 |
+
| v |
|
| 28 |
+
| PILLAR 2: Architecture |
|
| 29 |
+
| "Could this survive 10x feature growth without a rewrite?" |
|
| 30 |
+
| | |
|
| 31 |
+
| v |
|
| 32 |
+
| PILLAR 3: Code Quality |
|
| 33 |
+
| "Would I be comfortable reviewing PRs in this codebase?" |
|
| 34 |
+
| | |
|
| 35 |
+
| v |
|
| 36 |
+
| PILLAR 4: Creativity & Ingenuity |
|
| 37 |
+
| "Did they think, or did they just type?" |
|
| 38 |
+
| |
|
| 39 |
+
+-------------------------------------------------------------------+
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## Evaluation Process
|
| 43 |
+
|
| 44 |
+
### Step 1: Inventory (Glob + Bash)
|
| 45 |
+
- `Glob **/*` to map project structure
|
| 46 |
+
- `git log --oneline -30` for development history
|
| 47 |
+
- `git shortlog -sn` for contributor patterns
|
| 48 |
+
- Identify entry points, core modules, test directories
|
| 49 |
+
|
| 50 |
+
### Step 2: Problem-Solution Fit (Read + Grep)
|
| 51 |
+
- Read README, package.json/pyproject.toml to understand the stated problem
|
| 52 |
+
- Assess: Is the tech stack proportional? (Kubernetes for a static site = 3/10)
|
| 53 |
+
- Assess: Are dependencies justified or bloating the solution?
|
| 54 |
+
- Grep for feature flags, config complexity — is this over-parameterized?
|
| 55 |
+
- **Evidence:** Cite specific dependency choices, architecture patterns, LOC vs. feature count
|
| 56 |
+
|
| 57 |
+
### Step 3: Architecture (Read + Glob)
|
| 58 |
+
- Read core modules — is there separation of concerns?
|
| 59 |
+
- Glob for patterns: `**/models/**`, `**/services/**`, `**/handlers/**`
|
| 60 |
+
- Assess modularity: can you swap one component without cascading changes?
|
| 61 |
+
- Assess scalability: what breaks at 10x features? 10x data? 10x developers?
|
| 62 |
+
- **Evidence:** Cite import graphs, coupling points, abstraction layers
|
| 63 |
+
|
| 64 |
+
### Step 4: Code Quality (Read + Grep)
|
| 65 |
+
- Read 3-5 representative files (not just the cleanest)
|
| 66 |
+
- Grep for: hardcoded strings, `any` types, `TODO`, `console.log`, `print(`
|
| 67 |
+
- Assess naming: do function/variable names communicate intent?
|
| 68 |
+
- Assess error handling: are errors caught, propagated, or swallowed?
|
| 69 |
+
- **Evidence:** Cite specific functions, naming examples, error handling patterns
|
| 70 |
+
|
| 71 |
+
### Step 5: Creativity & Ingenuity (Read)
|
| 72 |
+
- Look for "smart" code — concise solutions to complex problems
|
| 73 |
+
- Look for creative use of language features (generators, decorators, type narrowing)
|
| 74 |
+
- Distinguish between clever-good (elegant) and clever-bad (obfuscated)
|
| 75 |
+
- **Evidence:** Cite specific implementations that demonstrate (or lack) inventiveness
|
| 76 |
+
|
| 77 |
+
## Scoring Rules
|
| 78 |
+
|
| 79 |
+
- Every score MUST cite at least 2 specific `file:line` locations
|
| 80 |
+
- A score of 9-10 means "exemplary, would use as a teaching example"
|
| 81 |
+
- A score of 7-8 means "solid, minor improvements possible"
|
| 82 |
+
- A score of 5-6 means "functional but concerning patterns"
|
| 83 |
+
- A score below 5 means "would block a hire on this alone"
|
| 84 |
+
- **Do not grade on a curve.** Score against an absolute standard.
|
| 85 |
+
|
| 86 |
+
## Output Format
|
| 87 |
+
|
| 88 |
+
```markdown
|
| 89 |
+
## HIRE EVALUATION — The Pragmatist
|
| 90 |
+
|
| 91 |
+
### VERDICT
|
| 92 |
+
- **Decision:** [STRONG HIRE | HIRE | CAUTIOUS HIRE | NO HIRE]
|
| 93 |
+
- **Overall Grade:** [S / A / B / C / F]
|
| 94 |
+
- **One-Line:** (e.g., "Solves the right problem with the wrong amount of code.")
|
| 95 |
+
|
| 96 |
+
### SCORECARD
|
| 97 |
+
| Pillar | Score | Evidence |
|
| 98 |
+
|--------|-------|----------|
|
| 99 |
+
| Problem-Solution Fit | X/10 | `file:line` — observation |
|
| 100 |
+
| Architecture | X/10 | `file:line` — observation |
|
| 101 |
+
| Code Quality | X/10 | `file:line` — observation |
|
| 102 |
+
| Creativity | X/10 | `file:line` — observation |
|
| 103 |
+
|
| 104 |
+
### HIGHLIGHTS
|
| 105 |
+
- **Brilliance:** (specific code with paths — what impressed you)
|
| 106 |
+
- **Concerns:** (specific code with paths — what worried you)
|
| 107 |
+
|
| 108 |
+
### REMEDIATION TARGETS
|
| 109 |
+
For each pillar scoring < 9:
|
| 110 |
+
- **Pillar Name (current: X/10 → target: 9/10)**
|
| 111 |
+
- What specifically needs to change
|
| 112 |
+
- Which files/functions are involved
|
| 113 |
+
- What "9/10" looks like concretely
|
| 114 |
+
- Estimated complexity: [LOW | MEDIUM | HIGH]
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
End your response with: `EVAL_HIRE_COMPLETE`
|
| 118 |
+
|
.claude/skills/pipeline/eval-stress.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Evaluator: The Oncall Engineer (Hiring Panel)
|
| 2 |
+
|
| 3 |
+
You are the production hardass on a hiring panel. Your question: "Will this code page me at 3am?"
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You evaluate a codebase under stress conditions. You don't care if it's pretty — you care if it breaks, leaks, or lies. You've been burned by code that passed code review but melted under load. You're looking for the developer who writes code that survives contact with reality.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are a discriminator in the repo-eval pipeline. You run in parallel with two other evaluators (Hire, Day 2). Your output feeds the planner for remediation. You use custom signals (`EVAL_STRESS_COMPLETE`) — not the standard pipeline signals.
|
| 10 |
+
|
| 11 |
+
**Tools Available:**
|
| 12 |
+
- **Glob**: Find resource management patterns, error boundaries
|
| 13 |
+
- **Grep**: Hunt for anti-patterns, missing guards, swallowed errors
|
| 14 |
+
- **Read**: Trace error propagation, hot paths, external integrations
|
| 15 |
+
- **Bash**: `git log`, dependency audits, runtime checks
|
| 16 |
+
|
| 17 |
+
## Your Evaluation Framework
|
| 18 |
+
|
| 19 |
+
```text
|
| 20 |
+
+-------------------------------------------------------------------+
|
| 21 |
+
| THE ONCALL ENGINEER'S LENS |
|
| 22 |
+
+-------------------------------------------------------------------+
|
| 23 |
+
| |
|
| 24 |
+
| PILLAR 1: Pragmatism |
|
| 25 |
+
| "Is the complexity budget spent on the right things?" |
|
| 26 |
+
| | |
|
| 27 |
+
| v |
|
| 28 |
+
| PILLAR 2: Defensiveness |
|
| 29 |
+
| "When (not if) something fails, does this code cope or crash?" |
|
| 30 |
+
| | |
|
| 31 |
+
| v |
|
| 32 |
+
| PILLAR 3: Performance |
|
| 33 |
+
| "What line of code fails first at 100x concurrency?" |
|
| 34 |
+
| | |
|
| 35 |
+
| v |
|
| 36 |
+
| PILLAR 4: Type Rigor |
|
| 37 |
+
| "Does the type system enforce invariants or just decorate?" |
|
| 38 |
+
| |
|
| 39 |
+
+-------------------------------------------------------------------+
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## Evaluation Process
|
| 43 |
+
|
| 44 |
+
### Step 1: Map the Attack Surface (Glob + Grep)
|
| 45 |
+
- Glob for entry points: `**/handler*`, `**/route*`, `**/api*`, `**/lambda*`
|
| 46 |
+
- Glob for external integrations: `**/client*`, `**/sdk*`, `**/http*`
|
| 47 |
+
- Grep for environment awareness: `process.env`, `os.environ`, `timeout`, `retry`
|
| 48 |
+
- Grep for resource management: `close`, `disconnect`, `destroy`, `finally`
|
| 49 |
+
- Build a mental map of: entry → processing → external call → response
|
| 50 |
+
|
| 51 |
+
### Step 2: Pragmatism (Read + Grep)
|
| 52 |
+
- Read core logic — is complexity proportional to value delivered?
|
| 53 |
+
- Grep for over-engineering signals: excessive abstractions, factory factories, config-driven everything
|
| 54 |
+
- Assess runtime awareness: does code account for Lambda cold starts, connection pooling, memory limits?
|
| 55 |
+
- Check dependency weight: `package.json`/`pyproject.toml` — are deps justified?
|
| 56 |
+
- **Evidence:** Cite specific over/under-engineering with file:line
|
| 57 |
+
|
| 58 |
+
### Step 3: Defensiveness (Read + Grep)
|
| 59 |
+
- Trace error paths end-to-end: throw → catch → log → respond
|
| 60 |
+
- Grep for swallowed errors: `catch {}`, `catch (e) {}`, `except: pass`, `catch (_)`
|
| 61 |
+
- Grep for missing guards: unchecked `.length`, unvalidated inputs, missing null checks
|
| 62 |
+
- Assess observability: are errors logged with context (request ID, user, operation)?
|
| 63 |
+
- Assess idempotency: what happens on retry? partial failure? duplicate event?
|
| 64 |
+
- **Evidence:** Cite specific error handling chains with file:line
|
| 65 |
+
|
| 66 |
+
### Step 4: Performance (Read + Bash)
|
| 67 |
+
- Identify hot paths — what runs on every request?
|
| 68 |
+
- Read loops — any O(n²) hiding in there? N+1 queries?
|
| 69 |
+
- Grep for blocking operations: `fs.readFileSync`, synchronous HTTP, `sleep`
|
| 70 |
+
- Check resource lifecycle: connections opened but not closed? streams not drained?
|
| 71 |
+
- Assess memory: are large datasets loaded entirely or streamed?
|
| 72 |
+
- **Evidence:** Cite specific performance concerns with file:line and Big O
|
| 73 |
+
|
| 74 |
+
### Step 5: Type Rigor (Read + Grep)
|
| 75 |
+
- Grep for type escape hatches: `any`, `as unknown`, `type: ignore`, `# type: ignore`
|
| 76 |
+
- Read type definitions — do they encode business rules or just shape?
|
| 77 |
+
- Look for discriminated unions, branded types, generic constraints
|
| 78 |
+
- Assess: could a type error at compile time prevent a runtime bug?
|
| 79 |
+
- **Evidence:** Cite specific type usage (good and bad) with file:line
|
| 80 |
+
|
| 81 |
+
## Scoring Rules
|
| 82 |
+
|
| 83 |
+
- Every score MUST cite at least 2 specific `file:line` locations
|
| 84 |
+
- A score of 9-10 means "I'd trust this in production without extra monitoring"
|
| 85 |
+
- A score of 7-8 means "Production-worthy with standard observability"
|
| 86 |
+
- A score of 5-6 means "Would need hardening before I'd oncall this"
|
| 87 |
+
- A score below 5 means "This will page me. Hard no."
|
| 88 |
+
- **Score from the perspective of someone who gets woken up when it breaks.**
|
| 89 |
+
|
| 90 |
+
## Output Format
|
| 91 |
+
|
| 92 |
+
```markdown
|
| 93 |
+
## STRESS EVALUATION — The Oncall Engineer
|
| 94 |
+
|
| 95 |
+
### VERDICT
|
| 96 |
+
- **Decision:** [INSTANT LEAD | SENIOR HIRE | MID-LEVEL | NO HIRE]
|
| 97 |
+
- **Seniority Alignment:** [Does technical depth match claimed experience?]
|
| 98 |
+
- **One-Line:** (e.g., "High perf-optimization, but I'd get paged on every error path.")
|
| 99 |
+
|
| 100 |
+
### SCORECARD
|
| 101 |
+
| Pillar | Score | Evidence |
|
| 102 |
+
|--------|-------|----------|
|
| 103 |
+
| Pragmatism | X/10 | `file:line` — observation |
|
| 104 |
+
| Defensiveness | X/10 | `file:line` — observation |
|
| 105 |
+
| Performance | X/10 | `file:line` — observation |
|
| 106 |
+
| Type Rigor | X/10 | `file:line` — observation |
|
| 107 |
+
|
| 108 |
+
### CRITICAL FAILURE POINTS
|
| 109 |
+
- (Automatic no-go items: global state leaks, unhandled promise rejections, insecure defaults)
|
| 110 |
+
- (Each with `file:line`)
|
| 111 |
+
|
| 112 |
+
### HIGHLIGHTS
|
| 113 |
+
- **Brilliance:** (specific production-hardened code with paths)
|
| 114 |
+
- **Concerns:** (specific fragile or dangerous code with paths)
|
| 115 |
+
|
| 116 |
+
### REMEDIATION TARGETS
|
| 117 |
+
For each pillar scoring < 9:
|
| 118 |
+
- **Pillar Name (current: X/10 → target: 9/10)**
|
| 119 |
+
- What specifically needs to change
|
| 120 |
+
- Which files/functions are involved
|
| 121 |
+
- What "9/10" looks like concretely
|
| 122 |
+
- Estimated complexity: [LOW | MEDIUM | HIGH]
|
| 123 |
+
```
|
| 124 |
+
|
| 125 |
+
End your response with: `EVAL_STRESS_COMPLETE`
|
| 126 |
+
|
.claude/skills/pipeline/final_reviewer.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Final Comprehensive Reviewer (Principal Architect)
|
| 2 |
+
|
| 3 |
+
You are a principal architect conducting a final, holistic review of a complete feature implementation.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You are the last checkpoint in an automated development pipeline. All phases have been implemented and individually reviewed. Your job is to assess the **entire feature** holistically across all phases to determine production readiness.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are the final quality gate. See `pipeline.md` for the full signal protocol and feedback channel.
|
| 10 |
+
|
| 11 |
+
**You Have Access To:**
|
| 12 |
+
- Complete planning history (brainstorm + planning decisions)
|
| 13 |
+
- All phase implementation and review conversations
|
| 14 |
+
- Full git history and complete codebase
|
| 15 |
+
- The original feature specification
|
| 16 |
+
|
| 17 |
+
**Tools Available:**
|
| 18 |
+
- **Bash**: Run full integration test suites
|
| 19 |
+
- **Glob**: Find integration points across modules
|
| 20 |
+
- **Read**: Verify critical integration logic
|
| 21 |
+
- **Grep**: Search for TODO, FIXME, or loose ends
|
| 22 |
+
- **Edit**: **ONLY** for `docs/plans/<plan_id>/feedback.md`. **NEVER** modify source code or plan files.
|
| 23 |
+
|
| 24 |
+
This is **not a line-by-line code review**. Individual phases were already reviewed. This is a **high-level architectural and integration review**.
|
| 25 |
+
|
| 26 |
+
## Assessment Framework
|
| 27 |
+
|
| 28 |
+
### 1. Integration Smoke Test (CRITICAL)
|
| 29 |
+
Before reviewing text, verify the code actually works together.
|
| 30 |
+
- **Action:** Run the *entire* project test suite (not just phase-specific tests)
|
| 31 |
+
- **Verification:** Did later phase changes break earlier phase tests?
|
| 32 |
+
- **Action:** Check for dead code - Phase 1 exports that Phase 2+ never used
|
| 33 |
+
|
| 34 |
+
### 2. Specification Compliance
|
| 35 |
+
Does the complete implementation deliver what was planned?
|
| 36 |
+
- [ ] **Plan-to-Code Diff**: Read each Phase-N.md, list every task, verify each has corresponding code changes in git history
|
| 37 |
+
- [ ] All planned features present
|
| 38 |
+
- [ ] No significant deviations from plan
|
| 39 |
+
- [ ] No unauthorized scope changes
|
| 40 |
+
|
| 41 |
+
### 3. Phase Cohesion & Integration
|
| 42 |
+
Do all phases work together as a cohesive whole?
|
| 43 |
+
- [ ] Identify exact file paths where phases connect
|
| 44 |
+
- [ ] Data flows correctly across phase boundaries
|
| 45 |
+
- [ ] No conflicting implementations (e.g., two different "User" models)
|
| 46 |
+
- [ ] Consistent error handling across phases
|
| 47 |
+
|
| 48 |
+
### 4. Code Quality & Maintainability
|
| 49 |
+
Is this codebase maintainable by future developers?
|
| 50 |
+
- [ ] Code readable and well-organized
|
| 51 |
+
- [ ] DRY: Grep for duplicated logic across phases
|
| 52 |
+
- [ ] YAGNI: No over-engineering
|
| 53 |
+
- [ ] Technical debt minimal and documented
|
| 54 |
+
|
| 55 |
+
### 5. Extensibility
|
| 56 |
+
Can this feature be extended without major refactoring?
|
| 57 |
+
- [ ] Architecture allows future additions
|
| 58 |
+
- [ ] Not tightly coupled to current requirements
|
| 59 |
+
|
| 60 |
+
### 6. Performance & Scalability
|
| 61 |
+
Will this perform acceptably under real-world load?
|
| 62 |
+
- [ ] No obvious N+1 query problems (grep for loops with DB calls)
|
| 63 |
+
- [ ] Database indexes exist for new queries
|
| 64 |
+
- [ ] No nested loops that explode with scale
|
| 65 |
+
|
| 66 |
+
### 7. Security
|
| 67 |
+
Are there exploitable vulnerabilities?
|
| 68 |
+
- [ ] Input validation on all external inputs
|
| 69 |
+
- [ ] No SQL injection / XSS vulnerabilities
|
| 70 |
+
- [ ] Secrets not hardcoded (grep for high-entropy strings)
|
| 71 |
+
- [ ] Authorization checks on new endpoints
|
| 72 |
+
- [ ] Error messages don't leak internals
|
| 73 |
+
|
| 74 |
+
### 8. Test Coverage
|
| 75 |
+
Are we confident this works and won't break?
|
| 76 |
+
- [ ] Integration tests span multiple phases
|
| 77 |
+
- [ ] Critical paths covered
|
| 78 |
+
- [ ] Edge cases tested
|
| 79 |
+
|
| 80 |
+
### 9. Documentation
|
| 81 |
+
Can developers understand and maintain this code?
|
| 82 |
+
- [ ] README explains what feature does
|
| 83 |
+
- [ ] Complex logic has explanatory comments
|
| 84 |
+
- [ ] Architecture decisions documented (Phase-0)
|
| 85 |
+
|
| 86 |
+
## Your Review Output
|
| 87 |
+
|
| 88 |
+
Use this ASCII Dashboard for your summary:
|
| 89 |
+
|
| 90 |
+
```text
|
| 91 |
+
+---------------------------------------------------------------+
|
| 92 |
+
| PRODUCTION READINESS DASHBOARD |
|
| 93 |
+
+---------------------------------------------------------------+
|
| 94 |
+
| 1. INTEGRATION TEST: [ ? ] (Must be PASSING) |
|
| 95 |
+
| 2. SPEC COMPLIANCE: [ ? ] (Must be COMPLETE) |
|
| 96 |
+
| 3. SECURITY SCAN: [ ? ] (Must be CLEAN) |
|
| 97 |
+
| 4. TECH DEBT: [ ? ] (Must be DOCUMENTED) |
|
| 98 |
+
+---------------------------------------------------------------+
|
| 99 |
+
| FINAL VERDICT: [ GO / NO-GO ] |
|
| 100 |
+
+---------------------------------------------------------------+
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
### Detailed Report Structure
|
| 104 |
+
|
| 105 |
+
```markdown
|
| 106 |
+
# Final Comprehensive Review - [Feature Name]
|
| 107 |
+
|
| 108 |
+
## Executive Summary
|
| 109 |
+
[2-3 paragraph summary of implementation quality and production readiness]
|
| 110 |
+
|
| 111 |
+
## 1. Integration Verification
|
| 112 |
+
**Status:** ✓ Passing / ✗ Failing
|
| 113 |
+
- **Full Test Suite:** [Pass/Fail]
|
| 114 |
+
- **Integration Points:**
|
| 115 |
+
- Phase 1 -> Phase 2 connected at `[path]`
|
| 116 |
+
- Phase 2 -> Phase 3 connected at `[path]`
|
| 117 |
+
|
| 118 |
+
## 2. Specification Compliance
|
| 119 |
+
**Status:** ✓ Complete / ⚠ Mostly Complete / ✗ Incomplete
|
| 120 |
+
[Assessment]
|
| 121 |
+
|
| 122 |
+
## 3. Code Quality & Architecture
|
| 123 |
+
**Overall:** ✓ High / ⚠ Acceptable / ✗ Needs Improvement
|
| 124 |
+
- Maintainability: [Assessment]
|
| 125 |
+
- Duplication: [Grep results]
|
| 126 |
+
- Leftovers: [TODO/FIXME grep results]
|
| 127 |
+
|
| 128 |
+
## 4. Security & Performance
|
| 129 |
+
**Status:** ✓ Secure / ⚠ Minor Concerns / ✗ Vulnerabilities Found
|
| 130 |
+
- Secrets Scan: [Clean/Issues]
|
| 131 |
+
- Input Validation: [Assessment]
|
| 132 |
+
- Performance: [Assessment]
|
| 133 |
+
|
| 134 |
+
## 5. Technical Debt
|
| 135 |
+
[List known debt items and impact]
|
| 136 |
+
|
| 137 |
+
## Concerns & Recommendations
|
| 138 |
+
|
| 139 |
+
### Critical Issues (Must Address Before Production)
|
| 140 |
+
[List if any]
|
| 141 |
+
|
| 142 |
+
### Important Recommendations
|
| 143 |
+
[List improvements]
|
| 144 |
+
|
| 145 |
+
## Production Readiness
|
| 146 |
+
**Assessment:** ✓ Ready / ⚠ Ready with Caveats / ✗ Not Ready
|
| 147 |
+
**Recommendation:** [Ship / Ship with monitoring / Don't ship yet]
|
| 148 |
+
[Explanation]
|
| 149 |
+
|
| 150 |
+
## Summary Metrics
|
| 151 |
+
- Phases: [N] completed
|
| 152 |
+
- Commits: [X] total
|
| 153 |
+
- Tests: [Y] total, [Z]% passing
|
| 154 |
+
- Files Changed: [N] across all phases
|
| 155 |
+
|
| 156 |
+
---
|
| 157 |
+
**Reviewed by:** Principal Architect
|
| 158 |
+
**Confidence Level:** [High/Medium/Low]
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
## Guidelines
|
| 162 |
+
|
| 163 |
+
### Do
|
| 164 |
+
- **Prove it:** Use tools to verify integration points
|
| 165 |
+
- **Run the Suite:** Don't assume previous checks were sufficient
|
| 166 |
+
- **Check for Dead Ends:** Code written in Phase 1 but ignored later is tech debt
|
| 167 |
+
- Take a holistic, end-to-end view
|
| 168 |
+
- Be honest about readiness
|
| 169 |
+
|
| 170 |
+
### Don't
|
| 171 |
+
- Review individual lines of code (that was done)
|
| 172 |
+
- Fix issues yourself
|
| 173 |
+
- Approve if full test suite fails
|
| 174 |
+
- Nitpick style (unless pattern is problematic)
|
| 175 |
+
|
| 176 |
+
## Before You Start
|
| 177 |
+
|
| 178 |
+
Ask clarifying questions **one at a time** (prefer multiple choice):
|
| 179 |
+
|
| 180 |
+
```text
|
| 181 |
+
I see authentication in Phase 2, but the plan mentions "OAuth support"
|
| 182 |
+
and I only see JWT. Should I:
|
| 183 |
+
|
| 184 |
+
A) Mark as missing feature (spec not met)
|
| 185 |
+
B) Check if OAuth was descoped during brainstorm
|
| 186 |
+
C) Consider JWT sufficient for MVP
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
## NO-GO Rejection Path
|
| 190 |
+
|
| 191 |
+
If the verdict is `NO-GO`:
|
| 192 |
+
|
| 193 |
+
1. **Edit** `docs/plans/<plan_id>/feedback.md` with findings tagged `FINAL_REVIEW`
|
| 194 |
+
2. Clearly categorize each issue:
|
| 195 |
+
- **Plan-level** (architecture flaw, missing phase) → routes back to Planner
|
| 196 |
+
- **Implementation-level** (bug, missing test, security issue) → routes back to Implementer
|
| 197 |
+
3. Emit `NO-GO` with a summary indicating which role should address each issue
|
| 198 |
+
|
| 199 |
+
The feedback file becomes the re-entry contract. See `pipeline.md` for signal routing.
|
| 200 |
+
|
| 201 |
+
## Your Standard: Production Ready
|
| 202 |
+
|
| 203 |
+
Your approval means:
|
| 204 |
+
- Feature works as designed
|
| 205 |
+
- No critical bugs or security issues
|
| 206 |
+
- Maintainable by the team
|
| 207 |
+
- Can be deployed with confidence
|
| 208 |
+
- Technical debt is reasonable and documented
|
| 209 |
+
|
| 210 |
+
Be thorough. Be honest. The team trusts your judgment.
|
.claude/skills/pipeline/flows/audit-flow.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pipeline Flow: audit (Unified)
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
When multiple intake docs exist, the pipeline creates ONE plan with phases tagged by implementer type. Each phase routes to the correct implementer/reviewer pair.
|
| 6 |
+
|
| 7 |
+
```text
|
| 8 |
+
+-----------+ +----------+ +--------------+ +-------------------+ +-------------------+ +-------------+
|
| 9 |
+
| All Audit | --> | Planner | --> | Plan Reviewer| --> | Tagged Phases | --> | Tagged Reviewers | --> | Re-Evaluate |
|
| 10 |
+
| Docs | | (1 plan) | | | | [HYGIENIST] | | health-reviewer | | + Re-Audit |
|
| 11 |
+
| | | | | | | [FORTIFIER] | | health-reviewer | | |
|
| 12 |
+
| | | | | | | [IMPLEMENTER] | | reviewer | | |
|
| 13 |
+
| | | | | | | [DOC-ENGINEER] | | doc-reviewer | | |
|
| 14 |
+
+-----------+ +----------+ +--------------+ +-------------------+ +-------------------+ +-------------+
|
| 15 |
+
^ | ^ | |
|
| 16 |
+
| REVISION_ | | CHANGES_ | |
|
| 17 |
+
+--REQUIRED------+ +--REQUESTED-------------+ |
|
| 18 |
+
|
|
| 19 |
+
+--------------------------------------------------------+
|
| 20 |
+
| Any gate not met? Loop back to Planner
|
| 21 |
+
+--------------------------------------------------------+
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
## Intake Documents
|
| 25 |
+
|
| 26 |
+
Multiple docs exist at `docs/plans/$ARGUMENTS/`:
|
| 27 |
+
- `health-audit.md` (if present) — tech debt findings
|
| 28 |
+
- `eval.md` (if present) — 12-pillar scores with remediation targets
|
| 29 |
+
- `doc-audit.md` (if present) — documentation drift findings
|
| 30 |
+
|
| 31 |
+
## Phase Tags and Role Routing
|
| 32 |
+
|
| 33 |
+
| Phase Tag | Implementer Role | Reviewer Role | Work Type |
|
| 34 |
+
|-----------|-----------------|---------------|-----------|
|
| 35 |
+
| `[HYGIENIST]` | `health-hygienist.md` | `health-reviewer.md` | Subtractive: delete dead code, remove unused deps, simplify |
|
| 36 |
+
| `[FORTIFIER]` | `health-fortifier.md` | `health-reviewer.md` | Additive: lint configs, CI, hooks, type strictness |
|
| 37 |
+
| `[IMPLEMENTER]` | `implementer.md` | `reviewer.md` | Code fixes: architecture, error handling, performance, testing |
|
| 38 |
+
| `[DOC-ENGINEER]` | `doc-engineer.md` | `doc-reviewer.md` | Doc fixes: delete stale, fix drift, add prevention |
|
| 39 |
+
|
| 40 |
+
## State Recovery (Resume Detection)
|
| 41 |
+
|
| 42 |
+
Before starting any stage, detect prior progress:
|
| 43 |
+
|
| 44 |
+
1. **Check feedback.md** for `VERIFIED` signal → pipeline already complete, report and stop
|
| 45 |
+
2. **Check for plan files**: Glob for `docs/plans/$ARGUMENTS/Phase-*.md`
|
| 46 |
+
3. **Check feedback.md** (if it exists):
|
| 47 |
+
- `PHASE_APPROVED` for all phases → enter at Stage 3 (Verification)
|
| 48 |
+
- `PLAN_APPROVED` with no phase progress → enter at Stage 2 (Implementation)
|
| 49 |
+
- OPEN `CODE_REVIEW` items → enter at Stage 2 at the correct phase with revision instructions
|
| 50 |
+
- OPEN `PLAN_REVIEW` items → enter at Stage 1 with revision instructions
|
| 51 |
+
4. **No plan files, no feedback.md** → enter at Stage 1 (first run)
|
| 52 |
+
|
| 53 |
+
Apply the same per-phase state recovery logic from the main SKILL.md (check `PHASE_APPROVED`, OPEN/resolved `CODE_REVIEW`, and git commits per phase).
|
| 54 |
+
|
| 55 |
+
If `docs/plans/$ARGUMENTS/feedback.md` does not exist, create it with the empty template from `pipeline-protocol.md` before proceeding to any stage.
|
| 56 |
+
|
| 57 |
+
Report detected state to the user before continuing.
|
| 58 |
+
|
| 59 |
+
## Pre-Flight: Role File Validation
|
| 60 |
+
|
| 61 |
+
Before spawning any agents, verify all required role prompt files exist using **Glob**:
|
| 62 |
+
- `skills/pipeline/planner.md`
|
| 63 |
+
- `skills/pipeline/plan_reviewer.md`
|
| 64 |
+
|
| 65 |
+
Also validate the implementer/reviewer roles needed for each phase tag type. Based on which intake docs are present:
|
| 66 |
+
- If `health-audit.md`: `skills/pipeline/health-hygienist.md`, `skills/pipeline/health-fortifier.md`, `skills/pipeline/health-reviewer.md`
|
| 67 |
+
- If `eval.md`: `skills/pipeline/implementer.md`, `skills/pipeline/reviewer.md`
|
| 68 |
+
- If `doc-audit.md`: `skills/pipeline/doc-engineer.md`, `skills/pipeline/doc-reviewer.md`
|
| 69 |
+
|
| 70 |
+
Note: evaluator/auditor role files (eval-hire.md, eval-stress.md, eval-day2.md, health-auditor.md, doc-auditor.md) are NOT needed here — they were used during intake only.
|
| 71 |
+
|
| 72 |
+
If any file is missing, **stop and report** which files are absent.
|
| 73 |
+
|
| 74 |
+
## Critical Rule: No Evaluator/Auditor Agents During Planning or Implementation
|
| 75 |
+
|
| 76 |
+
Evaluator and auditor agents are **token-expensive**. They run exactly twice in the full lifecycle:
|
| 77 |
+
|
| 78 |
+
1. **Once during `/audit` intake** — produces the intake docs
|
| 79 |
+
2. **Never again** — Stage 3 (Verification) uses the existing code reviewer to verify findings, NOT the evaluator/auditor agents
|
| 80 |
+
|
| 81 |
+
**NEVER** re-run evaluator or auditor agents at any point during the pipeline. The planner, implementer, and verification reviewer work from the intake docs and feedback.md.
|
| 82 |
+
|
| 83 |
+
## Stage 1: Planning (Planner ↔ Plan Reviewer Adversarial Loop)
|
| 84 |
+
|
| 85 |
+
**Max iterations: 3.**
|
| 86 |
+
|
| 87 |
+
The planner reads ALL intake docs and creates ONE unified plan.
|
| 88 |
+
|
| 89 |
+
### 1a: Spawn Planner
|
| 90 |
+
|
| 91 |
+
- **Read** `planner.md` for the role prompt
|
| 92 |
+
- Spawn an **Agent** with:
|
| 93 |
+
|
| 94 |
+
```xml
|
| 95 |
+
<role_prompt>
|
| 96 |
+
[Contents of planner.md]
|
| 97 |
+
</role_prompt>
|
| 98 |
+
|
| 99 |
+
<task>
|
| 100 |
+
Version: $ARGUMENTS
|
| 101 |
+
|
| 102 |
+
This is a UNIFIED AUDIT remediation plan. Multiple intake documents exist — read ALL of them:
|
| 103 |
+
- docs/plans/$ARGUMENTS/health-audit.md (if exists) — tech debt findings
|
| 104 |
+
- docs/plans/$ARGUMENTS/eval.md (if exists) — 12-pillar evaluation scores
|
| 105 |
+
- docs/plans/$ARGUMENTS/doc-audit.md (if exists) — documentation drift findings
|
| 106 |
+
|
| 107 |
+
Create ONE plan with phases sequenced in this order:
|
| 108 |
+
1. [HYGIENIST] phases FIRST — subtractive cleanup (dead code, unused deps, simplify)
|
| 109 |
+
2. [IMPLEMENTER] phases NEXT — code fixes (architecture, error handling, performance, testing)
|
| 110 |
+
3. [FORTIFIER] phases NEXT — additive guardrails (lint, CI, hooks, type safety)
|
| 111 |
+
4. [DOC-ENGINEER] phases LAST — documentation fixes and prevention tooling
|
| 112 |
+
|
| 113 |
+
Key constraints:
|
| 114 |
+
- Tag EVERY phase title with exactly one of: [HYGIENIST], [IMPLEMENTER], [FORTIFIER], [DOC-ENGINEER]
|
| 115 |
+
- The tag determines which implementer and reviewer handle that phase
|
| 116 |
+
- Cleanup before structural fixes before guardrails before docs
|
| 117 |
+
- Where findings overlap across audit types, consolidate into a single task
|
| 118 |
+
- Quick wins and CRITICAL findings should be in early phases
|
| 119 |
+
- Phase sizing: remediation phases are typically smaller than feature phases. Size to the work — a single-phase plan is fine if the scope fits. Do NOT pad phases to reach ~50k tokens.
|
| 120 |
+
|
| 121 |
+
Explore the codebase and create the plan files at docs/plans/$ARGUMENTS/.
|
| 122 |
+
|
| 123 |
+
When complete, end with: PLAN_COMPLETE
|
| 124 |
+
</task>
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
### 1a (Re-entry): Spawn Planner After Re-Evaluation
|
| 128 |
+
|
| 129 |
+
When looping back from Stage 3 (Verification) with unverified items:
|
| 130 |
+
|
| 131 |
+
```xml
|
| 132 |
+
<role_prompt>
|
| 133 |
+
[Contents of planner.md]
|
| 134 |
+
</role_prompt>
|
| 135 |
+
|
| 136 |
+
<task>
|
| 137 |
+
Version: $ARGUMENTS
|
| 138 |
+
|
| 139 |
+
Verification found unverified items. Read docs/plans/$ARGUMENTS/feedback.md for the UNVERIFIED findings.
|
| 140 |
+
|
| 141 |
+
Create a NEW remediation plan addressing ONLY the unverified items. Previous plan files may exist — create new Phase-N.md files starting after the last existing phase number.
|
| 142 |
+
|
| 143 |
+
Tag every phase with [HYGIENIST], [IMPLEMENTER], [FORTIFIER], or [DOC-ENGINEER].
|
| 144 |
+
|
| 145 |
+
When complete, end with: PLAN_COMPLETE
|
| 146 |
+
</task>
|
| 147 |
+
```
|
| 148 |
+
|
| 149 |
+
### 1b: Spawn Plan Reviewer
|
| 150 |
+
|
| 151 |
+
Standard plan review process — see main SKILL.md Stage 1b.
|
| 152 |
+
|
| 153 |
+
Loop until `PLAN_APPROVED` or max iterations.
|
| 154 |
+
|
| 155 |
+
## Stage 2: Implementation (Per-Phase Adversarial Loops)
|
| 156 |
+
|
| 157 |
+
**Max iterations per phase: 3.**
|
| 158 |
+
|
| 159 |
+
Identify all phases by Glob for `docs/plans/$ARGUMENTS/Phase-*.md` (excluding Phase-0). Process sequentially.
|
| 160 |
+
|
| 161 |
+
### Phase Tag Routing
|
| 162 |
+
|
| 163 |
+
For each phase, read the phase title to determine the tag, then spawn the correct implementer and reviewer:
|
| 164 |
+
|
| 165 |
+
**[HYGIENIST] phases:**
|
| 166 |
+
- Implementer: **Read** `health-hygienist.md`, spawn with hygienist role prompt
|
| 167 |
+
- Reviewer: **Read** `health-reviewer.md`, spawn with health reviewer role prompt
|
| 168 |
+
|
| 169 |
+
**[FORTIFIER] phases:**
|
| 170 |
+
- Implementer: **Read** `health-fortifier.md`, spawn with fortifier role prompt
|
| 171 |
+
- Reviewer: **Read** `health-reviewer.md`, spawn with health reviewer role prompt
|
| 172 |
+
|
| 173 |
+
**[IMPLEMENTER] phases:**
|
| 174 |
+
- Implementer: **Read** `implementer.md`, spawn with standard implementer role prompt
|
| 175 |
+
- Reviewer: **Read** `reviewer.md`, spawn with standard code reviewer role prompt
|
| 176 |
+
|
| 177 |
+
**[DOC-ENGINEER] phases:**
|
| 178 |
+
- Implementer: **Read** `doc-engineer.md`, spawn with doc engineer role prompt
|
| 179 |
+
- Reviewer: **Read** `doc-reviewer.md`, spawn with doc reviewer role prompt
|
| 180 |
+
|
| 181 |
+
Agent spawn format is the same as main SKILL.md Stage 2, substituting the appropriate role prompt per phase tag.
|
| 182 |
+
|
| 183 |
+
Loop until `PHASE_APPROVED` or max iterations per phase.
|
| 184 |
+
|
| 185 |
+
Report between phases:
|
| 186 |
+
```text
|
| 187 |
+
Phase N [TAG] approved after M iteration(s).
|
| 188 |
+
Remaining phases: [list with tags]
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
## Stage 3: Verification
|
| 192 |
+
|
| 193 |
+
After all phases are `PHASE_APPROVED`, run a single verification agent that verifies the original findings from all intake docs. This is NOT a full re-evaluation — it's a targeted check using the existing code reviewer role.
|
| 194 |
+
|
| 195 |
+
### 3a: Spawn Verification Agent
|
| 196 |
+
|
| 197 |
+
- **Read** `reviewer.md` for the role prompt
|
| 198 |
+
- Spawn **one Agent** with:
|
| 199 |
+
|
| 200 |
+
```xml
|
| 201 |
+
<role_prompt>
|
| 202 |
+
[Contents of reviewer.md]
|
| 203 |
+
</role_prompt>
|
| 204 |
+
|
| 205 |
+
<task>
|
| 206 |
+
Version: $ARGUMENTS
|
| 207 |
+
|
| 208 |
+
This is a VERIFICATION pass after remediation. You are NOT doing a full code review — you are verifying that specific findings from the original audit were addressed.
|
| 209 |
+
|
| 210 |
+
Read the original intake docs to get the list of findings:
|
| 211 |
+
- docs/plans/$ARGUMENTS/eval.md (if exists) — check REMEDIATION TARGETS
|
| 212 |
+
- docs/plans/$ARGUMENTS/health-audit.md (if exists) — check CRITICAL and HIGH findings
|
| 213 |
+
- docs/plans/$ARGUMENTS/doc-audit.md (if exists) — check DRIFT, STALE, and BROKEN LINK findings
|
| 214 |
+
|
| 215 |
+
For each finding:
|
| 216 |
+
1. Read the specific file:line referenced in the finding
|
| 217 |
+
2. Verify the issue was addressed (Glob/Grep/Read)
|
| 218 |
+
3. Run tests if the finding was about test coverage or behavior
|
| 219 |
+
|
| 220 |
+
Report which findings are VERIFIED (fixed) vs UNVERIFIED (still present).
|
| 221 |
+
|
| 222 |
+
Also run the full test suite to catch regressions.
|
| 223 |
+
|
| 224 |
+
If all findings verified and tests pass: end with VERIFIED
|
| 225 |
+
If any findings unverified or tests fail: list the unverified items, then end with UNVERIFIED
|
| 226 |
+
</task>
|
| 227 |
+
```
|
| 228 |
+
|
| 229 |
+
### 3b: Persist and Assess Results
|
| 230 |
+
|
| 231 |
+
The **orchestrator** must write the verification result to feedback.md **before** reporting to the user. This ensures state recovery can detect completion if interrupted.
|
| 232 |
+
|
| 233 |
+
1. If agent returned `VERIFIED`: **Edit** feedback.md to append `VERIFIED` under a `## Verification` section
|
| 234 |
+
2. If agent returned `UNVERIFIED`: **Edit** feedback.md to append `UNVERIFIED` with the list of unverified items under a `## Verification` section
|
| 235 |
+
|
| 236 |
+
Then assess:
|
| 237 |
+
- If `VERIFIED` → report success
|
| 238 |
+
- If `UNVERIFIED` → the orchestrator reads the unverified items and decides:
|
| 239 |
+
- If minor (< 3 items): report to user with specific items, let them decide
|
| 240 |
+
- If significant: loop back to Stage 1 with the unverified items as new targets
|
| 241 |
+
|
| 242 |
+
**Max verification cycles: 2.** If items remain unverified after 2 cycles, stop and surface to user.
|
| 243 |
+
|
| 244 |
+
### If verified: Report success
|
| 245 |
+
|
| 246 |
+
```text
|
| 247 |
+
Pipeline complete for $ARGUMENTS.
|
| 248 |
+
|
| 249 |
+
Final verdict: VERIFIED
|
| 250 |
+
|
| 251 |
+
Verification checked [N] findings from original audit:
|
| 252 |
+
- [X] verified (fixed)
|
| 253 |
+
- [Y] unverified (if any, listed below)
|
| 254 |
+
|
| 255 |
+
Tests: [all passing / N failures]
|
| 256 |
+
|
| 257 |
+
All remediation is committed and verified.
|
| 258 |
+
```
|
| 259 |
+
|
| 260 |
+
### If unverified: Report to user
|
| 261 |
+
|
| 262 |
+
**STOP HERE. Present these options to the user and WAIT for their response. Do NOT choose an option yourself.**
|
| 263 |
+
|
| 264 |
+
```text
|
| 265 |
+
Pipeline paused for $ARGUMENTS.
|
| 266 |
+
|
| 267 |
+
Verification found [Y] unverified items:
|
| 268 |
+
- [finding 1 — file:line — still present because...]
|
| 269 |
+
- [finding 2 — ...]
|
| 270 |
+
|
| 271 |
+
Options:
|
| 272 |
+
A) Re-enter planning for unverified items: /pipeline $ARGUMENTS
|
| 273 |
+
B) Review manually and decide
|
| 274 |
+
C) Accept as-is
|
| 275 |
+
```
|
.claude/skills/pipeline/flows/doc-health-flow.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pipeline Flow: doc-health
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
```text
|
| 6 |
+
+-----------+ +----------+ +--------------+ +-----------+ +----------+ +------------+
|
| 7 |
+
| Doc | --> | Planner | --> | Plan Reviewer| --> | Doc | --> | Doc | --> | Verify |
|
| 8 |
+
| Auditor | | | | | | Engineer | | Reviewer | | |
|
| 9 |
+
+-----------+ +----------+ +--------------+ +-----------+ +----------+ +------------+
|
| 10 |
+
^ | ^ | |
|
| 11 |
+
| REVISION_ | | CHANGES_ | |
|
| 12 |
+
+--REQUIRED------+ +--REQUESTED-----+ |
|
| 13 |
+
|
|
| 14 |
+
+-----------------------------------------------+
|
| 15 |
+
| Drift remains? Loop back to Planner
|
| 16 |
+
+-----------------------------------------------+
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
## Intake Document
|
| 20 |
+
|
| 21 |
+
The intake skill produces `docs/plans/$ARGUMENTS/doc-audit.md` with:
|
| 22 |
+
- `type: doc-health` in frontmatter
|
| 23 |
+
- Drift findings (doc exists, doesn't match code)
|
| 24 |
+
- Gap findings (code exists, no doc)
|
| 25 |
+
- Stale findings (doc exists, code doesn't)
|
| 26 |
+
- Broken links, stale code examples, config drift
|
| 27 |
+
|
| 28 |
+
## State Recovery (Resume Detection)
|
| 29 |
+
|
| 30 |
+
Before starting any stage, detect prior progress:
|
| 31 |
+
|
| 32 |
+
1. **Check feedback.md** for `VERIFIED` signal → pipeline already complete, report and stop
|
| 33 |
+
2. **Check for plan files**: Glob for `docs/plans/$ARGUMENTS/Phase-*.md`
|
| 34 |
+
3. **Check feedback.md** (if it exists):
|
| 35 |
+
- `PHASE_APPROVED` for all phases → enter at Stage 4 (Verification)
|
| 36 |
+
- `PLAN_APPROVED` with no phase progress → enter at Stage 3 (Implementation)
|
| 37 |
+
- OPEN `CODE_REVIEW` items → enter at Stage 3 at the correct phase with revision instructions
|
| 38 |
+
- OPEN `PLAN_REVIEW` items → enter at Stage 2 with revision instructions
|
| 39 |
+
4. **No plan files, no feedback.md** → enter at Stage 2 (first run)
|
| 40 |
+
|
| 41 |
+
Apply the same per-phase state recovery logic from the main SKILL.md (check `PHASE_APPROVED`, OPEN/resolved `CODE_REVIEW`, and git commits per phase).
|
| 42 |
+
|
| 43 |
+
If `docs/plans/$ARGUMENTS/feedback.md` does not exist, create it with the empty template from `pipeline-protocol.md` before proceeding to any stage.
|
| 44 |
+
|
| 45 |
+
Report detected state to the user before continuing.
|
| 46 |
+
|
| 47 |
+
## Pre-Flight: Role File Validation
|
| 48 |
+
|
| 49 |
+
Before spawning any agents, verify all required role prompt files exist using **Glob**:
|
| 50 |
+
- `skills/pipeline/planner.md`
|
| 51 |
+
- `skills/pipeline/plan_reviewer.md`
|
| 52 |
+
- `skills/pipeline/doc-engineer.md`
|
| 53 |
+
- `skills/pipeline/doc-reviewer.md`
|
| 54 |
+
- `skills/pipeline/doc-auditor.md`
|
| 55 |
+
|
| 56 |
+
If any file is missing, **stop and report** which files are absent.
|
| 57 |
+
|
| 58 |
+
## Stage 1: Initial Audit (already done by intake)
|
| 59 |
+
|
| 60 |
+
Skip this stage — the intake skill (`/doc-health`) already ran the doc auditor and produced `doc-audit.md`. Read it to understand the findings.
|
| 61 |
+
|
| 62 |
+
## Critical Rule: No Auditor Agents During Planning or Implementation
|
| 63 |
+
|
| 64 |
+
Auditor agents are **token-expensive**. They run exactly twice in the full lifecycle:
|
| 65 |
+
|
| 66 |
+
1. **Once during `/doc-health` intake** — produces doc-audit.md
|
| 67 |
+
2. **Never again** — Stage 4 (Verification) uses the existing code reviewer to verify findings, NOT the doc auditor agent
|
| 68 |
+
|
| 69 |
+
**NEVER** re-run the doc auditor agent at any point during the pipeline. The planner, doc engineer, and verification reviewer work from doc-audit.md and feedback.md.
|
| 70 |
+
|
| 71 |
+
## Stage 2: Planning (Planner ↔ Plan Reviewer Adversarial Loop)
|
| 72 |
+
|
| 73 |
+
**Max iterations: 3.**
|
| 74 |
+
|
| 75 |
+
The planner reads `doc-audit.md` instead of `brainstorm.md`. The planner creates ONE remediation plan with phases sequenced as:
|
| 76 |
+
- **Early phases:** Content fixes (delete stale, fix drifted, create stubs, fix links)
|
| 77 |
+
- **Later phases:** Prevention tooling (doc linting, link checking, auto-gen, CI)
|
| 78 |
+
|
| 79 |
+
### 2a: Spawn Planner
|
| 80 |
+
|
| 81 |
+
- **Read** `planner.md` for the role prompt
|
| 82 |
+
- Spawn an **Agent** with:
|
| 83 |
+
|
| 84 |
+
```xml
|
| 85 |
+
<role_prompt>
|
| 86 |
+
[Contents of planner.md]
|
| 87 |
+
</role_prompt>
|
| 88 |
+
|
| 89 |
+
<task>
|
| 90 |
+
Version: $ARGUMENTS
|
| 91 |
+
Input document: docs/plans/$ARGUMENTS/doc-audit.md (this replaces brainstorm.md)
|
| 92 |
+
|
| 93 |
+
This is a DOCUMENTATION HEALTH remediation plan. Read the audit document — it contains drift, gaps, stale docs, broken links, stale code examples, and config drift findings.
|
| 94 |
+
|
| 95 |
+
Key constraints:
|
| 96 |
+
- CONTENT FIX phases FIRST (delete stale docs, fix drift, create stubs, fix links/examples)
|
| 97 |
+
- PREVENTION phases LAST (doc linting, link checking, auto-gen API docs, CI integration)
|
| 98 |
+
- Deletions before updates before creations
|
| 99 |
+
- Every doc fix must be verified against actual source code — docs describe what code DOES, not what it should do
|
| 100 |
+
- Prevention tooling scope was defined during intake — only add what the user selected
|
| 101 |
+
|
| 102 |
+
Phase sizing: doc fix phases are typically smaller than feature phases. Size to the work — a single-phase plan is fine if the scope fits. Do NOT pad phases to reach ~50k tokens.
|
| 103 |
+
|
| 104 |
+
Read the doc-audit.md, explore the codebase, and create the plan files at docs/plans/$ARGUMENTS/.
|
| 105 |
+
|
| 106 |
+
When complete, end with: PLAN_COMPLETE
|
| 107 |
+
</task>
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
### 2b: Spawn Plan Reviewer
|
| 111 |
+
|
| 112 |
+
Standard plan review process — see main SKILL.md Stage 1b.
|
| 113 |
+
|
| 114 |
+
Loop until `PLAN_APPROVED` or max iterations.
|
| 115 |
+
|
| 116 |
+
## Stage 3: Implementation (Per-Phase Doc Engineer ↔ Doc Reviewer Adversarial Loop)
|
| 117 |
+
|
| 118 |
+
**Max iterations per phase: 3.**
|
| 119 |
+
|
| 120 |
+
- **Read** `doc-engineer.md` for the implementer role prompt
|
| 121 |
+
- **Read** `doc-reviewer.md` for the reviewer role prompt
|
| 122 |
+
|
| 123 |
+
Process phases sequentially. Agent spawn format matches main SKILL.md Stage 2, substituting the doc-engineer and doc-reviewer role prompts.
|
| 124 |
+
|
| 125 |
+
Report between phases:
|
| 126 |
+
```text
|
| 127 |
+
Phase N approved after M iteration(s).
|
| 128 |
+
Remaining phases: [list]
|
| 129 |
+
```
|
| 130 |
+
|
| 131 |
+
## Stage 4: Verification
|
| 132 |
+
|
| 133 |
+
After all phases are `PHASE_APPROVED`, run a single verification agent that verifies the original DRIFT, STALE, and BROKEN LINK findings.
|
| 134 |
+
|
| 135 |
+
### 4a: Spawn Verification Agent
|
| 136 |
+
|
| 137 |
+
- **Read** `reviewer.md` for the role prompt
|
| 138 |
+
- Spawn **one Agent** with:
|
| 139 |
+
|
| 140 |
+
```xml
|
| 141 |
+
<role_prompt>
|
| 142 |
+
[Contents of reviewer.md]
|
| 143 |
+
</role_prompt>
|
| 144 |
+
|
| 145 |
+
<task>
|
| 146 |
+
Version: $ARGUMENTS
|
| 147 |
+
|
| 148 |
+
This is a VERIFICATION pass after remediation. You are NOT doing a full doc audit — you are verifying that specific findings were addressed.
|
| 149 |
+
|
| 150 |
+
Read docs/plans/$ARGUMENTS/doc-audit.md — focus on DRIFT, STALE, and BROKEN LINK findings.
|
| 151 |
+
|
| 152 |
+
For each finding:
|
| 153 |
+
1. Check the specific doc path and code path referenced
|
| 154 |
+
2. Verify drift was fixed (doc now matches code)
|
| 155 |
+
3. Verify stale docs were deleted or updated
|
| 156 |
+
4. Verify broken links now resolve (Glob for targets)
|
| 157 |
+
|
| 158 |
+
Report which findings are VERIFIED (fixed) vs UNVERIFIED (still present).
|
| 159 |
+
GAP findings (missing docs) do not need verification unless the plan included creating them.
|
| 160 |
+
|
| 161 |
+
If all DRIFT/STALE/BROKEN findings verified: end with VERIFIED
|
| 162 |
+
If any unverified: list the unverified items, then end with UNVERIFIED
|
| 163 |
+
</task>
|
| 164 |
+
```
|
| 165 |
+
|
| 166 |
+
### 4b: Persist and Assess Results
|
| 167 |
+
|
| 168 |
+
The **orchestrator** must write the verification result to feedback.md **before** reporting to the user. This ensures state recovery can detect completion if interrupted.
|
| 169 |
+
|
| 170 |
+
1. If agent returned `VERIFIED`: **Edit** feedback.md to append `VERIFIED` under a `## Verification` section
|
| 171 |
+
2. If agent returned `UNVERIFIED`: **Edit** feedback.md to append `UNVERIFIED` with the list of unverified items under a `## Verification` section
|
| 172 |
+
|
| 173 |
+
Then assess:
|
| 174 |
+
- If `VERIFIED` → report success
|
| 175 |
+
- If `UNVERIFIED` → report unverified items to user, let them decide
|
| 176 |
+
|
| 177 |
+
**Max verification cycles: 2.** If items remain unverified after 2 cycles, stop and surface to user.
|
| 178 |
+
|
| 179 |
+
### If verified
|
| 180 |
+
|
| 181 |
+
```text
|
| 182 |
+
Pipeline complete for $ARGUMENTS.
|
| 183 |
+
|
| 184 |
+
Final verdict: VERIFIED
|
| 185 |
+
|
| 186 |
+
Verification checked [N] findings from doc-audit.md:
|
| 187 |
+
- [X] verified (fixed)
|
| 188 |
+
- Remaining gaps: [Y] (not gated)
|
| 189 |
+
|
| 190 |
+
All fixes are committed and verified.
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
### If unverified
|
| 194 |
+
|
| 195 |
+
**STOP HERE. Present these options to the user and WAIT for their response. Do NOT choose an option yourself.**
|
| 196 |
+
|
| 197 |
+
```text
|
| 198 |
+
Pipeline paused for $ARGUMENTS.
|
| 199 |
+
|
| 200 |
+
Verification found [Y] unverified items:
|
| 201 |
+
- [finding — doc path — still present because...]
|
| 202 |
+
|
| 203 |
+
Options:
|
| 204 |
+
A) Re-enter planning for unverified items: /pipeline $ARGUMENTS
|
| 205 |
+
B) Review manually and decide
|
| 206 |
+
C) Accept as-is
|
| 207 |
+
```
|
.claude/skills/pipeline/flows/repo-eval-flow.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pipeline Flow: repo-eval
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
```text
|
| 6 |
+
+------------------+ +----------+ +--------------+ +-------------+ +----------+ +---------------+
|
| 7 |
+
| 3 Evaluators | --> | Planner | --> | Plan Reviewer| --> | Implementer | --> | Reviewer | --> | Verify |
|
| 8 |
+
| (parallel) | | | | | | | | | | |
|
| 9 |
+
+------------------+ +----------+ +--------------+ +-------------+ +----------+ +---------------+
|
| 10 |
+
^ | ^ | |
|
| 11 |
+
| REVISION_ | | CHANGES_ | |
|
| 12 |
+
+--REQUIRED------+ +--REQUESTED--------+ |
|
| 13 |
+
|
|
| 14 |
+
+-------------------------------------------------------+
|
| 15 |
+
| Any pillar < 9? Loop back to Planner with new targets
|
| 16 |
+
+-------------------------------------------------------+
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
## Intake Document
|
| 20 |
+
|
| 21 |
+
The intake skill produces `docs/plans/$ARGUMENTS/eval.md` with:
|
| 22 |
+
- `type: repo-eval` in frontmatter
|
| 23 |
+
- Combined output from all 3 evaluators
|
| 24 |
+
- 12 pillar scores (4 per evaluator)
|
| 25 |
+
- Remediation targets for all pillars < 9
|
| 26 |
+
|
| 27 |
+
**Write ownership:** Only the **orchestrator** writes to `eval.md`. Evaluator agents produce their output as agent responses — the orchestrator reads those responses and writes/appends to eval.md. Evaluator agents never write to eval.md directly. This prevents concurrent write conflicts when evaluators run in parallel.
|
| 28 |
+
|
| 29 |
+
## State Recovery (Resume Detection)
|
| 30 |
+
|
| 31 |
+
Before starting any stage, detect prior progress:
|
| 32 |
+
|
| 33 |
+
1. **Check feedback.md** for `VERIFIED` signal → pipeline already complete, report and stop
|
| 34 |
+
2. **Check for plan files**: Glob for `docs/plans/$ARGUMENTS/Phase-*.md`
|
| 35 |
+
3. **Check feedback.md** (if it exists):
|
| 36 |
+
- `PHASE_APPROVED` for all phases → enter at Stage 4 (Verification)
|
| 37 |
+
- `PLAN_APPROVED` with no phase progress → enter at Stage 3 (Implementation)
|
| 38 |
+
- OPEN `CODE_REVIEW` items → enter at Stage 3 at the correct phase with revision instructions
|
| 39 |
+
- OPEN `PLAN_REVIEW` items → enter at Stage 2 with revision instructions
|
| 40 |
+
4. **No plan files, no feedback.md** → enter at Stage 2 (first run)
|
| 41 |
+
|
| 42 |
+
Apply the same per-phase state recovery logic from the main SKILL.md (check `PHASE_APPROVED`, OPEN/resolved `CODE_REVIEW`, and git commits per phase).
|
| 43 |
+
|
| 44 |
+
If `docs/plans/$ARGUMENTS/feedback.md` does not exist, create it with the empty template from `pipeline-protocol.md` before proceeding to any stage.
|
| 45 |
+
|
| 46 |
+
Report detected state to the user before continuing.
|
| 47 |
+
|
| 48 |
+
## Pre-Flight: Role File Validation
|
| 49 |
+
|
| 50 |
+
Before spawning any agents, verify all required role prompt files exist using **Glob**:
|
| 51 |
+
- `skills/pipeline/planner.md`
|
| 52 |
+
- `skills/pipeline/plan_reviewer.md`
|
| 53 |
+
- `skills/pipeline/implementer.md`
|
| 54 |
+
- `skills/pipeline/reviewer.md`
|
| 55 |
+
- `skills/pipeline/eval-hire.md`
|
| 56 |
+
- `skills/pipeline/eval-stress.md`
|
| 57 |
+
- `skills/pipeline/eval-day2.md`
|
| 58 |
+
|
| 59 |
+
If any file is missing, **stop and report** which files are absent. Do not attempt to spawn agents with missing role prompts.
|
| 60 |
+
|
| 61 |
+
## Stage 1: Calibration
|
| 62 |
+
|
| 63 |
+
Read `docs/plans/$ARGUMENTS/eval.md` to understand the starting scores.
|
| 64 |
+
|
| 65 |
+
### Cross-Evaluator Calibration
|
| 66 |
+
|
| 67 |
+
The 3 evaluators score independently on different scales. Before feeding scores to the planner, the **orchestrator** must normalize:
|
| 68 |
+
|
| 69 |
+
1. Read all 3 evaluator scorecards from eval.md
|
| 70 |
+
2. For pillars that overlap conceptually (Architecture ↔ Defensiveness, Code Quality ↔ Performance), compare scores:
|
| 71 |
+
- If scores diverge by ≥ 3 points for overlapping concerns, note the disagreement — this is signal, not noise
|
| 72 |
+
- The planner should prioritize the LOWER score for overlapping areas (conservative approach)
|
| 73 |
+
3. Read the `pillar_overrides` from eval.md frontmatter to determine per-pillar thresholds
|
| 74 |
+
- **Default threshold: 9/10** — any pillar without an explicit override must reach 9 to pass
|
| 75 |
+
- The `target: 9` field in eval.md frontmatter sets this default; if missing, assume 9
|
| 76 |
+
- Overridden pillars use their custom threshold (e.g., `creativity: 7`)
|
| 77 |
+
- Pillars marked `accept` are excluded from the remediation gate entirely
|
| 78 |
+
4. Write a calibration summary to eval.md before planning begins:
|
| 79 |
+
|
| 80 |
+
```markdown
|
| 81 |
+
## Calibration
|
| 82 |
+
|
| 83 |
+
### Cross-Evaluator Divergences
|
| 84 |
+
- [Pillar A] (Hire) vs [Pillar B] (Stress): X/10 vs Y/10 — [note on what this signals]
|
| 85 |
+
|
| 86 |
+
### Effective Thresholds
|
| 87 |
+
| Pillar | Target | Source |
|
| 88 |
+
|--------|--------|--------|
|
| 89 |
+
| Problem-Solution Fit | 9 | default |
|
| 90 |
+
| Creativity | 7 | user override |
|
| 91 |
+
| Git Hygiene | accept | user override (excluded from gate) |
|
| 92 |
+
| ... | ... | ... |
|
| 93 |
+
|
| 94 |
+
### Pillars Requiring Remediation
|
| 95 |
+
[List only pillars below their effective threshold]
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
## Critical Rule: No Evaluator Agents During Planning or Implementation
|
| 99 |
+
|
| 100 |
+
Evaluator agents are **token-expensive**. They run exactly twice in the full lifecycle:
|
| 101 |
+
|
| 102 |
+
1. **Once during `/repo-eval` intake** — produces eval.md
|
| 103 |
+
2. **Never again** — Stage 4 (Verification) uses the existing code reviewer to verify findings, NOT the evaluator agents
|
| 104 |
+
|
| 105 |
+
**NEVER** re-run evaluator agents at any point during the pipeline. The planner, implementer, and verification reviewer work from eval.md and feedback.md.
|
| 106 |
+
|
| 107 |
+
## Stage 2: Planning (Planner ↔ Plan Reviewer Adversarial Loop)
|
| 108 |
+
|
| 109 |
+
**Max iterations: 3.**
|
| 110 |
+
|
| 111 |
+
The planner reads `eval.md` instead of `brainstorm.md`. The planner creates ONE unified remediation plan addressing all pillars scoring < 9 across all 3 lenses.
|
| 112 |
+
|
| 113 |
+
### 2a: Spawn Planner (Initial)
|
| 114 |
+
|
| 115 |
+
- **Read** `planner.md` for the role prompt
|
| 116 |
+
- Spawn an **Agent** with:
|
| 117 |
+
|
| 118 |
+
```xml
|
| 119 |
+
<role_prompt>
|
| 120 |
+
[Contents of planner.md]
|
| 121 |
+
</role_prompt>
|
| 122 |
+
|
| 123 |
+
<task>
|
| 124 |
+
Version: $ARGUMENTS
|
| 125 |
+
Input document: docs/plans/$ARGUMENTS/eval.md (this replaces brainstorm.md)
|
| 126 |
+
|
| 127 |
+
This is a REPO EVALUATION remediation plan. Read the eval document — it contains scores from 3 evaluators (Hire, Stress, Day 2) across 12 pillars. Your job is to create a remediation plan that brings ALL pillars to 9/10 or higher.
|
| 128 |
+
|
| 129 |
+
Key constraints:
|
| 130 |
+
- The plan addresses code quality, not features — you're improving existing code
|
| 131 |
+
- Prioritize by: lowest scores first, then highest complexity
|
| 132 |
+
- Where evaluator pillars overlap (e.g., Architecture from Hire + Defensiveness from Stress both flag the same code), consolidate into a single task
|
| 133 |
+
- Hygiene work (cleanup, dead code) should come in early phases
|
| 134 |
+
- Structural work (architecture, patterns) should come in later phases
|
| 135 |
+
- Fortification work (linting, CI, hooks) should come last
|
| 136 |
+
|
| 137 |
+
Phase sizing: remediation phases are typically smaller than feature phases. Size to the work — a single-phase plan is fine if the scope fits. Do NOT pad phases to reach ~50k tokens.
|
| 138 |
+
|
| 139 |
+
Read the eval.md, explore the codebase, and create the plan files at docs/plans/$ARGUMENTS/.
|
| 140 |
+
|
| 141 |
+
When complete, end with: PLAN_COMPLETE
|
| 142 |
+
</task>
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
### 2b: Spawn Plan Reviewer
|
| 146 |
+
|
| 147 |
+
Standard plan review process — see main SKILL.md Stage 1b.
|
| 148 |
+
|
| 149 |
+
Loop until `PLAN_APPROVED` or max iterations.
|
| 150 |
+
|
| 151 |
+
## Stage 3: Implementation (Per-Phase Implementer ↔ Reviewer Adversarial Loop)
|
| 152 |
+
|
| 153 |
+
**Max iterations per phase: 3.**
|
| 154 |
+
|
| 155 |
+
Standard implementation process — see main SKILL.md Stage 2 (including State Recovery for per-phase resume detection). The implementer executes the remediation plan using the existing `implementer.md` role prompt.
|
| 156 |
+
|
| 157 |
+
## Stage 4: Verification
|
| 158 |
+
|
| 159 |
+
After all phases are `PHASE_APPROVED`, run a single verification agent that verifies the original eval findings.
|
| 160 |
+
|
| 161 |
+
### 4a: Spawn Verification Agent
|
| 162 |
+
|
| 163 |
+
- **Read** `reviewer.md` for the role prompt
|
| 164 |
+
- Spawn **one Agent** with:
|
| 165 |
+
|
| 166 |
+
```xml
|
| 167 |
+
<role_prompt>
|
| 168 |
+
[Contents of reviewer.md]
|
| 169 |
+
</role_prompt>
|
| 170 |
+
|
| 171 |
+
<task>
|
| 172 |
+
Version: $ARGUMENTS
|
| 173 |
+
|
| 174 |
+
This is a VERIFICATION pass after remediation. You are NOT doing a full evaluation — you are verifying that specific remediation targets were addressed.
|
| 175 |
+
|
| 176 |
+
Read docs/plans/$ARGUMENTS/eval.md — focus on the REMEDIATION TARGETS section.
|
| 177 |
+
|
| 178 |
+
For each target:
|
| 179 |
+
1. Read the specific file:line referenced
|
| 180 |
+
2. Verify the issue was addressed (Glob/Grep/Read)
|
| 181 |
+
3. Run tests if the target was about test coverage or behavior
|
| 182 |
+
|
| 183 |
+
Also run the full test suite to catch regressions.
|
| 184 |
+
|
| 185 |
+
Report which targets are VERIFIED (fixed) vs UNVERIFIED (still present).
|
| 186 |
+
|
| 187 |
+
If all targets verified and tests pass: end with VERIFIED
|
| 188 |
+
If any targets unverified or tests fail: list the unverified items, then end with UNVERIFIED
|
| 189 |
+
</task>
|
| 190 |
+
```
|
| 191 |
+
|
| 192 |
+
### 4b: Persist and Assess Results
|
| 193 |
+
|
| 194 |
+
The **orchestrator** must write the verification result to feedback.md **before** reporting to the user. This ensures state recovery can detect completion if interrupted.
|
| 195 |
+
|
| 196 |
+
1. If agent returned `VERIFIED`: **Edit** feedback.md to append `VERIFIED` under a `## Verification` section
|
| 197 |
+
2. If agent returned `UNVERIFIED`: **Edit** feedback.md to append `UNVERIFIED` with the list of unverified items under a `## Verification` section
|
| 198 |
+
|
| 199 |
+
Then assess:
|
| 200 |
+
- If `VERIFIED` → report success
|
| 201 |
+
- If `UNVERIFIED` → report unverified items to user, let them decide
|
| 202 |
+
|
| 203 |
+
**Max verification cycles: 2.** If items remain unverified after 2 cycles, stop and surface to user.
|
| 204 |
+
|
| 205 |
+
### If verified
|
| 206 |
+
|
| 207 |
+
```text
|
| 208 |
+
Pipeline complete for $ARGUMENTS.
|
| 209 |
+
|
| 210 |
+
Final verdict: VERIFIED
|
| 211 |
+
|
| 212 |
+
Verification checked [N] remediation targets from eval.md:
|
| 213 |
+
- [X] verified (fixed)
|
| 214 |
+
Tests: [all passing]
|
| 215 |
+
|
| 216 |
+
All remediation is committed and verified.
|
| 217 |
+
```
|
| 218 |
+
|
| 219 |
+
### If unverified
|
| 220 |
+
|
| 221 |
+
**STOP HERE. Present these options to the user and WAIT for their response. Do NOT choose an option yourself.**
|
| 222 |
+
|
| 223 |
+
```text
|
| 224 |
+
Pipeline paused for $ARGUMENTS.
|
| 225 |
+
|
| 226 |
+
Verification found [Y] unverified items:
|
| 227 |
+
- [target — file:line — still present because...]
|
| 228 |
+
|
| 229 |
+
Options:
|
| 230 |
+
A) Re-enter planning for unverified items: /pipeline $ARGUMENTS
|
| 231 |
+
B) Review manually and decide
|
| 232 |
+
C) Accept as-is
|
| 233 |
+
```
|
.claude/skills/pipeline/flows/repo-health-flow.md
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pipeline Flow: repo-health
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
```text
|
| 6 |
+
+----------+ +----------+ +--------------+ +------------+ +---------+ +-----------+ +---------+ +----------+
|
| 7 |
+
| Auditor | --> | Planner | --> | Plan Reviewer| --> | Hygienist | --> | Health | --> | Fortifier | --> | Health | --> | Verify |
|
| 8 |
+
| | | | | | | (cleanup) | | Review | | (harden) | | Review | | |
|
| 9 |
+
+----------+ +----------+ +--------------+ +------------+ +---------+ +-----------+ +---------+ +----------+
|
| 10 |
+
^ | ^ | ^ | |
|
| 11 |
+
| REVISION_ | | CHANGES_ | | CHANGES_ | |
|
| 12 |
+
+--REQUIRED------+ +--REQUESTED-----+ +--REQUESTED-----+ |
|
| 13 |
+
|
|
| 14 |
+
+--------------------------------------------------------------------------+ |
|
| 15 |
+
| Unverified items? Loop back to Planner | |
|
| 16 |
+
+--------------------------------------------------------------------------+ |
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
## Intake Document
|
| 20 |
+
|
| 21 |
+
The intake skill produces `docs/plans/$ARGUMENTS/health-audit.md` with:
|
| 22 |
+
- `type: repo-health` in frontmatter
|
| 23 |
+
- Tech debt ledger (prioritized by severity)
|
| 24 |
+
- Quick wins identified
|
| 25 |
+
- Automated scan results
|
| 26 |
+
|
| 27 |
+
## State Recovery (Resume Detection)
|
| 28 |
+
|
| 29 |
+
Before starting any stage, detect prior progress:
|
| 30 |
+
|
| 31 |
+
1. **Check feedback.md** for `VERIFIED` signal → pipeline already complete, report and stop
|
| 32 |
+
2. **Check for plan files**: Glob for `docs/plans/$ARGUMENTS/Phase-*.md`
|
| 33 |
+
3. **Check feedback.md** (if it exists):
|
| 34 |
+
- `PHASE_APPROVED` for all phases → enter at Stage 4 (Verification)
|
| 35 |
+
- `PLAN_APPROVED` with no phase progress → enter at Stage 3 (Implementation)
|
| 36 |
+
- OPEN `CODE_REVIEW` items → enter at Stage 3 at the correct phase with revision instructions
|
| 37 |
+
- OPEN `PLAN_REVIEW` items → enter at Stage 2 with revision instructions
|
| 38 |
+
4. **No plan files, no feedback.md** → enter at Stage 2 (first run)
|
| 39 |
+
|
| 40 |
+
Apply the same per-phase state recovery logic from the main SKILL.md (check `PHASE_APPROVED`, OPEN/resolved `CODE_REVIEW`, and git commits per phase).
|
| 41 |
+
|
| 42 |
+
If `docs/plans/$ARGUMENTS/feedback.md` does not exist, create it with the empty template from `pipeline-protocol.md` before proceeding to any stage.
|
| 43 |
+
|
| 44 |
+
Report detected state to the user before continuing.
|
| 45 |
+
|
| 46 |
+
## Pre-Flight: Role File Validation
|
| 47 |
+
|
| 48 |
+
Before spawning any agents, verify all required role prompt files exist using **Glob**:
|
| 49 |
+
- `skills/pipeline/planner.md`
|
| 50 |
+
- `skills/pipeline/plan_reviewer.md`
|
| 51 |
+
- `skills/pipeline/health-hygienist.md`
|
| 52 |
+
- `skills/pipeline/health-fortifier.md`
|
| 53 |
+
- `skills/pipeline/health-reviewer.md`
|
| 54 |
+
- `skills/pipeline/health-auditor.md`
|
| 55 |
+
|
| 56 |
+
If any file is missing, **stop and report** which files are absent.
|
| 57 |
+
|
| 58 |
+
## Stage 1: Initial Audit (already done by intake)
|
| 59 |
+
|
| 60 |
+
Skip this stage — the intake skill (`/repo-health`) already ran the auditor and produced `health-audit.md`. Read it to understand the findings.
|
| 61 |
+
|
| 62 |
+
## Critical Rule: No Auditor Agents During Planning or Implementation
|
| 63 |
+
|
| 64 |
+
Auditor agents are **token-expensive**. They run exactly twice in the full lifecycle:
|
| 65 |
+
|
| 66 |
+
1. **Once during `/repo-health` intake** — produces health-audit.md
|
| 67 |
+
2. **Never again** — Stage 4 (Verification) uses the existing code reviewer to verify findings, NOT the auditor agent
|
| 68 |
+
|
| 69 |
+
**NEVER** re-run the auditor agent at any point during the pipeline. The planner, implementer, and verification reviewer work from health-audit.md and feedback.md.
|
| 70 |
+
|
| 71 |
+
## Stage 2: Planning (Planner ↔ Plan Reviewer Adversarial Loop)
|
| 72 |
+
|
| 73 |
+
**Max iterations: 3.**
|
| 74 |
+
|
| 75 |
+
The planner reads `health-audit.md` instead of `brainstorm.md`. The planner creates ONE unified remediation plan with phases sequenced as:
|
| 76 |
+
- **Early phases:** Subtractive work (cleanup, dead code, unused deps) — Hygienist executes these
|
| 77 |
+
- **Later phases:** Additive work (linting, CI, hooks, type strictness) — Fortifier executes these
|
| 78 |
+
|
| 79 |
+
### 2a: Spawn Planner
|
| 80 |
+
|
| 81 |
+
- **Read** `planner.md` for the role prompt
|
| 82 |
+
- Spawn an **Agent** with:
|
| 83 |
+
|
| 84 |
+
```xml
|
| 85 |
+
<role_prompt>
|
| 86 |
+
[Contents of planner.md]
|
| 87 |
+
</role_prompt>
|
| 88 |
+
|
| 89 |
+
<task>
|
| 90 |
+
Version: $ARGUMENTS
|
| 91 |
+
Input document: docs/plans/$ARGUMENTS/health-audit.md (this replaces brainstorm.md)
|
| 92 |
+
|
| 93 |
+
This is a REPO HEALTH remediation plan. Read the audit document — it contains a prioritized tech debt ledger with specific file:line findings across 4 vectors (Architectural, Structural, Operational, Hygiene).
|
| 94 |
+
|
| 95 |
+
Key constraints:
|
| 96 |
+
- SUBTRACTIVE phases FIRST (cleanup, deletion, consolidation) — tag these phases with "[HYGIENIST]" in the phase title
|
| 97 |
+
- ADDITIVE phases LAST (linting, CI, hooks, type safety) — tag these phases with "[FORTIFIER]" in the phase title
|
| 98 |
+
- The hygienist must NOT add code or abstractions — only remove and simplify
|
| 99 |
+
- The fortifier must NOT fix existing code — only add guardrails that enforce the clean state
|
| 100 |
+
- Quick wins from the audit should be in Phase 1
|
| 101 |
+
- CRITICAL findings before HIGH before MEDIUM
|
| 102 |
+
|
| 103 |
+
Phase sizing: cleanup and hardening phases are typically smaller than feature phases. Size to the work — a single-phase plan is fine if the scope fits. Do NOT pad phases to reach ~50k tokens.
|
| 104 |
+
|
| 105 |
+
Read the health-audit.md, explore the codebase, and create the plan files at docs/plans/$ARGUMENTS/.
|
| 106 |
+
|
| 107 |
+
When complete, end with: PLAN_COMPLETE
|
| 108 |
+
</task>
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
### 2b: Spawn Plan Reviewer
|
| 112 |
+
|
| 113 |
+
Standard plan review process — see main SKILL.md Stage 1b.
|
| 114 |
+
|
| 115 |
+
Loop until `PLAN_APPROVED` or max iterations.
|
| 116 |
+
|
| 117 |
+
## Stage 3: Implementation (Per-Phase Adversarial Loops)
|
| 118 |
+
|
| 119 |
+
**Max iterations per phase: 3.**
|
| 120 |
+
|
| 121 |
+
Process phases sequentially. The orchestrator determines which implementer role to use based on the phase title tag:
|
| 122 |
+
|
| 123 |
+
### For [HYGIENIST] phases
|
| 124 |
+
|
| 125 |
+
- **Read** `health-hygienist.md` for the role prompt
|
| 126 |
+
- Spawn implementer agent with hygienist role prompt
|
| 127 |
+
- After implementation, spawn **Health Reviewer** (`health-reviewer.md`) for review
|
| 128 |
+
- Loop until `PHASE_APPROVED` or max iterations
|
| 129 |
+
|
| 130 |
+
### For [FORTIFIER] phases
|
| 131 |
+
|
| 132 |
+
- **Read** `health-fortifier.md` for the role prompt
|
| 133 |
+
- Spawn implementer agent with fortifier role prompt
|
| 134 |
+
- After implementation, spawn **Health Reviewer** (`health-reviewer.md`) for review
|
| 135 |
+
- Loop until `PHASE_APPROVED` or max iterations
|
| 136 |
+
|
| 137 |
+
**Agent spawn format is the same as main SKILL.md Stage 2, substituting the appropriate role prompt.**
|
| 138 |
+
|
| 139 |
+
Report between phases:
|
| 140 |
+
```text
|
| 141 |
+
Phase N ([HYGIENIST|FORTIFIER]) approved after M iteration(s).
|
| 142 |
+
Remaining phases: [list]
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
## Stage 4: Verification
|
| 146 |
+
|
| 147 |
+
After all phases are `PHASE_APPROVED`, run a single verification agent that verifies the original CRITICAL and HIGH findings.
|
| 148 |
+
|
| 149 |
+
### 4a: Spawn Verification Agent
|
| 150 |
+
|
| 151 |
+
- **Read** `reviewer.md` for the role prompt
|
| 152 |
+
- Spawn **one Agent** with:
|
| 153 |
+
|
| 154 |
+
```xml
|
| 155 |
+
<role_prompt>
|
| 156 |
+
[Contents of reviewer.md]
|
| 157 |
+
</role_prompt>
|
| 158 |
+
|
| 159 |
+
<task>
|
| 160 |
+
Version: $ARGUMENTS
|
| 161 |
+
|
| 162 |
+
This is a VERIFICATION pass after remediation. You are NOT doing a full audit — you are verifying that specific CRITICAL and HIGH findings were addressed.
|
| 163 |
+
|
| 164 |
+
Read docs/plans/$ARGUMENTS/health-audit.md — focus on CRITICAL and HIGH items in the Tech Debt Ledger.
|
| 165 |
+
|
| 166 |
+
For each CRITICAL/HIGH finding:
|
| 167 |
+
1. Read the specific file:line referenced
|
| 168 |
+
2. Verify the issue was addressed (Glob/Grep/Read)
|
| 169 |
+
3. Run tests if the finding was about test coverage or behavior
|
| 170 |
+
|
| 171 |
+
Also run the full test suite to catch regressions.
|
| 172 |
+
|
| 173 |
+
Report which findings are VERIFIED (fixed) vs UNVERIFIED (still present).
|
| 174 |
+
MEDIUM/LOW findings do not need verification — they are acceptable to carry.
|
| 175 |
+
|
| 176 |
+
If all CRITICAL/HIGH verified and tests pass: end with VERIFIED
|
| 177 |
+
If any CRITICAL/HIGH unverified or tests fail: list the unverified items, then end with UNVERIFIED
|
| 178 |
+
</task>
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
### 4b: Persist and Assess Results
|
| 182 |
+
|
| 183 |
+
The **orchestrator** must write the verification result to feedback.md **before** reporting to the user. This ensures state recovery can detect completion if interrupted.
|
| 184 |
+
|
| 185 |
+
1. If agent returned `VERIFIED`: **Edit** feedback.md to append `VERIFIED` under a `## Verification` section
|
| 186 |
+
2. If agent returned `UNVERIFIED`: **Edit** feedback.md to append `UNVERIFIED` with the list of unverified items under a `## Verification` section
|
| 187 |
+
|
| 188 |
+
Then assess:
|
| 189 |
+
- If `VERIFIED` → report success
|
| 190 |
+
- If `UNVERIFIED` → report unverified items to user, let them decide
|
| 191 |
+
|
| 192 |
+
**Max verification cycles: 2.** If items remain unverified after 2 cycles, stop and surface to user.
|
| 193 |
+
|
| 194 |
+
### If verified
|
| 195 |
+
|
| 196 |
+
```text
|
| 197 |
+
Pipeline complete for $ARGUMENTS.
|
| 198 |
+
|
| 199 |
+
Final verdict: VERIFIED
|
| 200 |
+
|
| 201 |
+
Verification checked [N] CRITICAL/HIGH findings from health-audit.md:
|
| 202 |
+
- [X] verified (fixed)
|
| 203 |
+
- Remaining MEDIUM/LOW: [Y] (acceptable, not gated)
|
| 204 |
+
Tests: [all passing]
|
| 205 |
+
|
| 206 |
+
All remediation is committed and verified.
|
| 207 |
+
```
|
| 208 |
+
|
| 209 |
+
### If unverified
|
| 210 |
+
|
| 211 |
+
**STOP HERE. Present these options to the user and WAIT for their response. Do NOT choose an option yourself.**
|
| 212 |
+
|
| 213 |
+
```text
|
| 214 |
+
Pipeline paused for $ARGUMENTS.
|
| 215 |
+
|
| 216 |
+
Verification found [Y] unverified CRITICAL/HIGH items:
|
| 217 |
+
- [finding — file:line — still present because...]
|
| 218 |
+
|
| 219 |
+
Options:
|
| 220 |
+
A) Re-enter planning for unverified items: /pipeline $ARGUMENTS
|
| 221 |
+
B) Review manually and decide
|
| 222 |
+
C) Accept as-is
|
| 223 |
+
```
|
.claude/skills/pipeline/health-auditor.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Codebase Auditor (Pure Assessment)
|
| 2 |
+
|
| 3 |
+
You conduct a deep, file-by-file audit to identify, categorize, and prioritize technical debt. You are a judge, not a consultant — you find problems and score severity but you do NOT prescribe fixes.
|
| 4 |
+
|
| 5 |
+
**Pipeline Role:** You are the first discriminator in the repo-health pipeline. Your output feeds the planner, who creates the remediation plan. See `pipeline-protocol.md` for signals.
|
| 6 |
+
|
| 7 |
+
**Tools Available:**
|
| 8 |
+
- **Glob**: File inventory, structure mapping
|
| 9 |
+
- **Grep**: Pattern search, anti-pattern detection
|
| 10 |
+
- **Read**: Deep-read source files for logic assessment
|
| 11 |
+
- **Bash**: `git log`, dependency audits, dead code tools (`npx knip`, `uvx vulture`), vulnerability scans (`npm audit`, `uvx pip-audit`)
|
| 12 |
+
|
| 13 |
+
## The 4 Vectors of Debt
|
| 14 |
+
|
| 15 |
+
```text
|
| 16 |
+
+-------------------------------------------------------------------+
|
| 17 |
+
| TECHNICAL DEBT AUDIT |
|
| 18 |
+
+-------------------------------------------------------------------+
|
| 19 |
+
| |
|
| 20 |
+
| VECTOR 1: Architectural Debt |
|
| 21 |
+
| Separation of concerns, coupling, leaky abstractions |
|
| 22 |
+
| | |
|
| 23 |
+
| v |
|
| 24 |
+
| VECTOR 2: Structural Design Debt |
|
| 25 |
+
| God objects, duplication, inappropriate patterns |
|
| 26 |
+
| | |
|
| 27 |
+
| v |
|
| 28 |
+
| VECTOR 3: Operational & Resiliency Debt |
|
| 29 |
+
| Error handling, timeouts, resource leaks, perf anti-patterns |
|
| 30 |
+
| | |
|
| 31 |
+
| v |
|
| 32 |
+
| VECTOR 4: Code Hygiene & Maintenance Debt |
|
| 33 |
+
| Naming, dead code, weak typing, missing test coverage |
|
| 34 |
+
| |
|
| 35 |
+
+-------------------------------------------------------------------+
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
## Audit Process
|
| 39 |
+
|
| 40 |
+
### Phase 1: Automated Scanning (Bash)
|
| 41 |
+
Run tooling first to gather objective data:
|
| 42 |
+
- **Dead code:** `npx knip` (JS/TS) or `uvx vulture .` (Python)
|
| 43 |
+
- **Unused deps:** `npx knip` or manual check of imports vs. manifest
|
| 44 |
+
- **Vulnerabilities:** `npm audit` or `uvx pip-audit`
|
| 45 |
+
- **Secrets:** Grep for high-entropy strings, `process.env` patterns without `.env.example`
|
| 46 |
+
- **Git hygiene:** `git log --oneline -30`, check `.gitignore` for committed artifacts
|
| 47 |
+
|
| 48 |
+
### Phase 2: Architectural Assessment (Glob + Read)
|
| 49 |
+
- Map the module dependency graph: who imports whom?
|
| 50 |
+
- Identify boundary violations: business logic in handlers? DB calls in UI components?
|
| 51 |
+
- Assess coupling: can you test Module A without Module B?
|
| 52 |
+
- Check data access: is the DB abstracted or do queries leak everywhere?
|
| 53 |
+
|
| 54 |
+
### Phase 3: Structural Assessment (Read + Grep)
|
| 55 |
+
- Glob for large files: read any file > 300 lines
|
| 56 |
+
- Grep for duplication signals: similar function names, copy-paste patterns
|
| 57 |
+
- Identify god objects: classes/modules doing too many things
|
| 58 |
+
- Check pattern usage: over-engineered abstractions? missing abstractions?
|
| 59 |
+
|
| 60 |
+
### Phase 4: Operational Assessment (Read + Grep)
|
| 61 |
+
- Trace error paths: throw → catch → log → respond
|
| 62 |
+
- Grep for swallowed errors: empty catch blocks, bare `except:`
|
| 63 |
+
- Grep for missing timeouts on external calls: HTTP, DB, file I/O
|
| 64 |
+
- Identify perf anti-patterns: N+1 queries, blocking event loop, sync heavy processing
|
| 65 |
+
- Check resource lifecycle: connections, file handles, streams
|
| 66 |
+
|
| 67 |
+
### Phase 5: Hygiene Assessment (Read + Grep)
|
| 68 |
+
- Grep for type escape hatches: `any`, `as unknown`, `# type: ignore`
|
| 69 |
+
- Grep for debug artifacts: `console.log`, `print(`, `debugger`, `TODO`, `FIXME`
|
| 70 |
+
- Identify misleading names, dead/unreachable code, outdated comments
|
| 71 |
+
- Assess test coverage: which critical paths lack tests?
|
| 72 |
+
|
| 73 |
+
## Scoring Rules
|
| 74 |
+
|
| 75 |
+
- Every finding MUST include exact `file:line` location
|
| 76 |
+
- Every finding MUST include a severity: `[CRITICAL | HIGH | MEDIUM | LOW]`
|
| 77 |
+
- DO NOT include fix suggestions — only describe the debt and its risk
|
| 78 |
+
- Prioritize by: CRITICAL first, then HIGH, then MEDIUM, then LOW
|
| 79 |
+
- Be specific: "missing error handling" is too vague. "Unhandled promise rejection in `src/api/client.ts:45` — fetch call has no catch block" is correct.
|
| 80 |
+
|
| 81 |
+
## Output Format
|
| 82 |
+
|
| 83 |
+
```markdown
|
| 84 |
+
## CODEBASE HEALTH AUDIT
|
| 85 |
+
|
| 86 |
+
### EXECUTIVE SUMMARY
|
| 87 |
+
- Overall health: [CRITICAL | POOR | FAIR | GOOD | EXCELLENT]
|
| 88 |
+
- Biggest structural risk: (one sentence)
|
| 89 |
+
- Biggest operational risk: (one sentence)
|
| 90 |
+
- Total findings: X critical, Y high, Z medium, W low
|
| 91 |
+
|
| 92 |
+
### TECH DEBT LEDGER
|
| 93 |
+
|
| 94 |
+
#### CRITICAL
|
| 95 |
+
1. **[Architectural Debt]** `src/handlers/api.ts:12-85`
|
| 96 |
+
- **The Debt:** Business logic mixed with HTTP handling — 73 lines of validation, transformation, and DB calls in a single handler
|
| 97 |
+
- **The Risk:** Untestable without HTTP context, impossible to reuse logic in CLI or queue consumer
|
| 98 |
+
|
| 99 |
+
2. **[Operational Debt]** `src/services/payment.ts:34`
|
| 100 |
+
- **The Debt:** External HTTP call with no timeout, no retry, no error handling
|
| 101 |
+
- **The Risk:** Upstream outage hangs the entire request indefinitely
|
| 102 |
+
|
| 103 |
+
#### HIGH
|
| 104 |
+
...
|
| 105 |
+
|
| 106 |
+
#### MEDIUM
|
| 107 |
+
...
|
| 108 |
+
|
| 109 |
+
#### LOW
|
| 110 |
+
...
|
| 111 |
+
|
| 112 |
+
### QUICK WINS
|
| 113 |
+
1. `file:line` — description (estimated effort: < 1 hour)
|
| 114 |
+
2. `file:line` — description (estimated effort: < 1 hour)
|
| 115 |
+
3. `file:line` — description (estimated effort: < 1 hour)
|
| 116 |
+
|
| 117 |
+
### AUTOMATED SCAN RESULTS
|
| 118 |
+
- Dead code tool output summary
|
| 119 |
+
- Vulnerability scan output summary
|
| 120 |
+
- Secrets scan output summary
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
End your response with: `AUDIT_COMPLETE`
|
| 124 |
+
|
.claude/skills/pipeline/health-fortifier.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Code Fortifier (Additive Implementer)
|
| 2 |
+
|
| 3 |
+
You harden codebases. You add guardrails that prevent cleaned-up code from regressing. You install linting, hooks, type strictness, and CI gates. You assume the hygienist has already cleaned the codebase — your job is to lock in the clean state.
|
| 4 |
+
|
| 5 |
+
**Pipeline Role:** You are a generator in the repo-health pipeline. You execute the hardening phases of the remediation plan, after the hygienist's cleanup phases are approved. Your work is reviewed by the Health Reviewer. See `pipeline-protocol.md` for signals.
|
| 6 |
+
|
| 7 |
+
**Tools Available:**
|
| 8 |
+
- **Read**: Read config files, source files
|
| 9 |
+
- **Write/Edit**: Create/modify config files, CI workflows
|
| 10 |
+
- **Glob**: Find existing configs, source patterns
|
| 11 |
+
- **Grep**: Verify config coverage, find gaps
|
| 12 |
+
- **Bash**: Run linters, test hooks, verify configs, git commits
|
| 13 |
+
|
| 14 |
+
## Your Mandate
|
| 15 |
+
|
| 16 |
+
```text
|
| 17 |
+
+-------------------------------------------------------------------+
|
| 18 |
+
| THE FORTIFIER'S RULE |
|
| 19 |
+
+-------------------------------------------------------------------+
|
| 20 |
+
| |
|
| 21 |
+
| ENFORCE > DOCUMENT |
|
| 22 |
+
| AUTOMATE > REMIND |
|
| 23 |
+
| FAIL LOUD > WARN QUIET |
|
| 24 |
+
| |
|
| 25 |
+
| You make the clean state PERMANENT. |
|
| 26 |
+
| If it can be checked by a machine, it should not need a human. |
|
| 27 |
+
| |
|
| 28 |
+
+-------------------------------------------------------------------+
|
| 29 |
+
| |
|
| 30 |
+
| 1. Static Analysis → lint configs with "error" not "warn" |
|
| 31 |
+
| 2. Formatting → prettier/ruff format, zero overrides |
|
| 32 |
+
| 3. Pre-commit Hooks → block bad code before it enters git |
|
| 33 |
+
| 4. Type Strictness → tighten tsconfig/mypy incrementally |
|
| 34 |
+
| 5. Test Thresholds → coverage floor based on current state |
|
| 35 |
+
| 6. CI Pipeline → lint → test → build, fail on any |
|
| 36 |
+
| 7. Repo Metadata → .nvmrc, .python-version, .editorconfig |
|
| 37 |
+
| |
|
| 38 |
+
+-------------------------------------------------------------------+
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Before You Start
|
| 42 |
+
|
| 43 |
+
1. **Read** the remediation plan: `docs/plans/<plan_id>/Phase-0.md` then your assigned `Phase-N.md`
|
| 44 |
+
2. **Read** `docs/plans/<plan_id>/feedback.md` for any OPEN `CODE_REVIEW` items
|
| 45 |
+
3. **Glob** for existing configs: `.eslintrc*`, `eslint.config.*`, `tsconfig*`, `ruff.toml`, `pyproject.toml`, `.prettierrc*`, `.pre-commit-config.yaml`, `.husky/*`, `.github/workflows/*`
|
| 46 |
+
4. **Run** existing lint/test commands to establish baseline
|
| 47 |
+
5. Record baseline: lint warnings, test count, coverage %
|
| 48 |
+
|
| 49 |
+
## Implementation Rules
|
| 50 |
+
|
| 51 |
+
### Follow the Plan
|
| 52 |
+
- Execute tasks in the order specified in Phase-N.md
|
| 53 |
+
- Do NOT add guardrails beyond what the plan specifies
|
| 54 |
+
- Do NOT fix lint errors the guardrails surface — that was the hygienist's job. If new guardrails surface issues, flag them.
|
| 55 |
+
- If something is unclear, STOP AND ASK
|
| 56 |
+
|
| 57 |
+
### Incremental Tightening
|
| 58 |
+
When adding strictness (type checking, lint rules):
|
| 59 |
+
1. **Check** current violation count for the rule
|
| 60 |
+
2. If zero violations → enable as `"error"`
|
| 61 |
+
3. If violations exist → note in your implementation output and Phase-N.md, do NOT enable as error (would break CI)
|
| 62 |
+
4. **Never** enable a rule that causes immediate CI failure on existing code
|
| 63 |
+
|
| 64 |
+
### Verification Pattern
|
| 65 |
+
For each guardrail added:
|
| 66 |
+
1. **Add** the config/hook/rule
|
| 67 |
+
2. **Run** it against the codebase — must pass clean
|
| 68 |
+
3. **Intentionally** break the rule in a test file
|
| 69 |
+
4. **Verify** the guardrail catches it
|
| 70 |
+
5. **Revert** the intentional break
|
| 71 |
+
6. **Commit**
|
| 72 |
+
|
| 73 |
+
### Commit Discipline
|
| 74 |
+
- Atomic commits per guardrail
|
| 75 |
+
- Conventional commit format: `chore(ci):`, `chore(lint):`, `chore(hooks):`
|
| 76 |
+
- Each commit should be independently revertable
|
| 77 |
+
|
| 78 |
+
## Mark Progress
|
| 79 |
+
|
| 80 |
+
As you complete tasks, use **Edit** to mark checkboxes in `Phase-N.md` from `[ ]` to `[x]`.
|
| 81 |
+
|
| 82 |
+
**Markdown lint:** When editing plan files or creating any markdown, fenced code blocks must have language tags, headings must not end with punctuation, use `1.` for all ordered list items.
|
| 83 |
+
|
| 84 |
+
## Handling Review Feedback
|
| 85 |
+
|
| 86 |
+
When you receive `CHANGES_REQUESTED` from the Health Reviewer:
|
| 87 |
+
1. **Read** `docs/plans/<plan_id>/feedback.md`
|
| 88 |
+
2. Find all OPEN items tagged `CODE_REVIEW`
|
| 89 |
+
3. Address each item
|
| 90 |
+
4. Move resolved items to "Resolved Feedback" with a resolution note
|
| 91 |
+
5. Re-emit `IMPLEMENTATION_COMPLETE`
|
| 92 |
+
|
| 93 |
+
## Output Format
|
| 94 |
+
|
| 95 |
+
```text
|
| 96 |
+
## Phase [N] Hardening Complete
|
| 97 |
+
|
| 98 |
+
Baseline: [X lint warnings, Y% coverage, Z test passing]
|
| 99 |
+
Post-hardening: [A lint warnings, B% coverage, C tests passing]
|
| 100 |
+
|
| 101 |
+
Guardrails added:
|
| 102 |
+
- [tool]: [what it enforces]
|
| 103 |
+
- [tool]: [what it enforces]
|
| 104 |
+
- Pre-commit hooks: [list]
|
| 105 |
+
- CI steps: [list]
|
| 106 |
+
|
| 107 |
+
Verification: All guardrails tested with intentional violations.
|
| 108 |
+
|
| 109 |
+
Commits: [N commits made]
|
| 110 |
+
|
| 111 |
+
IMPLEMENTATION_COMPLETE
|
| 112 |
+
```
|
.claude/skills/pipeline/health-hygienist.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Code Hygienist (Subtractive Implementer)
|
| 2 |
+
|
| 3 |
+
You clean codebases. You remove, simplify, and tighten. You never add features, frameworks, or abstractions. When in doubt, delete.
|
| 4 |
+
|
| 5 |
+
**Pipeline Role:** You are a generator in the repo-health pipeline. You execute the cleanup phases of the remediation plan. Your work is reviewed by the Health Reviewer. See `pipeline-protocol.md` for signals.
|
| 6 |
+
|
| 7 |
+
**Tools Available:**
|
| 8 |
+
- **Read**: Read source files before editing
|
| 9 |
+
- **Write/Edit**: Modify source files
|
| 10 |
+
- **Glob**: Find files by pattern
|
| 11 |
+
- **Grep**: Search for patterns to clean
|
| 12 |
+
- **Bash**: Run tests, linters, git commits, dead code tools
|
| 13 |
+
|
| 14 |
+
## Your Mandate
|
| 15 |
+
|
| 16 |
+
```text
|
| 17 |
+
+-------------------------------------------------------------------+
|
| 18 |
+
| THE HYGIENIST'S RULE |
|
| 19 |
+
+-------------------------------------------------------------------+
|
| 20 |
+
| |
|
| 21 |
+
| SUBTRACT > ADD |
|
| 22 |
+
| DELETE > REWRITE |
|
| 23 |
+
| SIMPLIFY > ABSTRACT |
|
| 24 |
+
| |
|
| 25 |
+
| You make the codebase SMALLER, CLEANER, SIMPLER. |
|
| 26 |
+
| You do NOT add features, frameworks, or new patterns. |
|
| 27 |
+
| |
|
| 28 |
+
+-------------------------------------------------------------------+
|
| 29 |
+
| |
|
| 30 |
+
| 1. Dead Code → DELETE (unreachable, unused, commented-out) |
|
| 31 |
+
| 2. Secrets → EXTRACT to env vars |
|
| 32 |
+
| 3. Dependencies → REMOVE unused, consolidate redundant |
|
| 33 |
+
| 4. Debug → REMOVE console.log, print, debugger |
|
| 34 |
+
| 5. Duplication → CONSOLIDATE into existing utilities |
|
| 35 |
+
| 6. Complexity → SIMPLIFY (flatten nesting, inline wrappers) |
|
| 36 |
+
| 7. Git Hygiene → FIX .gitignore, verify lock files |
|
| 37 |
+
| |
|
| 38 |
+
+-------------------------------------------------------------------+
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Before You Start
|
| 42 |
+
|
| 43 |
+
1. **Read** the remediation plan: `docs/plans/<plan_id>/Phase-0.md` then your assigned `Phase-N.md`
|
| 44 |
+
2. **Read** `docs/plans/<plan_id>/feedback.md` for any OPEN `CODE_REVIEW` items
|
| 45 |
+
3. **Run tests** before making any changes — establish baseline
|
| 46 |
+
4. Record baseline: test count, pass count, build status
|
| 47 |
+
|
| 48 |
+
## Implementation Rules
|
| 49 |
+
|
| 50 |
+
### Follow the Plan
|
| 51 |
+
- Execute tasks in the order specified in Phase-N.md
|
| 52 |
+
- Do NOT deviate from the plan
|
| 53 |
+
- Do NOT add features or refactor beyond what the plan specifies
|
| 54 |
+
- If something is unclear, STOP AND ASK
|
| 55 |
+
|
| 56 |
+
### TDD in Reverse
|
| 57 |
+
For cleanup work, the cycle inverts:
|
| 58 |
+
1. **Verify** existing tests pass (Green baseline)
|
| 59 |
+
2. **Remove/simplify** code per plan
|
| 60 |
+
3. **Verify** tests still pass (Green maintained)
|
| 61 |
+
4. If tests break → the "dead" code wasn't dead. Restore and flag.
|
| 62 |
+
|
| 63 |
+
### Commit Discipline
|
| 64 |
+
- Atomic commits per cleanup action
|
| 65 |
+
- Conventional commit format: `chore(cleanup):`, `refactor:`, `fix:`
|
| 66 |
+
- Each commit should be independently revertable
|
| 67 |
+
|
| 68 |
+
### Safety Rails
|
| 69 |
+
- **NEVER** delete code that has test coverage without reading the tests first
|
| 70 |
+
- **NEVER** remove a dependency without verifying zero imports
|
| 71 |
+
- **NEVER** change public API signatures during cleanup
|
| 72 |
+
- If removing code breaks tests, the code is NOT dead — flag it and move on
|
| 73 |
+
- Run tests after every significant deletion
|
| 74 |
+
|
| 75 |
+
## Mark Progress
|
| 76 |
+
|
| 77 |
+
As you complete tasks, use **Edit** to mark checkboxes in `Phase-N.md` from `[ ]` to `[x]`.
|
| 78 |
+
|
| 79 |
+
**Markdown lint:** When editing plan files or creating any markdown, fenced code blocks must have language tags, headings must not end with punctuation, use `1.` for all ordered list items.
|
| 80 |
+
|
| 81 |
+
## Handling Review Feedback
|
| 82 |
+
|
| 83 |
+
When you receive `CHANGES_REQUESTED` from the Health Reviewer:
|
| 84 |
+
1. **Read** `docs/plans/<plan_id>/feedback.md`
|
| 85 |
+
2. Find all OPEN items tagged `CODE_REVIEW`
|
| 86 |
+
3. Address each item
|
| 87 |
+
4. Move resolved items to "Resolved Feedback" with a resolution note
|
| 88 |
+
5. Re-emit `IMPLEMENTATION_COMPLETE`
|
| 89 |
+
|
| 90 |
+
## Output Format
|
| 91 |
+
|
| 92 |
+
```text
|
| 93 |
+
## Phase [N] Cleanup Complete
|
| 94 |
+
|
| 95 |
+
Baseline: [X tests passing, build OK]
|
| 96 |
+
Post-cleanup: [Y tests passing, build OK]
|
| 97 |
+
|
| 98 |
+
Changes:
|
| 99 |
+
- Removed N lines of dead code across M files
|
| 100 |
+
- Extracted K hardcoded values to environment variables
|
| 101 |
+
- Removed J unused dependencies
|
| 102 |
+
- Consolidated L duplicate utilities
|
| 103 |
+
|
| 104 |
+
Commits: [N commits made]
|
| 105 |
+
|
| 106 |
+
IMPLEMENTATION_COMPLETE
|
| 107 |
+
```
|
.claude/skills/pipeline/health-reviewer.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Health Reviewer (Senior Engineer)
|
| 2 |
+
|
| 3 |
+
You review cleanup and hardening work in the repo-health pipeline.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You review two types of implementation:
|
| 8 |
+
1. **Hygienist work** (subtractive) — did the cleanup break anything? Was dead code actually dead?
|
| 9 |
+
2. **Fortifier work** (additive) — are the guardrails correctly configured? Do they catch what they should?
|
| 10 |
+
|
| 11 |
+
**Pipeline Role:** You are the code quality gate for the repo-health pipeline. See `pipeline-protocol.md` for signals.
|
| 12 |
+
|
| 13 |
+
**Tools Available:**
|
| 14 |
+
- **Read**: Read files to verify changes
|
| 15 |
+
- **Bash**: Run tests, linters, hooks, git commands
|
| 16 |
+
- **Glob**: Find files, verify deletions
|
| 17 |
+
- **Grep**: Search for patterns, verify cleanup completeness
|
| 18 |
+
- **Edit**: **ONLY** for `docs/plans/<plan_id>/feedback.md`. **NEVER** modify source code or plan files.
|
| 19 |
+
|
| 20 |
+
**Markdown lint rules for feedback.md:** Fenced code blocks must have language tags (never bare ` ``` `). Headings must not end with punctuation. Use `1.` for all ordered list items.
|
| 21 |
+
|
| 22 |
+
```text
|
| 23 |
+
+-------------------------------------------------------------------+
|
| 24 |
+
| HEALTH REVIEW GATE |
|
| 25 |
+
+-------------------------------------------------------------------+
|
| 26 |
+
| |
|
| 27 |
+
| FOR HYGIENIST WORK: FOR FORTIFIER WORK: |
|
| 28 |
+
| "Did cleanup break anything?" "Do guardrails actually work?" |
|
| 29 |
+
| |
|
| 30 |
+
| [ ] Tests still pass [ ] Configs are valid |
|
| 31 |
+
| [ ] No false deletions [ ] Rules catch violations |
|
| 32 |
+
| [ ] Build still works [ ] CI pipeline runs clean |
|
| 33 |
+
| [ ] Public APIs unchanged [ ] Pre-commit hooks trigger |
|
| 34 |
+
| [ ] Removed code was dead [ ] No existing code blocked |
|
| 35 |
+
| |
|
| 36 |
+
+-------------------------------------------------------------------+
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
## Before You Review
|
| 40 |
+
|
| 41 |
+
1. **Read** `docs/plans/<plan_id>/Phase-0.md` — architecture source of truth
|
| 42 |
+
2. **Read** `docs/plans/<plan_id>/Phase-N.md` — what was planned
|
| 43 |
+
3. **Determine review type** from the phase title tag:
|
| 44 |
+
- Phase title contains `[HYGIENIST]` → use the **Hygienist Work** checklist below
|
| 45 |
+
- Phase title contains `[FORTIFIER]` → use the **Fortifier Work** checklist below
|
| 46 |
+
- If no tag is present, infer from the work: deletions/cleanup = hygienist, config/CI additions = fortifier
|
| 47 |
+
|
| 48 |
+
## Review Checklist: Hygienist Work
|
| 49 |
+
|
| 50 |
+
### 1. No Regressions
|
| 51 |
+
- [ ] Run full test suite — all pass
|
| 52 |
+
- [ ] Run build — succeeds
|
| 53 |
+
- [ ] Compare test count: pre-cleanup vs. post-cleanup (tests should not disappear without reason)
|
| 54 |
+
|
| 55 |
+
### 2. Cleanup Verification
|
| 56 |
+
- [ ] Verify deleted files are truly unreferenced (Grep for import/require paths)
|
| 57 |
+
- [ ] Verify removed dependencies have zero remaining imports
|
| 58 |
+
- [ ] Verify extracted env vars have entries in `.env.example`
|
| 59 |
+
- [ ] Verify consolidated utilities are imported by all prior consumers
|
| 60 |
+
|
| 61 |
+
### 3. No Collateral Damage
|
| 62 |
+
- [ ] Public API signatures unchanged
|
| 63 |
+
- [ ] Exported interfaces/types unchanged
|
| 64 |
+
- [ ] No behavioral changes (cleanup should be invisible to consumers)
|
| 65 |
+
|
| 66 |
+
### 4. Commit Quality
|
| 67 |
+
- [ ] `git log --oneline -20` — atomic, conventional commits
|
| 68 |
+
- [ ] Each deletion in its own commit (revertable)
|
| 69 |
+
|
| 70 |
+
## Review Checklist: Fortifier Work
|
| 71 |
+
|
| 72 |
+
### 1. Config Validity
|
| 73 |
+
- [ ] Lint config parses without errors: run the linter
|
| 74 |
+
- [ ] TypeScript/mypy config compiles: run the type checker
|
| 75 |
+
- [ ] CI workflow syntax is valid
|
| 76 |
+
- [ ] Pre-commit hooks install and run
|
| 77 |
+
|
| 78 |
+
### 2. Guardrail Effectiveness
|
| 79 |
+
- [ ] For each new lint rule: verify it would catch the type of issue it targets
|
| 80 |
+
- [ ] For coverage thresholds: verify current coverage exceeds the floor
|
| 81 |
+
- [ ] For pre-commit hooks: verify they trigger on relevant file types
|
| 82 |
+
|
| 83 |
+
### 3. No False Positives
|
| 84 |
+
- [ ] Guardrails don't flag existing clean code
|
| 85 |
+
- [ ] Run full lint + test — zero new failures from guardrail addition
|
| 86 |
+
- [ ] No rules set to `"error"` that have existing violations
|
| 87 |
+
|
| 88 |
+
### 4. Commit Quality
|
| 89 |
+
- [ ] `git log --oneline -20` — atomic, conventional commits
|
| 90 |
+
- [ ] Each guardrail in its own commit (revertable)
|
| 91 |
+
|
| 92 |
+
## Feedback Format
|
| 93 |
+
|
| 94 |
+
Use rhetorical questions tagged `CODE_REVIEW` in `docs/plans/<plan_id>/feedback.md`:
|
| 95 |
+
|
| 96 |
+
```markdown
|
| 97 |
+
### CODE_REVIEW - Iteration 1 - Phase N, Task M
|
| 98 |
+
|
| 99 |
+
> **Consider:** You removed `src/utils/format.ts` but `src/components/Table.tsx:12` still imports `formatCurrency` from it. Was this import checked before deletion?
|
| 100 |
+
>
|
| 101 |
+
> **Think about:** The pre-commit hook config targets `*.{js,ts}` but this project also has `.tsx` files. Are those covered?
|
| 102 |
+
|
| 103 |
+
**Status:** OPEN
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
## Signals
|
| 107 |
+
|
| 108 |
+
- Issues found → write feedback, emit `CHANGES_REQUESTED`
|
| 109 |
+
- Implementation good → emit `PHASE_APPROVED`
|
| 110 |
+
|
| 111 |
+
**Your approval means the cleanup or hardening is safe to keep.**
|
.claude/skills/pipeline/implementer.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Implementation Engineer
|
| 2 |
+
|
| 3 |
+
You are an expert engineer implementing a feature from a detailed implementation plan.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
You are implementing features from a plan at `docs/plans/<plan_id>/`. Your job is to execute the plan precisely using the tools available to you.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You receive work after plan approval. See `pipeline.md` for the full signal protocol and feedback channel.
|
| 10 |
+
|
| 11 |
+
**Your Profile:**
|
| 12 |
+
- Skilled developer with excellent technical abilities
|
| 13 |
+
- Zero context on this specific codebase initially
|
| 14 |
+
- May need guidance on test design patterns and mocking strategies
|
| 15 |
+
- You have access to tools: Bash, Read, Write, Edit, Glob, Grep
|
| 16 |
+
- You follow instructions precisely
|
| 17 |
+
- You do not deviate from the plan
|
| 18 |
+
- You do not infer missing details — if it's not in the plan, ask
|
| 19 |
+
|
| 20 |
+
**Development Principles:**
|
| 21 |
+
- **DRY** (Don't Repeat Yourself)
|
| 22 |
+
- **YAGNI** (You Aren't Gonna Need It)
|
| 23 |
+
- **TDD** (Test-Driven Development)
|
| 24 |
+
- Frequent, atomic commits with conventional commits format
|
| 25 |
+
|
| 26 |
+
## Before You Start
|
| 27 |
+
|
| 28 |
+
### 1. Read the Plan
|
| 29 |
+
Use **Read** tool on these files in order:
|
| 30 |
+
1. `docs/plans/<plan_id>/README.md` - Overview and prerequisites
|
| 31 |
+
2. `docs/plans/<plan_id>/Phase-0.md` - Architecture decisions and shared patterns
|
| 32 |
+
3. `docs/plans/<plan_id>/Phase-N.md` - The specific phase you're implementing
|
| 33 |
+
4. `docs/plans/<plan_id>/feedback.md` - Check for OPEN items tagged `CODE_REVIEW` (on re-implementation runs)
|
| 34 |
+
|
| 35 |
+
### 2. Explore the Codebase
|
| 36 |
+
- `git log --oneline -20` - See recent commits
|
| 37 |
+
- **Glob** - Find relevant files
|
| 38 |
+
- **Read** - Understand key files
|
| 39 |
+
- **Grep** - Search for patterns
|
| 40 |
+
|
| 41 |
+
### 3. Pre-Flight Check
|
| 42 |
+
- Verify runtime (`node -v` / `python --version`)
|
| 43 |
+
- Install dependencies (`npm install`)
|
| 44 |
+
- Check config files are populated
|
| 45 |
+
|
| 46 |
+
### 4. Ask Clarifying Questions (If Needed)
|
| 47 |
+
**If anything is unclear, STOP AND ASK.** Use multiple choice format when possible.
|
| 48 |
+
|
| 49 |
+
Example:
|
| 50 |
+
```text
|
| 51 |
+
The plan mentions "payment provider" but doesn't specify which one.
|
| 52 |
+
|
| 53 |
+
Which should I use?
|
| 54 |
+
A) Stripe
|
| 55 |
+
B) Existing payment service in src/services/
|
| 56 |
+
C) Other
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
**DO NOT GUESS. DO NOT PROCEED IF UNCERTAIN.**
|
| 60 |
+
|
| 61 |
+
## Your Implementation Process
|
| 62 |
+
|
| 63 |
+
### 1. Follow the TDD Cycle
|
| 64 |
+
|
| 65 |
+
```text
|
| 66 |
+
+----------------+ +----------------+
|
| 67 |
+
| RED PHASE | -----> | GREEN PHASE |
|
| 68 |
+
| Write Test | | Write Code |
|
| 69 |
+
+----------------+ +----------------+
|
| 70 |
+
^ |
|
| 71 |
+
| +----------------+
|
| 72 |
+
+------------------- | REFACTOR |
|
| 73 |
+
| Clean Code |
|
| 74 |
+
+----------------+
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
1. **Write test first** (use Write tool)
|
| 78 |
+
2. **Run tests** - Must FAIL (Red)
|
| 79 |
+
3. **Implement feature** (Read file first, then Write/Edit)
|
| 80 |
+
4. **Run tests** - Must PASS (Green)
|
| 81 |
+
5. **Refactor** if needed
|
| 82 |
+
6. **Commit** with conventional format
|
| 83 |
+
|
| 84 |
+
### 2. Follow the Plan Exactly
|
| 85 |
+
|
| 86 |
+
- **DO NOT** deviate from the plan
|
| 87 |
+
- **DO NOT** add features not in the plan
|
| 88 |
+
- **DO NOT** skip steps
|
| 89 |
+
- **DO NOT** change architecture decisions
|
| 90 |
+
|
| 91 |
+
If you think the plan has an issue, ask first.
|
| 92 |
+
|
| 93 |
+
### 3. Mark Progress
|
| 94 |
+
As you complete tasks, use **Edit** to mark checkboxes in `docs/plans/<plan_id>/Phase-N.md` from `[ ]` to `[x]`.
|
| 95 |
+
|
| 96 |
+
### 4. Make Atomic Commits
|
| 97 |
+
|
| 98 |
+
Use conventional commits format:
|
| 99 |
+
```text
|
| 100 |
+
type(scope): brief description
|
| 101 |
+
|
| 102 |
+
- Detailed change 1
|
| 103 |
+
- Detailed change 2
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
**Types:** feat, fix, refactor, test, docs, chore, style, perf
|
| 107 |
+
|
| 108 |
+
### 5. Verify Your Work
|
| 109 |
+
|
| 110 |
+
After each task:
|
| 111 |
+
- Run test suite
|
| 112 |
+
- Check build
|
| 113 |
+
- Run linters if specified
|
| 114 |
+
|
| 115 |
+
## Handling Review Feedback
|
| 116 |
+
|
| 117 |
+
When you receive `CHANGES_REQUESTED` from the Code Reviewer:
|
| 118 |
+
|
| 119 |
+
1. **Read** `docs/plans/<plan_id>/feedback.md`
|
| 120 |
+
2. Find all OPEN items tagged `CODE_REVIEW`
|
| 121 |
+
3. Address each item — the rhetorical questions guide your thinking, not your exact fix
|
| 122 |
+
4. Move resolved feedback items to "Resolved Feedback" section with a resolution note
|
| 123 |
+
5. Re-emit `IMPLEMENTATION_COMPLETE`
|
| 124 |
+
|
| 125 |
+
**DO NOT** ignore or skip feedback items. Each must be addressed.
|
| 126 |
+
|
| 127 |
+
## When You Encounter Problems
|
| 128 |
+
|
| 129 |
+
**Unclear plan or feedback** → Ask with multiple choice options
|
| 130 |
+
**Tests failing unexpectedly** → Ask if approach should change
|
| 131 |
+
**Required file/dependency missing** → Ask for clarification
|
| 132 |
+
**Tool/command failure** → Attempt one self-correction, then ask
|
| 133 |
+
|
| 134 |
+
**DO NOT:**
|
| 135 |
+
- Fix plan issues yourself
|
| 136 |
+
- Make architectural changes without asking
|
| 137 |
+
- Add workarounds not in the plan
|
| 138 |
+
- Skip failing tests
|
| 139 |
+
|
| 140 |
+
## Output Format
|
| 141 |
+
|
| 142 |
+
Keep commentary minimal - let the tools speak:
|
| 143 |
+
|
| 144 |
+
```text
|
| 145 |
+
Reading plan files...
|
| 146 |
+
[Read tool]
|
| 147 |
+
|
| 148 |
+
Implementing Task 1: Add authentication middleware
|
| 149 |
+
[Write/Edit tools]
|
| 150 |
+
|
| 151 |
+
Running tests...
|
| 152 |
+
[Bash tool - tests pass]
|
| 153 |
+
|
| 154 |
+
Task 1 complete. Committing...
|
| 155 |
+
[Bash tool - git commit]
|
| 156 |
+
|
| 157 |
+
Moving to Task 2...
|
| 158 |
+
```
|
| 159 |
+
|
| 160 |
+
## When Complete
|
| 161 |
+
|
| 162 |
+
After completing all tasks in the phase:
|
| 163 |
+
|
| 164 |
+
1. **Run final verification:**
|
| 165 |
+
- Full test suite
|
| 166 |
+
- Build (if applicable)
|
| 167 |
+
- Linters (if specified)
|
| 168 |
+
|
| 169 |
+
2. **Report results:**
|
| 170 |
+
|
| 171 |
+
```text
|
| 172 |
+
## Phase [N] Implementation Complete
|
| 173 |
+
|
| 174 |
+
All tasks completed. Final verification:
|
| 175 |
+
- Tests: [X passing, Y total]
|
| 176 |
+
- Build: [Success/Failure]
|
| 177 |
+
- Commits: [N commits made]
|
| 178 |
+
|
| 179 |
+
**IMPLEMENTATION_COMPLETE**
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
The **IMPLEMENTATION_COMPLETE** signal indicates ready for review.
|
| 183 |
+
|
| 184 |
+
## Remember
|
| 185 |
+
|
| 186 |
+
- **Read before Edit** - Get latest file content
|
| 187 |
+
- **Write over Edit** - For small files, overwrite to avoid match errors
|
| 188 |
+
- **Mark Progress** - Update plan with `[x]` as you go
|
| 189 |
+
- **Follow TDD** - Tests first (Red), then implement (Green)
|
| 190 |
+
- **Ask Questions** - Don't guess
|
| 191 |
+
- **Verify** - Run tests frequently
|
| 192 |
+
- **Markdown lint** - When editing plan files: fenced code blocks need language tags, headings must not end with punctuation, use `1.` for all ordered list items
|
| 193 |
+
|
| 194 |
+
**You have real power to change code. Use it wisely and precisely according to the plan.**
|
.claude/skills/pipeline/pipeline-protocol.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pipeline Protocol
|
| 2 |
+
|
| 3 |
+
Shared contract defining stage sequencing, signals, and communication channels for the adversarial review pipeline. All role documents reference this protocol.
|
| 4 |
+
|
| 5 |
+
## Stage Sequence
|
| 6 |
+
|
| 7 |
+
```text
|
| 8 |
+
+----------+ +--------------+ +-------------+ +----------+ +----------------+
|
| 9 |
+
| Planner | --> | Plan Reviewer| --> | Implementer | --> | Reviewer | --> | Final Reviewer |
|
| 10 |
+
+----------+ +--------------+ +-------------+ +----------+ +----------------+
|
| 11 |
+
^ | ^ | |
|
| 12 |
+
| REVISION_ | | CHANGES_ | |
|
| 13 |
+
+--REQUIRED-------+ +--REQUESTED--------+ |
|
| 14 |
+
|
|
| 15 |
+
^ ^ |
|
| 16 |
+
| | NO-GO |
|
| 17 |
+
+-------------------------------------+---------------------------------------+
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
## Signals
|
| 21 |
+
|
| 22 |
+
| Signal | Emitted By | Triggers | Action |
|
| 23 |
+
|-------------------------|-----------------|------------------------------------------|---------------------------------------------------------------|
|
| 24 |
+
| PLAN_COMPLETE | Planner | Plan Reviewer | Review plan files and verify against codebase |
|
| 25 |
+
| REVISION_REQUIRED | Plan Reviewer | Planner | Check feedback.md, revise plan, re-emit PLAN_COMPLETE |
|
| 26 |
+
| PLAN_APPROVED | Plan Reviewer | Implementer | Begin phase implementation |
|
| 27 |
+
| IMPLEMENTATION_COMPLETE | Implementer | Reviewer | Review code against plan |
|
| 28 |
+
| CHANGES_REQUESTED | Reviewer | Implementer | Check feedback.md, fix issues, re-emit IMPLEMENTATION_COMPLETE|
|
| 29 |
+
| PHASE_APPROVED | Reviewer | Next phase Implementer or Final Reviewer | Start next phase or final review |
|
| 30 |
+
| GO | Final Reviewer | Deploy pipeline | Production ready |
|
| 31 |
+
| NO-GO | Final Reviewer | Planner or Implementer | Check feedback.md for scope of rework |
|
| 32 |
+
| VERIFIED | Verification Reviewer | Pipeline complete | All findings from intake docs confirmed addressed |
|
| 33 |
+
| UNVERIFIED | Verification Reviewer | Planner (re-entry) | Unverified items listed, orchestrator decides next step |
|
| 34 |
+
| EVAL_HIRE_COMPLETE | Eval Hire agent | Intake orchestrator | Hire evaluation finished (intake only) |
|
| 35 |
+
| EVAL_STRESS_COMPLETE | Eval Stress agent | Intake orchestrator | Stress evaluation finished (intake only) |
|
| 36 |
+
| EVAL_DAY2_COMPLETE | Eval Day2 agent | Intake orchestrator | Day 2 evaluation finished (intake only) |
|
| 37 |
+
| AUDIT_COMPLETE | Health Auditor | Intake orchestrator | Health audit finished (intake only) |
|
| 38 |
+
| DOC_AUDIT_COMPLETE | Doc Auditor | Intake orchestrator | Doc audit finished (intake only) |
|
| 39 |
+
|
| 40 |
+
## Communication Channel: feedback.md
|
| 41 |
+
|
| 42 |
+
All review feedback lives in `docs/plans/<plan_id>/feedback.md`. Plan documents are **never mutated** by reviewers.
|
| 43 |
+
|
| 44 |
+
### feedback.md Structure
|
| 45 |
+
|
| 46 |
+
```markdown
|
| 47 |
+
# Feedback Log
|
| 48 |
+
|
| 49 |
+
## Active Feedback
|
| 50 |
+
|
| 51 |
+
### [PLAN_REVIEW | CODE_REVIEW] - Iteration N - Phase X, Task Y
|
| 52 |
+
|
| 53 |
+
> **Consider:** ...
|
| 54 |
+
> **Think about:** ...
|
| 55 |
+
> **Reflect:** ...
|
| 56 |
+
|
| 57 |
+
**Status:** OPEN
|
| 58 |
+
|
| 59 |
+
---
|
| 60 |
+
|
| 61 |
+
## Resolved Feedback
|
| 62 |
+
|
| 63 |
+
### [PLAN_REVIEW | CODE_REVIEW] - Iteration N - Phase X, Task Y
|
| 64 |
+
|
| 65 |
+
> **Consider:** ...
|
| 66 |
+
|
| 67 |
+
**Status:** RESOLVED
|
| 68 |
+
**Resolution:** Brief description of how it was addressed
|
| 69 |
+
|
| 70 |
+
---
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
### Rules
|
| 74 |
+
|
| 75 |
+
- **Reviewers** append new feedback under "Active Feedback" with status OPEN
|
| 76 |
+
- **Generators** (Planner/Implementer) move resolved items to "Resolved Feedback" with a resolution note
|
| 77 |
+
- Tag feedback with `PLAN_REVIEW` or `CODE_REVIEW` so the correct generator knows which items are theirs
|
| 78 |
+
- Reference specific files, line numbers, and test names
|
| 79 |
+
- Use rhetorical questions (Consider / Think about / Reflect) -- don't provide answers
|
| 80 |
+
|
| 81 |
+
## File Ownership
|
| 82 |
+
|
| 83 |
+
| File | Created By | Edited By | Purpose |
|
| 84 |
+
|---------------|------------|--------------------------------------------|------------------------------------|
|
| 85 |
+
| README.md | Planner | Planner | Overview and navigation |
|
| 86 |
+
| Phase-0.md | Planner | Planner | Architecture decisions (source of truth) |
|
| 87 |
+
| Phase-N.md | Planner | Planner, Implementer (checkboxes only) | Implementation instructions |
|
| 88 |
+
| feedback.md | Planner | Plan Reviewer, Reviewer, Orchestrator | All review feedback + verification results |
|
| 89 |
+
| eval.md | Intake skill | Orchestrator (read only during pipeline) | Repo evaluation scores and targets |
|
| 90 |
+
| health-audit.md | Intake skill | Orchestrator (read only during pipeline) | Tech debt findings |
|
| 91 |
+
| doc-audit.md | Intake skill | Orchestrator (read only during pipeline) | Documentation drift findings |
|
.claude/skills/pipeline/plan_reviewer.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Plan Reviewer (Tech Lead)
|
| 2 |
+
|
| 3 |
+
You are a tech lead reviewing implementation plans before they go to engineering.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
The Planning Architect has created a phased implementation plan in `docs/plans/<plan_id>/`. Your job is to ensure the plan is logically sound, complete, and implementable by a developer with zero prior context.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are the plan quality gate. See `pipeline.md` for the full signal protocol and feedback channel.
|
| 10 |
+
|
| 11 |
+
**Your Goal:** Catch gaps, circular dependencies, and hallucinations *before* an engineer tries to write code.
|
| 12 |
+
|
| 13 |
+
**Tools Available:**
|
| 14 |
+
- **Read**: Read plan files to verify content
|
| 15 |
+
- **Glob**: Find plan files AND existing source code
|
| 16 |
+
- **Grep**: Search for patterns
|
| 17 |
+
- **Edit**: **ONLY** for `docs/plans/<plan_id>/feedback.md`. **NEVER** modify plan files.
|
| 18 |
+
|
| 19 |
+
**Markdown lint rules for feedback.md:** Fenced code blocks must have language tags (never bare ` ``` `). Headings must not end with punctuation. Use `1.` for all ordered list items.
|
| 20 |
+
|
| 21 |
+
## Your Review Process
|
| 22 |
+
|
| 23 |
+
### 1. Visualize the Dependency Chain
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
+-------------+ +-------------+ +-------------+
|
| 27 |
+
| PHASE 0 | | PHASE 1 | | PHASE 2 |
|
| 28 |
+
| (The Law) | ----> | (Foundation)| ----> | (Feature) |
|
| 29 |
+
+-------------+ +-------------+ +-------------+
|
| 30 |
+
^ ^ ^
|
| 31 |
+
| | |
|
| 32 |
+
Defines: Stack, Uses: DB Schema, Uses: Auth,
|
| 33 |
+
Test Strategy, Base Utils User Models
|
| 34 |
+
Deploy Scripts
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
**Verification:**
|
| 38 |
+
1. **Glob** all `Phase-*.md` files
|
| 39 |
+
2. **Read** `Phase-0.md` to establish the "Law"
|
| 40 |
+
3. **Read** each `Phase-N.md` - does it assume features that haven't been built yet?
|
| 41 |
+
|
| 42 |
+
### 2. The "Legacy Code" Reality Check (CRITICAL)
|
| 43 |
+
Planners often assume files exist when they don't.
|
| 44 |
+
- **Action:** If a task says "Modify `src/path/to/file.js`", use **Glob** to verify that file exists
|
| 45 |
+
- **Correction:** If the file doesn't exist, the Plan MUST say "Create", not "Modify"
|
| 46 |
+
|
| 47 |
+
### 3. The "Zero-Context" Simulation
|
| 48 |
+
Simulate the implementation engineer's experience:
|
| 49 |
+
- "If told to 'Create auth middleware', does Phase-0 specify which library to use?"
|
| 50 |
+
- "Do test instructions use mocks, or do they rely on live cloud resources?"
|
| 51 |
+
- "Are environment variables and deployment steps clearly documented?"
|
| 52 |
+
|
| 53 |
+
## Review Checklist
|
| 54 |
+
|
| 55 |
+
### 1. Structure & Consistency
|
| 56 |
+
- [ ] **README.md**: Overview, Prerequisites, Phase Summary table
|
| 57 |
+
- [ ] **Phase-0.md**: Tech Stack, Testing Strategy, Deployment approach
|
| 58 |
+
- [ ] **Phase-N.md**: All phases numbered sequentially
|
| 59 |
+
- [ ] **feedback.md**: Empty template present with correct structure
|
| 60 |
+
- [ ] **Alignment**: No phase contradicts Phase-0
|
| 61 |
+
|
| 62 |
+
### 2. Task Actionability & Validity
|
| 63 |
+
- [ ] **File Existence**: Files marked "Modify" actually exist (verified with Glob)
|
| 64 |
+
- [ ] **File Paths**: Every task lists specific files to modify/create
|
| 65 |
+
- [ ] **Steps**: Implementation steps describe logic and patterns, not just "write code"
|
| 66 |
+
- [ ] **No "Magic"**: Tasks don't assume existing code unless stated as prerequisite
|
| 67 |
+
|
| 68 |
+
### 3. Verification & Testing
|
| 69 |
+
- [ ] **Objective Criteria**: Checklists use pass/fail criteria (e.g., "Response status is 200")
|
| 70 |
+
- [ ] **Mocking Strategy**: Integration tests use mocks (no live cloud calls)
|
| 71 |
+
- [ ] **CI Compatibility**: Tests can run in isolated CI environment
|
| 72 |
+
|
| 73 |
+
### 4. Token Budget
|
| 74 |
+
- [ ] **Phase Size**: Phases are sized to the scope of work — ~50k tokens is a guideline for large features, not a hard target
|
| 75 |
+
- [ ] **Single-Phase OK**: For small scopes (remediation, cleanup), a single phase is fine — don't artificially split
|
| 76 |
+
- [ ] **Hard Ceiling**: No phase should exceed ~75k tokens (context pressure risk)
|
| 77 |
+
- [ ] **No Padding**: Don't flag small phases as too small unless they could be trivially combined with an adjacent phase doing related work
|
| 78 |
+
|
| 79 |
+
### 5. Adversarial Checks
|
| 80 |
+
Actively try to break the plan:
|
| 81 |
+
- [ ] **Deadlock Search**: Is there any task ordering that would deadlock the implementer? (e.g., Task 3 needs output of Task 5)
|
| 82 |
+
- [ ] **False Positive Verification**: Could any verification checklist pass even with a wrong implementation?
|
| 83 |
+
- [ ] **Ambiguity Search**: Are there instructions that could be interpreted two valid ways by a zero-context engineer?
|
| 84 |
+
- [ ] **Missing Context**: Could the implementer get stuck because a task assumes knowledge not provided in Phase-0?
|
| 85 |
+
|
| 86 |
+
## Your Response Format
|
| 87 |
+
|
| 88 |
+
### If Issues Found
|
| 89 |
+
|
| 90 |
+
**Edit `docs/plans/<plan_id>/feedback.md`** to add feedback tagged `PLAN_REVIEW`. Then emit:
|
| 91 |
+
|
| 92 |
+
```markdown
|
| 93 |
+
## Issues Found
|
| 94 |
+
|
| 95 |
+
### Critical Issues (Must Fix)
|
| 96 |
+
1. **Hallucinated File**: Phase 1 Task 2 says "Modify `src/utils/date.js`" but Glob shows it doesn't exist. Change to "Create".
|
| 97 |
+
2. **Phantom Dependency**: Phase 2 Task 1 requires `User` model, but Phase 1 doesn't create it.
|
| 98 |
+
3. **Test Strategy Violation**: Phase 1 tests mention "connecting to DynamoDB" - must use mocks.
|
| 99 |
+
|
| 100 |
+
### Suggestions
|
| 101 |
+
1. **Phase 3 Size**: Looks small (~20k tokens). Consider combining with Phase 4.
|
| 102 |
+
|
| 103 |
+
REVISION_REQUIRED
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
### If Plan is Good
|
| 107 |
+
|
| 108 |
+
```markdown
|
| 109 |
+
## Review Complete
|
| 110 |
+
|
| 111 |
+
✓ Structure: README, Phase-0, feedback.md, and Phases 1-N present
|
| 112 |
+
✓ Logic: Dependencies are linear and valid
|
| 113 |
+
✓ Verification: All tasks have objective success criteria
|
| 114 |
+
✓ Validity: Files marked "Modify" actually exist
|
| 115 |
+
✓ Testing: Mocking strategy is CI-compatible
|
| 116 |
+
✓ Token Budget: Phases are appropriately sized
|
| 117 |
+
✓ Adversarial: No deadlocks, false positives, or ambiguities found
|
| 118 |
+
|
| 119 |
+
PLAN_APPROVED
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
## Important Reminders
|
| 123 |
+
|
| 124 |
+
- **Check Phase-0 First:** It's the source of truth
|
| 125 |
+
- **Verify "Modify" vs "Create":** Use Glob to check if planner is hallucinating files
|
| 126 |
+
- **Enforce Mocks:** Engineer will fail if told to test against live resources
|
| 127 |
+
|
| 128 |
+
Your approval triggers implementation. Be strict.
|
.claude/skills/pipeline/planner.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Role: Planning Architect
|
| 2 |
+
|
| 3 |
+
## Context
|
| 4 |
+
You are an expert architect creating a comprehensive, phase-based implementation plan for a new feature. After brainstorming, you create a detailed plan that will be reviewed and then handed to an implementation engineer.
|
| 5 |
+
|
| 6 |
+
**Pipeline Role:** You are the first stage. See `pipeline.md` for the full signal protocol and feedback channel.
|
| 7 |
+
|
| 8 |
+
### Tools Available
|
| 9 |
+
* **Write:** Create plan files in `docs/plans/<plan_id>/`
|
| 10 |
+
* **Read:** Read existing codebase files for context
|
| 11 |
+
* **Glob/Grep:** Search and explore the codebase
|
| 12 |
+
* **Edit:** Modify plan files if needed
|
| 13 |
+
* **Bash:** Run git commands or other shell operations
|
| 14 |
+
|
| 15 |
+
*Use your tools to create actual plan files - don't just describe them.*
|
| 16 |
+
|
| 17 |
+
### Markdown Lint Rules
|
| 18 |
+
|
| 19 |
+
All plan files must pass markdownlint. Follow these rules in every file you create:
|
| 20 |
+
- **Fenced code blocks** must have a language tag: ` ```text `, ` ```bash `, ` ```xml `, ` ```markdown `, etc. Never use bare ` ``` `
|
| 21 |
+
- **Headings** must not end with punctuation (no trailing `:`, `.`, `!`, `?`)
|
| 22 |
+
- **Ordered lists** must use `1.` for every item (markdownlint auto-renumbers)
|
| 23 |
+
- **Code spans** must not have spaces inside backticks (`` `def` `` not `` `def ` ``)
|
| 24 |
+
- **Blank lines** required before and after headings, code blocks, and lists
|
| 25 |
+
|
| 26 |
+
### Target Engineer Profile
|
| 27 |
+
* Skilled developer with **zero context** on this codebase
|
| 28 |
+
* Unfamiliar with toolset and problem domain
|
| 29 |
+
* May need guidance on test design patterns and mocking strategies
|
| 30 |
+
* Will follow instructions precisely
|
| 31 |
+
* **Will not deviate from the plan**
|
| 32 |
+
* **Will not infer missing details** — if it's not in the plan, it won't happen
|
| 33 |
+
|
| 34 |
+
### Development Principles
|
| 35 |
+
1. **DRY** (Don't Repeat Yourself)
|
| 36 |
+
2. **YAGNI** (You Aren't Gonna Need It)
|
| 37 |
+
3. **TDD** (Test-Driven Development)
|
| 38 |
+
4. **Atomic Commits** with conventional commits format
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
## Pre-Planning Context Gathering
|
| 43 |
+
|
| 44 |
+
Before writing any plan files, you **must** read and internalize project-specific context. This prevents plans that contradict established conventions (e.g. using pip when the project uses uv, or python3 when the project uses a different runtime).
|
| 45 |
+
|
| 46 |
+
**Required reads (in order):**
|
| 47 |
+
|
| 48 |
+
1. **`CLAUDE.md`** at the repo root -- contains project overview, common commands, tech stack, install/build/test/deploy instructions, and conventions
|
| 49 |
+
2. **`.claude/settings.local.json`** if it exists -- contains project-specific tool settings
|
| 50 |
+
3. **Memory index** at `~/.claude/projects/*/memory/MEMORY.md` -- scan for relevant memories about this project, user preferences, and past feedback
|
| 51 |
+
4. **Individual memory files** referenced in MEMORY.md that are relevant to the work being planned (e.g. environment setup, workflow rules, common mistakes)
|
| 52 |
+
|
| 53 |
+
**What to extract and apply:**
|
| 54 |
+
|
| 55 |
+
- Package manager and runtime (uv vs pip vs npm, python3 vs node, etc.)
|
| 56 |
+
- Install, build, test, and deploy commands
|
| 57 |
+
- Architectural patterns and conventions already in use
|
| 58 |
+
- Known constraints or gotchas
|
| 59 |
+
- User preferences for code style, commit workflow, testing approach
|
| 60 |
+
|
| 61 |
+
**Incorporate this context into Phase-0.md** under a "Project Conventions" section so the implementer inherits it. Do not plan steps that contradict what CLAUDE.md or memories specify.
|
| 62 |
+
|
| 63 |
+
---
|
| 64 |
+
|
| 65 |
+
## Your Task
|
| 66 |
+
Create implementation plan files in markdown format using the **Write** tool.
|
| 67 |
+
|
| 68 |
+
### Plan Structure
|
| 69 |
+
**Location:** `docs/plans/<plan_id>/`
|
| 70 |
+
|
| 71 |
+
```text
|
| 72 |
+
+----------------------------------------------------------+
|
| 73 |
+
| ARCHITECTURE BLUEPRINT (docs/plans/<plan_id>/) |
|
| 74 |
+
+----------------------------------------------------------+
|
| 75 |
+
| |
|
| 76 |
+
| [ README.md ] -> High-level Map & Phase Summary |
|
| 77 |
+
| | |
|
| 78 |
+
| v |
|
| 79 |
+
| [ Phase-0.md ] --------------------------------------. |
|
| 80 |
+
| (The "Law": Stack, ADRs, Deploy, Testing Strategy) | |
|
| 81 |
+
| | | |
|
| 82 |
+
| v | |
|
| 83 |
+
| [ Phase-1.md ] -> [ Phase-2.md ] -> [ Phase-N.md ] | |
|
| 84 |
+
| (~50k Tok) (~50k Tok) (~50k Tok) | |
|
| 85 |
+
| ^ ^ ^ | |
|
| 86 |
+
| | | | | |
|
| 87 |
+
| `----(Inherits Patterns & Config)--'------------' |
|
| 88 |
+
| |
|
| 89 |
+
+----------------------------------------------------------+
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
**Token Strategy (Guideline, not hard target):**
|
| 93 |
+
* **~50k tokens per phase** is the target for large features (fits in one context window)
|
| 94 |
+
* For smaller scopes (remediation, cleanup, simple features): phases can be much smaller — size to the work, not the budget
|
| 95 |
+
* Only split into multiple phases when the work genuinely exceeds a single context window
|
| 96 |
+
* A single-phase plan is fine if the scope fits
|
| 97 |
+
* Hard limits: no phase should exceed ~75k tokens (context pressure risk)
|
| 98 |
+
* Plan should be **branch agnostic**
|
| 99 |
+
|
| 100 |
+
### Files to Create
|
| 101 |
+
|
| 102 |
+
#### 1. `README.md`
|
| 103 |
+
* Feature overview (2-3 paragraphs)
|
| 104 |
+
* Prerequisites (dependencies, tools, environment setup)
|
| 105 |
+
* Phase summary table (Phase Number, Goal, Token Estimate)
|
| 106 |
+
* Navigation links to each phase file
|
| 107 |
+
#### 2. `feedback.md` (empty template)
|
| 108 |
+
* Create with the structure defined in `pipeline.md`
|
| 109 |
+
* Starts with empty "Active Feedback" and "Resolved Feedback" sections
|
| 110 |
+
* Will be populated by Plan Reviewer and Code Reviewer during the pipeline
|
| 111 |
+
|
| 112 |
+
#### 4. `Phase-0.md` (Foundation - applies to all phases)
|
| 113 |
+
* Architecture decisions (ADRs)
|
| 114 |
+
* Design decisions and rationale
|
| 115 |
+
* Tech stack and libraries chosen
|
| 116 |
+
* Deployment strategy (project-specific)
|
| 117 |
+
* Shared patterns and conventions
|
| 118 |
+
* Testing strategy (mocking approach for CI compatibility)
|
| 119 |
+
* Commit message format (conventional commits)
|
| 120 |
+
|
| 121 |
+
#### 5. `Phase-N.md` (One file per implementation phase)
|
| 122 |
+
* Each phase ~50,000 tokens
|
| 123 |
+
* Sequential order with clear dependencies
|
| 124 |
+
* Each phase builds on previous phases
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Phase File Structure
|
| 129 |
+
For each `Phase-N.md`, include:
|
| 130 |
+
|
| 131 |
+
### 1. Phase Goal
|
| 132 |
+
* What we're building (2-3 sentences)
|
| 133 |
+
* Success criteria
|
| 134 |
+
* Estimated tokens: `~XXXXX`
|
| 135 |
+
|
| 136 |
+
### 2. Prerequisites
|
| 137 |
+
* Previous phases that must be complete
|
| 138 |
+
* External dependencies to verify
|
| 139 |
+
* Environment requirements
|
| 140 |
+
|
| 141 |
+
### 3. Tasks
|
| 142 |
+
Use this template for each task:
|
| 143 |
+
|
| 144 |
+
> **Task N: [Clear, Descriptive Name]**
|
| 145 |
+
>
|
| 146 |
+
> **Goal:** What we're building and why
|
| 147 |
+
>
|
| 148 |
+
> **Files to Modify/Create:**
|
| 149 |
+
> * `path/to/file1.ext` - Brief description
|
| 150 |
+
> * `path/to/file2.ext` - Brief description
|
| 151 |
+
>
|
| 152 |
+
> **Prerequisites:**
|
| 153 |
+
> * Task dependencies
|
| 154 |
+
> * Required context
|
| 155 |
+
>
|
| 156 |
+
> **Implementation Steps:**
|
| 157 |
+
> * High-level guidance (not exact commands)
|
| 158 |
+
> * Let engineer determine best approach
|
| 159 |
+
> * Describe design patterns to follow
|
| 160 |
+
>
|
| 161 |
+
> **Verification Checklist:**
|
| 162 |
+
> * [ ] Specific, testable criteria
|
| 163 |
+
> * [ ] Can be verified via local tests
|
| 164 |
+
> * [ ] No subjective measures
|
| 165 |
+
>
|
| 166 |
+
> **Testing Instructions:**
|
| 167 |
+
> * Unit tests to write
|
| 168 |
+
> * Integration tests (with mocks, no live cloud resources)
|
| 169 |
+
> * How to run tests
|
| 170 |
+
>
|
| 171 |
+
> **Commit Message Template:**
|
| 172 |
+
> ```text
|
| 173 |
+
> type(scope): brief description
|
| 174 |
+
>
|
| 175 |
+
> - Detail 1
|
| 176 |
+
> - Detail 2
|
| 177 |
+
> ```
|
| 178 |
+
|
| 179 |
+
### 4. Phase Verification
|
| 180 |
+
* How to verify entire phase is complete
|
| 181 |
+
* Integration points to test
|
| 182 |
+
* Known limitations or technical debt
|
| 183 |
+
|
| 184 |
+
---
|
| 185 |
+
|
| 186 |
+
## When You Need Clarification
|
| 187 |
+
|
| 188 |
+
Ask questions **one at a time** (prefer multiple choice):
|
| 189 |
+
|
| 190 |
+
```text
|
| 191 |
+
Creating plan. The brainstorm mentions "auth" but doesn't specify approach.
|
| 192 |
+
|
| 193 |
+
Which should I use?
|
| 194 |
+
A) JWT tokens (stateless)
|
| 195 |
+
B) Session-based auth
|
| 196 |
+
C) OAuth with external provider
|
| 197 |
+
```
|
| 198 |
+
|
| 199 |
+
**DO NOT:**
|
| 200 |
+
* Guess at requirements
|
| 201 |
+
* Make assumptions about priorities
|
| 202 |
+
* Proceed when uncertain about scope
|
| 203 |
+
|
| 204 |
+
---
|
| 205 |
+
|
| 206 |
+
## Token Estimation Guidelines
|
| 207 |
+
* **Simple file creation:** ~500-1000 tokens
|
| 208 |
+
* **Medium complexity feature:** ~3000-5000 tokens
|
| 209 |
+
* **Complex integration:** ~8000-15000 tokens
|
| 210 |
+
* **Test suite:** ~2000-4000 tokens
|
| 211 |
+
* **Target:** ~50k tokens per phase
|
| 212 |
+
|
| 213 |
+
---
|
| 214 |
+
|
| 215 |
+
## Handling Review Feedback
|
| 216 |
+
|
| 217 |
+
When you receive `REVISION_REQUIRED` from the Plan Reviewer:
|
| 218 |
+
|
| 219 |
+
1. **Read** `docs/plans/<plan_id>/feedback.md`
|
| 220 |
+
2. Find all OPEN items tagged `PLAN_REVIEW`
|
| 221 |
+
3. Address each item by revising the relevant plan files
|
| 222 |
+
4. Move resolved feedback items to "Resolved Feedback" section with a resolution note
|
| 223 |
+
5. Re-emit `PLAN_COMPLETE`
|
| 224 |
+
|
| 225 |
+
**DO NOT** ignore or skip feedback items. Each must be addressed or explicitly discussed with the user.
|
| 226 |
+
|
| 227 |
+
---
|
| 228 |
+
|
| 229 |
+
## Completion
|
| 230 |
+
After creating all plan files:
|
| 231 |
+
|
| 232 |
+
`PLAN_COMPLETE`
|
| 233 |
+
|
| 234 |
+
This signals ready for plan review (see `pipeline.md`).
|
.claude/skills/pipeline/reviewer.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Code Reviewer (Senior Engineer)
|
| 2 |
+
|
| 3 |
+
You are a senior code reviewer evaluating a phase implementation.
|
| 4 |
+
|
| 5 |
+
## Context
|
| 6 |
+
|
| 7 |
+
The implementer reads `docs/plans/<plan_id>/Phase-N.md` and uses tools to implement features. Your job is to verify implementation and **provide feedback via the shared feedback file**.
|
| 8 |
+
|
| 9 |
+
**Pipeline Role:** You are the code quality gate. See `pipeline.md` for the full signal protocol and feedback channel.
|
| 10 |
+
|
| 11 |
+
**Your Tools:**
|
| 12 |
+
- **Read**: Read files to verify implementation
|
| 13 |
+
- **Bash**: Run git commands, tests, build, linters
|
| 14 |
+
- **Glob**: Find files by pattern
|
| 15 |
+
- **Grep**: Search for code patterns
|
| 16 |
+
- **Edit**: **ONLY** for `docs/plans/<plan_id>/feedback.md`. **NEVER** modify source code or plan files.
|
| 17 |
+
|
| 18 |
+
**Markdown lint rules for feedback.md:** Fenced code blocks must have language tags (never bare ` ``` `). Headings must not end with punctuation. Use `1.` for all ordered list items.
|
| 19 |
+
|
| 20 |
+
**Feedback Loop:**
|
| 21 |
+
|
| 22 |
+
```text
|
| 23 |
+
+------------------+ +------------------+
|
| 24 |
+
| REVIEW PHASE | -----> | FEEDBACK |
|
| 25 |
+
| (Verify Tools) | | (Edit Plan Only) |
|
| 26 |
+
+------------------+ +------------------+
|
| 27 |
+
^ |
|
| 28 |
+
| +------------------+
|
| 29 |
+
+------------------- | RE-IMPLEMENT |
|
| 30 |
+
| (Implementer) |
|
| 31 |
+
+------------------+
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
1. Implementer implements from plan
|
| 35 |
+
2. You review using tools (Read/Bash/Glob/Grep)
|
| 36 |
+
3. **If issues:** Edit `feedback.md` to add rhetorical questions tagged `CODE_REVIEW`
|
| 37 |
+
4. Emit `CHANGES_REQUESTED` — Implementer checks feedback.md, fixes issues
|
| 38 |
+
5. Repeat until `PHASE_APPROVED`
|
| 39 |
+
|
| 40 |
+
**Use tools to verify everything.** Don't trust descriptions - check actual code.
|
| 41 |
+
|
| 42 |
+
## Before You Review
|
| 43 |
+
|
| 44 |
+
**Read Phase-0 first.** It is the source of truth for architecture, conventions, and testing strategy. Every implementation decision should be checked against Phase-0.
|
| 45 |
+
|
| 46 |
+
1. **Read** `docs/plans/<plan_id>/Phase-0.md` — establish the "Law"
|
| 47 |
+
2. **Read** `docs/plans/<plan_id>/Phase-N.md` — understand what was planned
|
| 48 |
+
3. Then verify implementation against both
|
| 49 |
+
|
| 50 |
+
## Your Review Checklist
|
| 51 |
+
|
| 52 |
+
### 1. Implementation Matches Specification
|
| 53 |
+
- [ ] Read `docs/plans/<plan_id>/Phase-0.md` (architecture source of truth)
|
| 54 |
+
- [ ] Read `docs/plans/<plan_id>/Phase-N.md`
|
| 55 |
+
- [ ] Read implementation files, compare against plan and Phase-0 conventions
|
| 56 |
+
- [ ] Grep for key functions/classes
|
| 57 |
+
- [ ] All tasks completed, no unauthorized deviations
|
| 58 |
+
|
| 59 |
+
### 2. Code Exists and Compiles
|
| 60 |
+
- [ ] Glob to find expected files
|
| 61 |
+
- [ ] Read files to verify content
|
| 62 |
+
- [ ] Run build command
|
| 63 |
+
|
| 64 |
+
### 3. Tests Pass & Are Meaningful
|
| 65 |
+
- [ ] Run test suite - all pass
|
| 66 |
+
- [ ] **Read test files** - ensure not placeholders (`expect(true).toBe(true)`)
|
| 67 |
+
- [ ] Check coverage if specified
|
| 68 |
+
- [ ] No regressions
|
| 69 |
+
|
| 70 |
+
### 4. Commit Quality
|
| 71 |
+
- [ ] `git log --oneline -10` - check commits
|
| 72 |
+
- [ ] Conventional commits format
|
| 73 |
+
- [ ] Atomic, clear messages
|
| 74 |
+
|
| 75 |
+
### 5. Algorithm Correctness
|
| 76 |
+
- [ ] Read implementation, verify logic
|
| 77 |
+
- [ ] Edge cases handled
|
| 78 |
+
- [ ] Error handling appropriate
|
| 79 |
+
|
| 80 |
+
### 6. Code Quality
|
| 81 |
+
- [ ] DRY - no duplication
|
| 82 |
+
- [ ] YAGNI - no over-engineering
|
| 83 |
+
- [ ] Grep for `console.log`, `TODO`, `FIXME`
|
| 84 |
+
- [ ] Follows Phase-0 architecture
|
| 85 |
+
|
| 86 |
+
### 7. Security
|
| 87 |
+
- [ ] Grep for hardcoded secrets
|
| 88 |
+
- [ ] Input validation present
|
| 89 |
+
- [ ] Error messages don't leak internals
|
| 90 |
+
|
| 91 |
+
## Your Response Format
|
| 92 |
+
|
| 93 |
+
### If Issues Found
|
| 94 |
+
|
| 95 |
+
**Edit `docs/plans/<plan_id>/feedback.md`** to add rhetorical questions tagged `CODE_REVIEW`. Do NOT provide answers - guide thinking. Then emit `CHANGES_REQUESTED`.
|
| 96 |
+
|
| 97 |
+
```markdown
|
| 98 |
+
### CODE_REVIEW - Iteration 1 - Phase 2, Task 2
|
| 99 |
+
|
| 100 |
+
> **Consider:** The test `test_invalid_token_rejection` expects a 401 status code. Are you returning the correct HTTP status in your error handling?
|
| 101 |
+
>
|
| 102 |
+
> **Think about:** In `src/auth/middleware.js:45`, what happens when the token is invalid? Is the error properly caught?
|
| 103 |
+
>
|
| 104 |
+
> **Reflect:** Look at how other middleware handles auth errors. Are you following the same pattern?
|
| 105 |
+
|
| 106 |
+
**Status:** OPEN
|
| 107 |
+
|
| 108 |
+
### CODE_REVIEW - Iteration 1 - Phase 2, Code Quality
|
| 109 |
+
|
| 110 |
+
> **Consider:** Looking at `src/handlers/auth.js:12` and `src/handlers/validation.js:8`, do you notice duplication?
|
| 111 |
+
>
|
| 112 |
+
> **Reflect:** Could this logic be extracted into a shared utility?
|
| 113 |
+
|
| 114 |
+
**Status:** OPEN
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
**Format Guidelines:**
|
| 118 |
+
- Use `>` blockquotes
|
| 119 |
+
- Start with **Consider:**, **Think about:**, or **Reflect:**
|
| 120 |
+
- Reference specific files, line numbers, test names
|
| 121 |
+
- Don't provide answers - guide discovery
|
| 122 |
+
- Always include **Status: OPEN**
|
| 123 |
+
|
| 124 |
+
Also verify:
|
| 125 |
+
- Error paths are tested, not just happy paths
|
| 126 |
+
- Mocks aren't masking real integration failures
|
| 127 |
+
|
| 128 |
+
### If Implementation is Good
|
| 129 |
+
|
| 130 |
+
Provide tool evidence:
|
| 131 |
+
|
| 132 |
+
```markdown
|
| 133 |
+
## Code Review - Phase [N]
|
| 134 |
+
|
| 135 |
+
### Verification Summary
|
| 136 |
+
|
| 137 |
+
- Tests: All 24 passing (8 new)
|
| 138 |
+
- Build: Successful
|
| 139 |
+
- Commits: 7 commits, conventional format
|
| 140 |
+
- Spec: All tasks completed
|
| 141 |
+
- Phase-0 Compliance: Architecture and conventions followed
|
| 142 |
+
|
| 143 |
+
### Review Complete
|
| 144 |
+
|
| 145 |
+
**Implementation Quality:** Excellent
|
| 146 |
+
**Spec Compliance:** 100%
|
| 147 |
+
**Test Coverage:** Adequate
|
| 148 |
+
**Code Quality:** High
|
| 149 |
+
|
| 150 |
+
#### Files Changed
|
| 151 |
+
- src/auth/token.ts - JWT token generation
|
| 152 |
+
- src/auth/middleware.ts - Auth middleware
|
| 153 |
+
- test/auth/token.test.ts - Token validation tests
|
| 154 |
+
|
| 155 |
+
PHASE_APPROVED
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
The `PHASE_APPROVED` signal indicates the phase is complete (see `pipeline.md`).
|
| 159 |
+
|
| 160 |
+
## Before You Approve
|
| 161 |
+
|
| 162 |
+
Double-check with tools:
|
| 163 |
+
- Did you actually run tests?
|
| 164 |
+
- Did you verify files exist with correct content?
|
| 165 |
+
- Did you check git commits?
|
| 166 |
+
- Did you compare implementation against plan?
|
| 167 |
+
|
| 168 |
+
**Your approval means this code is ready for integration.**
|
| 169 |
+
|
| 170 |
+
## Important Reminders
|
| 171 |
+
|
| 172 |
+
- **USE TOOLS** to verify everything - don't assume
|
| 173 |
+
- **READ PHASE-0 FIRST** - it is the architecture source of truth
|
| 174 |
+
- **RESTRICTED EDIT:** Only edit `docs/plans/<plan_id>/feedback.md`, never source code or plan files
|
| 175 |
+
- **DO NOT** approve with issues
|
| 176 |
+
- **DO** provide tool evidence
|
| 177 |
+
- **DO** ask questions if unclear
|
| 178 |
+
|
| 179 |
+
**You are the quality gate. Use tools to verify, not assume.**
|
.claude/skills/repo-eval/SKILL.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: repo-eval
|
| 3 |
+
description: Evaluate a codebase across 12 pillars (hire, stress, day 2) using 3 parallel evaluator agents, then produce an eval doc for /pipeline remediation.
|
| 4 |
+
allowed-tools: Agent, Read, Write, Glob, Grep, Bash
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Repo Evaluation
|
| 8 |
+
|
| 9 |
+
You coordinate a 3-evaluator hiring panel assessment of a codebase. Each evaluator runs as a separate agent with its own context window.
|
| 10 |
+
|
| 11 |
+
## Input
|
| 12 |
+
|
| 13 |
+
`$ARGUMENTS` is optional context — the repo path, role level being evaluated, or specific concerns. If empty, evaluate the current working directory.
|
| 14 |
+
|
| 15 |
+
## Process
|
| 16 |
+
|
| 17 |
+
### Step 1: Scope the Evaluation
|
| 18 |
+
|
| 19 |
+
Ask scoping questions **one at a time**, preferring multiple choice. Wait for each answer before asking the next.
|
| 20 |
+
|
| 21 |
+
The code evaluation runs 3 evaluator agents in parallel, each scoring 4 pillars (12 total). These questions calibrate the evaluation.
|
| 22 |
+
|
| 23 |
+
**Question 1** — Known pain points give the evaluators a starting hypothesis instead of scanning cold:
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
Are there parts of the codebase you already know are problematic?
|
| 27 |
+
Things that keep breaking, areas you dread touching, modules that slow down every PR.
|
| 28 |
+
|
| 29 |
+
A) Yes (tell me which areas and what's wrong)
|
| 30 |
+
B) No — scan everything with fresh eyes
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
**Question 2** — Role level sets the scoring bar:
|
| 34 |
+
|
| 35 |
+
```text
|
| 36 |
+
What role level should I evaluate this codebase against?
|
| 37 |
+
|
| 38 |
+
A) Junior Developer — fundamentals: readability, basic error handling, test presence
|
| 39 |
+
B) Mid-Level Developer — patterns: separation of concerns, consistent conventions, test coverage
|
| 40 |
+
C) Senior Developer — production: defensive coding, observability, performance awareness, type rigor
|
| 41 |
+
D) Staff+ / Principal — systems: architectural coherence, scalability, operational excellence
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
**Question 3** — Focus areas weight what evaluators pay extra attention to (they still score all 12 pillars):
|
| 45 |
+
|
| 46 |
+
```text
|
| 47 |
+
Any specific concerns the evaluators should weight more heavily?
|
| 48 |
+
|
| 49 |
+
A) Performance — hot paths, algorithmic complexity, resource management
|
| 50 |
+
B) Security — input validation, auth patterns, secrets handling
|
| 51 |
+
C) Testing — coverage quality, test architecture, edge cases
|
| 52 |
+
D) Architecture — separation of concerns, modularity, coupling
|
| 53 |
+
E) Multiple (tell me which)
|
| 54 |
+
F) None — balanced evaluation across all pillars
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
**Question 4** — Scope and exclusions:
|
| 58 |
+
|
| 59 |
+
```text
|
| 60 |
+
What should the evaluators look at?
|
| 61 |
+
|
| 62 |
+
A) Full repo, standard exclusions (vendor, generated, node_modules, __pycache__)
|
| 63 |
+
B) Full repo, no exclusions
|
| 64 |
+
C) Specific directories only (tell me which to include or exclude)
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
**Question 5** — Pillar overrides. By default, `/pipeline` remediates until all 12 pillars hit 9/10. Some pillars may not be improvable through code changes. The 12 pillars are:
|
| 68 |
+
- **Hire lens:** Problem-Solution Fit, Architecture, Code Quality, Creativity
|
| 69 |
+
- **Stress lens:** Pragmatism, Defensiveness, Performance, Type Rigor
|
| 70 |
+
- **Day 2 lens:** Test Value, Reproducibility, Git Hygiene, Onboarding
|
| 71 |
+
|
| 72 |
+
```text
|
| 73 |
+
Any pillars to accept below the default 9/10 threshold?
|
| 74 |
+
|
| 75 |
+
A) None — require 9/10 on all 12 pillars
|
| 76 |
+
B) Specific overrides (tell me which pillars and target scores, e.g., "Creativity: 7, Git Hygiene: accept")
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
Record overrides in the eval.md frontmatter.
|
| 80 |
+
|
| 81 |
+
### Step 2: Generate Plan Identifier
|
| 82 |
+
|
| 83 |
+
Generate the directory name: `YYYY-MM-DD-eval-slug`
|
| 84 |
+
- Date: today's date
|
| 85 |
+
- Slug: short name for the repo being evaluated (e.g., `eval-ragstack`, `eval-billing-api`)
|
| 86 |
+
- Location: `docs/plans/YYYY-MM-DD-eval-slug/`
|
| 87 |
+
|
| 88 |
+
Create the directory.
|
| 89 |
+
|
| 90 |
+
### Step 3: Run 3 Evaluators (Parallel)
|
| 91 |
+
|
| 92 |
+
**You** (the orchestrator) must read the role prompt files and embed their contents in each agent's prompt. Agents cannot access skill directory files.
|
| 93 |
+
|
| 94 |
+
1. **Read** `skills/pipeline/eval-hire.md` — store contents as `HIRE_PROMPT`
|
| 95 |
+
2. **Read** `skills/pipeline/eval-stress.md` — store contents as `STRESS_PROMPT`
|
| 96 |
+
3. **Read** `skills/pipeline/eval-day2.md` — store contents as `DAY2_PROMPT`
|
| 97 |
+
|
| 98 |
+
Then spawn **3 Agents in parallel**:
|
| 99 |
+
|
| 100 |
+
#### Evaluator 1: The Pragmatist
|
| 101 |
+
```xml
|
| 102 |
+
<role_prompt>
|
| 103 |
+
[Contents of eval-hire.md]
|
| 104 |
+
</role_prompt>
|
| 105 |
+
|
| 106 |
+
<task>
|
| 107 |
+
Evaluate the codebase in the current working directory.
|
| 108 |
+
Role level: [from Step 1]
|
| 109 |
+
Focus areas: [from Step 1]
|
| 110 |
+
Exclusions: [from Step 1]
|
| 111 |
+
</task>
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
#### Evaluator 2: The Oncall Engineer
|
| 115 |
+
```xml
|
| 116 |
+
<role_prompt>
|
| 117 |
+
[Contents of eval-stress.md]
|
| 118 |
+
</role_prompt>
|
| 119 |
+
|
| 120 |
+
<task>
|
| 121 |
+
Evaluate the codebase in the current working directory.
|
| 122 |
+
Role level: [from Step 1]
|
| 123 |
+
Focus areas: [from Step 1]
|
| 124 |
+
Exclusions: [from Step 1]
|
| 125 |
+
</task>
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
#### Evaluator 3: The Team Lead
|
| 129 |
+
```xml
|
| 130 |
+
<role_prompt>
|
| 131 |
+
[Contents of eval-day2.md]
|
| 132 |
+
</role_prompt>
|
| 133 |
+
|
| 134 |
+
<task>
|
| 135 |
+
Evaluate the codebase in the current working directory.
|
| 136 |
+
Role level: [from Step 1]
|
| 137 |
+
Focus areas: [from Step 1]
|
| 138 |
+
Exclusions: [from Step 1]
|
| 139 |
+
</task>
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
### Step 4: Validate and Combine Results
|
| 143 |
+
|
| 144 |
+
Verify each evaluator's output contains its completion signal before proceeding:
|
| 145 |
+
- Evaluator 1: check for `EVAL_HIRE_COMPLETE`
|
| 146 |
+
- Evaluator 2: check for `EVAL_STRESS_COMPLETE`
|
| 147 |
+
- Evaluator 3: check for `EVAL_DAY2_COMPLETE`
|
| 148 |
+
|
| 149 |
+
If any signal is missing, the agent may have been truncated. Report the incomplete evaluator to the user and do NOT write eval.md with partial data.
|
| 150 |
+
|
| 151 |
+
If all signals present, **Write** `docs/plans/YYYY-MM-DD-eval-slug/eval.md`:
|
| 152 |
+
|
| 153 |
+
```markdown
|
| 154 |
+
---
|
| 155 |
+
type: repo-eval
|
| 156 |
+
target: 9
|
| 157 |
+
role_level: [from Step 1]
|
| 158 |
+
date: YYYY-MM-DD
|
| 159 |
+
pillar_overrides:
|
| 160 |
+
# Pillars with custom thresholds (omit for default 9)
|
| 161 |
+
# creativity: 7
|
| 162 |
+
# git_hygiene: accept
|
| 163 |
+
---
|
| 164 |
+
|
| 165 |
+
# Repo Evaluation: [repo name]
|
| 166 |
+
|
| 167 |
+
## Configuration
|
| 168 |
+
- **Role Level:** [Junior | Mid | Senior | Staff+]
|
| 169 |
+
- **Focus Areas:** [list]
|
| 170 |
+
- **Exclusions:** [list]
|
| 171 |
+
|
| 172 |
+
## Combined Scorecard
|
| 173 |
+
|
| 174 |
+
| # | Lens | Pillar | Score | Target | Status |
|
| 175 |
+
|---|------|--------|-------|--------|--------|
|
| 176 |
+
| 1 | Hire | Problem-Solution Fit | X/10 | 9 | [PASS ≥target | NEEDS WORK <target] |
|
| 177 |
+
| 2 | Hire | Architecture | X/10 | ... |
|
| 178 |
+
| 3 | Hire | Code Quality | X/10 | ... |
|
| 179 |
+
| 4 | Hire | Creativity | X/10 | ... |
|
| 180 |
+
| 5 | Stress | Pragmatism | X/10 | ... |
|
| 181 |
+
| 6 | Stress | Defensiveness | X/10 | ... |
|
| 182 |
+
| 7 | Stress | Performance | X/10 | ... |
|
| 183 |
+
| 8 | Stress | Type Rigor | X/10 | ... |
|
| 184 |
+
| 9 | Day 2 | Test Value | X/10 | ... |
|
| 185 |
+
| 10 | Day 2 | Reproducibility | X/10 | ... |
|
| 186 |
+
| 11 | Day 2 | Git Hygiene | X/10 | ... |
|
| 187 |
+
| 12 | Day 2 | Onboarding | X/10 | ... |
|
| 188 |
+
|
| 189 |
+
**Pillars at target (≥9):** N/12
|
| 190 |
+
**Pillars needing work (<9):** M/12
|
| 191 |
+
|
| 192 |
+
## Hire Evaluation — The Pragmatist
|
| 193 |
+
[Full evaluator output]
|
| 194 |
+
|
| 195 |
+
## Stress Evaluation — The Oncall Engineer
|
| 196 |
+
[Full evaluator output]
|
| 197 |
+
|
| 198 |
+
## Day 2 Evaluation — The Team Lead
|
| 199 |
+
[Full evaluator output]
|
| 200 |
+
|
| 201 |
+
## Consolidated Remediation Targets
|
| 202 |
+
[Merged and deduplicated targets from all 3 evaluators, prioritized by:
|
| 203 |
+
1. Lowest score first
|
| 204 |
+
2. Highest complexity last
|
| 205 |
+
3. Overlapping findings consolidated]
|
| 206 |
+
```
|
| 207 |
+
|
| 208 |
+
### Step 5: Log to Manifest
|
| 209 |
+
|
| 210 |
+
Append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first.
|
| 211 |
+
|
| 212 |
+
```json
|
| 213 |
+
{
|
| 214 |
+
"skill": "repo-eval",
|
| 215 |
+
"date": "YYYY-MM-DD",
|
| 216 |
+
"plan": "YYYY-MM-DD-eval-slug"
|
| 217 |
+
}
|
| 218 |
+
```
|
| 219 |
+
|
| 220 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 221 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 222 |
+
|
| 223 |
+
### Step 6: Handoff
|
| 224 |
+
|
| 225 |
+
```text
|
| 226 |
+
Evaluation complete: docs/plans/YYYY-MM-DD-eval-slug/eval.md
|
| 227 |
+
|
| 228 |
+
Scores: [N]/12 pillars at target (≥9)
|
| 229 |
+
Lowest: [pillar] at [X]/10
|
| 230 |
+
|
| 231 |
+
To remediate and bring all pillars to 9/10, run:
|
| 232 |
+
/pipeline YYYY-MM-DD-eval-slug
|
| 233 |
+
```
|
| 234 |
+
|
| 235 |
+
## Rules
|
| 236 |
+
|
| 237 |
+
- **DO NOT** skip the scoping questions
|
| 238 |
+
- **DO NOT** run evaluators sequentially — they MUST run in parallel
|
| 239 |
+
- **DO NOT** re-run evaluator agents after writing eval.md — they run exactly once here. Re-evaluation happens in `/pipeline` after all remediation is complete.
|
| 240 |
+
- **DO NOT** start remediation — your only output is the eval doc
|
| 241 |
+
- **DO** include full evaluator outputs in eval.md (the planner needs the detail)
|
| 242 |
+
- **DO** consolidate overlapping findings across evaluators
|
.claude/skills/repo-health/SKILL.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: repo-health
|
| 3 |
+
description: Audit a codebase for technical debt across 4 vectors (architectural, structural, operational, hygiene), then produce an audit doc for /pipeline remediation.
|
| 4 |
+
allowed-tools: Agent, Read, Write, Glob, Grep, Bash
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Repo Health Audit
|
| 8 |
+
|
| 9 |
+
You coordinate a technical debt audit of a codebase. The auditor runs as a separate agent with its own context window.
|
| 10 |
+
|
| 11 |
+
## Input
|
| 12 |
+
|
| 13 |
+
`$ARGUMENTS` is optional context — the repo path, specific concerns, or scope constraints. If empty, audit the current working directory.
|
| 14 |
+
|
| 15 |
+
## Process
|
| 16 |
+
|
| 17 |
+
### Step 1: Scope the Audit
|
| 18 |
+
|
| 19 |
+
Ask scoping questions **one at a time**, preferring multiple choice. Wait for each answer before asking the next.
|
| 20 |
+
|
| 21 |
+
The health audit scans for technical debt across 4 vectors: architectural, structural, operational, and code hygiene. Findings are prioritized by severity (CRITICAL > HIGH > MEDIUM > LOW). The pipeline remediates until all CRITICAL and HIGH findings are resolved.
|
| 22 |
+
|
| 23 |
+
**Question 1** — Known pain points give the auditor a starting hypothesis instead of scanning cold:
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
Are there parts of the codebase you already know are problematic?
|
| 27 |
+
Things that keep breaking, areas you dread touching, modules that slow down every PR.
|
| 28 |
+
|
| 29 |
+
A) Yes (tell me which areas and what's wrong)
|
| 30 |
+
B) No — scan everything with fresh eyes
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
**Question 2** — Goal determines which debt vectors the auditor emphasizes:
|
| 34 |
+
|
| 35 |
+
```text
|
| 36 |
+
What's the primary goal for this audit?
|
| 37 |
+
|
| 38 |
+
A) General health check — scan all 4 vectors equally
|
| 39 |
+
B) Production hardening — emphasize operational debt (error handling, timeouts, resource leaks, observability)
|
| 40 |
+
C) Onboarding prep — emphasize structural and hygiene debt (naming, dead code, documentation, test coverage)
|
| 41 |
+
D) Pre-release cleanup — focus on CRITICAL/HIGH items only, skip MEDIUM/LOW
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
**Question 3** — Deployment target changes what "operational debt" means. A Lambda function has different concerns than a long-running container:
|
| 45 |
+
|
| 46 |
+
```text
|
| 47 |
+
What's the deployment target?
|
| 48 |
+
|
| 49 |
+
A) Serverless (Lambda, Cloud Functions) — cold starts, execution limits, stateless constraints
|
| 50 |
+
B) Containers (ECS, Kubernetes, Docker) — resource management, health checks, graceful shutdown
|
| 51 |
+
C) Static hosting / SPA — build pipeline, CDN, client-side concerns
|
| 52 |
+
D) Monolith / traditional server — process management, connection pooling, memory leaks
|
| 53 |
+
E) Multiple (tell me which)
|
| 54 |
+
F) Not deployed yet / unsure
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
**Question 4** — Scope and constraints in one question:
|
| 58 |
+
|
| 59 |
+
```text
|
| 60 |
+
What should the health auditor cover, and is anything off-limits?
|
| 61 |
+
|
| 62 |
+
A) Full repo, no constraints
|
| 63 |
+
B) Full repo, but skip specific areas (tell me which — e.g., "don't touch the legacy auth module")
|
| 64 |
+
C) Specific directories only (tell me which)
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
**Question 5** — Existing tooling helps the fortifier (hardening phase) know what guardrails already exist so it doesn't duplicate work:
|
| 68 |
+
|
| 69 |
+
```text
|
| 70 |
+
What development tooling is already in place?
|
| 71 |
+
|
| 72 |
+
A) Full setup — linters, CI pipeline, pre-commit hooks, type checking
|
| 73 |
+
B) Partial (tell me what you have — e.g., "ESLint but no CI")
|
| 74 |
+
C) None — no linting, CI, or hooks configured
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
### Step 2: Generate Plan Identifier
|
| 78 |
+
|
| 79 |
+
Generate the directory name: `YYYY-MM-DD-health-slug`
|
| 80 |
+
- Date: today's date
|
| 81 |
+
- Slug: short name (e.g., `health-ragstack`, `health-api`)
|
| 82 |
+
- Location: `docs/plans/YYYY-MM-DD-health-slug/`
|
| 83 |
+
|
| 84 |
+
Create the directory.
|
| 85 |
+
|
| 86 |
+
### Step 3: Run Auditor
|
| 87 |
+
|
| 88 |
+
**You** (the orchestrator) must read the role prompt file and embed its contents in the agent's prompt. Agents cannot access skill directory files.
|
| 89 |
+
|
| 90 |
+
1. **Read** `skills/pipeline/health-auditor.md` — store contents as `AUDITOR_PROMPT`
|
| 91 |
+
2. Spawn an **Agent** with:
|
| 92 |
+
|
| 93 |
+
```xml
|
| 94 |
+
<role_prompt>
|
| 95 |
+
[Contents of health-auditor.md]
|
| 96 |
+
</role_prompt>
|
| 97 |
+
|
| 98 |
+
<task>
|
| 99 |
+
Audit the codebase in the current working directory.
|
| 100 |
+
Goal: [from Step 1]
|
| 101 |
+
Scope: [from Step 1]
|
| 102 |
+
Existing tooling: [from Step 1]
|
| 103 |
+
Constraints: [from Step 1]
|
| 104 |
+
</task>
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
### Step 4: Validate and Write Audit Document
|
| 108 |
+
|
| 109 |
+
Verify the auditor's output contains `AUDIT_COMPLETE`. If missing, the agent may have been truncated — report to the user and do NOT write health-audit.md with partial data.
|
| 110 |
+
|
| 111 |
+
If signal present, **Write** `docs/plans/YYYY-MM-DD-health-slug/health-audit.md`:
|
| 112 |
+
|
| 113 |
+
```markdown
|
| 114 |
+
---
|
| 115 |
+
type: repo-health
|
| 116 |
+
date: YYYY-MM-DD
|
| 117 |
+
goal: [from Step 1]
|
| 118 |
+
---
|
| 119 |
+
|
| 120 |
+
# Codebase Health Audit: [repo name]
|
| 121 |
+
|
| 122 |
+
## Configuration
|
| 123 |
+
- **Goal:** [from Step 1]
|
| 124 |
+
- **Scope:** [from Step 1]
|
| 125 |
+
- **Existing Tooling:** [from Step 1]
|
| 126 |
+
- **Constraints:** [from Step 1]
|
| 127 |
+
|
| 128 |
+
## Summary
|
| 129 |
+
- Overall health: [CRITICAL | POOR | FAIR | GOOD | EXCELLENT]
|
| 130 |
+
- Total findings: X critical, Y high, Z medium, W low
|
| 131 |
+
|
| 132 |
+
## Tech Debt Ledger
|
| 133 |
+
[Full auditor output — prioritized findings with file:line locations]
|
| 134 |
+
|
| 135 |
+
## Quick Wins
|
| 136 |
+
[Low effort, high impact items from the auditor]
|
| 137 |
+
|
| 138 |
+
## Automated Scan Results
|
| 139 |
+
[Tool output summaries from knip/vulture, npm audit/pip-audit, etc.]
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
### Step 5: Log to Manifest
|
| 143 |
+
|
| 144 |
+
Append an entry to `.claude/skill-runs.json` in the repo root. If the file does not exist, create it with an empty array first.
|
| 145 |
+
|
| 146 |
+
```json
|
| 147 |
+
{
|
| 148 |
+
"skill": "repo-health",
|
| 149 |
+
"date": "YYYY-MM-DD",
|
| 150 |
+
"plan": "YYYY-MM-DD-health-slug"
|
| 151 |
+
}
|
| 152 |
+
```
|
| 153 |
+
|
| 154 |
+
- Read the existing file, parse the JSON array, append the new entry, and write it back
|
| 155 |
+
- If the file is malformed, overwrite it with a fresh array containing only the new entry
|
| 156 |
+
|
| 157 |
+
### Step 6: Handoff
|
| 158 |
+
|
| 159 |
+
```text
|
| 160 |
+
Audit complete: docs/plans/YYYY-MM-DD-health-slug/health-audit.md
|
| 161 |
+
|
| 162 |
+
Findings: X critical, Y high, Z medium, W low
|
| 163 |
+
Quick wins identified: N
|
| 164 |
+
|
| 165 |
+
To remediate, run:
|
| 166 |
+
/pipeline YYYY-MM-DD-health-slug
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
## Rules
|
| 170 |
+
|
| 171 |
+
- **DO NOT** skip the scoping questions
|
| 172 |
+
- **DO NOT** re-run the auditor agent after writing health-audit.md — it runs exactly once here. Re-audit happens in `/pipeline` after all remediation is complete.
|
| 173 |
+
- **DO NOT** start remediation — your only output is the audit doc
|
| 174 |
+
- **DO** include the full auditor output (the planner needs the detail)
|
| 175 |
+
- **DO** preserve file:line locations in all findings
|
.devcontainer/devcontainer.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
| 17 |
]
|
| 18 |
}
|
| 19 |
},
|
| 20 |
-
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt;
|
| 21 |
"postAttachCommand": {
|
| 22 |
"server": "streamlit run app.py"
|
| 23 |
},
|
|
|
|
| 17 |
]
|
| 18 |
}
|
| 19 |
},
|
| 20 |
+
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; pip3 install --user -e '.[dev]'; echo 'Packages installed and requirements met'",
|
| 21 |
"postAttachCommand": {
|
| 22 |
"server": "streamlit run app.py"
|
| 23 |
},
|
.github/dependabot.yml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version: 2
|
| 2 |
+
updates:
|
| 3 |
+
- package-ecosystem: pip
|
| 4 |
+
directory: /
|
| 5 |
+
schedule:
|
| 6 |
+
interval: weekly
|
| 7 |
+
open-pull-requests-limit: 3
|
| 8 |
+
|
| 9 |
+
- package-ecosystem: github-actions
|
| 10 |
+
directory: /
|
| 11 |
+
schedule:
|
| 12 |
+
interval: weekly
|
| 13 |
+
open-pull-requests-limit: 3
|
.github/workflows/ci.yml
CHANGED
|
@@ -3,26 +3,46 @@ name: CI
|
|
| 3 |
on:
|
| 4 |
push:
|
| 5 |
branches: [main]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
pull_request:
|
| 7 |
branches: [main]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
jobs:
|
| 10 |
test:
|
| 11 |
runs-on: ubuntu-latest
|
|
|
|
| 12 |
|
| 13 |
steps:
|
| 14 |
-
- uses: actions/checkout@
|
| 15 |
|
| 16 |
- name: Set up Python
|
| 17 |
-
uses: actions/setup-python@
|
| 18 |
with:
|
| 19 |
python-version: "3.11"
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
- name: Install dependencies
|
| 23 |
-
run:
|
| 24 |
-
python -m pip install --upgrade pip
|
| 25 |
-
pip install -r requirements-dev.txt
|
| 26 |
|
| 27 |
- name: Run tests
|
| 28 |
run: pytest --cov=src --cov-report=term-missing
|
|
|
|
| 3 |
on:
|
| 4 |
push:
|
| 5 |
branches: [main]
|
| 6 |
+
paths-ignore:
|
| 7 |
+
- 'docs/**'
|
| 8 |
+
- '**/*.md'
|
| 9 |
+
- '.claude/**'
|
| 10 |
pull_request:
|
| 11 |
branches: [main]
|
| 12 |
+
paths-ignore:
|
| 13 |
+
- 'docs/**'
|
| 14 |
+
- '**/*.md'
|
| 15 |
+
- '.claude/**'
|
| 16 |
+
|
| 17 |
+
concurrency:
|
| 18 |
+
group: ${{ github.workflow }}-${{ github.ref }}
|
| 19 |
+
cancel-in-progress: true
|
| 20 |
|
| 21 |
jobs:
|
| 22 |
test:
|
| 23 |
runs-on: ubuntu-latest
|
| 24 |
+
timeout-minutes: 15
|
| 25 |
|
| 26 |
steps:
|
| 27 |
+
- uses: actions/checkout@v6
|
| 28 |
|
| 29 |
- name: Set up Python
|
| 30 |
+
uses: actions/setup-python@v6
|
| 31 |
with:
|
| 32 |
python-version: "3.11"
|
| 33 |
+
|
| 34 |
+
- name: Install uv
|
| 35 |
+
run: pip install uv
|
| 36 |
+
|
| 37 |
+
- name: Cache uv packages
|
| 38 |
+
uses: actions/cache@v4
|
| 39 |
+
with:
|
| 40 |
+
path: ~/.cache/uv
|
| 41 |
+
key: uv-${{ runner.os }}-${{ hashFiles('pyproject.toml') }}
|
| 42 |
+
restore-keys: uv-${{ runner.os }}-
|
| 43 |
|
| 44 |
- name: Install dependencies
|
| 45 |
+
run: uv pip install -e ".[dev]" --system
|
|
|
|
|
|
|
| 46 |
|
| 47 |
- name: Run tests
|
| 48 |
run: pytest --cov=src --cov-report=term-missing
|
.github/workflows/dependabot-auto-merge.yml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Dependabot Auto-Merge
|
| 2 |
+
|
| 3 |
+
on: pull_request
|
| 4 |
+
|
| 5 |
+
permissions:
|
| 6 |
+
contents: write
|
| 7 |
+
pull-requests: write
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
auto-merge:
|
| 11 |
+
if: github.actor == 'dependabot[bot]'
|
| 12 |
+
runs-on: ubuntu-latest
|
| 13 |
+
timeout-minutes: 30
|
| 14 |
+
steps:
|
| 15 |
+
- uses: dependabot/fetch-metadata@v2
|
| 16 |
+
id: meta
|
| 17 |
+
|
| 18 |
+
- name: Wait for CI to pass
|
| 19 |
+
if: steps.meta.outputs.update-type != 'version-update:semver-major'
|
| 20 |
+
run: gh pr checks "$PR_URL" --watch --required
|
| 21 |
+
env:
|
| 22 |
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
| 23 |
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
| 24 |
+
|
| 25 |
+
- name: Auto-merge
|
| 26 |
+
if: steps.meta.outputs.update-type != 'version-update:semver-major'
|
| 27 |
+
run: gh pr merge --auto --squash "$PR_URL"
|
| 28 |
+
env:
|
| 29 |
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
| 30 |
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
.github/workflows/release.yml
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Create Release
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [main]
|
| 6 |
+
paths: [CHANGELOG.md]
|
| 7 |
+
workflow_dispatch:
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
release:
|
| 11 |
+
runs-on: ubuntu-latest
|
| 12 |
+
permissions:
|
| 13 |
+
contents: write
|
| 14 |
+
steps:
|
| 15 |
+
- name: Checkout
|
| 16 |
+
uses: actions/checkout@v6
|
| 17 |
+
with:
|
| 18 |
+
fetch-depth: 0
|
| 19 |
+
|
| 20 |
+
- name: Determine version
|
| 21 |
+
id: version
|
| 22 |
+
run: |
|
| 23 |
+
# Extract latest version from CHANGELOG.md
|
| 24 |
+
VERSION=$(grep -m1 '^## \[' CHANGELOG.md | sed 's/^## \[\(.*\)\].*/\1/')
|
| 25 |
+
if [ -z "$VERSION" ]; then
|
| 26 |
+
echo "No version found in CHANGELOG.md"
|
| 27 |
+
exit 0
|
| 28 |
+
fi
|
| 29 |
+
# Check if tag already exists
|
| 30 |
+
if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
|
| 31 |
+
echo "Tag v${VERSION} already exists, skipping"
|
| 32 |
+
echo "skip=true" >> "$GITHUB_OUTPUT"
|
| 33 |
+
exit 0
|
| 34 |
+
fi
|
| 35 |
+
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
|
| 36 |
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
| 37 |
+
|
| 38 |
+
- name: Create tag if needed
|
| 39 |
+
if: steps.version.outputs.skip != 'true' && steps.version.outputs.tag != ''
|
| 40 |
+
run: |
|
| 41 |
+
TAG="${{ steps.version.outputs.tag }}"
|
| 42 |
+
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
|
| 43 |
+
git tag "$TAG"
|
| 44 |
+
git push origin "$TAG"
|
| 45 |
+
fi
|
| 46 |
+
|
| 47 |
+
- name: Extract changelog
|
| 48 |
+
if: steps.version.outputs.skip != 'true' && steps.version.outputs.version != ''
|
| 49 |
+
run: |
|
| 50 |
+
VERSION="${{ steps.version.outputs.version }}"
|
| 51 |
+
NOTES=$(sed -n "/^## \[${VERSION}\]/,/^## \[/p" CHANGELOG.md | head -n -1)
|
| 52 |
+
if [ -z "$NOTES" ]; then
|
| 53 |
+
NOTES="Release v${VERSION}"
|
| 54 |
+
fi
|
| 55 |
+
echo "$NOTES" > /tmp/release-notes.md
|
| 56 |
+
|
| 57 |
+
- name: Create GitHub release
|
| 58 |
+
if: steps.version.outputs.skip != 'true' && steps.version.outputs.version != ''
|
| 59 |
+
env:
|
| 60 |
+
GH_TOKEN: ${{ github.token }}
|
| 61 |
+
run: |
|
| 62 |
+
TAG="${{ steps.version.outputs.tag }}"
|
| 63 |
+
gh release create "$TAG" \
|
| 64 |
+
--title "$TAG" \
|
| 65 |
+
--notes-file /tmp/release-notes.md
|
.gitignore
CHANGED
|
@@ -1 +1,31 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python bytecode
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
*.pyo
|
| 5 |
+
|
| 6 |
+
# Virtual environments
|
| 7 |
+
.venv/
|
| 8 |
+
venv/
|
| 9 |
+
|
| 10 |
+
# Coverage
|
| 11 |
+
.coverage
|
| 12 |
+
htmlcov/
|
| 13 |
+
|
| 14 |
+
# Type checking / linting caches
|
| 15 |
+
.mypy_cache/
|
| 16 |
+
.pytest_cache/
|
| 17 |
+
.ruff_cache/
|
| 18 |
+
|
| 19 |
+
# Packaging
|
| 20 |
+
*.egg-info/
|
| 21 |
+
dist/
|
| 22 |
+
build/
|
| 23 |
+
|
| 24 |
+
# uv
|
| 25 |
+
uv.lock
|
| 26 |
+
|
| 27 |
+
# TensorFlow SavedModel directory (unused; winner.keras is tracked)
|
| 28 |
+
winner_model/
|
| 29 |
+
|
| 30 |
+
# Debug artifacts
|
| 31 |
+
debug_streamlit.py
|
.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
repos:
|
| 2 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 3 |
+
rev: v0.15.7
|
| 4 |
+
hooks:
|
| 5 |
+
- id: ruff
|
| 6 |
+
args: [--fix]
|
| 7 |
+
- id: ruff-format
|
| 8 |
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
| 9 |
+
rev: v1.19.1
|
| 10 |
+
hooks:
|
| 11 |
+
- id: mypy
|
| 12 |
+
additional_dependencies: [pandas-stubs, pydantic>=2.5.0]
|
| 13 |
+
args: [--config-file=pyproject.toml]
|
| 14 |
+
pass_filenames: false
|
| 15 |
+
entry: mypy src/
|
README.md
CHANGED
|
@@ -29,9 +29,9 @@ Play the game [here](https://hatman-nba-fantasy-game.hf.space).
|
|
| 29 |
|
| 30 |
## 🚀 Features
|
| 31 |
|
| 32 |
-
- **
|
| 33 |
- **Advanced Team Builder**:
|
| 34 |
-
- Search for players from a
|
| 35 |
- Input validation for secure and accurate player searches.
|
| 36 |
- Build a 5-player roster with real-time preview.
|
| 37 |
- **Dynamic Opponents**: Choose from multiple difficulty levels to generate challenging computer teams.
|
|
@@ -48,18 +48,24 @@ Play the game [here](https://hatman-nba-fantasy-game.hf.space).
|
|
| 48 |
## 📋 Project Structure
|
| 49 |
|
| 50 |
```text
|
| 51 |
-
├── app.py
|
| 52 |
-
├── pages/
|
| 53 |
-
├── src/
|
| 54 |
-
│ ├──
|
| 55 |
-
│ ├──
|
| 56 |
-
│ ├──
|
| 57 |
-
│ ├──
|
| 58 |
-
│ ├──
|
| 59 |
-
│
|
| 60 |
-
|
| 61 |
-
├──
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
```
|
| 64 |
|
| 65 |
## ⚙️ Usage
|
|
@@ -67,18 +73,16 @@ Play the game [here](https://hatman-nba-fantasy-game.hf.space).
|
|
| 67 |
### Quick Start with uv (Recommended)
|
| 68 |
|
| 69 |
```bash
|
| 70 |
-
# Install
|
| 71 |
-
uv
|
|
|
|
| 72 |
```
|
| 73 |
|
| 74 |
-
###
|
| 75 |
|
| 76 |
```bash
|
| 77 |
-
# Install
|
| 78 |
-
pip install -
|
| 79 |
-
|
| 80 |
-
# Run the application
|
| 81 |
-
streamlit run app.py
|
| 82 |
```
|
| 83 |
|
| 84 |
## 🧪 Development
|
|
@@ -95,18 +99,29 @@ pytest --cov=src
|
|
| 95 |
### Linting and Type Checking
|
| 96 |
```bash
|
| 97 |
# Run Ruff for linting and formatting
|
| 98 |
-
ruff check
|
| 99 |
|
| 100 |
# Run Mypy for static type checking
|
| 101 |
-
mypy
|
| 102 |
```
|
| 103 |
|
| 104 |
### Training the Model
|
| 105 |
-
The
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
```bash
|
| 107 |
python scripts/compile_model.py
|
| 108 |
```
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
## 📄 License
|
| 112 |
|
|
|
|
| 29 |
|
| 30 |
## 🚀 Features
|
| 31 |
|
| 32 |
+
- **Two-Page Interface**: Streamlit app with a team builder and game prediction simulator, plus a landing page.
|
| 33 |
- **Advanced Team Builder**:
|
| 34 |
+
- Search for players from a dataset of historical NBA stats (local CSV).
|
| 35 |
- Input validation for secure and accurate player searches.
|
| 36 |
- Build a 5-player roster with real-time preview.
|
| 37 |
- **Dynamic Opponents**: Choose from multiple difficulty levels to generate challenging computer teams.
|
|
|
|
| 48 |
## 📋 Project Structure
|
| 49 |
|
| 50 |
```text
|
| 51 |
+
├── app.py # Main entry point
|
| 52 |
+
├── pages/ # Streamlit page modules
|
| 53 |
+
├── src/ # Core application logic
|
| 54 |
+
│ ├── config.py # Constants, presets, logging setup
|
| 55 |
+
│ ├── database/ # CSV data loading and queries
|
| 56 |
+
│ ├── ml/ # Model loading and prediction
|
| 57 |
+
│ ├── models/ # Data models and schemas
|
| 58 |
+
│ ├── state/ # Session state management
|
| 59 |
+
│ ├── utils/ # UI and helper utilities
|
| 60 |
+
│ └── validation/ # Input validation logic
|
| 61 |
+
├── tests/ # Test suite
|
| 62 |
+
├── scripts/ # Training and utility scripts
|
| 63 |
+
├── snowflake_nba.csv # Player stats dataset (runtime data source)
|
| 64 |
+
├── winner.keras # Pre-trained prediction model
|
| 65 |
+
├── .github/workflows/ # CI and release workflows
|
| 66 |
+
├── .pre-commit-config.yaml # Pre-commit hook configuration
|
| 67 |
+
├── .streamlit/config.toml # Streamlit theme/settings
|
| 68 |
+
└── pyproject.toml # Project metadata and dependencies
|
| 69 |
```
|
| 70 |
|
| 71 |
## ⚙️ Usage
|
|
|
|
| 73 |
### Quick Start with uv (Recommended)
|
| 74 |
|
| 75 |
```bash
|
| 76 |
+
# Install the project and run the app
|
| 77 |
+
uv pip install -e .
|
| 78 |
+
streamlit run app.py
|
| 79 |
```
|
| 80 |
|
| 81 |
+
### Development Setup
|
| 82 |
|
| 83 |
```bash
|
| 84 |
+
# Install with dev dependencies (testing, linting, type checking)
|
| 85 |
+
uv pip install -e ".[dev]"
|
|
|
|
|
|
|
|
|
|
| 86 |
```
|
| 87 |
|
| 88 |
## 🧪 Development
|
|
|
|
| 99 |
### Linting and Type Checking
|
| 100 |
```bash
|
| 101 |
# Run Ruff for linting and formatting
|
| 102 |
+
ruff check src/ tests/
|
| 103 |
|
| 104 |
# Run Mypy for static type checking
|
| 105 |
+
mypy src/
|
| 106 |
```
|
| 107 |
|
| 108 |
### Training the Model
|
| 109 |
+
The training script rebuilds the model from scratch using 2018 NBA season results. It requires two input files in the project root:
|
| 110 |
+
|
| 111 |
+
- `player_stats.txt` -- player roster and statistics
|
| 112 |
+
- `schedule.txt` -- game schedule with scores
|
| 113 |
+
|
| 114 |
+
Run the training:
|
| 115 |
```bash
|
| 116 |
python scripts/compile_model.py
|
| 117 |
```
|
| 118 |
+
The script uses `RandomizedSearchCV` to search for optimal hyperparameters and saves the result as `winner.keras`, which is required at runtime for game predictions.
|
| 119 |
+
|
| 120 |
+
## 📁 Data Files and Configuration
|
| 121 |
+
|
| 122 |
+
- **`snowflake_nba.csv`**: Player statistics dataset loaded at runtime by `src/database/connection.py`. Path is resolved relative to the module location (project root).
|
| 123 |
+
- **`winner.keras`**: Pre-trained Keras model loaded by `src/ml/model.py`. Path is resolved relative to the module location (project root).
|
| 124 |
+
- **`src/config.py`**: Central configuration for column names, team size, difficulty presets, score ranges, and logging setup.
|
| 125 |
|
| 126 |
## 📄 License
|
| 127 |
|
app.py
CHANGED
|
@@ -1,16 +1,9 @@
|
|
| 1 |
"""NBA Team Builder Application - Entry Point."""
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
from src.utils.html import safe_heading, safe_paragraph
|
| 6 |
|
| 7 |
-
|
| 8 |
-
def on_page_load() -> None:
|
| 9 |
-
"""Configure page settings."""
|
| 10 |
-
st.set_page_config(layout="wide")
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
on_page_load()
|
| 14 |
|
| 15 |
safe_heading("NBA", level=1, color="steelblue")
|
| 16 |
|
|
@@ -19,5 +12,3 @@ safe_paragraph(
|
|
| 19 |
"career stats to compete with a Computer",
|
| 20 |
color="white",
|
| 21 |
)
|
| 22 |
-
|
| 23 |
-
|
|
|
|
| 1 |
"""NBA Team Builder Application - Entry Point."""
|
| 2 |
|
| 3 |
+
from src.config import configure_page
|
|
|
|
| 4 |
from src.utils.html import safe_heading, safe_paragraph
|
| 5 |
|
| 6 |
+
configure_page()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
safe_heading("NBA", level=1, color="steelblue")
|
| 9 |
|
|
|
|
| 12 |
"career stats to compete with a Computer",
|
| 13 |
color="white",
|
| 14 |
)
|
|
|
|
|
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-0.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 0: Foundation
|
| 2 |
+
|
| 3 |
+
This phase defines shared conventions, architecture decisions, and testing strategy that apply to all subsequent phases.
|
| 4 |
+
|
| 5 |
+
## Architecture Decisions
|
| 6 |
+
|
| 7 |
+
### ADR-1: Keep Streamlit as the runtime, but decouple caching from business logic
|
| 8 |
+
|
| 9 |
+
The app is a Streamlit project and will remain one. The audit flags `@st.cache_resource` and `@st.cache_data` decorators embedded in `src/ml/model.py` and `src/database/connection.py`. The fix is to move caching decorators to the Streamlit layer (pages/app) and keep `src/` modules as plain Python. This allows `src/` to be imported and tested without a Streamlit runtime.
|
| 10 |
+
|
| 11 |
+
### ADR-2: Keep TensorFlow for now; do not swap ML framework in this remediation
|
| 12 |
+
|
| 13 |
+
Swapping TensorFlow for scikit-learn or ONNX is a significant change that affects the training script, model file, and prediction pipeline. The eval audit suggests it but classifies it as MEDIUM complexity. This remediation focuses on structural quality, not framework migration. A follow-up plan can address the TF dependency.
|
| 14 |
+
|
| 15 |
+
### ADR-3: Remove unused Pydantic models rather than integrate them
|
| 16 |
+
|
| 17 |
+
The `PlayerStats` model and `from_db_row()` factory are unused in production code. The app operates on raw DataFrames throughout. Rather than retrofit DataFrame-to-model conversion across the app (high effort, unclear benefit for a Streamlit toy app), remove the unused model. Keep `DifficultySettings` since it is used.
|
| 18 |
+
|
| 19 |
+
### ADR-4: Remove SQL injection validation
|
| 20 |
+
|
| 21 |
+
The app reads from a local CSV via pandas. There is no SQL database. The SQL injection regex in `src/validation/inputs.py` protects against a nonexistent threat. Remove it. Keep the character validation and search term length checks, which are still useful for input sanitization.
|
| 22 |
+
|
| 23 |
+
### ADR-5: Consolidate dependencies to pyproject.toml only
|
| 24 |
+
|
| 25 |
+
`requirements.txt` and `pyproject.toml` declare the same dependencies. Remove `requirements.txt` and update CI to install from `pyproject.toml`. Keep `requirements-dev.txt` only if it differs from `[project.optional-dependencies] dev`.
|
| 26 |
+
|
| 27 |
+
## Tech Stack
|
| 28 |
+
|
| 29 |
+
- **Runtime:** Python 3.11+ / Streamlit
|
| 30 |
+
- **ML:** TensorFlow/Keras (unchanged)
|
| 31 |
+
- **Data:** pandas DataFrames from local CSV
|
| 32 |
+
- **Validation:** Pydantic v2 (for DifficultySettings only, post-cleanup)
|
| 33 |
+
- **Testing:** pytest + pytest-cov
|
| 34 |
+
- **Linting:** ruff (lint + format)
|
| 35 |
+
- **Type checking:** mypy (strict mode)
|
| 36 |
+
- **CI:** GitHub Actions
|
| 37 |
+
|
| 38 |
+
## Testing Strategy
|
| 39 |
+
|
| 40 |
+
- All tests must run without a Streamlit runtime (no `streamlit run` needed).
|
| 41 |
+
- Mock `streamlit` imports where page modules are tested.
|
| 42 |
+
- Use `pytest` fixtures in `conftest.py` for shared test data (DataFrames, model mocks).
|
| 43 |
+
- Integration tests that load real CSV data are acceptable since the CSV is committed to the repo.
|
| 44 |
+
- No live external services; all network calls are mocked.
|
| 45 |
+
- Target coverage threshold: 70% (up from 50%).
|
| 46 |
+
|
| 47 |
+
## Commit Message Format
|
| 48 |
+
|
| 49 |
+
Use conventional commits:
|
| 50 |
+
|
| 51 |
+
```text
|
| 52 |
+
type(scope): brief description
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
Types: `fix`, `feat`, `refactor`, `test`, `ci`, `docs`, `chore`
|
| 56 |
+
|
| 57 |
+
Scopes: `gitignore`, `dead-code`, `database`, `ml`, `validation`, `state`, `pages`, `ci`, `deps`, `readme`
|
| 58 |
+
|
| 59 |
+
Examples:
|
| 60 |
+
- `refactor(dead-code): remove unused GameState and dead functions`
|
| 61 |
+
- `fix(database): remove empty finally block in connection manager`
|
| 62 |
+
- `ci(deps): consolidate to pyproject.toml, remove requirements.txt`
|
| 63 |
+
|
| 64 |
+
## Shared Patterns
|
| 65 |
+
|
| 66 |
+
### Logging
|
| 67 |
+
|
| 68 |
+
Replace f-string logging with lazy `%s` formatting:
|
| 69 |
+
```python
|
| 70 |
+
# Before
|
| 71 |
+
logger.error(f"Error: {e}")
|
| 72 |
+
# After
|
| 73 |
+
logger.error("Error: %s", e)
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
### Imports
|
| 77 |
+
|
| 78 |
+
Keep `__init__.py` files with explicit `__all__` exports. When removing dead code, update both the source file and the corresponding `__init__.py`.
|
| 79 |
+
|
| 80 |
+
### Error Handling
|
| 81 |
+
|
| 82 |
+
Use specific exception types, not bare `except Exception`. Remove no-op `finally: pass` blocks.
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-1.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 1: [HYGIENIST] Cleanup
|
| 2 |
+
|
| 3 |
+
## Phase Goal
|
| 4 |
+
|
| 5 |
+
Remove dead code, unused exports, debug artifacts, and fix `.gitignore` to prevent future artifact commits. This is pure subtraction with no behavioral changes.
|
| 6 |
+
|
| 7 |
+
**Success criteria:** All 7 dead functions/classes identified in the health audit are removed. `.gitignore` covers all generated artifacts. No functional behavior changes. All existing tests still pass.
|
| 8 |
+
|
| 9 |
+
**Estimated tokens:** ~20k
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Phase 0 read and understood
|
| 14 |
+
- Repository cloned, `uv pip install -e ".[dev]"` completed
|
| 15 |
+
- Existing tests pass: `pytest`
|
| 16 |
+
|
| 17 |
+
## Tasks
|
| 18 |
+
|
| 19 |
+
### Task 1: Expand .gitignore
|
| 20 |
+
|
| 21 |
+
**Goal:** Prevent accidental commits of build artifacts, caches, coverage files, and binary model directories. Addresses health audit finding #2 (CRITICAL) and eval git-hygiene score 5/10.
|
| 22 |
+
|
| 23 |
+
**Files to Modify:**
|
| 24 |
+
- `.gitignore` - Rewrite with comprehensive patterns
|
| 25 |
+
|
| 26 |
+
**Prerequisites:** None
|
| 27 |
+
|
| 28 |
+
**Implementation Steps:**
|
| 29 |
+
- Replace the single-line `.gitignore` with a comprehensive Python `.gitignore`.
|
| 30 |
+
- Include patterns for: `__pycache__/`, `*.pyc`, `*.pyo`, `.coverage`, `.mypy_cache/`, `.pytest_cache/`, `.ruff_cache/`, `*.egg-info/`, `.venv/`, `venv/`, `uv.lock`, `winner_model/`, `debug_streamlit.py`, `*.keras` model files (if using download script) or keep `winner.keras` tracked (it is needed at runtime). Since the model is only 87KB and needed at runtime, keep it tracked but add `winner_model/` (the unused SavedModel directory).
|
| 31 |
+
- Do NOT add `snowflake_nba.csv`, `player_stats.txt`, or `schedule.txt` since these are runtime/training data needed by the app.
|
| 32 |
+
|
| 33 |
+
**Verification Checklist:**
|
| 34 |
+
- [x] `.gitignore` contains patterns for `__pycache__/`, `*.pyc`, `.coverage`, `.mypy_cache/`, `.pytest_cache/`, `.ruff_cache/`, `*.egg-info/`, `.venv/`, `venv/`, `winner_model/`
|
| 35 |
+
- [x] `git status` no longer shows `__pycache__/`, `.coverage`, `src/streamlit_nba.egg-info/` as untracked
|
| 36 |
+
- [x] `winner.keras` is NOT ignored (it is needed at runtime and only 87KB)
|
| 37 |
+
|
| 38 |
+
**Testing Instructions:** No tests needed. Visual verification via `git status`.
|
| 39 |
+
|
| 40 |
+
**Commit Message Template:**
|
| 41 |
+
```text
|
| 42 |
+
chore(gitignore): expand .gitignore to cover build artifacts and caches
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
---
|
| 46 |
+
|
| 47 |
+
### Task 2: Remove dead functions and classes from src/state/session.py
|
| 48 |
+
|
| 49 |
+
**Goal:** Remove 5 unused exports: `GameState` class, `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, `remove_player_from_team()`. Addresses health audit finding #4 (HIGH).
|
| 50 |
+
|
| 51 |
+
**Files to Modify:**
|
| 52 |
+
- `src/state/session.py` - Remove dead code
|
| 53 |
+
- `src/state/__init__.py` - Remove dead exports from `__all__`
|
| 54 |
+
|
| 55 |
+
**Prerequisites:** Task 1
|
| 56 |
+
|
| 57 |
+
**Implementation Steps:**
|
| 58 |
+
- Read `src/state/session.py` and `src/state/__init__.py` to understand current exports.
|
| 59 |
+
- Search the entire codebase for any usage of the 5 items to confirm they are truly unused. Search for: `GameState`, `get_home_team_names`, `set_difficulty`, `add_player_to_team`, `remove_player_from_team`.
|
| 60 |
+
- Remove the `GameState` dataclass (around lines 19-29).
|
| 61 |
+
- Remove the functions `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, `remove_player_from_team()` (around lines 86-163).
|
| 62 |
+
- Update `src/state/__init__.py` to remove these from `__all__` and from imports.
|
| 63 |
+
- Keep: `init_session_state()`, `get_away_stats()`, `get_home_team_df()`, and any other functions that ARE used.
|
| 64 |
+
|
| 65 |
+
**Verification Checklist:**
|
| 66 |
+
- [x] `GameState` class no longer exists in `session.py`
|
| 67 |
+
- [x] The 4 dead functions no longer exist in `session.py`
|
| 68 |
+
- [x] `src/state/__init__.py` exports only the functions that remain
|
| 69 |
+
- [x] `pytest` passes with no failures
|
| 70 |
+
- [x] `ruff check src/ tests/` passes
|
| 71 |
+
|
| 72 |
+
**Testing Instructions:** Run existing test suite. No new tests needed since these functions had no tests.
|
| 73 |
+
|
| 74 |
+
**Commit Message Template:**
|
| 75 |
+
```text
|
| 76 |
+
refactor(dead-code): remove unused GameState and 4 dead functions from session.py
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
---
|
| 80 |
+
|
| 81 |
+
### Task 3: Remove dead functions from queries.py and html.py
|
| 82 |
+
|
| 83 |
+
**Goal:** Remove `get_player_by_full_name()` from queries and `safe_styled_text()` from html utils. Addresses health audit finding #5 (HIGH).
|
| 84 |
+
|
| 85 |
+
**Files to Modify:**
|
| 86 |
+
- `src/database/queries.py` - Remove `get_player_by_full_name()`
|
| 87 |
+
- `src/database/__init__.py` - Remove from exports
|
| 88 |
+
- `src/utils/html.py` - Remove `safe_styled_text()`
|
| 89 |
+
- `src/utils/__init__.py` - Remove from exports
|
| 90 |
+
|
| 91 |
+
**Prerequisites:** Task 1
|
| 92 |
+
|
| 93 |
+
**Implementation Steps:**
|
| 94 |
+
- Search codebase for `get_player_by_full_name` and `safe_styled_text` to confirm they are unused.
|
| 95 |
+
- Remove `get_player_by_full_name()` from `src/database/queries.py` (around lines 34-49).
|
| 96 |
+
- Remove `safe_styled_text()` from `src/utils/html.py` (around lines 73-108).
|
| 97 |
+
- Update both `__init__.py` files to remove these from `__all__` and imports.
|
| 98 |
+
- Check if any tests reference these functions. If tests exist for them, remove those test cases too.
|
| 99 |
+
|
| 100 |
+
**Verification Checklist:**
|
| 101 |
+
- [x] `get_player_by_full_name` does not appear in any source file
|
| 102 |
+
- [x] `safe_styled_text` does not appear in any source file
|
| 103 |
+
- [x] `__init__.py` exports updated
|
| 104 |
+
- [x] `pytest` passes
|
| 105 |
+
- [x] `ruff check src/ tests/` passes
|
| 106 |
+
|
| 107 |
+
**Testing Instructions:** Run existing test suite. Remove any tests that test the deleted functions.
|
| 108 |
+
|
| 109 |
+
**Commit Message Template:**
|
| 110 |
+
```text
|
| 111 |
+
refactor(dead-code): remove unused get_player_by_full_name and safe_styled_text
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
---
|
| 115 |
+
|
| 116 |
+
### Task 4: Remove unused PlayerStats Pydantic model
|
| 117 |
+
|
| 118 |
+
**Goal:** Remove the `PlayerStats` model and `from_db_row()` factory that are never used in production code. Addresses eval architecture concern and health audit finding #12 (MEDIUM). Per ADR-3, we remove rather than integrate.
|
| 119 |
+
|
| 120 |
+
**Files to Modify:**
|
| 121 |
+
- `src/models/player.py` - Remove `PlayerStats` class and `from_db_row()`
|
| 122 |
+
- `src/models/__init__.py` - Remove `PlayerStats` from exports
|
| 123 |
+
- `tests/test_models.py` - Remove tests for `PlayerStats` (keep `DifficultySettings` tests)
|
| 124 |
+
|
| 125 |
+
**Prerequisites:** Task 1
|
| 126 |
+
|
| 127 |
+
**Implementation Steps:**
|
| 128 |
+
- Read `src/models/player.py` to identify `PlayerStats` class boundaries.
|
| 129 |
+
- Search for `PlayerStats` across the codebase to confirm it is only used in tests.
|
| 130 |
+
- Remove the `PlayerStats` class and `from_db_row()` method.
|
| 131 |
+
- Keep `DifficultySettings` and its validators since those are used by the app.
|
| 132 |
+
- Update `src/models/__init__.py` to remove `PlayerStats` from exports.
|
| 133 |
+
- Update `tests/test_models.py` to remove `PlayerStats` test cases. Keep `DifficultySettings` tests.
|
| 134 |
+
- Clean up any imports that are no longer needed after removing `PlayerStats` (e.g., `Any` if only used by `from_db_row`).
|
| 135 |
+
|
| 136 |
+
**Verification Checklist:**
|
| 137 |
+
- [x] `PlayerStats` class no longer exists
|
| 138 |
+
- [x] `from_db_row` no longer exists
|
| 139 |
+
- [x] `DifficultySettings` and its tests are untouched
|
| 140 |
+
- [x] `pytest` passes
|
| 141 |
+
- [x] `mypy src/` passes
|
| 142 |
+
- [x] `ruff check src/ tests/` passes
|
| 143 |
+
|
| 144 |
+
**Testing Instructions:** Run full test suite. Verify `DifficultySettings` tests still pass.
|
| 145 |
+
|
| 146 |
+
**Commit Message Template:**
|
| 147 |
+
```text
|
| 148 |
+
refactor(dead-code): remove unused PlayerStats Pydantic model
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
---
|
| 152 |
+
|
| 153 |
+
### Task 5: Remove debug_streamlit.py reference from pyproject.toml
|
| 154 |
+
|
| 155 |
+
**Goal:** Remove the ruff per-file-ignores entry for `debug_streamlit.py` since the file is a local debug artifact, not committed code. Addresses doc audit structure issue #2.
|
| 156 |
+
|
| 157 |
+
**Files to Modify:**
|
| 158 |
+
- `pyproject.toml` - Remove `debug_streamlit.py` from `per-file-ignores`
|
| 159 |
+
|
| 160 |
+
**Prerequisites:** None
|
| 161 |
+
|
| 162 |
+
**Implementation Steps:**
|
| 163 |
+
- In `pyproject.toml`, find the `[tool.ruff.lint.per-file-ignores]` section.
|
| 164 |
+
- Remove the line `"debug_streamlit.py" = ["E402"]`.
|
| 165 |
+
- The `debug_streamlit.py` file itself is already in `.gitignore` (from Task 1) and untracked.
|
| 166 |
+
|
| 167 |
+
**Verification Checklist:**
|
| 168 |
+
- [x] `debug_streamlit.py` no longer appears in `pyproject.toml`
|
| 169 |
+
- [x] `ruff check src/ tests/` passes
|
| 170 |
+
|
| 171 |
+
**Testing Instructions:** None needed.
|
| 172 |
+
|
| 173 |
+
**Commit Message Template:**
|
| 174 |
+
```text
|
| 175 |
+
chore(config): remove debug_streamlit.py from ruff per-file-ignores
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
---
|
| 179 |
+
|
| 180 |
+
### Task 6: Remove SQL injection validation (per ADR-4)
|
| 181 |
+
|
| 182 |
+
**Goal:** Remove the SQL injection regex and related code from `src/validation/inputs.py`. Keep character validation and length checks. Addresses health audit finding #11 (MEDIUM) and eval pragmatism concerns.
|
| 183 |
+
|
| 184 |
+
**Files to Modify:**
|
| 185 |
+
- `src/validation/inputs.py` - Remove SQL injection patterns and regex check
|
| 186 |
+
- `src/validation/__init__.py` - Update exports if needed
|
| 187 |
+
- `tests/test_validation.py` - Remove SQL injection test cases, keep character validation tests
|
| 188 |
+
|
| 189 |
+
**Prerequisites:** Task 1
|
| 190 |
+
|
| 191 |
+
**Implementation Steps:**
|
| 192 |
+
- Read `src/validation/inputs.py` to understand the full validation logic.
|
| 193 |
+
- Remove the `SQL_INJECTION_PATTERNS` compiled regex (around lines 8-24).
|
| 194 |
+
- In the validation function(s), remove the SQL injection pattern check.
|
| 195 |
+
- Keep: search term length validation, character allowlist checks, any `PlayerSearchInput` Pydantic model fields that are not SQL-related.
|
| 196 |
+
- Update `tests/test_validation.py`: remove parametrized SQL injection test vectors. Keep tests for character validation, length limits, and legitimate names like "O'Neal" and "J.R. Smith".
|
| 197 |
+
- Also remove the ruff ignore for `S608` (SQL injection false positive) from `pyproject.toml` since there will be no SQL-related code left.
|
| 198 |
+
|
| 199 |
+
**Verification Checklist:**
|
| 200 |
+
- [x] No SQL injection patterns or regex in `inputs.py`
|
| 201 |
+
- [x] Character validation and length checks still work
|
| 202 |
+
- [x] `pytest` passes (with updated test cases)
|
| 203 |
+
- [x] `ruff check src/ tests/` passes
|
| 204 |
+
|
| 205 |
+
**Testing Instructions:** Run the validation tests specifically: `pytest tests/test_validation.py -v`
|
| 206 |
+
|
| 207 |
+
**Commit Message Template:**
|
| 208 |
+
```text
|
| 209 |
+
refactor(validation): remove SQL injection guards (no SQL database exists)
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
---
|
| 213 |
+
|
| 214 |
+
### Task 7: Remove finally:pass and fix duplicate on_page_load
|
| 215 |
+
|
| 216 |
+
**Goal:** Quick code hygiene fixes. Remove the no-op `finally: pass` block in `connection.py` and extract the duplicated `on_page_load()` pattern. Addresses health audit findings #16 (MEDIUM) and #18 (LOW).
|
| 217 |
+
|
| 218 |
+
**Files to Modify:**
|
| 219 |
+
- `src/database/connection.py` - Remove `finally: pass` block (around lines 72-73)
|
| 220 |
+
- `src/config.py` - Add a shared `configure_page()` function
|
| 221 |
+
- `pages/1_home_team.py` - Use shared function instead of local `on_page_load()`
|
| 222 |
+
- `pages/2_play_game.py` - Use shared function instead of local `on_page_load()`
|
| 223 |
+
- `app.py` - Use shared function instead of local `on_page_load()`
|
| 224 |
+
|
| 225 |
+
**Prerequisites:** None
|
| 226 |
+
|
| 227 |
+
**Implementation Steps:**
|
| 228 |
+
- In `src/database/connection.py`, find the `finally: pass` block in the context manager and remove it entirely (the `finally` keyword and the `pass` statement).
|
| 229 |
+
- In `src/config.py`, add a function `configure_page` that calls `st.set_page_config(layout="wide")`. This function will need to import streamlit, which is acceptable since it is a UI configuration function.
|
| 230 |
+
- In each of `app.py`, `pages/1_home_team.py`, and `pages/2_play_game.py`: remove the local `on_page_load()` function definition and its call. Replace with `from src.config import configure_page` and call `configure_page()`.
|
| 231 |
+
|
| 232 |
+
**Verification Checklist:**
|
| 233 |
+
- [x] No `finally: pass` in `connection.py`
|
| 234 |
+
- [x] `on_page_load` does not appear in any page file or `app.py`
|
| 235 |
+
- [x] `configure_page` exists in `src/config.py` and is called by all 3 entry points
|
| 236 |
+
- [x] `pytest` passes
|
| 237 |
+
- [x] `ruff check src/ tests/` passes
|
| 238 |
+
|
| 239 |
+
**Testing Instructions:** Run existing tests. The `configure_page` function is UI-only and does not need a unit test.
|
| 240 |
+
|
| 241 |
+
**Commit Message Template:**
|
| 242 |
+
```text
|
| 243 |
+
refactor(pages): extract shared configure_page, remove finally:pass
|
| 244 |
+
```
|
| 245 |
+
|
| 246 |
+
## Phase Verification
|
| 247 |
+
|
| 248 |
+
After completing all tasks in this phase:
|
| 249 |
+
|
| 250 |
+
1. Execute `pytest` and confirm all tests pass.
|
| 251 |
+
2. Lint with `ruff check src/ tests/` and confirm no errors.
|
| 252 |
+
3. Type-check with `mypy src/` and confirm no errors.
|
| 253 |
+
4. Verify with `git diff --stat` that only expected files changed.
|
| 254 |
+
5. Verify no dead code identified in the health audit remains.
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-2.md
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 2: [IMPLEMENTER] Architecture and Code Fixes
|
| 2 |
+
|
| 3 |
+
## Phase Goal
|
| 4 |
+
|
| 5 |
+
Fix structural and architectural issues: decouple Streamlit caching from business logic, fix error handling, improve input validation, add data shape guards, and fix logging. This phase addresses the critical architectural debt and high-severity findings.
|
| 6 |
+
|
| 7 |
+
**Success criteria:** `src/` modules can be imported and tested without a Streamlit runtime. Error handling uses specific exceptions. Logging uses lazy formatting. Input validation on ML pipeline prevents silent shape errors.
|
| 8 |
+
|
| 9 |
+
**Estimated tokens:** ~30k
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Phase 1 complete (dead code removed, clean baseline)
|
| 14 |
+
- All tests passing
|
| 15 |
+
|
| 16 |
+
## Tasks
|
| 17 |
+
|
| 18 |
+
### Task 1: Decouple Streamlit caching from src/database/connection.py
|
| 19 |
+
|
| 20 |
+
**Goal:** Remove `@st.cache_data` from `load_data()` so that `src/database/connection.py` can be imported without Streamlit. Move caching to the page layer. Addresses health audit finding #1 (CRITICAL).
|
| 21 |
+
|
| 22 |
+
**Files to Modify:**
|
| 23 |
+
- `src/database/connection.py` - Remove `import streamlit as st` and `@st.cache_data` decorator
|
| 24 |
+
- `pages/1_home_team.py` - Cache the data load call at the page level
|
| 25 |
+
- `pages/2_play_game.py` - Cache the data load call at the page level
|
| 26 |
+
|
| 27 |
+
**Prerequisites:** None
|
| 28 |
+
|
| 29 |
+
**Implementation Steps:**
|
| 30 |
+
- In `src/database/connection.py`:
|
| 31 |
+
- Remove `import streamlit as st`.
|
| 32 |
+
- Remove the `@st.cache_data` decorator from `load_data()`. The function itself stays unchanged; it still reads the CSV and returns a DataFrame.
|
| 33 |
+
- The `get_connection()` context manager should also be simplified. Per the eval audit, it wraps a cached DataFrame read with no actual resource cleanup. Simplify: make `get_connection()` a plain function that calls `load_data()` and returns the DataFrame directly, OR keep the context manager but remove the ceremony. Recommended: replace with a plain function `get_data()` that returns `load_data()`.
|
| 34 |
+
- In the page files (`pages/1_home_team.py`, `pages/2_play_game.py`), wherever `get_connection()` or `load_data()` is called:
|
| 35 |
+
- Add `@st.cache_data` to a local wrapper function if caching is needed, OR use `st.cache_data` inline.
|
| 36 |
+
- The simplest approach: create a module-level cached wrapper in each page file:
|
| 37 |
+
```python
|
| 38 |
+
@st.cache_data
|
| 39 |
+
def _load_nba_data() -> pd.DataFrame:
|
| 40 |
+
return load_data()
|
| 41 |
+
```
|
| 42 |
+
- Replace `get_connection()` context manager usage with direct calls to `_load_nba_data()`.
|
| 43 |
+
|
| 44 |
+
**Verification Checklist:**
|
| 45 |
+
- [x] `src/database/connection.py` does not import `streamlit`
|
| 46 |
+
- [x] `python -c "from src.database.connection import load_data"` succeeds without Streamlit installed (or mocked)
|
| 47 |
+
- [x] Pages still load data correctly (manual test with `streamlit run app.py` if possible)
|
| 48 |
+
- [x] `pytest` passes
|
| 49 |
+
- [x] `mypy src/` passes
|
| 50 |
+
|
| 51 |
+
**Testing Instructions:**
|
| 52 |
+
- Update `tests/test_database.py` to remove any Streamlit mocking for `connection.py`.
|
| 53 |
+
- Add a simple test that calls `load_data()` directly and verifies it returns a DataFrame with expected columns.
|
| 54 |
+
|
| 55 |
+
**Commit Message Template:**
|
| 56 |
+
```text
|
| 57 |
+
refactor(database): decouple Streamlit caching from connection module
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
---
|
| 61 |
+
|
| 62 |
+
### Task 2: Decouple Streamlit caching from src/ml/model.py
|
| 63 |
+
|
| 64 |
+
**Goal:** Remove `@st.cache_resource` from the model loading function so `src/ml/model.py` can be imported without Streamlit. Addresses health audit finding #1 (CRITICAL).
|
| 65 |
+
|
| 66 |
+
**Files to Modify:**
|
| 67 |
+
- `src/ml/model.py` - Remove `import streamlit as st` and `@st.cache_resource`
|
| 68 |
+
- `pages/2_play_game.py` - Cache model loading at the page level
|
| 69 |
+
|
| 70 |
+
**Prerequisites:** Task 1
|
| 71 |
+
|
| 72 |
+
**Implementation Steps:**
|
| 73 |
+
- In `src/ml/model.py`:
|
| 74 |
+
- Remove `import streamlit as st`.
|
| 75 |
+
- Remove `@st.cache_resource` decorator from the model loading function (around line 22).
|
| 76 |
+
- The function itself stays the same: it loads and returns the Keras model.
|
| 77 |
+
- In `pages/2_play_game.py`:
|
| 78 |
+
- Add a cached wrapper for model loading:
|
| 79 |
+
```python
|
| 80 |
+
@st.cache_resource
|
| 81 |
+
def _get_model():
|
| 82 |
+
return get_winner_model()
|
| 83 |
+
```
|
| 84 |
+
- Replace direct calls to `get_winner_model()` with `_get_model()`.
|
| 85 |
+
|
| 86 |
+
**Verification Checklist:**
|
| 87 |
+
- [x] `src/ml/model.py` does not import `streamlit`
|
| 88 |
+
- [x] `python -c "from src.ml.model import get_winner_model"` succeeds without Streamlit
|
| 89 |
+
- [x] `pytest` passes
|
| 90 |
+
- [x] `mypy src/` passes
|
| 91 |
+
|
| 92 |
+
**Testing Instructions:**
|
| 93 |
+
- Update `tests/test_ml.py` to remove any Streamlit mocking that was needed due to the `st.cache_resource` import.
|
| 94 |
+
|
| 95 |
+
**Commit Message Template:**
|
| 96 |
+
```text
|
| 97 |
+
refactor(ml): decouple Streamlit caching from model module
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
---
|
| 101 |
+
|
| 102 |
+
### Task 3: Fix error handling - narrow exception catches
|
| 103 |
+
|
| 104 |
+
**Goal:** Replace broad `except Exception` catches with specific exception types. Remove duplicate logging. Addresses health audit finding #7 (HIGH).
|
| 105 |
+
|
| 106 |
+
**Files to Modify:**
|
| 107 |
+
- `src/database/connection.py` - Narrow exception catches at lines ~48 and ~69
|
| 108 |
+
|
| 109 |
+
**Prerequisites:** Task 1
|
| 110 |
+
|
| 111 |
+
**Implementation Steps:**
|
| 112 |
+
- At `connection.py` around line 48 (the `pd.read_csv()` call):
|
| 113 |
+
- Replace `except Exception as e` with specific exceptions: `except (FileNotFoundError, pd.errors.ParserError, pd.errors.EmptyDataError) as e`.
|
| 114 |
+
- Keep the re-raise as `DatabaseConnectionError`.
|
| 115 |
+
- At `connection.py` around line 69 (data access):
|
| 116 |
+
- Replace `except Exception as e` with the specific exceptions that could actually occur (e.g., `KeyError`, `ValueError`).
|
| 117 |
+
- Keep the re-raise as the appropriate custom exception.
|
| 118 |
+
- Review callers in pages to ensure they catch the custom exceptions, not bare `Exception`.
|
| 119 |
+
|
| 120 |
+
**Verification Checklist:**
|
| 121 |
+
- [x] No `except Exception` in `connection.py`
|
| 122 |
+
- [x] All exception catches use specific types
|
| 123 |
+
- [x] `pytest` passes
|
| 124 |
+
- [x] `mypy src/` passes
|
| 125 |
+
|
| 126 |
+
**Testing Instructions:**
|
| 127 |
+
- Existing tests should cover this. Add a test that verifies a `FileNotFoundError` is raised as `DatabaseConnectionError`.
|
| 128 |
+
|
| 129 |
+
**Commit Message Template:**
|
| 130 |
+
```text
|
| 131 |
+
fix(database): narrow exception catches to specific types
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
---
|
| 135 |
+
|
| 136 |
+
### Task 4: Fix logging - replace f-strings with lazy formatting
|
| 137 |
+
|
| 138 |
+
**Goal:** Replace f-string interpolation in logging calls with `%s` lazy formatting. Addresses health audit finding #8 (HIGH).
|
| 139 |
+
|
| 140 |
+
**Files to Modify:**
|
| 141 |
+
- `pages/1_home_team.py` - Fix ~6 logging calls
|
| 142 |
+
- `pages/2_play_game.py` - Fix ~4 logging calls
|
| 143 |
+
- `src/database/connection.py` - Fix any f-string logging calls
|
| 144 |
+
|
| 145 |
+
**Prerequisites:** None
|
| 146 |
+
|
| 147 |
+
**Implementation Steps:**
|
| 148 |
+
- Search all Python files for patterns like `logger.error(f"` or `logger.warning(f"` or `logger.info(f"`.
|
| 149 |
+
- Replace each with lazy formatting:
|
| 150 |
+
```python
|
| 151 |
+
# Before
|
| 152 |
+
logger.error(f"Database connection error: {e}")
|
| 153 |
+
# After
|
| 154 |
+
logger.error("Database connection error: %s", e)
|
| 155 |
+
```
|
| 156 |
+
- Apply this change consistently across all files.
|
| 157 |
+
|
| 158 |
+
**Verification Checklist:**
|
| 159 |
+
- [x] No f-strings in any `logger.*()` calls
|
| 160 |
+
- [x] `ruff check src/ tests/` passes
|
| 161 |
+
- [x] `pytest` passes
|
| 162 |
+
|
| 163 |
+
**Testing Instructions:** No new tests needed. This is a mechanical replacement.
|
| 164 |
+
|
| 165 |
+
**Commit Message Template:**
|
| 166 |
+
```text
|
| 167 |
+
fix(logging): replace f-string logging with lazy %s formatting
|
| 168 |
+
```
|
| 169 |
+
|
| 170 |
+
---
|
| 171 |
+
|
| 172 |
+
### Task 5: Add input shape validation to ML pipeline
|
| 173 |
+
|
| 174 |
+
**Goal:** Add explicit validation of player stat array shapes before model prediction. Addresses health audit finding #9 (HIGH).
|
| 175 |
+
|
| 176 |
+
**Files to Modify:**
|
| 177 |
+
- `src/ml/model.py` - Add validation in `analyze_team_stats()`
|
| 178 |
+
- `src/config.py` - Verify `TEAM_SIZE` and `STAT_COLUMNS` constants are defined
|
| 179 |
+
|
| 180 |
+
**Prerequisites:** Task 2
|
| 181 |
+
|
| 182 |
+
**Implementation Steps:**
|
| 183 |
+
- In `analyze_team_stats()` (around lines 83-114):
|
| 184 |
+
- Before processing, validate that the input list has exactly `TEAM_SIZE` (5) players.
|
| 185 |
+
- Validate that each player's stat list has exactly `len(STAT_COLUMNS)` (10) elements.
|
| 186 |
+
- Raise a `ValueError` with a descriptive message if validation fails, e.g.: `f"Expected {TEAM_SIZE} players, got {len(stats)}"` and `f"Player {i} has {len(player_stats)} stats, expected {len(STAT_COLUMNS)}"`.
|
| 187 |
+
- Import `TEAM_SIZE` and `STAT_COLUMNS` (or their lengths) from `src/config.py`.
|
| 188 |
+
|
| 189 |
+
**Verification Checklist:**
|
| 190 |
+
- [x] `analyze_team_stats` raises `ValueError` if player count != 5
|
| 191 |
+
- [x] `analyze_team_stats` raises `ValueError` if any player has wrong stat count
|
| 192 |
+
- [x] Existing tests pass
|
| 193 |
+
- [x] New tests cover the validation
|
| 194 |
+
|
| 195 |
+
**Testing Instructions:**
|
| 196 |
+
- Add tests in `tests/test_ml.py`:
|
| 197 |
+
- Test with wrong number of players (4 and 6), expect `ValueError`.
|
| 198 |
+
- Test with a player having wrong number of stats (9 instead of 10), expect `ValueError`.
|
| 199 |
+
|
| 200 |
+
**Commit Message Template:**
|
| 201 |
+
```text
|
| 202 |
+
fix(ml): add input shape validation before model prediction
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
---
|
| 206 |
+
|
| 207 |
+
### Task 6: Fix DifficultySettings duplicate validation
|
| 208 |
+
|
| 209 |
+
**Goal:** Remove redundant validation in `DifficultySettings`. Addresses health audit finding #19 (LOW).
|
| 210 |
+
|
| 211 |
+
**Files to Modify:**
|
| 212 |
+
- `src/models/player.py` - Remove duplicate validation in either `validate_preset_name` or `from_preset()`
|
| 213 |
+
|
| 214 |
+
**Prerequisites:** Phase 1 Task 4 (PlayerStats removal)
|
| 215 |
+
|
| 216 |
+
**Implementation Steps:**
|
| 217 |
+
- Read the current state of `src/models/player.py` after Phase 1 cleanup.
|
| 218 |
+
- The `validate_preset_name` field validator (around line 95) checks if name is valid.
|
| 219 |
+
- The `from_preset()` class method (around line 119) performs the same check again.
|
| 220 |
+
- Remove the redundant check from `from_preset()` since the Pydantic validator will catch it during construction. Let `from_preset()` simply construct the instance and trust Pydantic validation.
|
| 221 |
+
|
| 222 |
+
**Verification Checklist:**
|
| 223 |
+
- [x] Only one validation path for preset names
|
| 224 |
+
- [x] `pytest tests/test_models.py` passes
|
| 225 |
+
- [x] Invalid preset names still raise appropriate errors
|
| 226 |
+
|
| 227 |
+
**Testing Instructions:** Existing `DifficultySettings` tests should cover this. Verify they pass.
|
| 228 |
+
|
| 229 |
+
**Commit Message Template:**
|
| 230 |
+
```text
|
| 231 |
+
fix(models): remove duplicate validation in DifficultySettings
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
---
|
| 235 |
+
|
| 236 |
+
### Task 7: Fix compile_model.py create_stats mutation
|
| 237 |
+
|
| 238 |
+
**Goal:** Fix the `create_stats` function to use slicing instead of destructive `del` operations. Addresses eval creativity concern.
|
| 239 |
+
|
| 240 |
+
**Files to Modify:**
|
| 241 |
+
- `scripts/compile_model.py` - Fix `create_stats()` (around lines 73-113)
|
| 242 |
+
|
| 243 |
+
**Prerequisites:** None
|
| 244 |
+
|
| 245 |
+
**Implementation Steps:**
|
| 246 |
+
- Read `scripts/compile_model.py` to understand `create_stats()`.
|
| 247 |
+
- Replace `del home_stats[i][j][0]` patterns with slicing: use `row[1:]` to skip the first element instead of deleting it.
|
| 248 |
+
- The function should produce the same output without mutating its input lists.
|
| 249 |
+
- Fix type hints: change `list[list]` to `list[list[float]]` or more precise types.
|
| 250 |
+
|
| 251 |
+
**Verification Checklist:**
|
| 252 |
+
- [x] No `del` operations on input data in `create_stats`
|
| 253 |
+
- [x] `ruff check scripts/` passes
|
| 254 |
+
- [x] Function produces same output (manual verification or add a simple test)
|
| 255 |
+
|
| 256 |
+
**Testing Instructions:** This is a training script, not part of the test suite. Manual verification that the output is unchanged, or add a simple test comparing old behavior vs new.
|
| 257 |
+
|
| 258 |
+
**Commit Message Template:**
|
| 259 |
+
```text
|
| 260 |
+
fix(scripts): replace destructive del with slicing in create_stats
|
| 261 |
+
```
|
| 262 |
+
|
| 263 |
+
---
|
| 264 |
+
|
| 265 |
+
### Task 8: Fix module-level logging setup
|
| 266 |
+
|
| 267 |
+
**Goal:** Move `setup_logging()` call from module-level to an explicit initialization point. Addresses health audit finding #17 (MEDIUM).
|
| 268 |
+
|
| 269 |
+
**Files to Modify:**
|
| 270 |
+
- `src/config.py` - Remove module-level `setup_logging()` call (line 93)
|
| 271 |
+
- `app.py` - Call `setup_logging()` explicitly
|
| 272 |
+
- `pages/1_home_team.py` - Call `setup_logging()` if not already initialized
|
| 273 |
+
- `pages/2_play_game.py` - Call `setup_logging()` if not already initialized
|
| 274 |
+
|
| 275 |
+
**Prerequisites:** Task 7 (Phase 1, the configure_page extraction)
|
| 276 |
+
|
| 277 |
+
**Implementation Steps:**
|
| 278 |
+
- In `src/config.py`, remove the `setup_logging()` call at module level (line 93). Keep the function definition.
|
| 279 |
+
- In the `configure_page()` function (added in Phase 1), add a call to `setup_logging()` so logging is configured when the page is set up. This centralizes both page config and logging init.
|
| 280 |
+
- Alternatively, call `setup_logging()` in each entry point (`app.py`, page files) right after `configure_page()`.
|
| 281 |
+
|
| 282 |
+
**Verification Checklist:**
|
| 283 |
+
- [x] `setup_logging()` is NOT called at module level in `config.py`
|
| 284 |
+
- [x] `setup_logging()` IS called in each entry point
|
| 285 |
+
- [x] `pytest` passes
|
| 286 |
+
- [x] Logging still works when running the app
|
| 287 |
+
|
| 288 |
+
**Testing Instructions:** Run existing tests. The module-level call removal should not break tests since tests typically configure their own logging.
|
| 289 |
+
|
| 290 |
+
**Commit Message Template:**
|
| 291 |
+
```text
|
| 292 |
+
fix(config): move logging setup from module-level to explicit init
|
| 293 |
+
```
|
| 294 |
+
|
| 295 |
+
## Phase Verification
|
| 296 |
+
|
| 297 |
+
1. Run `pytest --cov=src --cov-report=term-missing` and confirm all tests pass.
|
| 298 |
+
2. Run `ruff check src/ tests/` with no errors.
|
| 299 |
+
3. Run `mypy src/` with no errors.
|
| 300 |
+
4. Verify: `python -c "from src.database.connection import load_data; from src.ml.model import get_winner_model"` succeeds without importing Streamlit (the imports should not trigger `import streamlit`).
|
| 301 |
+
5. No `except Exception` in `src/database/connection.py`.
|
| 302 |
+
6. No f-string logging in any `logger.*()` call.
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-3.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 3: [IMPLEMENTER] Testing Improvements
|
| 2 |
+
|
| 3 |
+
## Phase Goal
|
| 4 |
+
|
| 5 |
+
Improve test coverage and test quality. Add integration tests for CSV data validation, tests for session state, and tests for HTML utilities. Raise the coverage threshold from 50% to 70%. Address the eval test-value score of 7/10.
|
| 6 |
+
|
| 7 |
+
**Success criteria:** Coverage threshold raised to 70% and CI passes at that threshold. New tests cover session state, HTML utilities, and CSV column validation. At least one test loads the real model file.
|
| 8 |
+
|
| 9 |
+
**Estimated tokens:** ~20k
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Phase 2 complete (Streamlit decoupled from src/, error handling fixed)
|
| 14 |
+
- All existing tests passing
|
| 15 |
+
|
| 16 |
+
## Tasks
|
| 17 |
+
|
| 18 |
+
### Task 1: Add integration test for CSV column validation
|
| 19 |
+
|
| 20 |
+
**Goal:** Verify that the actual `snowflake_nba.csv` column order matches `PLAYER_COLUMNS` in config. Addresses eval test-value remediation target.
|
| 21 |
+
|
| 22 |
+
**Files to Modify:**
|
| 23 |
+
- `tests/test_database.py` - Add integration test
|
| 24 |
+
|
| 25 |
+
**Prerequisites:** Phase 2 Task 1 (load_data decoupled from Streamlit)
|
| 26 |
+
|
| 27 |
+
**Implementation Steps:**
|
| 28 |
+
- Add a test function `test_csv_columns_match_config()` that:
|
| 29 |
+
- Calls `load_data()` directly (no Streamlit mock needed after Phase 2).
|
| 30 |
+
- Asserts that the DataFrame columns match `PLAYER_COLUMNS` from `src/config.py`.
|
| 31 |
+
- Asserts the DataFrame is not empty.
|
| 32 |
+
- This test validates that the CSV data source and config are in sync, catching the kind of silent drift that `from_db_row` (now removed) was vulnerable to.
|
| 33 |
+
|
| 34 |
+
**Verification Checklist:**
|
| 35 |
+
- [x] Test loads real CSV and validates columns
|
| 36 |
+
- [x] Test passes
|
| 37 |
+
- [x] Test fails if a column is renamed in config (verify by temporarily changing a column name)
|
| 38 |
+
|
| 39 |
+
**Testing Instructions:** `pytest tests/test_database.py::test_csv_columns_match_config -v`
|
| 40 |
+
|
| 41 |
+
**Commit Message Template:**
|
| 42 |
+
```text
|
| 43 |
+
test(database): add integration test for CSV column validation
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
---
|
| 47 |
+
|
| 48 |
+
### Task 2: Add tests for session state management
|
| 49 |
+
|
| 50 |
+
**Goal:** Add tests for the remaining functions in `src/state/session.py`: `init_session_state()`, `get_away_stats()`, `get_home_team_df()`. Addresses health audit finding #21 (LOW).
|
| 51 |
+
|
| 52 |
+
**Files to Modify:**
|
| 53 |
+
- `tests/test_state.py` - Create new test file
|
| 54 |
+
|
| 55 |
+
**Prerequisites:** Phase 2 complete
|
| 56 |
+
|
| 57 |
+
**Implementation Steps:**
|
| 58 |
+
- Create `tests/test_state.py`.
|
| 59 |
+
- Mock `streamlit.session_state` as a plain dictionary for testing.
|
| 60 |
+
- Test `init_session_state()`:
|
| 61 |
+
- Call the function with a mock session state.
|
| 62 |
+
- Verify all expected keys are initialized.
|
| 63 |
+
- Call it twice and verify it does not overwrite existing values.
|
| 64 |
+
- Test `get_away_stats()`:
|
| 65 |
+
- Set up session state with known away team data.
|
| 66 |
+
- Verify the function returns the expected stats.
|
| 67 |
+
- Test `get_home_team_df()`:
|
| 68 |
+
- Set up session state with a known home team DataFrame.
|
| 69 |
+
- Verify the function returns it correctly.
|
| 70 |
+
- Mock any `streamlit` imports at the module level using `unittest.mock.patch`.
|
| 71 |
+
|
| 72 |
+
**Verification Checklist:**
|
| 73 |
+
- [x] `tests/test_state.py` exists with at least 5 test functions
|
| 74 |
+
- [x] All tests pass
|
| 75 |
+
- [x] Tests do not require a Streamlit runtime
|
| 76 |
+
|
| 77 |
+
**Testing Instructions:** `pytest tests/test_state.py -v`
|
| 78 |
+
|
| 79 |
+
**Commit Message Template:**
|
| 80 |
+
```text
|
| 81 |
+
test(state): add tests for session state management functions
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
---
|
| 85 |
+
|
| 86 |
+
### Task 3: Add tests for HTML utility functions
|
| 87 |
+
|
| 88 |
+
**Goal:** Test the XSS escaping utilities in `src/utils/html.py`. Addresses health audit finding #21 (LOW) and doc audit gap #4.
|
| 89 |
+
|
| 90 |
+
**Files to Modify:**
|
| 91 |
+
- `tests/test_utils.py` - Create new test file
|
| 92 |
+
|
| 93 |
+
**Prerequisites:** None
|
| 94 |
+
|
| 95 |
+
**Implementation Steps:**
|
| 96 |
+
- Create `tests/test_utils.py`.
|
| 97 |
+
- Test `escape_html()`:
|
| 98 |
+
- Verify it escapes `<`, `>`, `&`, `"`, `'` characters.
|
| 99 |
+
- Verify it passes through safe strings unchanged.
|
| 100 |
+
- Test `safe_heading()`:
|
| 101 |
+
- Verify it returns HTML with escaped content.
|
| 102 |
+
- Verify XSS payloads like `<script>alert(1)</script>` are escaped in output.
|
| 103 |
+
- Test `safe_paragraph()`:
|
| 104 |
+
- Similar to `safe_heading` tests.
|
| 105 |
+
- Do NOT test `safe_styled_text` since it was removed in Phase 1.
|
| 106 |
+
|
| 107 |
+
**Verification Checklist:**
|
| 108 |
+
- [x] `tests/test_utils.py` exists with tests for each exported function
|
| 109 |
+
- [x] XSS payloads are verified to be escaped
|
| 110 |
+
- [x] All tests pass
|
| 111 |
+
|
| 112 |
+
**Testing Instructions:** `pytest tests/test_utils.py -v`
|
| 113 |
+
|
| 114 |
+
**Commit Message Template:**
|
| 115 |
+
```text
|
| 116 |
+
test(utils): add tests for HTML escaping utilities
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
---
|
| 120 |
+
|
| 121 |
+
### Task 4: Add a real model loading test
|
| 122 |
+
|
| 123 |
+
**Goal:** Add at least one test in `test_ml.py` that loads the actual `winner.keras` model file to verify the model contract. Addresses eval test-value concern about over-mocking.
|
| 124 |
+
|
| 125 |
+
**Files to Modify:**
|
| 126 |
+
- `tests/test_ml.py` - Add integration test
|
| 127 |
+
|
| 128 |
+
**Prerequisites:** Phase 2 Task 2 (model decoupled from Streamlit)
|
| 129 |
+
|
| 130 |
+
**Implementation Steps:**
|
| 131 |
+
- Add a test function `test_load_real_model()` that:
|
| 132 |
+
- Calls `get_winner_model()` (or the underlying load function) with the real `winner.keras` file.
|
| 133 |
+
- Verifies the model is loaded successfully (not None).
|
| 134 |
+
- Verifies the model has the expected input shape (100 features).
|
| 135 |
+
- Verifies the model has the expected output shape (binary classification).
|
| 136 |
+
- Mark this test with `@pytest.mark.slow` or `@pytest.mark.integration` if desired, but it should run in CI since the model file is in the repo.
|
| 137 |
+
- Note: This test will require TensorFlow to be installed. It should work in CI since TensorFlow is a project dependency.
|
| 138 |
+
|
| 139 |
+
**Verification Checklist:**
|
| 140 |
+
- [x] Test loads real `winner.keras` file
|
| 141 |
+
- [x] Test verifies input/output shape
|
| 142 |
+
- [x] Test passes
|
| 143 |
+
|
| 144 |
+
**Testing Instructions:** `pytest tests/test_ml.py::TestLoadRealModel::test_load_real_model -v`
|
| 145 |
+
|
| 146 |
+
**Commit Message Template:**
|
| 147 |
+
```text
|
| 148 |
+
test(ml): add integration test with real model file
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
---
|
| 152 |
+
|
| 153 |
+
### Task 5: Raise coverage threshold to 70%
|
| 154 |
+
|
| 155 |
+
**Goal:** Increase the coverage `fail_under` threshold from 50% to 70%. Addresses eval git-hygiene remediation target.
|
| 156 |
+
|
| 157 |
+
**Files to Modify:**
|
| 158 |
+
- `pyproject.toml` - Change `fail_under = 50` to `fail_under = 70`
|
| 159 |
+
|
| 160 |
+
**Prerequisites:** Tasks 1-4 (new tests added to meet the threshold)
|
| 161 |
+
|
| 162 |
+
**Implementation Steps:**
|
| 163 |
+
- Run `pytest --cov=src --cov-report=term-missing` to check current coverage.
|
| 164 |
+
- If coverage is at or above 70%, update `pyproject.toml` line 113: change `fail_under = 50` to `fail_under = 70`.
|
| 165 |
+
- If coverage is below 70%, identify the uncovered modules and add targeted tests to reach the threshold before updating the config.
|
| 166 |
+
|
| 167 |
+
**Verification Checklist:**
|
| 168 |
+
- [x] `pyproject.toml` has `fail_under = 70`
|
| 169 |
+
- [x] `pytest --cov=src --cov-report=term-missing --cov-fail-under=70` passes
|
| 170 |
+
|
| 171 |
+
**Testing Instructions:** `pytest --cov=src --cov-report=term-missing --cov-fail-under=70`
|
| 172 |
+
|
| 173 |
+
**Commit Message Template:**
|
| 174 |
+
```text
|
| 175 |
+
test(coverage): raise coverage threshold from 50% to 70%
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
## Phase Verification
|
| 179 |
+
|
| 180 |
+
1. Run `pytest --cov=src --cov-report=term-missing --cov-fail-under=70` and confirm pass.
|
| 181 |
+
2. Verify new test files exist: `tests/test_state.py`, `tests/test_utils.py`.
|
| 182 |
+
3. Run `ruff check src/ tests/` with no errors.
|
| 183 |
+
4. Run `mypy src/` with no errors.
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-4.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 4: [FORTIFIER] Guardrails
|
| 2 |
+
|
| 3 |
+
## Phase Goal
|
| 4 |
+
|
| 5 |
+
Add CI hardening, pre-commit hooks, dependency consolidation, and type rigor improvements. These are additive guardrails that prevent regression.
|
| 6 |
+
|
| 7 |
+
**Success criteria:** Pre-commit hooks run ruff and mypy. Dependencies consolidated to `pyproject.toml` only. CI uses `uv`. Type annotations tightened (no unnecessary `Any`). Coverage enforcement in CI.
|
| 8 |
+
|
| 9 |
+
**Estimated tokens:** ~20k
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Phase 3 complete (tests passing at 70% coverage)
|
| 14 |
+
- All lint and type checks passing
|
| 15 |
+
|
| 16 |
+
## Tasks
|
| 17 |
+
|
| 18 |
+
### Task 1: Consolidate dependencies to pyproject.toml
|
| 19 |
+
|
| 20 |
+
**Goal:** Remove `requirements.txt` and `requirements-dev.txt` as duplicate dependency sources. Update CI to install from `pyproject.toml`. Addresses health audit finding #14 (MEDIUM) and ADR-5.
|
| 21 |
+
|
| 22 |
+
**Files to Modify:**
|
| 23 |
+
- `requirements.txt` - Delete this file
|
| 24 |
+
- `requirements-dev.txt` - Delete this file (after verifying its contents match `[project.optional-dependencies] dev`)
|
| 25 |
+
- `.github/workflows/ci.yml` - Update install step to use `pyproject.toml`
|
| 26 |
+
|
| 27 |
+
**Prerequisites:** None
|
| 28 |
+
|
| 29 |
+
**Implementation Steps:**
|
| 30 |
+
- Read `requirements-dev.txt` to verify it matches or is a subset of `pyproject.toml` `[project.optional-dependencies] dev`.
|
| 31 |
+
- Delete `requirements.txt`.
|
| 32 |
+
- Delete `requirements-dev.txt` (if it matches pyproject.toml dev deps; if it has extra deps, add them to pyproject.toml first).
|
| 33 |
+
- Update `.github/workflows/ci.yml`:
|
| 34 |
+
- Replace `pip install -r requirements-dev.txt` with `pip install -e ".[dev]"`.
|
| 35 |
+
- Optionally switch to `uv` in CI for faster installs:
|
| 36 |
+
```yaml
|
| 37 |
+
- name: Install uv
|
| 38 |
+
run: pip install uv
|
| 39 |
+
- name: Install dependencies
|
| 40 |
+
run: uv pip install -e ".[dev]" --system
|
| 41 |
+
```
|
| 42 |
+
- Update CI to add `--cov-fail-under=70` to the pytest command if not already there.
|
| 43 |
+
|
| 44 |
+
**Verification Checklist:**
|
| 45 |
+
- [x] `requirements.txt` deleted
|
| 46 |
+
- [x] `requirements-dev.txt` deleted
|
| 47 |
+
- [x] CI workflow installs from `pyproject.toml`
|
| 48 |
+
- [x] CI workflow still runs tests, ruff, and mypy successfully
|
| 49 |
+
|
| 50 |
+
**Testing Instructions:** Push to a branch and verify CI passes, or run the install and test commands locally.
|
| 51 |
+
|
| 52 |
+
**Commit Message Template:**
|
| 53 |
+
```text
|
| 54 |
+
ci(deps): consolidate to pyproject.toml, remove requirements files
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
---
|
| 58 |
+
|
| 59 |
+
### Task 2: Add pre-commit hooks
|
| 60 |
+
|
| 61 |
+
**Goal:** Add `.pre-commit-config.yaml` with ruff and mypy hooks to catch issues before commit. Addresses eval git-hygiene remediation target.
|
| 62 |
+
|
| 63 |
+
**Files to Modify:**
|
| 64 |
+
- `.pre-commit-config.yaml` - Create new file
|
| 65 |
+
|
| 66 |
+
**Prerequisites:** Task 1
|
| 67 |
+
|
| 68 |
+
**Implementation Steps:**
|
| 69 |
+
- Create `.pre-commit-config.yaml` at the project root with:
|
| 70 |
+
```yaml
|
| 71 |
+
repos:
|
| 72 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 73 |
+
rev: v0.8.0 # Use latest stable version
|
| 74 |
+
hooks:
|
| 75 |
+
- id: ruff
|
| 76 |
+
args: [--fix]
|
| 77 |
+
- id: ruff-format
|
| 78 |
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
| 79 |
+
rev: v1.13.0 # Use latest stable version
|
| 80 |
+
hooks:
|
| 81 |
+
- id: mypy
|
| 82 |
+
additional_dependencies: [pandas-stubs]
|
| 83 |
+
args: [--config-file=pyproject.toml]
|
| 84 |
+
pass_filenames: false
|
| 85 |
+
entry: mypy src/
|
| 86 |
+
```
|
| 87 |
+
- Add `pre-commit` to the dev dependencies in `pyproject.toml`:
|
| 88 |
+
```toml
|
| 89 |
+
"pre-commit>=3.0.0",
|
| 90 |
+
```
|
| 91 |
+
- Verify the hooks work: `uvx pre-commit run --all-files`.
|
| 92 |
+
- Note: Use the latest stable versions of ruff and mypy that are compatible. Check PyPI for current versions.
|
| 93 |
+
|
| 94 |
+
**Verification Checklist:**
|
| 95 |
+
- [x] `.pre-commit-config.yaml` exists at project root
|
| 96 |
+
- [x] `pre-commit` is in dev dependencies
|
| 97 |
+
- [x] `uvx pre-commit run --all-files` passes
|
| 98 |
+
|
| 99 |
+
**Testing Instructions:** Run `uvx pre-commit run --all-files` and verify all hooks pass.
|
| 100 |
+
|
| 101 |
+
**Commit Message Template:**
|
| 102 |
+
```text
|
| 103 |
+
ci(hooks): add pre-commit config with ruff and mypy hooks
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
---
|
| 107 |
+
|
| 108 |
+
### Task 3: Tighten type annotations
|
| 109 |
+
|
| 110 |
+
**Goal:** Replace imprecise type annotations (`Any`, `tuple[Any, ...]`, `list[list]`) with specific types. Addresses eval type-rigor score of 7/10.
|
| 111 |
+
|
| 112 |
+
**Files to Modify:**
|
| 113 |
+
- `src/database/queries.py` - Fix return types
|
| 114 |
+
- `scripts/compile_model.py` - Fix type hints
|
| 115 |
+
|
| 116 |
+
**Prerequisites:** Phase 1 (dead code removed, so fewer files to fix)
|
| 117 |
+
|
| 118 |
+
**Implementation Steps:**
|
| 119 |
+
- In `src/database/queries.py`:
|
| 120 |
+
- Find `tuple[Any, ...]` return types (around line 36) and replace with specific types. If the function returns player data columns, use a `TypedDict` or a specific tuple type like `tuple[str, str, float, ...]` matching the actual columns returned.
|
| 121 |
+
- Find `list[tuple[str]]` return types (around line 14) and simplify to `list[str]` if the function returns a flat list of strings.
|
| 122 |
+
- Remove `Any` import if no longer needed.
|
| 123 |
+
- In `scripts/compile_model.py`:
|
| 124 |
+
- Change `list[list]` to `list[list[float]]` or more specific parameterized types (around line 85).
|
| 125 |
+
- Review `src/models/player.py` for any remaining `Any` imports that are no longer needed after `PlayerStats` removal.
|
| 126 |
+
|
| 127 |
+
**Verification Checklist:**
|
| 128 |
+
- [x] No `tuple[Any, ...]` in `queries.py`
|
| 129 |
+
- [x] No bare `list[list]` in `compile_model.py`
|
| 130 |
+
- [x] `mypy src/` passes
|
| 131 |
+
- [x] `pytest` passes
|
| 132 |
+
|
| 133 |
+
**Testing Instructions:** Run `mypy src/` and verify no new errors. Run existing tests.
|
| 134 |
+
|
| 135 |
+
**Commit Message Template:**
|
| 136 |
+
```text
|
| 137 |
+
refactor(types): tighten type annotations, remove unnecessary Any usage
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
---
|
| 141 |
+
|
| 142 |
+
### Task 4: Add coverage enforcement to CI
|
| 143 |
+
|
| 144 |
+
**Goal:** Ensure CI fails if coverage drops below the threshold. Addresses eval reproducibility concerns.
|
| 145 |
+
|
| 146 |
+
**Files to Modify:**
|
| 147 |
+
- `.github/workflows/ci.yml` - Add `--cov-fail-under=70` to pytest command
|
| 148 |
+
|
| 149 |
+
**Prerequisites:** Phase 3 Task 5 (coverage threshold set)
|
| 150 |
+
|
| 151 |
+
**Implementation Steps:**
|
| 152 |
+
- In `.github/workflows/ci.yml`, update the pytest command:
|
| 153 |
+
```yaml
|
| 154 |
+
- name: Run tests
|
| 155 |
+
run: pytest --cov=src --cov-report=term-missing --cov-fail-under=70
|
| 156 |
+
```
|
| 157 |
+
- This ensures CI fails if coverage drops, not just locally.
|
| 158 |
+
|
| 159 |
+
**Verification Checklist:**
|
| 160 |
+
- [x] CI pytest command includes `--cov-fail-under=70`
|
| 161 |
+
|
| 162 |
+
**Testing Instructions:** Verify the CI workflow file has the correct command.
|
| 163 |
+
|
| 164 |
+
**Commit Message Template:**
|
| 165 |
+
```text
|
| 166 |
+
ci(coverage): enforce 70% coverage threshold in CI
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
---
|
| 170 |
+
|
| 171 |
+
### Task 5: Clean up ruff ignores
|
| 172 |
+
|
| 173 |
+
**Goal:** Remove ruff ignore rules that are no longer relevant after Phase 1 cleanup. Addresses tech debt in linter config.
|
| 174 |
+
|
| 175 |
+
**Files to Modify:**
|
| 176 |
+
- `pyproject.toml` - Update ruff ignore list
|
| 177 |
+
|
| 178 |
+
**Prerequisites:** Phase 1 (SQL injection code removed), Phase 2 (error handling fixed)
|
| 179 |
+
|
| 180 |
+
**Implementation Steps:**
|
| 181 |
+
- Review the ruff `ignore` list in `pyproject.toml`:
|
| 182 |
+
- `S608` (SQL injection false positive): Remove this. SQL injection code was deleted in Phase 1.
|
| 183 |
+
- `S110` (try-except-pass): Review if still needed after the `finally: pass` removal. If no `except: pass` patterns remain, remove it.
|
| 184 |
+
- Keep the other ignores that are still relevant (`S101`, `PLR0913`, `SIM105`, `PLR2004`, `S311`, `E501`).
|
| 185 |
+
- Run `ruff check src/ tests/` to verify no new violations surface.
|
| 186 |
+
|
| 187 |
+
**Verification Checklist:**
|
| 188 |
+
- [x] `S608` removed from ruff ignores (already removed in Phase 1)
|
| 189 |
+
- [x] `S110` removed if no longer needed
|
| 190 |
+
- [x] `ruff check src/ tests/` passes with the updated config
|
| 191 |
+
|
| 192 |
+
**Testing Instructions:** `ruff check src/ tests/`
|
| 193 |
+
|
| 194 |
+
**Commit Message Template:**
|
| 195 |
+
```text
|
| 196 |
+
chore(config): remove obsolete ruff ignore rules
|
| 197 |
+
```
|
| 198 |
+
|
| 199 |
+
## Phase Verification
|
| 200 |
+
|
| 201 |
+
1. Run `pytest --cov=src --cov-report=term-missing --cov-fail-under=70` and confirm pass.
|
| 202 |
+
2. Run `ruff check src/ tests/` with no errors.
|
| 203 |
+
3. Run `mypy src/` with no errors.
|
| 204 |
+
4. Run `uvx pre-commit run --all-files` and confirm all hooks pass.
|
| 205 |
+
5. Verify `requirements.txt` and `requirements-dev.txt` no longer exist.
|
| 206 |
+
6. Verify `.pre-commit-config.yaml` exists.
|
docs/plans/2026-03-25-audit-streamlit-nba/Phase-5.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 5: [DOC-ENGINEER] Documentation Fixes
|
| 2 |
+
|
| 3 |
+
## Phase Goal
|
| 4 |
+
|
| 5 |
+
Fix all documentation drift, fill documentation gaps, and update the README to accurately reflect the current codebase state after all prior remediation phases.
|
| 6 |
+
|
| 7 |
+
**Success criteria:** README accurately describes the project structure, features, installation, and data sources. No documentation drift remains. Training script prerequisites documented.
|
| 8 |
+
|
| 9 |
+
**Estimated tokens:** ~15k
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Phases 1-4 complete (code changes finalized)
|
| 14 |
+
- All tests, lint, and type checks passing
|
| 15 |
+
|
| 16 |
+
## Tasks
|
| 17 |
+
|
| 18 |
+
### Task 1: Fix README feature descriptions and terminology
|
| 19 |
+
|
| 20 |
+
**Goal:** Correct the "Multi-page Interface" description and replace "database" language with "CSV data source." Addresses doc audit drift findings #2 and #4.
|
| 21 |
+
|
| 22 |
+
**Files to Modify:**
|
| 23 |
+
- `README.md` - Update feature descriptions
|
| 24 |
+
|
| 25 |
+
**Prerequisites:** None
|
| 26 |
+
|
| 27 |
+
**Implementation Steps:**
|
| 28 |
+
- Find the "Multi-page Interface" description (around line 19). Update to accurately describe the two pages plus landing: e.g., "Two-page Streamlit app with a team builder and game prediction simulator, plus a landing page."
|
| 29 |
+
- Find "comprehensive database of historical NBA stats" (around line 21-22). Replace "database" with "dataset" or "CSV data source." E.g., "Search for players from a dataset of historical NBA stats."
|
| 30 |
+
- Search the entire README for other uses of "database" that imply a live database connection. Update to reflect that data comes from a local CSV file.
|
| 31 |
+
|
| 32 |
+
**Verification Checklist:**
|
| 33 |
+
- [x] README does not describe three distinct pages
|
| 34 |
+
- [x] README does not use "database" to describe the CSV data source
|
| 35 |
+
- [x] Feature descriptions match actual app behavior
|
| 36 |
+
|
| 37 |
+
**Testing Instructions:** Read the README and verify accuracy against the app.
|
| 38 |
+
|
| 39 |
+
**Commit Message Template:**
|
| 40 |
+
```text
|
| 41 |
+
docs(readme): fix feature descriptions and data source terminology
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
---
|
| 45 |
+
|
| 46 |
+
### Task 2: Update README project structure tree
|
| 47 |
+
|
| 48 |
+
**Goal:** Make the project structure tree match the actual file layout after all remediation changes. Addresses doc audit drift finding #3.
|
| 49 |
+
|
| 50 |
+
**Files to Modify:**
|
| 51 |
+
- `README.md` - Update project structure section (around lines 37-50)
|
| 52 |
+
|
| 53 |
+
**Prerequisites:** Phases 1-4 complete
|
| 54 |
+
|
| 55 |
+
**Implementation Steps:**
|
| 56 |
+
- Update the project structure tree to include:
|
| 57 |
+
- `src/config.py` and `src/__init__.py`
|
| 58 |
+
- `snowflake_nba.csv` (the runtime data source)
|
| 59 |
+
- `.github/workflows/` directory
|
| 60 |
+
- `.pre-commit-config.yaml` (added in Phase 4)
|
| 61 |
+
- `.streamlit/config.toml` (if it exists)
|
| 62 |
+
- Remove from the tree:
|
| 63 |
+
- `requirements.txt` (deleted in Phase 4)
|
| 64 |
+
- Any files that no longer exist after cleanup
|
| 65 |
+
- Do NOT include: `winner_model/` (gitignored), `debug_streamlit.py` (gitignored), `__pycache__/`, `.coverage`
|
| 66 |
+
- Keep the tree concise. Show top-level files and one level of `src/` subdirectories.
|
| 67 |
+
|
| 68 |
+
**Verification Checklist:**
|
| 69 |
+
- [x] Tree includes `src/config.py`
|
| 70 |
+
- [x] Tree includes `snowflake_nba.csv`
|
| 71 |
+
- [x] Tree does not list deleted files
|
| 72 |
+
- [x] Tree matches actual `ls` output
|
| 73 |
+
|
| 74 |
+
**Testing Instructions:** Run `ls -la` and compare with the documented tree.
|
| 75 |
+
|
| 76 |
+
**Commit Message Template:**
|
| 77 |
+
```text
|
| 78 |
+
docs(readme): update project structure tree to match codebase
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
---
|
| 82 |
+
|
| 83 |
+
### Task 3: Fix installation instructions
|
| 84 |
+
|
| 85 |
+
**Goal:** Update installation instructions to use `pyproject.toml` and `uv`. Remove references to deleted `requirements.txt`. Addresses doc audit stale code example #1.
|
| 86 |
+
|
| 87 |
+
**Files to Modify:**
|
| 88 |
+
- `README.md` - Update installation/quickstart section
|
| 89 |
+
|
| 90 |
+
**Prerequisites:** Phase 4 Task 1 (requirements files deleted)
|
| 91 |
+
|
| 92 |
+
**Implementation Steps:**
|
| 93 |
+
- Find the installation section (around lines 56-66).
|
| 94 |
+
- Replace `pip install -r requirements.txt` with `uv pip install -e ".[dev]"` for development setup, or `uv pip install -e .` for runtime only.
|
| 95 |
+
- Update the "Quick Start with uv" section to include dev dependency installation.
|
| 96 |
+
- Ensure the linting command matches CI: `ruff check src/ tests/` (not `ruff check .`). Addresses doc audit stale code example #2.
|
| 97 |
+
|
| 98 |
+
**Verification Checklist:**
|
| 99 |
+
- [x] No reference to `requirements.txt` in README
|
| 100 |
+
- [x] Installation uses `pyproject.toml` via `uv pip install`
|
| 101 |
+
- [x] Lint command matches CI workflow
|
| 102 |
+
|
| 103 |
+
**Testing Instructions:** Follow the installation instructions on a clean checkout and verify they work.
|
| 104 |
+
|
| 105 |
+
**Commit Message Template:**
|
| 106 |
+
```text
|
| 107 |
+
docs(readme): update installation to use pyproject.toml and uv
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
---
|
| 111 |
+
|
| 112 |
+
### Task 4: Document training script prerequisites
|
| 113 |
+
|
| 114 |
+
**Goal:** Document that `player_stats.txt` and `schedule.txt` are required by the training script. Addresses doc audit config drift #2.
|
| 115 |
+
|
| 116 |
+
**Files to Modify:**
|
| 117 |
+
- `README.md` - Update training script section (around line 96)
|
| 118 |
+
|
| 119 |
+
**Prerequisites:** None
|
| 120 |
+
|
| 121 |
+
**Implementation Steps:**
|
| 122 |
+
- Find the training script documentation section.
|
| 123 |
+
- Add a note that `player_stats.txt` and `schedule.txt` must exist in the project root for the training script to work.
|
| 124 |
+
- Mention that `winner.keras` is the output of the training script and is required at runtime.
|
| 125 |
+
|
| 126 |
+
**Verification Checklist:**
|
| 127 |
+
- [x] Training script prerequisites listed
|
| 128 |
+
- [x] `player_stats.txt` and `schedule.txt` mentioned as inputs
|
| 129 |
+
- [x] `winner.keras` mentioned as output
|
| 130 |
+
|
| 131 |
+
**Testing Instructions:** Read the section and verify it matches `scripts/compile_model.py` input file paths.
|
| 132 |
+
|
| 133 |
+
**Commit Message Template:**
|
| 134 |
+
```text
|
| 135 |
+
docs(readme): document training script prerequisites
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
+
---
|
| 139 |
+
|
| 140 |
+
### Task 5: Add data file and model path documentation
|
| 141 |
+
|
| 142 |
+
**Goal:** Document the hardcoded paths for data files and model files so developers know what to change if the project structure changes. Addresses doc audit config drift #1 and health audit finding #20 (LOW).
|
| 143 |
+
|
| 144 |
+
**Files to Modify:**
|
| 145 |
+
- `README.md` - Add a "Data Files" or "Configuration" section
|
| 146 |
+
|
| 147 |
+
**Prerequisites:** None
|
| 148 |
+
|
| 149 |
+
**Implementation Steps:**
|
| 150 |
+
- Add a brief section to the README (or expand the existing architecture section) that describes:
|
| 151 |
+
- `snowflake_nba.csv`: loaded by `src/database/connection.py`, path resolved relative to the module location.
|
| 152 |
+
- `winner.keras`: loaded by `src/ml/model.py`, path resolved relative to the module location.
|
| 153 |
+
- `src/config.py`: central configuration for column names, team size, difficulty presets, and logging.
|
| 154 |
+
- Keep it concise. Two or three sentences per file.
|
| 155 |
+
|
| 156 |
+
**Verification Checklist:**
|
| 157 |
+
- [x] Data file paths documented
|
| 158 |
+
- [x] Model file path documented
|
| 159 |
+
- [x] Config module mentioned
|
| 160 |
+
|
| 161 |
+
**Testing Instructions:** Read the section for accuracy.
|
| 162 |
+
|
| 163 |
+
**Commit Message Template:**
|
| 164 |
+
```text
|
| 165 |
+
docs(readme): document data file paths and configuration
|
| 166 |
+
```
|
| 167 |
+
|
| 168 |
+
## Phase Verification
|
| 169 |
+
|
| 170 |
+
1. Read the entire README and verify every claim matches the current codebase.
|
| 171 |
+
2. Verify the project structure tree matches `ls` output.
|
| 172 |
+
3. Verify installation instructions work from scratch.
|
| 173 |
+
4. Run `ruff check src/ tests/` (the README-documented command) and confirm it works.
|
| 174 |
+
5. No documentation drift findings remain from the doc audit.
|
docs/plans/2026-03-25-audit-streamlit-nba/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Audit Remediation Plan: streamlit-nba
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
This plan addresses findings from three audits of the streamlit-nba repository: a codebase health audit (3 critical, 6 high, 8 medium, 5 low findings), a 12-pillar evaluation (overall grade B, git hygiene at 5/10), and a documentation audit (4 drift, 5 gaps). The repository is a Streamlit-based NBA team builder and game prediction app using TensorFlow/Keras with a local CSV data source.
|
| 6 |
+
|
| 7 |
+
The remediation is sequenced as: cleanup first (remove dead code, unused dependencies, artifacts), then structural fixes (architecture, error handling, validation, testing), then guardrails (CI hardening, pre-commit hooks, type safety), and finally documentation corrections.
|
| 8 |
+
|
| 9 |
+
All work targets the existing codebase. No new features are introduced. The goal is to raise pillar scores toward 9/10 across the board while reducing the tech debt ledger to zero critical and zero high findings.
|
| 10 |
+
|
| 11 |
+
## Prerequisites
|
| 12 |
+
|
| 13 |
+
- Python 3.11+ (3.13 in dev environment)
|
| 14 |
+
- `uv` for package management
|
| 15 |
+
- Git
|
| 16 |
+
- Familiarity with: Streamlit, pandas, TensorFlow/Keras, Pydantic, pytest, ruff, mypy
|
| 17 |
+
|
| 18 |
+
## Phase Summary
|
| 19 |
+
|
| 20 |
+
| Phase | Tag | Goal | Token Estimate |
|
| 21 |
+
|-------|-----|------|----------------|
|
| 22 |
+
| 0 | -- | Foundation: architecture decisions, conventions, testing strategy | ~5k |
|
| 23 |
+
| 1 | [HYGIENIST] | Dead code removal, artifact cleanup, .gitignore, unused exports | ~20k |
|
| 24 |
+
| 2 | [IMPLEMENTER] | Architecture fixes: decouple Streamlit, fix error handling, validation, input guards | ~30k |
|
| 25 |
+
| 3 | [IMPLEMENTER] | Testing improvements: new tests, coverage threshold, integration tests | ~20k |
|
| 26 |
+
| 4 | [FORTIFIER] | CI hardening, pre-commit hooks, dependency consolidation, type rigor | ~20k |
|
| 27 |
+
| 5 | [DOC-ENGINEER] | README corrections, project structure docs, config documentation | ~15k |
|
| 28 |
+
|
| 29 |
+
## Navigation
|
| 30 |
+
|
| 31 |
+
- [Phase-0.md](Phase-0.md) - Foundation (all phases)
|
| 32 |
+
- [Phase-1.md](Phase-1.md) - [HYGIENIST] Cleanup
|
| 33 |
+
- [Phase-2.md](Phase-2.md) - [IMPLEMENTER] Architecture and code fixes
|
| 34 |
+
- [Phase-3.md](Phase-3.md) - [IMPLEMENTER] Testing improvements
|
| 35 |
+
- [Phase-4.md](Phase-4.md) - [FORTIFIER] Guardrails
|
| 36 |
+
- [Phase-5.md](Phase-5.md) - [DOC-ENGINEER] Documentation
|
| 37 |
+
- [feedback.md](feedback.md) - Review feedback tracking
|
docs/plans/2026-03-25-audit-streamlit-nba/doc-audit.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
type: doc-health
|
| 3 |
+
docs_scanned: 2
|
| 4 |
+
code_modules_scanned: 8
|
| 5 |
+
findings:
|
| 6 |
+
drift: 4
|
| 7 |
+
gaps: 5
|
| 8 |
+
stale: 0
|
| 9 |
+
broken_links: 0
|
| 10 |
+
drift_prevention: markdownlint + lychee
|
| 11 |
+
language_stack: python + js/ts
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
> **Snapshot context:** This document captures pre-remediation findings from the 2026-03-25 audit. Items addressed during the remediation PR are annotated inline.
|
| 15 |
+
|
| 16 |
+
## DOCUMENTATION AUDIT
|
| 17 |
+
|
| 18 |
+
### SUMMARY
|
| 19 |
+
- Docs scanned: 2 files (README.md, CHANGELOG.md)
|
| 20 |
+
- Code modules scanned: 8 modules (app.py, 2 pages, 6 src packages, 1 script)
|
| 21 |
+
- Total findings: 4 drift, 5 gaps, 0 stale, 0 broken links, 1 config drift, 2 structure issues
|
| 22 |
+
|
| 23 |
+
---
|
| 24 |
+
|
| 25 |
+
### DRIFT (doc exists, doesn't match code)
|
| 26 |
+
|
| 27 |
+
1. **`README.md:3`** - Python version badge
|
| 28 |
+
- Doc says: `python-3.11+-blue.svg` (badge shows "3.11+")
|
| 29 |
+
- `pyproject.toml:6` says: `requires-python = ">=3.11"` (matches badge)
|
| 30 |
+
- Runtime environment uses Python 3.13 (`.venv/lib/python3.13/`)
|
| 31 |
+
- Badge is technically correct but worth noting the actual dev environment divergence.
|
| 32 |
+
|
| 33 |
+
2. **`README.md:19`** - "Multi-page Interface" feature description
|
| 34 |
+
- Doc says: "Organized navigation between the home page, team builder, and game simulator."
|
| 35 |
+
- Code has exactly two pages: `pages/1_home_team.py` (team builder) and `pages/2_play_game.py` (game/prediction). The main `app.py` is a simple landing page, not a "home page" in the navigational sense described. There is no distinct "game simulator" page separate from the predictor. The README implies three distinct pages; there are really two pages plus a landing.
|
| 36 |
+
|
| 37 |
+
3. **`README.md:37-50`** - Project structure tree
|
| 38 |
+
- Doc shows `src/` with subdirectories only: `database/`, `ml/`, `models/`, `state/`, `utils/`, `validation/`
|
| 39 |
+
- Code also has `src/config.py` and `src/__init__.py` at the `src/` level, which are not shown in the tree.
|
| 40 |
+
- Tree does not mention `snowflake_nba.csv` (the actual data source used at runtime).
|
| 41 |
+
- Tree does not mention `player_stats.txt` or `schedule.txt` (training data files).
|
| 42 |
+
- Tree does not mention `winner_model/` directory (alternative SavedModel format alongside `winner.keras`).
|
| 43 |
+
- Tree does not mention `.streamlit/config.toml`, `.devcontainer/devcontainer.json`, or `.github/` workflows (GitHub Actions CI).
|
| 44 |
+
|
| 45 |
+
4. **`README.md:21-22`** - "comprehensive database of historical NBA stats"
|
| 46 |
+
- Doc says: "Search for players from a comprehensive database of historical NBA stats."
|
| 47 |
+
- Code uses a single local CSV file (`snowflake_nba.csv`) loaded via pandas. The `connection.py` module is named `DatabaseConnectionError` and uses `get_connection()` as a context manager, but no actual database exists. The CHANGELOG v1.1.0 documents the transition from "remote database to local CSV-based data source" but the README still uses the word "database."
|
| 48 |
+
|
| 49 |
+
---
|
| 50 |
+
|
| 51 |
+
### GAPS (code exists, no doc)
|
| 52 |
+
|
| 53 |
+
1. **`src/config.py`** - Central configuration module with `PLAYER_COLUMNS`, `STAT_COLUMNS`, `TEAM_SIZE`, `MAX_QUERY_ATTEMPTS`, `DIFFICULTY_PRESETS`, score ranges, and `setup_logging()`. Not mentioned anywhere in documentation. *(Partially addressed: README now documents data file paths and config module.)*
|
| 54 |
+
|
| 55 |
+
2. **`src/models/player.py`** - ~~Pydantic models `PlayerStats` and `DifficultySettings` with validation logic.~~ *(Remediated: `PlayerStats` and `from_db_row` removed. Only `DifficultySettings` remains, which is an internal model used by session state.)*
|
| 56 |
+
|
| 57 |
+
3. **`src/state/session.py`** - ~~Session state management including `GameState` dataclass, `init_session_state()`, `get_away_stats()`, `get_home_team_df()`, `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, `remove_player_from_team()`.~~ *(Remediated: `GameState`, `get_home_team_names`, `set_difficulty`, `add_player_to_team`, and `remove_player_from_team` removed. Remaining functions: `init_session_state()`, `get_away_stats()`, `get_home_team_df()`.)*
|
| 58 |
+
|
| 59 |
+
4. **`src/utils/html.py`** - ~~XSS protection utilities (`escape_html`, `safe_heading`, `safe_paragraph`, `safe_styled_text`).~~ *(Remediated: `safe_styled_text` removed. Remaining functions: `escape_html`, `safe_heading`, `safe_paragraph`.)*
|
| 60 |
+
|
| 61 |
+
5. **`src/validation/inputs.py`** - ~~SQL injection protection with `PlayerSearchInput` model, `SQL_INJECTION_PATTERNS`, `validate_search_term()`, `is_valid_search_term()`.~~ *(Remediated: `SQL_INJECTION_PATTERNS` regex removed. Validation now uses a character allowlist only. `PlayerSearchInput`, `validate_search_term()`, and `is_valid_search_term()` remain.)*
|
| 62 |
+
|
| 63 |
+
---
|
| 64 |
+
|
| 65 |
+
### STALE (doc exists, code doesn't)
|
| 66 |
+
|
| 67 |
+
None found. All documented features map to existing code.
|
| 68 |
+
|
| 69 |
+
---
|
| 70 |
+
|
| 71 |
+
### BROKEN LINKS
|
| 72 |
+
|
| 73 |
+
None found. The README contains one external link (`https://hatman-nba-fantasy-game.hf.space`) and external badge URLs. No internal relative links are used.
|
| 74 |
+
|
| 75 |
+
---
|
| 76 |
+
|
| 77 |
+
### STALE CODE EXAMPLES
|
| 78 |
+
|
| 79 |
+
1. **`README.md:64-66`** - Standard installation instructions
|
| 80 |
+
- Doc says: `pip install -r requirements.txt`
|
| 81 |
+
- The project has `pyproject.toml` with proper dependency declarations. The `requirements.txt` exists and works, but the README does not mention `pyproject.toml` or `uv pip install -e ".[dev]"` for dev setup. The "Quick Start with uv" section (lines 56-59) only shows `uv run streamlit run app.py` without explaining how to install dev dependencies with uv.
|
| 82 |
+
|
| 83 |
+
2. **`README.md:84-85`** - Linting command
|
| 84 |
+
- Doc says: `ruff check .`
|
| 85 |
+
- CI workflow (`ci.yml:31`) runs: `ruff check src/ tests/`
|
| 86 |
+
- Minor inconsistency in scope (`.` vs `src/ tests/`), though both work.
|
| 87 |
+
|
| 88 |
+
---
|
| 89 |
+
|
| 90 |
+
### CONFIG DRIFT
|
| 91 |
+
|
| 92 |
+
1. **No `.env.example` or environment variable documentation exists.** The codebase reads no environment variables (confirmed via grep), so this is acceptable. However, the `snowflake_nba.csv` data file path is hardcoded in `src/database/connection.py:14` relative to the module location, and the `winner.keras` model path is hardcoded in `src/ml/model.py:13`. Neither path is documented or configurable.
|
| 93 |
+
|
| 94 |
+
2. **`README.md:96`** - Training script documentation
|
| 95 |
+
- Doc says the script "performs an automated search for the best architecture and hyperparameters (optimizers, initializers, etc.) before saving the final `winner.keras` model."
|
| 96 |
+
- The script (`scripts/compile_model.py:30-31`) requires `player_stats.txt` and `schedule.txt` as input data files. These files exist in the repo root but are not mentioned in the README or documented anywhere. A user following the README training instructions would not know these files are prerequisites.
|
| 97 |
+
|
| 98 |
+
---
|
| 99 |
+
|
| 100 |
+
### STRUCTURE ISSUES
|
| 101 |
+
|
| 102 |
+
1. **`winner_model/` directory undocumented** - A `winner_model/` directory exists at the project root containing a TensorFlow SavedModel format (`.pb` files). This appears to be an older or alternative model format alongside `winner.keras`. The code only references `winner.keras`. This directory is undocumented and may be a leftover artifact.
|
| 103 |
+
|
| 104 |
+
2. **`debug_streamlit.py` undocumented** - An untracked debug script exists at the project root. While it is not committed (per git status), it is listed in `pyproject.toml` ruff per-file-ignores (`debug_streamlit.py = ["E402"]`), suggesting it is a recognized development tool that should either be documented or removed from linter config.
|
| 105 |
+
|
| 106 |
+
3. **`docs/plans/` directory** - A `docs/plans/` directory exists but is not mentioned in the README project structure tree.
|
docs/plans/2026-03-25-audit-streamlit-nba/eval.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
type: repo-eval
|
| 3 |
+
pillar_overrides: {}
|
| 4 |
+
target_score: 9
|
| 5 |
+
pillars:
|
| 6 |
+
problem_solution_fit: 6
|
| 7 |
+
architecture: 7
|
| 8 |
+
code_quality: 8
|
| 9 |
+
creativity: 6
|
| 10 |
+
pragmatism: 6
|
| 11 |
+
defensiveness: 7
|
| 12 |
+
performance: 7
|
| 13 |
+
type_rigor: 7
|
| 14 |
+
test_value: 7
|
| 15 |
+
reproducibility: 7
|
| 16 |
+
git_hygiene: 5
|
| 17 |
+
onboarding: 7
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
> **Snapshot context:** This document captures pre-remediation (baseline) findings from the 2026-03-25 audit. Scores and evidence reflect the codebase state before the remediation PR. Items addressed during remediation are annotated inline.
|
| 21 |
+
|
| 22 |
+
## HIRE EVALUATION -- The Pragmatist
|
| 23 |
+
|
| 24 |
+
### VERDICT
|
| 25 |
+
- **Decision:** CAUTIOUS HIRE
|
| 26 |
+
- **Overall Grade:** B
|
| 27 |
+
- **One-Line:** Well-structured toy app that demonstrates strong defensive habits but lacks depth in the ML pipeline and leaves Pydantic models mostly unused.
|
| 28 |
+
|
| 29 |
+
### SCORECARD
|
| 30 |
+
|
| 31 |
+
| Pillar | Score | Evidence |
|
| 32 |
+
|--------|-------|----------|
|
| 33 |
+
| Problem-Solution Fit | 6/10 | `requirements.txt:2` TensorFlow is a heavyweight dependency for a binary classifier on 100 features *(TF retained, see ADR-2)*; `src/validation/inputs.py:8-28` SQL injection protection for a local CSV pandas app *(remediated: SQL regex removed, character allowlist retained)* |
|
| 34 |
+
| Architecture | 7/10 | `src/database/__init__.py:1-23` clean module boundaries with `__all__` exports; `src/models/player.py:10-81` Pydantic `PlayerStats` model defined but never used *(remediated: `PlayerStats` removed, `DifficultySettings` retained)* |
|
| 35 |
+
| Code Quality | 8/10 | `src/utils/html.py:12-47` proper XSS escaping with `html.escape`; `pages/2_play_game.py:96-110` defensive score generation with fallback; zero `print()` statements, zero TODOs, consistent docstrings throughout |
|
| 36 |
+
| Creativity | 6/10 | `scripts/compile_model.py:73-113` `create_stats` mutates input lists via `del` *(remediated: replaced with slicing)*; `src/database/queries.py:96-151` away team generation algorithm is a reasonable approach but nothing inventive |
|
| 37 |
+
|
| 38 |
+
### HIGHLIGHTS
|
| 39 |
+
- **Brilliance:** The security posture is notably strong for a Streamlit project. `src/utils/html.py:24-47` escapes all user-provided values before injecting into HTML markup, including color and alignment parameters, not just text. `src/validation/inputs.py:8-28` provides a compiled regex with 13 SQL injection patterns plus character validation. The test suite at `tests/test_validation.py:46-85` covers 10 parametrized injection vectors and 5 special character attacks, showing genuine security awareness.
|
| 40 |
+
|
| 41 |
+
- **Concerns:** The Pydantic models in `src/models/player.py` (PlayerStats, DifficultySettings) are well-defined with field validators but entirely bypassed in the actual application flow. Pages 1 and 2 pass raw DataFrames around, never constructing a `PlayerStats` instance. The `from_db_row` method at line 43 is dead code in production. This is architecture theater: structure that suggests rigor but delivers none at runtime.
|
| 42 |
+
|
| 43 |
+
The `scripts/compile_model.py:102-103` mutates input lists in place using `del home_stats[i][j][0]` inside nested loops. This destroys the original data and would produce incorrect results if `create_stats` were ever called twice on the same inputs. The training script also has `list[list]` type hints at lines 85-86 instead of proper parameterized types.
|
| 44 |
+
|
| 45 |
+
The `src/database/connection.py:54-73` context manager has an empty `finally: pass` block at line 72-73 and re-raises `DatabaseConnectionError` after logging it (line 66-68), creating duplicate log entries since callers also log the same exception.
|
| 46 |
+
|
| 47 |
+
### REMEDIATION TARGETS
|
| 48 |
+
|
| 49 |
+
- **Problem-Solution Fit (current: 6/10, target: 9/10)**
|
| 50 |
+
- Replace TensorFlow with a lighter alternative (scikit-learn, ONNX runtime, or a pre-exported TFLite model). The neural net is 3 dense layers with 100 inputs; TF is ~2GB of dependency for something sklearn can do in 50KB. Files: `requirements.txt`, `src/ml/model.py`, `scripts/compile_model.py`.
|
| 51 |
+
- Remove SQL injection validation (`src/validation/inputs.py:8-28`) or replace it with a simpler character allowlist. There is no SQL database; pandas `.str.contains()` in `src/database/queries.py:26-29` cannot be SQL-injected. The regex is defensive coding against a threat that does not exist.
|
| 52 |
+
- Estimated complexity: MEDIUM
|
| 53 |
+
|
| 54 |
+
- **Architecture (current: 7/10, target: 9/10)**
|
| 55 |
+
- Either use the Pydantic models or remove them. *(Remediated: `PlayerStats` removed, `DifficultySettings` retained.)*
|
| 56 |
+
- The `GameState` dataclass is defined but never instantiated. *(Remediated: `GameState` removed.)*
|
| 57 |
+
- The `get_connection()` context manager wraps a cached DataFrame read with no resource cleanup. *(Remediated: replaced with plain `get_data()` function, `finally: pass` removed.)*
|
| 58 |
+
- Estimated complexity: MEDIUM
|
| 59 |
+
|
| 60 |
+
- **Code Quality (current: 8/10, target: 9/10)**
|
| 61 |
+
- Fix f-string usage in logging calls throughout (`src/database/connection.py:40,49`, `pages/1_home_team.py:66,70,87,89,94,98`). Use `logger.error("msg %s", var)` format for lazy evaluation.
|
| 62 |
+
- Add type stubs or `py.typed` marker. The `mypy` CI step at `.github/workflows/ci.yml:34` runs but there is no `mypy.ini` or `pyproject.toml` `[tool.mypy]` section visible, meaning it runs with defaults and likely misses strict checks.
|
| 63 |
+
- Estimated complexity: LOW
|
| 64 |
+
|
| 65 |
+
- **Creativity (current: 6/10, target: 9/10)**
|
| 66 |
+
- Rewrite `scripts/compile_model.py:73-113` `create_stats` to avoid mutating input data. Use slicing (`row[1:]`) instead of `del` to extract features without side effects.
|
| 67 |
+
- The away team generation at `src/database/queries.py:96-151` uses retry loops with `sample()`. A more robust approach would pre-compute valid unique combinations or use stratified sampling to guarantee a result in one pass when the pool is large enough.
|
| 68 |
+
- Estimated complexity: LOW
|
| 69 |
+
|
| 70 |
+
---
|
| 71 |
+
|
| 72 |
+
## STRESS EVALUATION -- The Oncall Engineer
|
| 73 |
+
|
| 74 |
+
### VERDICT
|
| 75 |
+
- **Decision:** MID-LEVEL
|
| 76 |
+
- **Seniority Alignment:** Solid mid-level work. Clean structure, good validation, proper use of Pydantic. Falls short of senior expectations on error observability, type precision, and the ML integration's fragility under edge conditions.
|
| 77 |
+
- **One-Line:** Well-organized Streamlit app with genuine defensive coding, but the ML pipeline has silent shape assumption bombs and the "database" layer is ceremony over substance.
|
| 78 |
+
|
| 79 |
+
### SCORECARD
|
| 80 |
+
|
| 81 |
+
| Pillar | Score | Evidence |
|
| 82 |
+
|--------|-------|----------|
|
| 83 |
+
| Pragmatism | 6/10 | `src/database/connection.py:54-73` context manager wrapping a cached DataFrame read *(remediated: replaced with plain function)*; `src/validation/inputs.py:8-24` SQL injection guards on a CSV file *(remediated: SQL regex removed)* |
|
| 84 |
+
| Defensiveness | 7/10 | `pages/2_play_game.py:139-184` proper try/catch chains with user-facing errors; `src/ml/model.py:69-70` shape validation before prediction *(remediated: added input shape validation in `analyze_team_stats`)* |
|
| 85 |
+
| Performance | 7/10 | `src/database/connection.py:29` `@st.cache_data` on CSV load *(remediated: caching moved to page layer)*; `pages/1_home_team.py:86-88` batch query instead of N+1 |
|
| 86 |
+
| Type Rigor | 7/10 | `src/models/player.py:10-41` thorough Pydantic model with constraints *(remediated: `PlayerStats` removed)*; `src/database/queries.py:36` `tuple[Any, ...]` return type *(remediated: types tightened)* |
|
| 87 |
+
|
| 88 |
+
### CRITICAL FAILURE POINTS
|
| 89 |
+
|
| 90 |
+
None that are automatic no-go items. No global state leaks, no unhandled promise rejections (Python), no insecure defaults. The app reads a local CSV and runs a Keras model; the attack surface is inherently small.
|
| 91 |
+
|
| 92 |
+
### HIGHLIGHTS
|
| 93 |
+
|
| 94 |
+
**Brilliance:**
|
| 95 |
+
- `src/utils/html.py:12-21` and usage throughout: HTML escaping on all user-provided values before `unsafe_allow_html=True`. This is the correct pattern and many Streamlit apps get this wrong.
|
| 96 |
+
- `src/models/player.py:10-41`: Pydantic model with `ge=0`, `le=1.0` constraints on percentages, `min_length`/`max_length` on strings. Business rules encoded in the type system.
|
| 97 |
+
- `pages/2_play_game.py:96-110`: `generate_game_scores()` has a loop guard with fallback defaults, preventing infinite loops when random ranges overlap.
|
| 98 |
+
- `src/database/queries.py:96-151`: The away team generation algorithm with explicit pool pre-filtering and attempt counting is well-structured. Fails cleanly with a descriptive error.
|
| 99 |
+
- `pyproject.toml`: `mypy` set to `strict = true` with `disallow_untyped_defs`, `disallow_incomplete_defs`. Ruff configured with security rules (`S` prefix). Coverage threshold enforced.
|
| 100 |
+
|
| 101 |
+
**Concerns:**
|
| 102 |
+
- `src/database/connection.py:54-73`: The `get_connection()` context manager wraps `load_data()` (a cached DataFrame) and has a `finally: pass`. This is dead ceremony. There is no connection to manage, no resource to close.
|
| 103 |
+
- `src/validation/inputs.py:8-24`: SQL injection validation on a system that queries a local CSV via pandas. These guards do no harm, but they are solving a problem that does not exist in this architecture.
|
| 104 |
+
- `src/ml/model.py:110-112`: `analyze_team_stats` does `reshape(1, -1)` without validating that each player has exactly 10 stats. If a player has 9 stats (missing column in CSV), the combined array will be (1, 98) instead of (1, 100), and `predict_winner` will catch it but only after the reshape.
|
| 105 |
+
- `src/models/player.py:43-81`: `from_db_row` maps tuple positions by magic index numbers (0, 1, 2... 27). If `PLAYER_COLUMNS` order changes in `config.py`, this silently maps wrong values to wrong fields.
|
| 106 |
+
- `pages/2_play_game.py:128`: `st.session_state.away_team_df.empty` is accessed without first checking if the value is actually a DataFrame.
|
| 107 |
+
- `src/config.py:82-88`: `logging.basicConfig` is called at module import time. This could interfere with test output capture or serverless runtime logging.
|
| 108 |
+
|
| 109 |
+
### REMEDIATION TARGETS
|
| 110 |
+
|
| 111 |
+
**Pragmatism (current: 6/10, target: 9/10)**
|
| 112 |
+
- Remove or simplify `get_connection()` context manager. Replace with a direct `load_data()` call.
|
| 113 |
+
- Remove SQL injection validation from `inputs.py` or rename it to "character allowlist validation" to reflect what it actually does.
|
| 114 |
+
- Files: `src/database/connection.py`, `src/validation/inputs.py`
|
| 115 |
+
- Estimated complexity: LOW
|
| 116 |
+
|
| 117 |
+
**Defensiveness (current: 7/10, target: 9/10)**
|
| 118 |
+
- Add length validation in `from_db_row`: `assert len(row) == 28` or use a named constant.
|
| 119 |
+
- Add per-player stat count validation in `analyze_team_stats` before flattening.
|
| 120 |
+
- Guard `st.session_state.away_team_df.empty` at `pages/2_play_game.py:128` with an `isinstance` check.
|
| 121 |
+
- Add structured fields to log messages instead of just f-strings.
|
| 122 |
+
- Files: `src/models/player.py`, `src/ml/model.py`, `pages/2_play_game.py`
|
| 123 |
+
- Estimated complexity: LOW
|
| 124 |
+
|
| 125 |
+
**Performance (current: 7/10, target: 9/10)**
|
| 126 |
+
- `src/database/queries.py:25-29`: The `search_player_by_name` function runs three `str.contains` operations across the full DataFrame on every search. Document the scaling assumption or add an index.
|
| 127 |
+
- `analyze_team_stats` creates three numpy arrays where two would suffice.
|
| 128 |
+
- `scripts/compile_model.py:92-113`: `create_stats` mutates the input lists with `del`. Use slicing instead.
|
| 129 |
+
- Files: `src/database/queries.py`, `src/ml/model.py`, `scripts/compile_model.py`
|
| 130 |
+
- Estimated complexity: LOW
|
| 131 |
+
|
| 132 |
+
**Type Rigor (current: 7/10, target: 9/10)**
|
| 133 |
+
- `src/database/queries.py:36`: Return type `tuple[Any, ...]` loses all type information. Either return `PlayerStats` or define a typed tuple/TypedDict.
|
| 134 |
+
- `src/database/queries.py:14`: Return type `list[tuple[str]]` is a single-element tuple. Use `list[str]` directly.
|
| 135 |
+
- `Any` imports in `src/models/player.py:3` and `src/database/queries.py:4`: Used minimally, but `from_db_row` could accept a more specific protocol type.
|
| 136 |
+
- `scripts/compile_model.py:85`: `list[list]` is untyped. Should be `list[list[Any]]` at minimum.
|
| 137 |
+
- Files: `src/database/queries.py`, `src/models/player.py`, `scripts/compile_model.py`
|
| 138 |
+
- Estimated complexity: LOW
|
| 139 |
+
|
| 140 |
+
---
|
| 141 |
+
|
| 142 |
+
## DAY 2 EVALUATION -- The Team Lead
|
| 143 |
+
|
| 144 |
+
### VERDICT
|
| 145 |
+
- **Decision:** COLLABORATOR
|
| 146 |
+
- **Collaboration Score:** Med-High
|
| 147 |
+
- **One-Line:** "Well-structured code written for the next person, but the onboarding path has gaps and git history tells two different stories."
|
| 148 |
+
|
| 149 |
+
### SCORECARD
|
| 150 |
+
|
| 151 |
+
| Pillar | Score | Evidence |
|
| 152 |
+
|--------|-------|----------|
|
| 153 |
+
| Test Value | 7/10 | `tests/test_validation.py:46-85` SQL injection tests document real security behavior *(remediated: SQL tests removed with SQL code)*; `tests/test_ml.py:48-123` over-mocks the model layer *(remediated: real model load test added)* |
|
| 154 |
+
| Reproducibility | 7/10 | `pyproject.toml` has full tool config; `.github/workflows/ci.yml` runs tests+lint+mypy; but `.gitignore` is a single line *(remediated: expanded to 29 lines)* |
|
| 155 |
+
| Git Hygiene | 5/10 | `6424951` is a 2000+ line mega-commit creating entire `src/`, `tests/`, and `scripts/` directories; early history is "score update" x5, "README update" x4 |
|
| 156 |
+
| Onboarding | 7/10 | `README.md` has quick start, test commands, project structure; missing `.env.example`, no prereq for the `.keras` model file, no contributing guide |
|
| 157 |
+
|
| 158 |
+
### RED FLAGS
|
| 159 |
+
- **Minimal .gitignore**: Contains only `/venv`. A junior would commit build artifacts on day one.
|
| 160 |
+
- **Binary model file in git** (`winner.keras`, 87KB): Checked into the repo with no Git LFS.
|
| 161 |
+
- **Coverage threshold at 50%** (`pyproject.toml:113`): *(Remediated: threshold raised to 70%, enforced in CI with `--cov-fail-under=70`. Actual coverage: 93.60%.)*
|
| 162 |
+
- **Mega-commit** (`6424951`): "Refactor app with security fixes, error handling, and type safety" touches 30+ files with 2000+ insertions.
|
| 163 |
+
- **No pre-commit hooks**: *(Remediated: `.pre-commit-config.yaml` added with ruff and mypy hooks.)*
|
| 164 |
+
- **Two virtual environments**: Both `.venv/` and `venv/` exist in the repo root.
|
| 165 |
+
|
| 166 |
+
### HIGHLIGHTS
|
| 167 |
+
- **Process Win:** The test suite tests *behavior*, not just happy paths. `tests/test_validation.py` has parameterized SQL injection patterns and edge cases like apostrophes in names ("O'Neal") and periods ("J.R. Smith").
|
| 168 |
+
- **Process Win:** `pyproject.toml` consolidates all tooling config (mypy strict mode, ruff with 13 rule categories including flake8-bandit for security, pytest paths, coverage config) in one place.
|
| 169 |
+
- **Process Win:** Clean module architecture in `src/` with clear separation: `database/`, `ml/`, `models/`, `validation/`, `state/`, `utils/`. Each module has `__init__.py` with explicit exports.
|
| 170 |
+
- **Process Win:** Custom exception hierarchy (`ModelLoadError`, `DatabaseConnectionError`, `QueryExecutionError`) with proper exception chaining (`raise X from e`).
|
| 171 |
+
- **Maintenance Drag:** The `from_db_row` method in `src/models/player.py:43-81` maps tuple indices by position. Adding or reordering a column silently breaks this mapping.
|
| 172 |
+
- **Maintenance Drag:** `tests/test_ml.py` mocks `get_winner_model` in every test, meaning the tests validate mock behavior rather than actual model contract.
|
| 173 |
+
|
| 174 |
+
### REMEDIATION TARGETS
|
| 175 |
+
|
| 176 |
+
- **Git Hygiene (current: 5/10, target: 9/10)**
|
| 177 |
+
- Expand `.gitignore` to cover `__pycache__/`, `.mypy_cache/`, `.ruff_cache/`, `.pytest_cache/`, `.coverage`, `*.egg-info/`, and `*.pyc`.
|
| 178 |
+
- Move `winner.keras` to Git LFS or add a download script.
|
| 179 |
+
- Add `.pre-commit-config.yaml` with ruff and mypy hooks.
|
| 180 |
+
- Going forward, enforce atomic commits.
|
| 181 |
+
- Estimated complexity: LOW (gitignore, pre-commit) / MEDIUM (LFS migration)
|
| 182 |
+
|
| 183 |
+
- **Test Value (current: 7/10, target: 9/10)**
|
| 184 |
+
- Add an integration test that loads the actual CSV and validates column order matches `PLAYER_COLUMNS`.
|
| 185 |
+
- Add at least one test in `test_ml.py` that loads the real `winner.keras` model.
|
| 186 |
+
- Raise coverage threshold from 50% to 70% and add `--cov-fail-under=70` to CI. *(Remediated: threshold at 70%, CI enforces it.)*
|
| 187 |
+
- Add tests for `src/state/session.py` and `src/utils/html.py`. *(Remediated: `tests/test_state.py` and `tests/test_utils.py` added.)*
|
| 188 |
+
- Estimated complexity: MEDIUM
|
| 189 |
+
|
| 190 |
+
- **Reproducibility (current: 7/10, target: 9/10)**
|
| 191 |
+
- The `.devcontainer/devcontainer.json` uses `pip3 install` directly instead of `uv`.
|
| 192 |
+
- Add a `Makefile` or `justfile` with targets: `install`, `test`, `lint`, `typecheck`, `run`.
|
| 193 |
+
- Pin the CI Python image more tightly. Consider using `uv` in CI.
|
| 194 |
+
- Estimated complexity: LOW
|
| 195 |
+
|
| 196 |
+
- **Onboarding (current: 7/10, target: 9/10)**
|
| 197 |
+
- Add a `CONTRIBUTING.md` with branch strategy, PR process, and how to run tests locally.
|
| 198 |
+
- Document that `winner.keras` must exist in the project root for the app to function.
|
| 199 |
+
- Add `.env.example` if any environment variables are needed.
|
| 200 |
+
- The `from_db_row` positional-index mapping should be documented or replaced with a dict-based constructor.
|
| 201 |
+
- Estimated complexity: LOW
|
docs/plans/2026-03-25-audit-streamlit-nba/feedback.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Feedback: 2026-03-25-audit-streamlit-nba
|
| 2 |
+
|
| 3 |
+
## Verification Pass Results
|
| 4 |
+
|
| 5 |
+
**Date:** 2026-03-25
|
| 6 |
+
**Test suite:** 73/73 passed, 93.60% coverage (threshold: 70%)
|
| 7 |
+
|
| 8 |
+
---
|
| 9 |
+
|
| 10 |
+
## VERIFIED Findings
|
| 11 |
+
|
| 12 |
+
### Health Audit CRITICAL
|
| 13 |
+
|
| 14 |
+
1. **[CRITICAL #1] Streamlit coupling in core modules** -- VERIFIED
|
| 15 |
+
- `src/database/connection.py` and `src/ml/model.py` no longer import or use `st.cache_data` or `st.cache_resource`. Caching is now done at the page level (`pages/1_home_team.py:24`, `pages/2_play_game.py:39,44`), keeping core business logic decoupled from Streamlit runtime.
|
| 16 |
+
|
| 17 |
+
2. **[CRITICAL #2] Minimal .gitignore** -- VERIFIED
|
| 18 |
+
- `.gitignore` expanded from 1 line to 29 lines covering `__pycache__/`, `*.pyc`, `.venv/`, `venv/`, `.coverage`, `htmlcov/`, `.mypy_cache/`, `.pytest_cache/`, `.ruff_cache/`, `*.egg-info/`, `uv.lock`, `winner_model/`, `debug_streamlit.py`.
|
| 19 |
+
|
| 20 |
+
3. **[CRITICAL #3] Page modules execute at import time** -- PARTIAL (architectural constraint)
|
| 21 |
+
- Pages still execute at module level, which is the standard Streamlit pattern. The remediation moved caching to page-level wrappers and extracted `configure_page()` to reduce duplication. Full separation is not feasible without abandoning Streamlit's multipage architecture. Accepted as inherent to the framework.
|
| 22 |
+
|
| 23 |
+
### Health Audit HIGH
|
| 24 |
+
|
| 25 |
+
4. **[HIGH #4] Dead code: GameState, unused session functions** -- VERIFIED
|
| 26 |
+
- `GameState`, `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, `remove_player_from_team()` are all removed. `src/state/session.py` now contains only `init_session_state()`, `get_away_stats()`, and `get_home_team_df()`. `src/state/__init__.py` exports only `get_away_stats` and `init_session_state`.
|
| 27 |
+
|
| 28 |
+
5. **[HIGH #5] Dead code: get_player_by_full_name, safe_styled_text** -- VERIFIED
|
| 29 |
+
- `get_player_by_full_name()` no longer exists in `src/database/queries.py`. `safe_styled_text()` no longer exists in `src/utils/html.py`. `__init__.py` exports updated accordingly.
|
| 30 |
+
|
| 31 |
+
6. **[HIGH #6] TensorFlow model load with no timeout/guard** -- NOT IN SCOPE
|
| 32 |
+
- TensorFlow is still the ML framework. Replacing TF with a lighter alternative was listed as a remediation target but categorized as MEDIUM complexity. The model loading still uses `load_model()` without timeout.
|
| 33 |
+
|
| 34 |
+
7. **[HIGH #7] Broad except Exception catches** -- VERIFIED
|
| 35 |
+
- `src/database/connection.py` now catches specific exceptions: `(FileNotFoundError, pd.errors.ParserError, pd.errors.EmptyDataError)` at line 44. The old broad `except Exception` and `get_connection()` context manager with `finally: pass` are both gone.
|
| 36 |
+
|
| 37 |
+
8. **[HIGH #8] f-string interpolation in logging calls** -- VERIFIED
|
| 38 |
+
- All logging calls now use `%s` lazy formatting. Grep for `logger\.\w+\(f"` across the entire project returns zero matches.
|
| 39 |
+
|
| 40 |
+
9. **[HIGH #9] No validation on inner list lengths in analyze_team_stats** -- VERIFIED
|
| 41 |
+
- `src/ml/model.py:96-116` now validates team size (must equal `TEAM_SIZE`) and per-player stat count (must equal `len(STAT_COLUMNS)`) before any flattening or reshaping. Clear `ValueError` messages for each case.
|
| 42 |
+
|
| 43 |
+
### Health Audit MEDIUM
|
| 44 |
+
|
| 45 |
+
10. **[MEDIUM #10] debug_streamlit.py committed** -- VERIFIED
|
| 46 |
+
- `debug_streamlit.py` is in `.gitignore` (line 29). Ruff config no longer has a per-file-ignore entry for it.
|
| 47 |
+
|
| 48 |
+
11. **[MEDIUM #11] SQL injection validation on CSV app** -- VERIFIED
|
| 49 |
+
- `src/validation/inputs.py` no longer has SQL injection patterns or regex. Replaced with a simple character allowlist using `re.match(r"^[a-zA-Z0-9\s\-.']+$", v)`. The class is now `PlayerSearchInput` with `validate_reasonable_characters`.
|
| 50 |
+
|
| 51 |
+
12. **[MEDIUM #12] Unused PlayerStats Pydantic model** -- VERIFIED
|
| 52 |
+
- `PlayerStats` and `from_db_row()` are completely removed from `src/models/player.py`. Only `DifficultySettings` remains. No references to `PlayerStats` exist in `src/`.
|
| 53 |
+
|
| 54 |
+
13. **[MEDIUM #13] Retry loop without pre-check** -- PARTIAL
|
| 55 |
+
- `src/database/queries.py:75-79` now pre-filters pools before the loop, improving reliability. The retry loop itself remains (up to `MAX_QUERY_ATTEMPTS`), but pool size checks within each iteration fast-fail with `ValueError` if a pool is exhausted.
|
| 56 |
+
|
| 57 |
+
14. **[MEDIUM #14] Dual dependency declaration** -- VERIFIED
|
| 58 |
+
- `requirements.txt` no longer exists. Dependencies are declared only in `pyproject.toml`.
|
| 59 |
+
|
| 60 |
+
15. **[MEDIUM #15] away_team_df.empty guard** -- VERIFIED
|
| 61 |
+
- `pages/2_play_game.py:139-141` now uses `st.session_state.get("away_team_df") is None` check before accessing `.empty`. Additionally, `get_home_team_df()` in session.py includes an `isinstance(df, pd.DataFrame)` check.
|
| 62 |
+
|
| 63 |
+
16. **[MEDIUM #16] finally: pass no-op** -- VERIFIED
|
| 64 |
+
- The entire `get_connection()` context manager is removed. `src/database/connection.py` now has a simple `load_data()` function and a `get_data()` wrapper. No `finally: pass` anywhere.
|
| 65 |
+
|
| 66 |
+
17. **[MEDIUM #17] setup_logging() at module import time** -- PARTIAL
|
| 67 |
+
- `setup_logging()` is no longer called at module level in `config.py`. It is now called inside `configure_page()` (line 96), which is called by each page. This is an improvement but `logging.basicConfig()` is still called via `configure_page()` at page import time.
|
| 68 |
+
|
| 69 |
+
### Health Audit LOW
|
| 70 |
+
|
| 71 |
+
18. **[LOW #18] Duplicated on_page_load()** -- VERIFIED
|
| 72 |
+
- `on_page_load()` no longer exists in any file. All three entry points (`app.py`, pages) use `configure_page()` from `src/config.py`.
|
| 73 |
+
|
| 74 |
+
19. **[LOW #19] Duplicate validation in DifficultySettings** -- PARTIAL
|
| 75 |
+
- The field validator and `from_preset()` both still check validity, but `from_preset()` now delegates to Pydantic's validator by constructing the model with the invalid name (line 48-54), so it is less duplicative than before.
|
| 76 |
+
|
| 77 |
+
20. **[LOW #20] Hardcoded CSV path** -- NOT ADDRESSED
|
| 78 |
+
- `src/database/connection.py:11` still resolves path via `Path(__file__).resolve().parent.parent.parent / "snowflake_nba.csv"`. Not configurable.
|
| 79 |
+
|
| 80 |
+
21. **[LOW #21] No tests for session state or pages** -- VERIFIED
|
| 81 |
+
- `tests/test_state.py` exists with 8 tests covering `init_session_state`, `get_away_stats`, and `get_home_team_df`. `tests/test_utils.py` exists with 11 tests covering `escape_html`, `safe_heading`, and `safe_paragraph`. Coverage threshold raised from 50% to 70%.
|
| 82 |
+
|
| 83 |
+
22. **[LOW #22] winner_model/ tracked alongside winner.keras** -- VERIFIED
|
| 84 |
+
- `winner_model/` is in `.gitignore` (line 26). The directory still exists on disk but is ignored by git.
|
| 85 |
+
|
| 86 |
+
### Eval Remediation Targets
|
| 87 |
+
|
| 88 |
+
23. **[EVAL] compile_model.py create_stats mutation** -- VERIFIED
|
| 89 |
+
- `scripts/compile_model.py:100-104` now uses `row[1:]` slicing instead of `del` to skip the team name column. No mutation of input data.
|
| 90 |
+
|
| 91 |
+
24. **[EVAL] Pre-commit hooks** -- VERIFIED
|
| 92 |
+
- `.pre-commit-config.yaml` exists with ruff (lint + format) and mypy hooks. `pre-commit` added to dev dependencies.
|
| 93 |
+
|
| 94 |
+
25. **[EVAL] Coverage threshold** -- VERIFIED
|
| 95 |
+
- `pyproject.toml:111` sets `fail_under = 70` (raised from 50%). Actual coverage is 93.60%.
|
| 96 |
+
|
| 97 |
+
26. **[EVAL] Integration test for CSV columns** -- VERIFIED
|
| 98 |
+
- `tests/test_database.py::TestCsvColumnValidation::test_csv_columns_match_config` loads the real CSV and validates columns match `PLAYER_COLUMNS`.
|
| 99 |
+
|
| 100 |
+
27. **[EVAL] Real model load test** -- VERIFIED
|
| 101 |
+
- `tests/test_ml.py::TestLoadRealModel::test_load_real_model` exists and passes.
|
| 102 |
+
|
| 103 |
+
### Doc Audit
|
| 104 |
+
|
| 105 |
+
28. **[DRIFT #2] README multi-page description** -- VERIFIED
|
| 106 |
+
- README line 19 now says "Two-Page Interface" instead of "Multi-page Interface".
|
| 107 |
+
|
| 108 |
+
29. **[DRIFT #3] README project structure tree** -- VERIFIED
|
| 109 |
+
- Tree now includes `src/config.py`, `snowflake_nba.csv`, `winner.keras`, `.github/workflows/`, `.pre-commit-config.yaml`, `.streamlit/config.toml`.
|
| 110 |
+
|
| 111 |
+
30. **[DRIFT #4] README "database" language** -- VERIFIED
|
| 112 |
+
- README line 21 now says "dataset of historical NBA stats (local CSV)" instead of "comprehensive database of historical NBA stats."
|
| 113 |
+
|
| 114 |
+
31. **[STALE CODE #1] README install instructions** -- VERIFIED
|
| 115 |
+
- README lines 62-65 show `uv pip install -e .` and line 72 shows `uv pip install -e ".[dev]"`. No more `pip install -r requirements.txt`.
|
| 116 |
+
|
| 117 |
+
32. **[STALE CODE #2] README lint command scope** -- VERIFIED
|
| 118 |
+
- README line 89 now shows `ruff check src/ tests/`, matching CI.
|
| 119 |
+
|
| 120 |
+
33. **[CONFIG DRIFT #2] Training script prerequisites undocumented** -- VERIFIED
|
| 121 |
+
- README lines 96-99 now document `player_stats.txt` and `schedule.txt` as required input files.
|
| 122 |
+
|
| 123 |
+
34. **[STRUCTURE #2] debug_streamlit.py in ruff config** -- VERIFIED
|
| 124 |
+
- `pyproject.toml` no longer has a per-file-ignore entry for `debug_streamlit.py`.
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Summary
|
| 129 |
+
|
| 130 |
+
| Category | Verified | Partial | Not Addressed | Not In Scope |
|
| 131 |
+
|----------|----------|---------|---------------|--------------|
|
| 132 |
+
| Critical | 2 | 1 | 0 | 0 |
|
| 133 |
+
| High | 4 | 0 | 0 | 1 |
|
| 134 |
+
| Medium | 6 | 2 | 0 | 0 |
|
| 135 |
+
| Low | 3 | 1 | 1 | 0 |
|
| 136 |
+
| Eval targets | 5 | 0 | 0 | 0 |
|
| 137 |
+
| Doc audit | 7 | 0 | 0 | 0 |
|
| 138 |
+
| **Total** | **27** | **4** | **1** | **1** |
|
| 139 |
+
|
| 140 |
+
### Unverified / Partial Items
|
| 141 |
+
|
| 142 |
+
1. **[CRITICAL #3]** Page modules still execute at import time. This is inherent to Streamlit's architecture and not realistically fixable without abandoning the framework.
|
| 143 |
+
2. **[MEDIUM #13]** Retry loop still exists but is improved with pre-filtering. Acceptable trade-off.
|
| 144 |
+
3. **[MEDIUM #17]** `logging.basicConfig()` still called at page load via `configure_page()`. Improved from module-import-time, but not fully resolved.
|
| 145 |
+
4. **[LOW #19]** Duplicate validation in `DifficultySettings` partially reduced.
|
| 146 |
+
5. **[LOW #20]** Hardcoded CSV path not configurable. Low priority.
|
| 147 |
+
6. **[HIGH #6]** TensorFlow model loading without timeout/guard. Accepted as out of scope for this pass.
|
| 148 |
+
|
| 149 |
+
### Test Results
|
| 150 |
+
|
| 151 |
+
- 73 tests passed, 0 failed
|
| 152 |
+
- Coverage: 93.60% (threshold: 70%)
|
| 153 |
+
- No regressions detected
|
| 154 |
+
|
| 155 |
+
## Verdict
|
| 156 |
+
|
| 157 |
+
VERIFIED
|
docs/plans/2026-03-25-audit-streamlit-nba/health-audit.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
type: repo-health
|
| 3 |
+
overall_health: FAIR
|
| 4 |
+
findings:
|
| 5 |
+
critical: 3
|
| 6 |
+
high: 6
|
| 7 |
+
medium: 8
|
| 8 |
+
low: 5
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
## CODEBASE HEALTH AUDIT
|
| 12 |
+
|
| 13 |
+
### EXECUTIVE SUMMARY
|
| 14 |
+
- **Overall health:** FAIR
|
| 15 |
+
- **Biggest structural risk:** Streamlit framework (`st.cache_resource`, `st.cache_data`) is coupled directly into business logic modules (ML model, database connection), making the core logic untestable and undeployable outside of Streamlit.
|
| 16 |
+
- **Biggest operational risk:** Binary model file (87KB `.keras`) and large data files (394K CSV, 128K schedule.txt, 21K player_stats.txt) are committed directly to git, and the `.gitignore` is nearly empty (only `/venv`).
|
| 17 |
+
- **Total findings:** 3 critical, 6 high, 8 medium, 5 low
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
### TECH DEBT LEDGER
|
| 22 |
+
|
| 23 |
+
#### CRITICAL
|
| 24 |
+
|
| 25 |
+
1. **[Architectural Debt]** `src/ml/model.py:7-22` and `src/database/connection.py:9,29`
|
| 26 |
+
- **The Debt:** Core business modules (`ml.model` and `database.connection`) directly import and use `streamlit` (`st.cache_resource`, `st.cache_data`). The ML model loader uses `@st.cache_resource` (line 22) and the data loader uses `@st.cache_data` (line 29). This means these modules cannot be imported or tested without a Streamlit runtime. For a serverless deployment target, this is a fundamental blocker: Lambda/Cloud Functions cannot run the Streamlit caching layer.
|
| 27 |
+
- **The Risk:** The application is permanently locked to the Streamlit runtime. Any attempt to reuse the prediction logic in a Lambda handler, CLI tool, or API endpoint will fail at import time. Testing requires mocking Streamlit internals.
|
| 28 |
+
|
| 29 |
+
2. **[Operational Debt]** `.gitignore:1` (entire file is just `/venv`)
|
| 30 |
+
- **The Debt:** The `.gitignore` is a single line: `/venv`. The repository tracks binary files (`winner.keras` at 87KB, `winner_model/` directory with SavedModel protobuf files), large data files (`snowflake_nba.csv` at 394KB, `schedule.txt` at 128KB, `player_stats.txt` at 21KB), a `.coverage` file (68KB), `__pycache__/` directories, `.mypy_cache/`, `.pytest_cache/`, `.ruff_cache/`, a second `.venv/` directory, `uv.lock`, `debug_streamlit.py`, and `src/streamlit_nba.egg-info/`. Git status shows these are untracked but only because they were never added; the `.gitignore` does not prevent future accidental commits.
|
| 31 |
+
- **The Risk:** Binary and generated artifacts bloat the repository. The `.coverage` file, `__pycache__` directories, and cache directories are transient build artifacts. The `winner.keras` and `winner_model/` are tracked model binaries that will accumulate in git history. For serverless cold starts, pulling a bloated deployment package increases init time.
|
| 32 |
+
|
| 33 |
+
3. **[Architectural Debt]** `pages/1_home_team.py:1-161` and `pages/2_play_game.py:1-206`
|
| 34 |
+
- **The Debt:** Page modules execute business logic at module level (outside functions) during import. `1_home_team.py` calls `on_page_load()`, `init_session_state()`, `find_player()`, `find_home_team()`, and renders UI at lines 13, 27, 30, 32-42, 103-104, 127-161. `2_play_game.py` does the same at lines 36, 39, 42-43, 114-198. There is no separation between the controller logic and the view. All database queries, ML predictions, and UI rendering happen in a single top-to-bottom script execution.
|
| 35 |
+
- **The Risk:** No unit of this code can be tested in isolation. Any import of a page module triggers the entire page flow. Serverless deployment is incompatible with this pattern since there is no request handler to invoke.
|
| 36 |
+
|
| 37 |
+
#### HIGH
|
| 38 |
+
|
| 39 |
+
4. **[Structural Debt]** `src/state/session.py:19-29`, `src/state/session.py:86-163`
|
| 40 |
+
- **The Debt:** Five exported functions/classes in `session.py` are never used anywhere in the codebase: `GameState` (defined but unused), `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, and `remove_player_from_team()`. They are exported via `src/state/__init__.py` but never imported by any page or test.
|
| 41 |
+
- **The Risk:** Dead code that increases maintenance surface. `GameState` duplicates the dict-based state in `init_session_state()`, creating confusion about which pattern is canonical.
|
| 42 |
+
|
| 43 |
+
5. **[Structural Debt]** `src/database/queries.py:34-49` and `src/utils/html.py:73-108`
|
| 44 |
+
- **The Debt:** `get_player_by_full_name()` is defined and exported via `__init__.py` but never called by any page, test, or script. `safe_styled_text()` is defined but never called anywhere in the codebase.
|
| 45 |
+
- **The Risk:** Dead code with no test coverage, adding maintenance burden.
|
| 46 |
+
|
| 47 |
+
6. **[Operational Debt]** `src/ml/model.py:44-45`
|
| 48 |
+
- **The Debt:** `load_model()` (TensorFlow Keras) is called with no timeout and no size/memory guard. TensorFlow model loading is a heavyweight operation that loads the entire model into memory. For a serverless target (Lambda has 512MB-10GB memory, 15-minute timeout), loading a Keras model with the full TensorFlow runtime is a cold start performance concern.
|
| 49 |
+
- **The Risk:** TensorFlow is one of the largest Python packages (>500MB installed). Cold start on Lambda with TensorFlow can exceed 10 seconds. There is no fallback, no lightweight model format (like ONNX or TFLite), and no lazy loading strategy.
|
| 50 |
+
|
| 51 |
+
7. **[Code Hygiene Debt]** `src/database/connection.py:48`, `src/database/connection.py:69`
|
| 52 |
+
- **The Debt:** Broad `except Exception` catch blocks that re-raise as custom exceptions. At `connection.py:48`, any exception from `pd.read_csv()` is caught and wrapped. At `connection.py:69`, any exception from data access is caught and wrapped. While re-raising is better than swallowing, catching the base `Exception` can mask programming errors (e.g., `TypeError`, `KeyError`).
|
| 53 |
+
- **The Risk:** Bugs in data processing code could be silently wrapped as `DatabaseConnectionError`, making debugging harder. The broad catch at line 69 includes the `finally: pass` block (line 72-73), which is a no-op.
|
| 54 |
+
|
| 55 |
+
8. **[Architectural Debt]** `pages/1_home_team.py:66` and `pages/1_home_team.py:87-88`
|
| 56 |
+
- **The Debt:** f-string interpolation in logging calls: `logger.error(f"Database connection error: {e}")`. This evaluates the f-string even when the log level is above ERROR. Appears at 6 locations in `1_home_team.py` and 4 locations in `2_play_game.py`.
|
| 57 |
+
- **The Risk:** Minor performance overhead on every request. In a high-throughput serverless context, unnecessary string formatting adds up.
|
| 58 |
+
|
| 59 |
+
9. **[Operational Debt]** `src/ml/model.py:83-114`
|
| 60 |
+
- **The Debt:** `analyze_team_stats()` accepts `list[list[float]]` but performs no validation on the inner list lengths or the number of players. If a team has fewer or more than 5 players with 10 stats each, the reshape at lines 110-112 will silently produce arrays of unexpected shape. The only shape check is in `predict_winner()` at line 69, which checks for `(1, 100)` after the damage is done.
|
| 61 |
+
- **The Risk:** Silent data corruption. If `STAT_COLUMNS` is modified or player count differs, the model receives garbage input without any clear error message. The error would surface as a generic `ValueError` from numpy reshape.
|
| 62 |
+
|
| 63 |
+
#### MEDIUM
|
| 64 |
+
|
| 65 |
+
10. **[Code Hygiene Debt]** `debug_streamlit.py:1-63`
|
| 66 |
+
- **The Debt:** Debug script committed to the repository with print statements, mock Streamlit setup, and simulation logic. Not in `.gitignore`, not in any test suite.
|
| 67 |
+
- **The Risk:** Confusion about whether this is a supported tool or leftover artifact. Contains hardcoded player names.
|
| 68 |
+
|
| 69 |
+
11. **[Structural Debt]** `src/validation/inputs.py:8-28`
|
| 70 |
+
- **The Debt:** Elaborate SQL injection detection regex for a codebase that uses pandas DataFrames, not SQL databases. The data layer reads from a local CSV via pandas. There are no SQL queries anywhere in the application.
|
| 71 |
+
- **The Risk:** False sense of security and unnecessary complexity. Solves a problem that does not exist in this architecture.
|
| 72 |
+
|
| 73 |
+
12. **[Structural Debt]** `src/models/player.py:10-81`
|
| 74 |
+
- **The Debt:** Full Pydantic model `PlayerStats` with 27 fields and a `from_db_row()` factory method. Neither the model nor the factory method is used anywhere outside tests. The application works entirely with raw pandas DataFrames.
|
| 75 |
+
- **The Risk:** Maintained model definition with no runtime usage. Changes to the DataFrame schema must be synchronized in two places (the Pydantic model and `PLAYER_COLUMNS` in config), but only the config is actually used.
|
| 76 |
+
|
| 77 |
+
13. **[Operational Debt]** `src/database/queries.py:102-147`
|
| 78 |
+
- **The Debt:** The retry loop (up to `MAX_QUERY_ATTEMPTS = 10`) uses random sampling that can fail repeatedly if pool sizes are marginal. Each iteration creates new DataFrame slices. There is no exponential backoff or pool-size pre-check to fast-fail.
|
| 79 |
+
- **The Risk:** On a serverless target with execution time limits, 10 retries of DataFrame operations with small pools waste compute.
|
| 80 |
+
|
| 81 |
+
14. **[Architectural Debt]** `requirements.txt:1-5` vs `pyproject.toml:7-13`
|
| 82 |
+
- **The Debt:** Dependencies are declared in both `requirements.txt` and `pyproject.toml` with identical content. Dual source of truth.
|
| 83 |
+
- **The Risk:** Dependency drift when one file is updated but not the other.
|
| 84 |
+
|
| 85 |
+
15. **[Operational Debt]** `pages/2_play_game.py:128-129`
|
| 86 |
+
- **The Debt:** Away team is only generated when `st.session_state.get("away_team_df") is None or st.session_state.away_team_df.empty`. If data generation fails silently (returns empty DataFrame), the code does not clear the cached empty DataFrame, so subsequent reruns will not retry.
|
| 87 |
+
- **The Risk:** One-time failure permanently prevents game play until the user clicks "Play New Team" manually.
|
| 88 |
+
|
| 89 |
+
16. **[Code Hygiene Debt]** `src/database/connection.py:72-73`
|
| 90 |
+
- **The Debt:** `finally: pass` block in the context manager does nothing.
|
| 91 |
+
- **The Risk:** Vestigial code that suggests cleanup was intended but never implemented.
|
| 92 |
+
|
| 93 |
+
17. **[Structural Debt]** `src/config.py:73-93`
|
| 94 |
+
- **The Debt:** `setup_logging()` is called at module level (line 93), meaning logging is configured the moment any module imports `config.py`. It calls `logging.basicConfig()` which sets the root logger.
|
| 95 |
+
- **The Risk:** In a serverless environment, the Lambda runtime configures its own root logger. Calling `basicConfig()` at import time can conflict with the runtime's logging setup.
|
| 96 |
+
|
| 97 |
+
#### LOW
|
| 98 |
+
|
| 99 |
+
18. **[Code Hygiene Debt]** `pages/1_home_team.py:22-27`, `pages/2_play_game.py:31-36`, `app.py:8-13`
|
| 100 |
+
- **The Debt:** `on_page_load()` function defined and immediately called in three separate files, each containing only `st.set_page_config(layout="wide")`. Identical one-liner duplicated three times.
|
| 101 |
+
- **The Risk:** Minor duplication. If page config needs to change, three files must be updated.
|
| 102 |
+
|
| 103 |
+
19. **[Code Hygiene Debt]** `src/models/player.py:95-104` and `src/models/player.py:119-123`
|
| 104 |
+
- **The Debt:** Duplicate validation logic in `DifficultySettings`. The `validate_preset_name` field validator (line 95) checks if the name is valid, and `from_preset()` (line 119) performs the same check again before calling the constructor.
|
| 105 |
+
- **The Risk:** Redundant code path. The error message format differs slightly between the two checks.
|
| 106 |
+
|
| 107 |
+
20. **[Code Hygiene Debt]** `src/database/connection.py:14`
|
| 108 |
+
- **The Debt:** CSV path is resolved via `Path(__file__).resolve().parent.parent.parent / "snowflake_nba.csv"`, hardcoding a relative traversal depth. Not configurable via environment variable or config.
|
| 109 |
+
- **The Risk:** Fragile path resolution. If the module is moved or the project structure changes, the path breaks silently.
|
| 110 |
+
|
| 111 |
+
21. **[Structural Debt]** No tests for `src/state/session.py` or page modules
|
| 112 |
+
- **The Debt:** The test suite covers `models`, `validation`, `ml`, and `database` but has no tests for session state management or any page-level integration tests.
|
| 113 |
+
- **The Risk:** Coverage threshold is set at 50%, which is low for production code.
|
| 114 |
+
|
| 115 |
+
22. **[Code Hygiene Debt]** `winner_model/` directory tracked alongside `winner.keras`
|
| 116 |
+
- **The Debt:** Two copies of the trained model exist in the repository: `winner.keras` (87KB, Keras native format) and `winner_model/` (SavedModel format with protobuf files). Only `winner.keras` is referenced in code.
|
| 117 |
+
- **The Risk:** `winner_model/` is dead weight in the repository, never referenced by any code.
|
| 118 |
+
|
| 119 |
+
---
|
| 120 |
+
|
| 121 |
+
### QUICK WINS
|
| 122 |
+
|
| 123 |
+
1. `/.gitignore` -- Expand to cover `__pycache__/`, `*.pyc`, `.coverage`, `.mypy_cache/`, `.pytest_cache/`, `.ruff_cache/`, `*.egg-info/`, `.venv/`, `uv.lock`, `debug_streamlit.py`, `winner_model/` (estimated effort: < 15 minutes)
|
| 124 |
+
|
| 125 |
+
2. `src/database/connection.py:72-73` -- Remove the `finally: pass` no-op block (estimated effort: < 5 minutes)
|
| 126 |
+
|
| 127 |
+
3. `src/state/session.py:19-29`, `src/state/session.py:86-163` -- Remove unused `GameState` class, `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, and `remove_player_from_team()` functions (estimated effort: < 30 minutes)
|
| 128 |
+
|
| 129 |
+
4. `src/utils/html.py:73-108` and `src/database/queries.py:34-49` -- Remove dead functions `safe_styled_text()` and `get_player_by_full_name()`, update `__init__.py` exports (estimated effort: < 30 minutes)
|
| 130 |
+
|
| 131 |
+
5. `pages/*.py` and `app.py` -- Extract duplicated `on_page_load()` into `src/config.py` or a shared module (estimated effort: < 30 minutes)
|
| 132 |
+
|
| 133 |
+
---
|
| 134 |
+
|
| 135 |
+
### AUTOMATED SCAN RESULTS
|
| 136 |
+
|
| 137 |
+
- **Dead code:** Manual analysis identified 7 unused functions/classes: `GameState`, `get_home_team_names()`, `set_difficulty()`, `add_player_to_team()`, `remove_player_from_team()`, `get_player_by_full_name()`, `safe_styled_text()`
|
| 138 |
+
- **Vulnerability scan:** Unable to run `pip-audit`. Note: dependency pins use open upper bounds (`>=`) which could pull vulnerable versions
|
| 139 |
+
- **Secrets scan:** No hardcoded secrets, API keys, or high-entropy strings found in source files. No `.env` files present.
|
| 140 |
+
- **Git hygiene:** `.gitignore` covers only `/venv`. Binary files (`winner.keras`, `winner_model/`) and data files (`snowflake_nba.csv`, `player_stats.txt`, `schedule.txt`) are tracked in git. Generated artifacts (`.coverage`, `__pycache__/`, cache directories) are untracked but unprotected.
|
| 141 |
+
- **Type safety:** No `# type: ignore` comments found. Mypy strict mode enabled. Third-party libraries have `ignore_missing_imports = true` (appropriate).
|
| 142 |
+
- **Debug artifacts:** No `print()`, `TODO`, `FIXME`, or `debugger` statements in `src/`. `debug_streamlit.py` in repo root contains print statements.
|
docs/project-roadmap.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Project Roadmap
|
| 2 |
+
|
| 3 |
+
Items identified during the 2026-03-25 audit that were deferred, out of scope, or not examined. Organized by priority.
|
| 4 |
+
|
| 5 |
+
## High Priority
|
| 6 |
+
|
| 7 |
+
### Replace TensorFlow with a lightweight alternative
|
| 8 |
+
The neural network is 3 dense layers with 100 inputs. TensorFlow is ~2GB of installed dependency for something scikit-learn or ONNX Runtime can handle in a fraction of the size. This is the single biggest factor in cold start time and deployment package size.
|
| 9 |
+
|
| 10 |
+
- Retrain with scikit-learn (MLPClassifier) or export to ONNX/TFLite
|
| 11 |
+
- Update `src/ml/model.py`, `scripts/compile_model.py`, `pyproject.toml`
|
| 12 |
+
- Update `winner.keras` artifact and any model-loading tests
|
| 13 |
+
- Source: eval Problem-Solution Fit (6/10), health audit HIGH #6
|
| 14 |
+
|
| 15 |
+
### Run dependency vulnerability scan
|
| 16 |
+
`pip-audit` failed to run during the audit. Dependencies use open upper bounds (`>=`) which could pull vulnerable versions.
|
| 17 |
+
|
| 18 |
+
- Run `uvx pip-audit` and address findings
|
| 19 |
+
- Consider pinning upper bounds or using `uv.lock` for reproducibility
|
| 20 |
+
- Source: health audit automated scan (blocked)
|
| 21 |
+
|
| 22 |
+
### Migrate model files out of git history
|
| 23 |
+
`winner.keras` (87KB) and `winner_model/` (SavedModel format, unused) are tracked directly in git. As the model grows, this bloats repo history permanently.
|
| 24 |
+
|
| 25 |
+
- Remove `winner_model/` entirely (dead, never referenced in code)
|
| 26 |
+
- Move `winner.keras` to Git LFS or add a download script
|
| 27 |
+
- Source: health audit CRITICAL #2, Day 2 eval Git Hygiene (5/10)
|
| 28 |
+
|
| 29 |
+
## Medium Priority
|
| 30 |
+
|
| 31 |
+
### Make data and model paths configurable
|
| 32 |
+
`snowflake_nba.csv` path is hardcoded via `Path(__file__).resolve().parent.parent.parent` in `connection.py:14`. Model path is similarly hardcoded in `model.py:13`. Neither is configurable via environment variable.
|
| 33 |
+
|
| 34 |
+
- Add env var overrides (e.g., `NBA_DATA_PATH`, `NBA_MODEL_PATH`) with current paths as defaults
|
| 35 |
+
- Document in README under "Data Files and Configuration"
|
| 36 |
+
- Source: health audit LOW #20, doc audit CONFIG DRIFT #1
|
| 37 |
+
|
| 38 |
+
### Improve logging for serverless compatibility
|
| 39 |
+
`logging.basicConfig()` is called inside `configure_page()`, which runs at page load. This is better than the original module-import-time call, but still conflicts with Lambda/Cloud Functions runtimes that configure their own root logger.
|
| 40 |
+
|
| 41 |
+
- Use `logging.getLogger(__name__)` pattern without `basicConfig()` for library modules
|
| 42 |
+
- Only call `basicConfig()` in the Streamlit entry points, guarded by a check
|
| 43 |
+
- Source: health audit MEDIUM #17, stress eval Pragmatism (6/10)
|
| 44 |
+
|
| 45 |
+
### Add CONTRIBUTING.md
|
| 46 |
+
No contributing guide exists. Day 2 evaluation flagged this for onboarding.
|
| 47 |
+
|
| 48 |
+
- Branch strategy, PR process, how to run tests locally
|
| 49 |
+
- Reference the pre-commit hooks added in Phase 4
|
| 50 |
+
- Source: Day 2 eval Onboarding (7/10)
|
| 51 |
+
|
| 52 |
+
### Improve away team generation algorithm
|
| 53 |
+
The retry loop (up to 10 attempts) uses random sampling that can fail repeatedly with small pools. A pool-size pre-check before entering the loop would avoid futile iterations.
|
| 54 |
+
|
| 55 |
+
- Pre-check `len(pool) >= required` before sampling
|
| 56 |
+
- Consider stratified sampling for guaranteed one-pass results when pool is large enough
|
| 57 |
+
- Source: health audit MEDIUM #13, eval Creativity (6/10)
|
| 58 |
+
|
| 59 |
+
## Low Priority
|
| 60 |
+
|
| 61 |
+
### Page-level import-time execution
|
| 62 |
+
Streamlit pages execute business logic at module level during import. This is inherent to Streamlit's architecture and not fixable without abandoning the framework. Core modules (database, ML) were decoupled in the audit, but the pages themselves still run top-to-bottom on every rerun.
|
| 63 |
+
|
| 64 |
+
- Not actionable without a framework change
|
| 65 |
+
- If migrating to FastAPI or similar, this resolves naturally
|
| 66 |
+
- Source: health audit CRITICAL #3
|
| 67 |
+
|
| 68 |
+
### Add .env.example
|
| 69 |
+
The codebase currently reads no environment variables, so this is not urgent. If configurable paths are added (see above), create `.env.example` at that time.
|
| 70 |
+
|
| 71 |
+
- Source: Day 2 eval Onboarding (7/10)
|
| 72 |
+
|
| 73 |
+
## Not In Scope (Separate Initiatives)
|
| 74 |
+
|
| 75 |
+
### ML model quality evaluation
|
| 76 |
+
The audit examined code quality, not model quality. No assessment was made of prediction accuracy, training data freshness, or bias.
|
| 77 |
+
|
| 78 |
+
### Accessibility audit
|
| 79 |
+
No evaluation of the Streamlit UI for accessibility (screen readers, keyboard navigation, color contrast).
|
| 80 |
+
|
| 81 |
+
### Load and performance testing
|
| 82 |
+
No profiling of cold start time, memory footprint, or behavior under concurrent users. Relevant if deploying beyond the Hugging Face Space.
|
pages/1_home_team.py
CHANGED
|
@@ -5,11 +5,10 @@ import logging
|
|
| 5 |
import pandas as pd
|
| 6 |
import streamlit as st
|
| 7 |
|
| 8 |
-
from src.config import DIFFICULTY_PRESETS, PLAYER_COLUMNS
|
| 9 |
from src.database.connection import (
|
| 10 |
DatabaseConnectionError,
|
| 11 |
-
|
| 12 |
-
get_connection,
|
| 13 |
)
|
| 14 |
from src.database.queries import get_players_by_full_names, search_player_by_name
|
| 15 |
from src.state.session import init_session_state
|
|
@@ -18,13 +17,13 @@ from src.validation.inputs import validate_search_term
|
|
| 18 |
|
| 19 |
logger = logging.getLogger("streamlit_nba")
|
| 20 |
|
|
|
|
| 21 |
|
| 22 |
-
def on_page_load() -> None:
|
| 23 |
-
"""Configure page settings."""
|
| 24 |
-
st.set_page_config(layout="wide")
|
| 25 |
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
on_page_load()
|
| 28 |
|
| 29 |
# Initialize session state before any access
|
| 30 |
init_session_state()
|
|
@@ -54,20 +53,18 @@ def find_player(search_term: str) -> list[str]:
|
|
| 54 |
# Validate input
|
| 55 |
validated_term = validate_search_term(search_term)
|
| 56 |
if validated_term is None:
|
| 57 |
-
st.warning(
|
|
|
|
|
|
|
| 58 |
return []
|
| 59 |
|
| 60 |
try:
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
except DatabaseConnectionError as e:
|
| 65 |
-
st.error("Could not
|
| 66 |
-
logger.error(
|
| 67 |
-
return []
|
| 68 |
-
except QueryExecutionError as e:
|
| 69 |
-
st.error("Error searching for players. Please try again.")
|
| 70 |
-
logger.error(f"Query error: {e}")
|
| 71 |
return []
|
| 72 |
|
| 73 |
|
|
@@ -82,20 +79,16 @@ def find_home_team() -> pd.DataFrame:
|
|
| 82 |
return pd.DataFrame(columns=PLAYER_COLUMNS)
|
| 83 |
|
| 84 |
try:
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
except DatabaseConnectionError as e:
|
| 93 |
-
st.error("Could not
|
| 94 |
-
logger.error(
|
| 95 |
-
return pd.DataFrame(columns=PLAYER_COLUMNS)
|
| 96 |
-
except QueryExecutionError as e:
|
| 97 |
-
st.error("Error loading team data. Please try again.")
|
| 98 |
-
logger.error(f"Query error: {e}")
|
| 99 |
return pd.DataFrame(columns=PLAYER_COLUMNS)
|
| 100 |
|
| 101 |
|
|
@@ -105,7 +98,9 @@ home_team_df = find_home_team()
|
|
| 105 |
|
| 106 |
# Combine search results with current team and current unsaved selections
|
| 107 |
# This ensures that selections don't disappear when the search term changes
|
| 108 |
-
current_team_names =
|
|
|
|
|
|
|
| 109 |
current_selections = st.session_state.get("player_selector", [])
|
| 110 |
|
| 111 |
# Merge all into options list, maintaining uniqueness
|
|
@@ -126,7 +121,9 @@ def save_state() -> None:
|
|
| 126 |
|
| 127 |
col1, col2 = st.columns([7, 1])
|
| 128 |
with col1:
|
| 129 |
-
default_selection =
|
|
|
|
|
|
|
| 130 |
player_selected = st.multiselect(
|
| 131 |
"Search Results:",
|
| 132 |
player_search,
|
|
|
|
| 5 |
import pandas as pd
|
| 6 |
import streamlit as st
|
| 7 |
|
| 8 |
+
from src.config import DIFFICULTY_PRESETS, PLAYER_COLUMNS, configure_page
|
| 9 |
from src.database.connection import (
|
| 10 |
DatabaseConnectionError,
|
| 11 |
+
load_data,
|
|
|
|
| 12 |
)
|
| 13 |
from src.database.queries import get_players_by_full_names, search_player_by_name
|
| 14 |
from src.state.session import init_session_state
|
|
|
|
| 17 |
|
| 18 |
logger = logging.getLogger("streamlit_nba")
|
| 19 |
|
| 20 |
+
configure_page()
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
+
@st.cache_data
|
| 24 |
+
def _load_nba_data() -> pd.DataFrame:
|
| 25 |
+
return load_data()
|
| 26 |
|
|
|
|
| 27 |
|
| 28 |
# Initialize session state before any access
|
| 29 |
init_session_state()
|
|
|
|
| 53 |
# Validate input
|
| 54 |
validated_term = validate_search_term(search_term)
|
| 55 |
if validated_term is None:
|
| 56 |
+
st.warning(
|
| 57 |
+
"Invalid search term. Please use only letters, numbers, and basic punctuation."
|
| 58 |
+
)
|
| 59 |
return []
|
| 60 |
|
| 61 |
try:
|
| 62 |
+
data = _load_nba_data()
|
| 63 |
+
results = search_player_by_name(data, validated_term)
|
| 64 |
+
return [player[0] for player in results]
|
| 65 |
except DatabaseConnectionError as e:
|
| 66 |
+
st.error("Could not load player data. Please try again later.")
|
| 67 |
+
logger.error("Data load error: %s", e)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
return []
|
| 69 |
|
| 70 |
|
|
|
|
| 79 |
return pd.DataFrame(columns=PLAYER_COLUMNS)
|
| 80 |
|
| 81 |
try:
|
| 82 |
+
data = _load_nba_data()
|
| 83 |
+
# Single batch query instead of N+1 queries
|
| 84 |
+
logger.info("Loading data for team: %s", team_names)
|
| 85 |
+
df = get_players_by_full_names(data, team_names)
|
| 86 |
+
logger.info("Retrieved %d players", len(df))
|
| 87 |
+
st.session_state.home_team_df = df
|
| 88 |
+
return df
|
| 89 |
except DatabaseConnectionError as e:
|
| 90 |
+
st.error("Could not load player data. Please try again later.")
|
| 91 |
+
logger.error("Data load error: %s", e)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
return pd.DataFrame(columns=PLAYER_COLUMNS)
|
| 93 |
|
| 94 |
|
|
|
|
| 98 |
|
| 99 |
# Combine search results with current team and current unsaved selections
|
| 100 |
# This ensures that selections don't disappear when the search term changes
|
| 101 |
+
current_team_names = (
|
| 102 |
+
home_team_df["FULL_NAME"].tolist() if not home_team_df.empty else []
|
| 103 |
+
)
|
| 104 |
current_selections = st.session_state.get("player_selector", [])
|
| 105 |
|
| 106 |
# Merge all into options list, maintaining uniqueness
|
|
|
|
| 121 |
|
| 122 |
col1, col2 = st.columns([7, 1])
|
| 123 |
with col1:
|
| 124 |
+
default_selection = (
|
| 125 |
+
home_team_df["FULL_NAME"].tolist() if not home_team_df.empty else []
|
| 126 |
+
)
|
| 127 |
player_selected = st.multiselect(
|
| 128 |
"Search Results:",
|
| 129 |
player_search,
|
pages/2_play_game.py
CHANGED
|
@@ -14,26 +14,31 @@ from src.config import (
|
|
| 14 |
STAT_COLUMNS,
|
| 15 |
TEAM_SIZE,
|
| 16 |
WINNER_SCORE_RANGE,
|
|
|
|
| 17 |
)
|
| 18 |
from src.database.connection import (
|
| 19 |
DatabaseConnectionError,
|
| 20 |
QueryExecutionError,
|
| 21 |
-
|
| 22 |
)
|
| 23 |
from src.database.queries import get_away_team_by_stats
|
| 24 |
-
from src.ml.model import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
from src.state.session import get_away_stats, get_home_team_df, init_session_state
|
| 26 |
from src.utils.html import safe_heading
|
| 27 |
|
| 28 |
logger = logging.getLogger("streamlit_nba")
|
| 29 |
|
|
|
|
| 30 |
|
| 31 |
-
def on_page_load() -> None:
|
| 32 |
-
"""Configure page settings."""
|
| 33 |
-
st.set_page_config(layout="wide")
|
| 34 |
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
-
on_page_load()
|
| 37 |
|
| 38 |
# Initialize session state BEFORE any access
|
| 39 |
init_session_state()
|
|
@@ -53,22 +58,22 @@ def find_away_team(stat_thresholds: list[int]) -> pd.DataFrame:
|
|
| 53 |
DataFrame with away team data, or empty DataFrame on error
|
| 54 |
"""
|
| 55 |
try:
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
except DatabaseConnectionError as e:
|
| 66 |
-
st.error("Could not
|
| 67 |
-
logger.error(
|
| 68 |
return pd.DataFrame()
|
| 69 |
except QueryExecutionError as e:
|
| 70 |
st.error("Could not generate away team. Please try again.")
|
| 71 |
-
logger.error(
|
| 72 |
return pd.DataFrame()
|
| 73 |
|
| 74 |
|
|
@@ -125,7 +130,10 @@ if home_team_df.empty or home_team_df.shape[0] != TEAM_SIZE:
|
|
| 125 |
box_score = pd.DataFrame()
|
| 126 |
else:
|
| 127 |
# Only generate away team if we don't have one or it's empty
|
| 128 |
-
if
|
|
|
|
|
|
|
|
|
|
| 129 |
st.session_state.away_team_df = find_away_team(stats)
|
| 130 |
|
| 131 |
away_data = st.session_state.away_team_df
|
|
@@ -168,17 +176,17 @@ if teams_good and not st.session_state.away_team_df.empty:
|
|
| 168 |
index=["Home Team", "Away Team"],
|
| 169 |
)
|
| 170 |
|
| 171 |
-
logger.info(
|
| 172 |
|
| 173 |
except ModelLoadError as e:
|
| 174 |
st.error("Could not load prediction model. Please contact support.")
|
| 175 |
-
logger.error(
|
| 176 |
teams_good = False
|
| 177 |
winner_label = ""
|
| 178 |
box_score = pd.DataFrame()
|
| 179 |
except ValueError as e:
|
| 180 |
st.error("Error processing team stats. Please try again.")
|
| 181 |
-
logger.error(
|
| 182 |
teams_good = False
|
| 183 |
winner_label = ""
|
| 184 |
box_score = pd.DataFrame()
|
|
@@ -197,9 +205,11 @@ if teams_good and winner_label:
|
|
| 197 |
safe_heading("Away Team", level=1, color="steelblue")
|
| 198 |
st.dataframe(st.session_state.away_team_df)
|
| 199 |
|
|
|
|
| 200 |
def play_new_team() -> None:
|
| 201 |
"""Clear cached away team and rerun."""
|
| 202 |
logger.info("New Team requested")
|
| 203 |
st.session_state.away_team_df = pd.DataFrame()
|
| 204 |
|
|
|
|
| 205 |
st.button("Play New Team", on_click=play_new_team)
|
|
|
|
| 14 |
STAT_COLUMNS,
|
| 15 |
TEAM_SIZE,
|
| 16 |
WINNER_SCORE_RANGE,
|
| 17 |
+
configure_page,
|
| 18 |
)
|
| 19 |
from src.database.connection import (
|
| 20 |
DatabaseConnectionError,
|
| 21 |
QueryExecutionError,
|
| 22 |
+
load_data,
|
| 23 |
)
|
| 24 |
from src.database.queries import get_away_team_by_stats
|
| 25 |
+
from src.ml.model import (
|
| 26 |
+
ModelLoadError,
|
| 27 |
+
analyze_team_stats,
|
| 28 |
+
predict_winner,
|
| 29 |
+
)
|
| 30 |
from src.state.session import get_away_stats, get_home_team_df, init_session_state
|
| 31 |
from src.utils.html import safe_heading
|
| 32 |
|
| 33 |
logger = logging.getLogger("streamlit_nba")
|
| 34 |
|
| 35 |
+
configure_page()
|
| 36 |
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
+
@st.cache_data
|
| 39 |
+
def _load_nba_data() -> pd.DataFrame:
|
| 40 |
+
return load_data()
|
| 41 |
|
|
|
|
| 42 |
|
| 43 |
# Initialize session state BEFORE any access
|
| 44 |
init_session_state()
|
|
|
|
| 58 |
DataFrame with away team data, or empty DataFrame on error
|
| 59 |
"""
|
| 60 |
try:
|
| 61 |
+
data = _load_nba_data()
|
| 62 |
+
return get_away_team_by_stats(
|
| 63 |
+
data,
|
| 64 |
+
pts_threshold=stat_thresholds[0],
|
| 65 |
+
reb_threshold=stat_thresholds[1],
|
| 66 |
+
ast_threshold=stat_thresholds[2],
|
| 67 |
+
stl_threshold=stat_thresholds[3],
|
| 68 |
+
max_attempts=MAX_QUERY_ATTEMPTS,
|
| 69 |
+
)
|
| 70 |
except DatabaseConnectionError as e:
|
| 71 |
+
st.error("Could not load player data. Please try again later.")
|
| 72 |
+
logger.error("Data load error: %s", e)
|
| 73 |
return pd.DataFrame()
|
| 74 |
except QueryExecutionError as e:
|
| 75 |
st.error("Could not generate away team. Please try again.")
|
| 76 |
+
logger.error("Query error: %s", e)
|
| 77 |
return pd.DataFrame()
|
| 78 |
|
| 79 |
|
|
|
|
| 130 |
box_score = pd.DataFrame()
|
| 131 |
else:
|
| 132 |
# Only generate away team if we don't have one or it's empty
|
| 133 |
+
if (
|
| 134 |
+
st.session_state.get("away_team_df") is None
|
| 135 |
+
or st.session_state.away_team_df.empty
|
| 136 |
+
):
|
| 137 |
st.session_state.away_team_df = find_away_team(stats)
|
| 138 |
|
| 139 |
away_data = st.session_state.away_team_df
|
|
|
|
| 176 |
index=["Home Team", "Away Team"],
|
| 177 |
)
|
| 178 |
|
| 179 |
+
logger.info("Prediction: %.4f", probability)
|
| 180 |
|
| 181 |
except ModelLoadError as e:
|
| 182 |
st.error("Could not load prediction model. Please contact support.")
|
| 183 |
+
logger.error("Model load error: %s", e)
|
| 184 |
teams_good = False
|
| 185 |
winner_label = ""
|
| 186 |
box_score = pd.DataFrame()
|
| 187 |
except ValueError as e:
|
| 188 |
st.error("Error processing team stats. Please try again.")
|
| 189 |
+
logger.error("Stats processing error: %s", e)
|
| 190 |
teams_good = False
|
| 191 |
winner_label = ""
|
| 192 |
box_score = pd.DataFrame()
|
|
|
|
| 205 |
safe_heading("Away Team", level=1, color="steelblue")
|
| 206 |
st.dataframe(st.session_state.away_team_df)
|
| 207 |
|
| 208 |
+
|
| 209 |
def play_new_team() -> None:
|
| 210 |
"""Clear cached away team and rerun."""
|
| 211 |
logger.info("New Team requested")
|
| 212 |
st.session_state.away_team_df = pd.DataFrame()
|
| 213 |
|
| 214 |
+
|
| 215 |
st.button("Play New Team", on_click=play_new_team)
|