Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

&& HAS_GO=true\necho \"$DIFF_FILES\" | grep -q '\\.py

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

&& HAS_PY=true\necho \"$(date -Iseconds) preflight: HAS_GO=$HAS_GO HAS_PY=$HAS_PY\" >> .agents/council/preflight.log\n```\n\n**For Python (only when `HAS_PY=true`):**\n```bash\nif [ \"$HAS_PY\" = \"true\" ]; then\n echo \"$(date -Iseconds) preflight: checking radon\" >> .agents/council/preflight.log\n if ! which radon >> .agents/council/preflight.log 2>&1; then\n echo \"⚠️ COMPLEXITY SKIPPED: radon not installed (pip install radon)\"\n else\n radon cc \u003cpath> -a -s 2>/dev/null | head -30\n radon mi \u003cpath> -s 2>/dev/null | head -30\n fi\nelse\n echo \"ℹ️ COMPLEXITY SKIPPED: no .py files in diff\"\nfi\n```\n\n**For Go (only when `HAS_GO=true`):**\n```bash\nif [ \"$HAS_GO\" = \"true\" ]; then\n echo \"$(date -Iseconds) preflight: checking gocyclo\" >> .agents/council/preflight.log\n if ! which gocyclo >> .agents/council/preflight.log 2>&1; then\n echo \"⚠️ COMPLEXITY SKIPPED: gocyclo not installed (go install github.com/fzipp/gocyclo/cmd/gocyclo@latest)\"\n else\n gocyclo -over 10 \u003cpath> 2>/dev/null | head -30\n fi\nelse\n echo \"ℹ️ COMPLEXITY SKIPPED: no .go files in diff\"\nfi\n```\n\n**For other languages:** Skip complexity with explicit note: \"⚠️ COMPLEXITY SKIPPED: No analyzer for \u003clanguage>\"\n\n**Interpret results:**\n\n| Score | Rating | Action |\n|-------|--------|--------|\n| A (1-5) | Simple | Good |\n| B (6-10) | Moderate | OK |\n| C (11-20) | Complex | Flag for council |\n| D (21-30) | Very complex | Recommend refactor |\n| F (31+) | Untestable | Must refactor |\n\n**Include complexity findings in council context.**\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2300,"content_sha256":"95129e01d3547c1ad795bb6f806c7109c5cbf49dc241491bbf18c143a2fe01ed"},{"filename":"references/deep-audit-protocol.md","content":"# Deep Audit Protocol\n\n> Used by `/vibe --deep`, `/vibe --sweep`, and `/post-mortem` (unless `--skip-sweep`).\n\nTwo-phase architecture: cheap per-file explorer sweep (discovery) followed by council judges (adjudication). All reporting caps removed.\n\n```\nFiles -> chunk into batches of 3-5\n -> [up to 8 Explore agents in parallel, 8-category checklist per file] -> raw findings\n -> sweep manifest (ALL findings merged)\n -> [council judges] adjudicate + add cross-cutting findings -> ALL findings reported\n```\n\n---\n\n## Phase 1: Explorer Sweep\n\n### File Chunking Rules\n\nSort target files by line count (largest first), then chunk:\n\n| File Size | Batch Size | Rationale |\n|-----------|-----------|-----------|\n| \u003c= 100 lines | 5 per batch | Small files — explorers can handle many |\n| 101–300 lines | 3 per batch | Medium files — moderate depth needed |\n| > 300 lines | 1 per batch (solo) | Large files — full attention required |\n\n**Max 8 batches.** If chunking produces more than 8 batches, merge the smallest batches until you have 8. If fewer than 8 batches, use fewer explorers.\n\n### Explorer Prompt Template\n\nEach explorer receives this prompt with its assigned file batch:\n\n```\nYou are a Deep Audit Explorer. Your job is DISCOVERY — find every concrete issue in\nthe assigned files. You are NOT a judge; you do not decide severity thresholds or\nship-readiness. Find problems. Be thorough. Be specific.\n\n## Assigned Files\n\n{FILE_LIST}\n\n## Mandatory 8-Category Checklist\n\nFor EACH file, you MUST check all 8 categories. Do not skip any category for any file.\n\n1. **Resource Leaks** — Unclosed files/connections/handles, missing defer/finally/cleanup,\n goroutine leaks, listener leaks, temp file accumulation\n2. **String Safety** — Unsanitized user input, format string injection, path traversal,\n SQL/command injection, XSS vectors, unsafe interpolation.\n **Boundary with Cat 8:** String Safety covers injection at the data layer (SQL, command, format string).\n HTTP-layer concerns (XSS in HTML output, CORS headers, CSRF tokens) belong to Cat 8.\n Path traversal appears in both: Cat 2 when sanitizing input strings, Cat 8 when serving HTTP file requests.\n3. **Dead Code** — Unreachable branches, unused imports/variables/functions, commented-out\n code left behind, feature flags that are always on/off\n4. **Hardcoded Values** — Magic numbers, hardcoded paths/URLs/credentials, environment-\n specific values not in config, hardcoded timeouts/limits\n5. **Edge Cases** — Nil/null/zero handling, empty collections, boundary values, integer\n overflow, off-by-one, Unicode edge cases, concurrent access\n6. **Concurrency** — Data races, missing locks, lock ordering issues, channel misuse,\n deadlock potential, shared state without synchronization\n7. **Error Handling** — Swallowed errors, generic catch-all, missing error propagation,\n panic/crash on recoverable errors, unclear error messages\n8. **HTTP/Web Security** — XSS vectors (innerHTML, document.write, dangerouslySetInnerHTML),\n path traversal (../ sequences, directory escape), CORS misconfiguration, CSRF tokens missing,\n HTTP response splitting, Content-Type mismatches, missing rate limiting, open redirects,\n SSRF (outbound URL/IP validation), missing security headers (Strict-Transport-Security,\n X-Frame-Options, Content-Security-Policy), credential/token exposure in logs\n\n## Per-File Coverage Certification\n\nFor each file, you MUST either:\n- Report at least 1 finding, OR\n- Explicitly certify all 8 categories clean with a brief reason per category\n\nDo NOT skip a file. Do NOT say \"looks fine\" without checking each category.\n\n## Output Format\n\nFor each file, produce:\n1. A category coverage checklist (checked = issue found, certified = explicitly clean)\n2. A findings table\n\n### Category Coverage\n\n```\nFile: {filename}\n[x] Resource Leaks — found: unclosed DB connection at line 45\n[ ] String Safety — CLEAN: all inputs validated via sanitize() helper\n[x] Dead Code — found: unused import \"fmt\" at line 3\n[ ] Hardcoded Values — CLEAN: all values from config package\n[x] Edge Cases — found: nil map access at line 78\n[ ] Concurrency — CLEAN: single-goroutine function, no shared state\n[ ] Error Handling — CLEAN: all errors returned with context wrapping\n[ ] HTTP/Web Security — CLEAN: no HTTP handlers, outbound requests, or log statements with credentials in this file\n```\n\n### Findings Table\n\n| File | Line | Category | Severity | Description | Evidence |\n|------|------|----------|----------|-------------|----------|\n| auth.go | 45 | Resource Leaks | high | DB connection opened but never closed in error path | `db.Open()` at L45, return at L52 skips `defer db.Close()` |\n| auth.go | 3 | Dead Code | low | Unused import \"fmt\" | No fmt.* calls in file |\n| auth.go | 78 | Edge Cases | high | Nil map access when config missing | `config[\"key\"]` without nil check, panics if config unset |\n\nSeverity levels:\n- **critical** — Security vulnerability, data loss, crash in production\n- **high** — Bug that will manifest under normal usage\n- **medium** — Code smell, maintainability issue, minor bug in edge case\n- **low** — Style issue, minor dead code, documentation gap\n\n## Rules\n\n- Read each file completely. Do not skim.\n- Every finding MUST have a specific line number and evidence quote.\n- Do not invent findings. If a category is clean, certify it clean.\n- Prefer false negatives over false positives — only report what you can evidence.\n- Do NOT assess overall quality or make ship/no-ship recommendations.\n```\n\n### Dispatching Explorers\n\nUse the Task tool with `subagent_type: \"Explore\"` for each batch. Launch all batches in parallel (single message, multiple tool calls):\n\n```\nTask(\n subagent_type=\"Explore\",\n description=\"Sweep batch N of M\",\n prompt=\"\u003cexplorer prompt with FILE_LIST filled in>\"\n)\n```\n\nEach explorer writes findings to `.agents/council/sweep-batch-{N}.md`.\n\n---\n\n## Phase 2: Sweep Manifest\n\nAfter all explorers complete, merge their findings into a single sweep manifest:\n\n**Write to:** `.agents/council/sweep-manifest.md`\n\n```markdown\n# Sweep Manifest\n\n**Files Scanned:** {total_file_count}\n**Batches:** {batch_count}\n**Total Findings:** {finding_count}\n\n## All Findings\n\n| # | File | Line | Category | Severity | Description | Evidence |\n|---|------|------|----------|----------|-------------|----------|\n| 1 | auth.go | 45 | Resource Leaks | high | DB connection unclosed in error path | `db.Open()` at L45... |\n| 2 | ... | ... | ... | ... | ... | ... |\n\n## Category Summary\n\n| Category | Findings | Files Affected |\n|----------|----------|----------------|\n| Resource Leaks | 3 | 2 |\n| String Safety | 1 | 1 |\n| Dead Code | 5 | 4 |\n| Hardcoded Values | 2 | 2 |\n| Edge Cases | 4 | 3 |\n| Concurrency | 0 | 0 |\n| Error Handling | 3 | 2 |\n| HTTP/Web Security | 1 | 1 |\n\n## Clean Certifications\n\n| File | Categories Certified Clean |\n|------|---------------------------|\n| utils.go | All 8 |\n| config.go | Resource Leaks, String Safety, Dead Code, Edge Cases, Concurrency |\n```\n\n**No caps.** Include ALL findings from ALL explorers. Do not filter, rank, or truncate.\n\n---\n\n## Phase 3: Council Adjudication\n\nWhen a sweep manifest exists, inject it into the council packet and shift judges from discovery to adjudication mode.\n\n### Council Injection Text\n\nAdd this to the council packet's `context.sweep_manifest`:\n\n```json\n{\n \"sweep_manifest\": {\n \"source\": \"deep-audit-protocol explorer sweep\",\n \"file\": \".agents/council/sweep-manifest.md\",\n \"finding_count\": N,\n \"summary\": \"\u003cfirst 3000 chars of sweep manifest>\"\n }\n}\n```\n\n### Judge Mode Shift\n\nWhen `sweep_manifest` is present in the council context, judges operate in **adjudication mode** instead of discovery mode. The judge prompt receives an additional section (see `council/references/agent-prompts.md` for the exact injection text).\n\nIn adjudication mode, judges:\n1. **Confirm or reject** each sweep finding (with brief rationale)\n2. **Reclassify severity** where the explorer got it wrong\n3. **Add cross-file findings** that individual explorers couldn't see (architectural issues, inconsistent patterns across files, missing integration points)\n4. **Assess overall readiness** considering the full sweep manifest\n\n### Reporting\n\nThe final report includes ALL findings — both confirmed sweep findings and judge-added cross-cutting findings. No caps on finding count. If more than 20 findings, group by category in the report.\n\n---\n\n## Flag Behavior\n\n| Flag | Sweep? | Judges | Notes |\n|------|--------|--------|-------|\n| `/vibe` (default) | No | 2 | Unchanged: lightweight bug-hunt + council |\n| `/vibe --quick` | No | 1 (inline) | Unchanged: fast inline check |\n| `/vibe --deep` | Yes | 3 | Enhanced: sweep + 3 judges in adjudication mode |\n| `/vibe --sweep` | Yes | 2 | New: sweep + 2 judges in adjudication mode |\n| `/vibe --sweep recent` | Yes | 2 | Same, targeting recent changes |\n| `/post-mortem` | Yes | 3 | Enhanced: sweep before retrospective council |\n| `/post-mortem --skip-sweep` | No | 3 | Old behavior: 3 judges, no sweep |\n| `/post-mortem --quick` | No | 1 (inline) | Unchanged: fast inline check |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9165,"content_sha256":"05e863d4d85e9cf02cf74bf2d65c078d651a55f57a6d18a55102a98571f01b3a"},{"filename":"references/deep-checks.md","content":"# Deep Checks (Steps 2.5, 2a–2f, 2h, 3–3.6)\n\n> **Extracted from:** `skills/vibe/SKILL.md`.\n> These are the pre-council deep analysis and preparation checks. Loaded automatically unless `--quick` mode is set.\n\n---\n\n### Step 2.4: Compiled Prevention Check\n\nBefore reading `.agents/rpi/next-work.jsonl`, load compiled prevention context from `.agents/pre-mortem-checks/*.md` and `.agents/planning-rules/*.md` when they exist. This is the primary reusable-prevention surface for review.\n\nUse the tracked contracts in `docs/contracts/finding-compiler.md` and `docs/contracts/finding-registry.md`:\n\n- prefer compiled pre-mortem checks and planning rules first\n- rank by severity, `applicable_when` overlap, language overlap, changed-file overlap, and literal target-text overlap\n- keep the ranking order consistent with `/plan` and `/pre-mortem`; do not invent a separate review-only heuristic\n- cap at top 5 findings / compiled files\n- if compiled outputs are missing, incomplete, or fewer than the matched finding set, fall back to `.agents/findings/registry.jsonl`\n- fail open:\n - missing compiled directory or registry -> skip silently\n - empty compiled directory or registry -> skip silently\n - malformed line -> warn and ignore that line\n - unreadable file -> warn once and continue without findings\n\nInclude matched entries in the council packet as `known_risks` / checklist context with:\n- `id`\n- `pattern`\n- `detection_question`\n- `checklist_item`\n\n### Step 2.5: Prior Findings Check\n\n**Skip if `--quick` (see Step 1.5).**\n\nRead `.agents/rpi/next-work.jsonl` and find unconsumed items with `severity=high` that match the target area. Include them in the council packet as `context.prior_findings` so judges have carry-forward context.\n\nTreat these high-severity queue items as part of the same ranked packet used earlier in discovery/plan/pre-mortem. The review stage should inherit and refine prior findings context, not restart retrieval from scratch.\n\n```bash\n# Count unconsumed high-severity items\nif [ -f .agents/rpi/next-work.jsonl ] && command -v jq &>/dev/null; then\n prior_count=$(jq -s '[.[] | select(.consumed == false) | .items[] | select(.severity == \"high\")] | length' \\\n .agents/rpi/next-work.jsonl 2>/dev/null || echo 0)\n if [ \"$prior_count\" -gt 0 ]; then\n echo \"Prior findings: $prior_count unconsumed high-severity items from next-work.jsonl\"\n jq -s '[.[] | select(.consumed == false) | .items[] | select(.severity == \"high\")]' \\\n .agents/rpi/next-work.jsonl 2>/dev/null\n fi\nfi\n```\n\nIf unconsumed high-severity items are found, include them in the council packet context:\n```json\n\"prior_findings\": {\n \"source\": \".agents/rpi/next-work.jsonl\",\n \"count\": 3,\n \"items\": [/* array of high-severity unconsumed items */]\n}\n```\n\n**Skip conditions:**\n- `--quick` mode → skip\n- `.agents/rpi/next-work.jsonl` does not exist → skip silently\n- `jq` not on PATH → skip silently\n- No unconsumed high-severity items found → skip (do not add empty `prior_findings` to packet)\n\n### Step 2a: Run Constraint Tests\n\n**Skip if `--quick` (see Step 1.5).**\n\n**If the project has constraint tests, run them before council:**\n\n```bash\n# Check if constraint tests exist\nif [ -d \"internal/constraints\" ] && ls internal/constraints/*_test.go &>/dev/null; then\n echo \"Running constraint tests...\"\n go test ./internal/constraints/ -run TestConstraint -v 2>&1\n # If FAIL → include failures in council context as CRITICAL findings\n # If PASS → note \"N constraint tests passed\" in report\nfi\n```\n\n**Why:** Constraint tests catch mechanical violations (ghost references, TOCTOU races, dead code at entry points) that council judges miss.\n\nInclude constraint test results in the council packet context. Failed constraint tests are CRITICAL findings that override council PASS verdict.\n\n### Step 2b: Metadata Verification Checklist (MANDATORY)\n\n**Skip if `--quick` (see Step 1.5).**\n\nRun mechanical checks BEFORE council — catches errors LLMs estimate instead of measure:\n1. **File existence** — every path in `git diff --name-only HEAD~3` must exist on disk\n2. **Line counts** — if a file claims \"N lines\", verify with `wc -l`\n3. **Cross-references** — internal markdown links resolve to existing files\n4. **Diagram sanity** — files with >3 ASCII boxes should have matching labels\n\nInclude failures in council packet as `context.metadata_failures` (MECHANICAL findings). If all pass, note in report.\n\n### Step 2d: Codex Review (opt-in via `--mixed`)\n\n**Skip unless `--mixed` is passed.** Also skip if `--quick` (see Step 1.5).\n\nCodex review is opt-in because it adds 30–60s latency and token cost. Users explicitly request cross-vendor input with `--mixed`.\n\n```bash\necho \"$(date -Iseconds) preflight: checking codex\" >> .agents/council/preflight.log\nif which codex >> .agents/council/preflight.log 2>&1; then\n codex review --uncommitted > .agents/council/codex-review-pre.md 2>&1 && \\\n echo \"Codex review complete — output at .agents/council/codex-review-pre.md\" || \\\n echo \"Codex review skipped (failed)\"\nelse\n echo \"Codex review skipped (CLI not found)\"\nfi\n```\n\n**If output exists**, summarize and include in council packet (cap at 2000 chars to prevent context bloat):\n```json\n\"codex_review\": {\n \"source\": \"codex review --uncommitted\",\n \"content\": \"\u003cfirst 2000 chars of .agents/council/codex-review-pre.md>\"\n}\n```\n\n**IMPORTANT:** The raw codex review can be 50k+ chars. Including the full text in every judge's packet multiplies token cost by N judges. Truncate to the first 2000 chars (covers the summary and top findings). Judges can read the full file from disk if they need more detail.\n\nThis gives council judges a Codex-generated review as pre-existing context — cheap, fast, diff-focused. It does NOT replace council judgment; it augments it.\n\n**Skip conditions:**\n- `--mixed` not passed → skip (opt-in only)\n- Codex CLI not on PATH → skip silently\n- `codex review` fails → skip silently, proceed with council only\n- No uncommitted changes → skip (nothing to review)\n\n### Step 2e: Search Knowledge Flywheel\n\n**Skip if `--quick` (see Step 1.5).**\n\n```bash\nif command -v ao &>/dev/null; then\n ao search \"code review findings \u003ctarget>\" 2>/dev/null | head -10\nfi\n```\nIf ao returns prior code review patterns for this area, include them in the council packet context. Skip silently if ao is unavailable or returns no results.\n\n### Step 2f: Bug Hunt or Deep Audit Sweep\n\n**Skip if `--quick` (see Step 1.5).**\n\n**Path A — Deep Audit Sweep (`--deep` or `--sweep`):**\n\nRead `references/deep-audit-protocol.md` for the full protocol. In summary:\n\n1. Chunk target files into batches of 3–5 (by line count — see protocol for rules)\n2. Dispatch up to 8 Explore agents in parallel, each with a mandatory 8-category checklist per file\n3. Merge all explorer findings into a sweep manifest at `.agents/council/sweep-manifest.md`\n4. Include sweep manifest in council packet (judges shift to adjudication mode — see Step 4)\n\n**Why:** Generalist judges exhibit satisfaction bias — they stop at ~10 findings regardless of actual issue count. Per-file explorers with category checklists eliminate this bias and find 3x more issues in a single pass.\n\n**Path B — Lightweight Bug Hunt (default, no `--deep`/`--sweep`):**\n\nRun a proactive bug hunt on the target files before council review:\n\n```\n/bug-hunt --audit \u003ctarget>\n```\n\nIf bug-hunt produces findings, include them in the council packet as `context.bug_hunt`:\n```json\n\"bug_hunt\": {\n \"source\": \"/bug-hunt --audit\",\n \"findings_count\": 3,\n \"high\": 1,\n \"medium\": 1,\n \"low\": 1,\n \"summary\": \"\u003cfirst 2000 chars of bug hunt report>\"\n}\n```\n\n**Why:** Bug hunt catches concrete line-level bugs (resource leaks, truncation errors, dead code) that council judges — reviewing holistically — often miss.\n\n**Skip conditions (both paths):**\n- `--quick` mode → skip (fast path)\n- No source files in target → skip (nothing to audit)\n- Target is non-code (pure docs/config) → skip\n\n### Step 2h: Check for Product Context\n\n**Skip if `--quick` (see Step 1.5).**\n\n```bash\nif [ -f PRODUCT.md ]; then\n # PRODUCT.md exists — include developer-experience perspectives\nfi\n```\n\nWhen `PRODUCT.md` exists in the project root AND the user did NOT pass an explicit `--preset` override:\n1. Read `PRODUCT.md` content and include in the council packet via `context.files`\n2. Add a single consolidated `developer-experience` perspective to the council invocation:\n - **With spec:** `/council --preset=code-review --perspectives=\"developer-experience\" validate \u003ctarget>` (3 judges: 2 code-review + 1 DX)\n - **Without spec:** `/council --perspectives=\"developer-experience\" validate \u003ctarget>` (3 judges: 2 independent + 1 DX)\n The DX judge covers api-clarity, error-experience, and discoverability in a single review.\n3. With `--deep`: adds 1 more judge per mode (4 judges total).\n\nWhen `PRODUCT.md` exists BUT the user passed an explicit `--preset`: skip DX auto-include (user's explicit preset takes precedence).\n\nWhen `PRODUCT.md` does not exist: proceed to Step 3 unchanged.\n\n> **Tip:** Create `PRODUCT.md` from `docs/PRODUCT-TEMPLATE.md` to enable developer-experience-aware code review.\n\n### Step 3: Load the Spec (New)\n\n**Skip if `--quick` (see Step 1.5).**\n\nBefore invoking council, try to find the relevant spec/bead:\n\n1. **If target looks like a bead ID** (e.g., `na-0042`): `bd show \u003cid>` to get the spec\n2. **Search for plan doc:** `ls .agents/plans/ | grep \u003ctarget-keyword>`\n3. **Check git log:** `git log --oneline | head -10` to find the relevant bead reference\n\nIf a spec is found, include it in the council packet's `context.spec` field:\n```json\n{\n \"spec\": {\n \"source\": \"bead na-0042\",\n \"content\": \"\u003cthe spec/bead description text>\"\n }\n}\n```\n\n### Step 3.5: Load Suppressions\n\nBefore invoking council, load the default suppression list from `references/vibe-suppressions.md` and any project-level overrides from `.agents/vibe-suppressions.jsonl`. Suppressions are applied post-verdict to classify findings as CRITICAL vs INFORMATIONAL and to filter known false positives. See [references/vibe-suppressions.md](vibe-suppressions.md) for the full pattern list.\n\n### Step 3.6: Load Pre-Mortem Predictions (Correlation)\n\nWhen a pre-mortem report exists for the current epic, load prediction IDs for downstream correlation:\n\n```bash\n# Find the most recent pre-mortem report\nPM_REPORT=$(ls -t .agents/council/*pre-mortem*.md 2>/dev/null | head -1)\nif [ -n \"$PM_REPORT\" ]; then\n # Extract prediction IDs from frontmatter\n PREDICTION_IDS=$(sed -n '/^prediction_ids:/,/^[^ -]/p' \"$PM_REPORT\" | grep '^\\s*-' | sed 's/^\\s*- //')\nfi\n```\n\nFor each vibe finding, check if it matches a pre-mortem prediction:\n- **Match found:** Tag finding with `predicted_by: pm-YYYYMMDD-NNN`\n- **No match:** Tag finding with `predicted_by: none` (surprise issue)\n\nInclude the prediction correlation in the vibe report's findings table. This feeds the post-mortem's Prediction Accuracy section. Skip silently if no pre-mortem report exists.\n\n### Model Cost Tiers\n\nVibe passes the model cost tier through to council for all validation calls. Tier resolution:\n\n1. Explicit `--tier=\u003cname>` flag on `/vibe`\n2. Skill-specific config: `models.skill_overrides.vibe` in `.agentops/config.yaml`\n3. Global default: `models.default_tier` in `.agentops/config.yaml`\n4. Built-in default: `balanced`\n\n```yaml\n# Example: force quality tier for all vibe reviews\nmodels:\n skill_overrides:\n vibe: quality\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11494,"content_sha256":"6a5c17b3452cee808cba8372ae57432e99f17307ad3e3d1f88f54685d5f0bd62"},{"filename":"references/examples.md","content":"# /vibe Examples\n\n## Security Audit with Spec Compliance\n\n**User says:** `/vibe --preset=security-audit src/auth/`\n\n**What happens:**\n1. Agent searches for spec (checks `bd show`, `.agents/plans/`, git log)\n2. Agent runs complexity analysis (radon/gocyclo) on `src/auth/`\n3. Agent runs constraint tests (`internal/constraints/*_test.go`) if present\n4. Agent runs `codex review --uncommitted` for diff-focused review\n5. Agent invokes `/council --deep --preset=security-audit validate src/auth/` with spec in packet\n6. Spec found: 3 judges use security-audit personas + spec-compliance judge added (4 total)\n7. Report written to `.agents/council/\u003ctimestamp>-vibe-src-auth.md`\n\n**Result:** Security-focused review with attacker/defender/compliance perspectives and spec validation.\n\n## Developer-Experience Code Review (PRODUCT.md detected)\n\n**User says:** `/vibe recent`\n\n**What happens:**\n1. Agent detects `PRODUCT.md` in project root\n2. Agent searches for spec (found: bead na-0042)\n3. Agent runs complexity + constraint tests + codex review\n4. Agent invokes `/council --deep --preset=code-review --perspectives=\"api-clarity,error-experience,discoverability\" validate recent`\n5. Auto-escalation: 6 judges spawn (3 code-review + 3 DX perspectives)\n6. Judges review against spec + developer experience criteria\n\n**Result:** Code review augmented with API clarity, error messages, and discoverability checks.\n\n## Fast Inline Check (No Spawning)\n\n**User says:** `/vibe --quick recent`\n\n**What happens:**\n1. Agent runs complexity analysis inline (radon/gocyclo)\n2. Agent runs constraint tests and codex review\n3. Agent performs structured self-review using council schema (no subprocess spawning)\n4. Report written to `.agents/council/\u003ctimestamp>-vibe-recent.md` labeled `Mode: quick (single-agent)`\n\n**Result:** Sub-60s validation for routine pre-commit checks, no multi-agent overhead.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1883,"content_sha256":"6affcb5b27828830a50eca58503df51d1320a03665ae60a2dae515fd6b757d27"},{"filename":"references/go-patterns.md","content":"# Go Patterns Quick Reference - Vibe\n\nQuick reference for Go patterns. Copy-paste these examples when writing new code.\n\n---\n\n## Error Handling\n\n### ✅ Wrap Errors with %w\n\n```go\n// DO THIS\nif err != nil {\n return fmt.Errorf(\"failed to initialize: %w\", err)\n}\n\n// NOT THIS - Breaks error chains (triggers P14)\nif err != nil {\n return fmt.Errorf(\"failed to initialize: %v\", err)\n}\n```\n\n**Prescan:** P14 detects `%v` in `fmt.Errorf` when wrapping errors\n\n### ✅ Custom Error Creation\n\n```go\n// Define custom error type\ntype AppError struct {\n Code string\n Message string\n Cause error\n}\n\nfunc (e *AppError) Error() string {\n if e.Cause != nil {\n return fmt.Sprintf(\"[%s] %s: %v\", e.Code, e.Message, e.Cause)\n }\n return fmt.Sprintf(\"[%s] %s\", e.Code, e.Message)\n}\n\nfunc (e *AppError) Unwrap() error { return e.Cause }\n\nfunc (e *AppError) Is(target error) bool {\n t, ok := target.(*AppError)\n return ok && e.Code == t.Code\n}\n\n// Use with errors.Is() and errors.As()\nif errors.Is(err, &AppError{Code: \"NOT_FOUND\"}) {\n // Handle not found\n}\n\nvar appErr *AppError\nif errors.As(err, &appErr) {\n log.Printf(\"Error code: %s\", appErr.Code)\n}\n```\n\n### ✅ Document Intentional Error Ignores\n\n```go\n// DO THIS (passes P13)\ndefer func() {\n _ = conn.Close() // nolint:errcheck - best effort cleanup\n}()\n\n// NOT THIS (triggers P13)\ndefer func() {\n _ = conn.Close() // Silent ignore\n}()\n```\n\n**Prescan:** P13 detects `_ =` without `nolint:errcheck` comment\n\n---\n\n## Concurrency\n\n### ✅ Always Use context.Context\n\n```go\n// DO THIS\nfunc (c *Client) SendTask(ctx context.Context, task *Task) error {\n req, err := http.NewRequestWithContext(ctx, \"POST\", url, body)\n if err != nil {\n return fmt.Errorf(\"creating request: %w\", err)\n }\n // ...\n}\n\n// NOT THIS - No cancellation support\nfunc (c *Client) SendTask(task *Task) error {\n req, err := http.NewRequest(\"POST\", url, body)\n // ...\n}\n```\n\n### ✅ WaitGroup Pattern\n\n```go\nvar wg sync.WaitGroup\nfor name, agent := range agents {\n wg.Add(1)\n\n // CRITICAL: Capture loop variables\n name := name\n agent := agent\n\n go func() {\n defer wg.Done() // Always defer, protects against panic\n\n if err := agent.Process(ctx); err != nil {\n mu.Lock()\n results[name] = err\n mu.Unlock()\n }\n }()\n}\nwg.Wait()\n```\n\n**Common Mistake:** Forgetting to capture loop variables causes race conditions\n\n### ✅ Mutex for Shared State\n\n```go\ntype Registry struct {\n items map[string]Item\n mu sync.RWMutex // Read-write mutex\n}\n\n// Read operations use RLock (concurrent reads OK)\nfunc (r *Registry) Get(name string) (Item, error) {\n r.mu.RLock()\n defer r.mu.RUnlock()\n item, ok := r.items[name]\n if !ok {\n return Item{}, ErrNotFound\n }\n return item, nil\n}\n\n// Write operations use Lock (exclusive)\nfunc (r *Registry) Register(name string, item Item) error {\n r.mu.Lock()\n defer r.mu.Unlock()\n r.items[name] = item\n return nil\n}\n```\n\n### ✅ Backpressure in Channels\n\n```go\nselect {\ncase eventChan \u003c- event:\n // Event sent successfully\ncase \u003c-time.After(30 * time.Second):\n return fmt.Errorf(\"event channel blocked - consumer too slow\")\ncase \u003c-ctx.Done():\n return ctx.Err()\n}\n```\n\n**Why:** Prevents unbounded memory growth from fast producer, slow consumer\n\n---\n\n## Security\n\n### ✅ Constant-Time Comparison\n\n```go\nimport \"crypto/subtle\"\n\n// DO THIS - Timing attack resistant\nif subtle.ConstantTimeCompare([]byte(token), []byte(expectedToken)) != 1 {\n return ErrUnauthorized\n}\n\n// NOT THIS - Vulnerable to timing attacks\nif token == expectedToken {\n // Attacker can brute-force byte-by-byte\n}\n```\n\n**Use Cases:** API keys, tokens, passwords, secrets\n\n### ✅ HMAC Signature Validation\n\n```go\nimport (\n \"crypto/hmac\"\n \"crypto/sha256\"\n \"encoding/hex\"\n)\n\nfunc validateHMAC(payload []byte, signature, secret string) bool {\n expectedMAC := hmac.New(sha256.New, []byte(secret))\n expectedMAC.Write(payload)\n expected := hex.EncodeToString(expectedMAC.Sum(nil))\n\n // Use constant-time comparison\n return hmac.Equal([]byte(expected), []byte(signature))\n}\n```\n\n**Use Cases:** Webhook signatures (GitHub, GitLab, Slack)\n\n### ✅ Timestamp Validation (Replay Attack Prevention)\n\n```go\nfunc validateTimestamp(ts string, maxAge time.Duration) error {\n timestamp, err := time.Parse(time.RFC3339, ts)\n if err != nil {\n return fmt.Errorf(\"invalid timestamp: %w\", err)\n }\n\n age := time.Since(timestamp)\n if age > maxAge {\n return fmt.Errorf(\"timestamp too old: %v > %v\", age, maxAge)\n }\n if age \u003c -1*time.Minute {\n return fmt.Errorf(\"timestamp in future: %v\", age)\n }\n\n return nil\n}\n```\n\n**Typical maxAge:** 5 minutes for webhooks, 1 minute for API requests\n\n---\n\n## HTTP Clients\n\n### ✅ Proper Body Handling\n\n```go\nresp, err := client.Do(req)\nif err != nil {\n return fmt.Errorf(\"request failed: %w\", err)\n}\ndefer func() {\n if err := resp.Body.Close(); err != nil {\n log.Printf(\"Failed to close response body: %v\", err)\n }\n}()\n\nbody, err := io.ReadAll(resp.Body)\nif err != nil {\n return fmt.Errorf(\"reading response: %w\", err)\n}\n```\n\n**CRITICAL:** Always close response body, even on error paths\n\n### ✅ Retry Logic with Exponential Backoff\n\n```go\nfunc (c *Client) doWithRetry(ctx context.Context, req *http.Request) (*http.Response, error) {\n var lastErr error\n\n for attempt := 0; attempt \u003c c.maxRetries; attempt++ {\n if attempt > 0 {\n backoff := time.Duration(math.Pow(2, float64(attempt))) * time.Second\n select {\n case \u003c-time.After(backoff):\n case \u003c-ctx.Done():\n return nil, ctx.Err()\n }\n }\n\n resp, err := c.httpClient.Do(req)\n if err != nil {\n lastErr = err\n continue\n }\n\n // Retry on 5xx\n if resp.StatusCode >= 500 {\n _ = resp.Body.Close() // nolint:errcheck - best effort\n lastErr = fmt.Errorf(\"server error: %d\", resp.StatusCode)\n continue\n }\n\n return resp, nil\n }\n\n return nil, fmt.Errorf(\"max retries exceeded: %w\", lastErr)\n}\n```\n\n---\n\n## Interface Design\n\n### ✅ Accept Interfaces, Return Structs\n\n```go\n// Define interface\ntype Processor interface {\n Process(ctx context.Context, data []byte) error\n}\n\n// Functions accept interface (flexible for testing)\nfunc RunPipeline(ctx context.Context, processor Processor, data []byte) error {\n if err := processor.Process(ctx, data); err != nil {\n return fmt.Errorf(\"processing failed: %w\", err)\n }\n return nil\n}\n\n// Constructors return struct (concrete)\nfunc NewDataProcessor() *DataProcessor {\n return &DataProcessor{\n cache: make(map[string][]byte),\n mu: sync.RWMutex{},\n }\n}\n```\n\n**Why:** Callers can pass any implementation (testability), return type can add methods\n\n### ✅ Small, Focused Interfaces\n\n```go\n// DO THIS - Single responsibility\ntype Initializer interface {\n Initialize(ctx context.Context) error\n}\n\ntype Processor interface {\n Process(ctx context.Context, data []byte) error\n}\n\n// Compose when needed\ntype Service interface {\n Initializer\n Processor\n}\n\n// NOT THIS - God interface\ntype Service interface {\n Initialize(ctx context.Context) error\n Process(ctx context.Context, data []byte) error\n Shutdown(ctx context.Context) error\n HealthCheck(ctx context.Context) error\n GetMetrics() *Metrics\n SetConfig(cfg *Config)\n // ... 20 more methods\n}\n```\n\n---\n\n## Testing\n\n### ✅ Table-Driven Tests\n\n```go\nfunc TestValidateEmail(t *testing.T) {\n tests := []struct {\n name string\n email string\n wantErr bool\n }{\n {\"valid\", \"[email protected]\", false},\n {\"missing @\", \"userexample.com\", true},\n {\"empty\", \"\", true},\n {\"no domain\", \"user@\", true},\n }\n\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n err := ValidateEmail(tt.email)\n if (err != nil) != tt.wantErr {\n t.Errorf(\"ValidateEmail(%q) error = %v, wantErr %v\",\n tt.email, err, tt.wantErr)\n }\n })\n }\n}\n```\n\n### ✅ Test Helpers\n\n```go\nfunc setupTestServer(t *testing.T) *httptest.Server {\n t.Helper() // Mark as helper - failures report caller line\n\n server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n // Mock responses\n }))\n\n t.Cleanup(func() {\n server.Close()\n })\n\n return server\n}\n\nfunc TestClient(t *testing.T) {\n server := setupTestServer(t) // Failures report this line, not inside helper\n client := NewClient(server.URL)\n // ... test code\n}\n```\n\n### ✅ Mock Interfaces\n\n```go\n// Define mockable interface\ntype Repository interface {\n GetUser(ctx context.Context, id string) (*User, error)\n}\n\n// Create mock\ntype MockRepository struct {\n GetUserFn func(ctx context.Context, id string) (*User, error)\n}\n\nfunc (m *MockRepository) GetUser(ctx context.Context, id string) (*User, error) {\n if m.GetUserFn != nil {\n return m.GetUserFn(ctx, id)\n }\n return nil, nil\n}\n\n// Use in tests\nfunc TestService(t *testing.T) {\n mock := &MockRepository{\n GetUserFn: func(ctx context.Context, id string) (*User, error) {\n return &User{ID: id, Name: \"Test\"}, nil\n },\n }\n\n service := NewService(mock)\n user, err := service.FetchUser(ctx, \"123\")\n if err != nil {\n t.Fatalf(\"unexpected error: %v\", err)\n }\n if user.Name != \"Test\" {\n t.Errorf(\"got name %q, want %q\", user.Name, \"Test\")\n }\n}\n```\n\n---\n\n## Common Mistakes to Avoid\n\n### ❌ Don't: Ignore Context\n\n```go\n// BAD\nfunc (c *Client) Send(req *Request) error {\n // No way to cancel or timeout\n return c.process(req)\n}\n\n// GOOD\nfunc (c *Client) Send(ctx context.Context, req *Request) error {\n select {\n case result := \u003c-c.process(req):\n return result\n case \u003c-ctx.Done():\n return ctx.Err()\n }\n}\n```\n\n### ❌ Don't: Use Pointer to Interface\n\n```go\n// BAD\nfunc Process(agent *Agent) error { // Interface is already a reference\n // ...\n}\n\n// GOOD\nfunc Process(agent Agent) error {\n // ...\n}\n```\n\n### ❌ Don't: Naked Returns with Named Results\n\n```go\n// BAD\nfunc calculate() (result int, err error) {\n result = 42\n return // What's being returned? Unclear!\n}\n\n// GOOD\nfunc calculate() (int, error) {\n result := 42\n return result, nil // Explicit and clear\n}\n```\n\n### ❌ Don't: Use panic in Library Code\n\n```go\n// BAD\nfunc GetItem(key string) Item {\n item, ok := registry[key]\n if !ok {\n panic(\"item not found\") // Caller can't recover\n }\n return item\n}\n\n// GOOD\nfunc GetItem(key string) (Item, error) {\n item, ok := registry[key]\n if !ok {\n return Item{}, ErrItemNotFound\n }\n return item, nil\n}\n```\n\n### ❌ Don't: Forget to Capture Loop Variables\n\n```go\n// BAD\nfor _, item := range items {\n go func() {\n process(item) // Race condition! All goroutines see last item\n }()\n}\n\n// GOOD\nfor _, item := range items {\n item := item // Capture variable\n go func() {\n process(item) // Each goroutine has its own copy\n }()\n}\n```\n\n### ❌ Don't: Leak Goroutines\n\n```go\n// BAD - Goroutine never exits\ngo func() {\n for {\n work() // No way to stop\n }\n}()\n\n// GOOD - Context-based cancellation\ngo func() {\n for {\n select {\n case \u003c-ctx.Done():\n return\n default:\n work()\n }\n }\n}()\n```\n\n---\n\n## Code Review Checklist\n\nBefore submitting PR, verify:\n\n- [ ] All errors wrapped with `%w` (P14 passing)\n- [ ] All long operations accept `context.Context`\n- [ ] All `defer` statements have error checking where needed\n- [ ] Loop variables captured before goroutines\n- [ ] HTTP response bodies closed with defer\n- [ ] Secrets compared with `subtle.ConstantTimeCompare()`\n- [ ] Intentional error ignores documented with `nolint:errcheck` (P13 passing)\n- [ ] Tests use table-driven pattern\n- [ ] Test helpers use `t.Helper()`\n- [ ] Interfaces are small and focused\n- [ ] Functions return concrete types (not interfaces)\n- [ ] golangci-lint passes (P15)\n- [ ] gofmt applied\n- [ ] Complexity \u003c 10 per function\n\n---\n\n## golangci-lint Commands\n\n```bash\n# Run all linters\ngolangci-lint run ./...\n\n# Run specific linter\ngolangci-lint run --enable=errcheck ./...\n\n# Fix auto-fixable issues\ngolangci-lint run --fix ./...\n\n# Show configuration\ngolangci-lint linters\n```\n\n---\n\n## Useful Commands\n\n```bash\n# Format code\ngofmt -w .\n\n# Check formatting\ngofmt -l .\n\n# Vet code\ngo vet ./...\n\n# Run tests\ngo test ./...\n\n# Run tests with coverage\ngo test -coverprofile=coverage.out ./...\ngo tool cover -html=coverage.out\n\n# Check for race conditions\ngo test -race ./...\n\n# Build all binaries\ngo build ./cmd/...\n\n# Tidy dependencies\ngo mod tidy\n\n# Check cyclomatic complexity\ngocyclo -over 10 .\n```\n\n---\n\n## Prescan Pattern Reference\n\n| Pattern | Severity | Triggers On |\n|---------|----------|-------------|\n| P13 | HIGH | `_ =` without `nolint:errcheck` comment |\n| P14 | MEDIUM | `fmt.Errorf.*%v` when wrapping errors |\n| P15 | HIGH | golangci-lint violations (requires golangci-lint installed) |\n\nRun prescan: `~/.claude/skills/vibe/scripts/prescan.sh recent`\n\n---\n\n## Additional Resources\n\n- [Effective Go](https://go.dev/doc/effective_go)\n- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)\n- [Go Proverbs](https://go-proverbs.github.io/)\n- [golangci-lint Linters](https://golangci-lint.run/usage/linters/)\n- [errcheck](https://github.com/kisielk/errcheck)\n\n---\n\n**See Also:** `go-standards.md` for comprehensive catalog with detailed explanations\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13788,"content_sha256":"51a007e2dccdd09c5d598b8cdcd61d467d3538bf0188ec6d448b1d9fa7e1cf40"},{"filename":"references/go-standards.md","content":"# Go Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-20\n**Purpose:** Canonical Go standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [Error Handling Patterns](#error-handling-patterns)\n2. [Interface Design](#interface-design)\n3. [Concurrency Patterns](#concurrency-patterns)\n4. [Security Practices](#security-practices)\n5. [Package Organization](#package-organization)\n6. [Testing Patterns](#testing-patterns)\n7. [Documentation Standards](#documentation-standards)\n8. [Code Quality Metrics](#code-quality-metrics)\n9. [Anti-Patterns Avoided](#anti-patterns-avoided)\n\n---\n\n## Error Handling Patterns\n\n### ✅ **Custom Error Types**\n\nProduction-grade error types follow these patterns:\n\n```go\ntype AppError struct {\n Code string // Machine-readable error code\n Message string // Human-readable message\n Cause error // Wrapped error (optional)\n Metadata map[string]any // Additional context\n}\n\n// Implements error interface\nfunc (e *AppError) Error() string {\n if e.Cause != nil {\n return fmt.Sprintf(\"[%s] %s: %v\", e.Code, e.Message, e.Cause)\n }\n return fmt.Sprintf(\"[%s] %s\", e.Code, e.Message)\n}\n\n// Supports errors.Unwrap()\nfunc (e *AppError) Unwrap() error {\n return e.Cause\n}\n\n// Supports errors.Is() for sentinel comparison\nfunc (e *AppError) Is(target error) bool {\n t, ok := target.(*AppError)\n if !ok {\n return false\n }\n return e.Code == t.Code\n}\n```\n\n**Requirements:**\n- ✅ Implements `error` interface\n- ✅ Implements `Unwrap()` for error chain inspection\n- ✅ Implements `Is()` for sentinel error comparison\n- ✅ Structured error codes enable programmatic handling\n- ✅ Preserves context with metadata\n- ✅ Proper nil-safety in `Unwrap()` and `Is()`\n\n### ✅ **Error Wrapping with %w**\n\nUse `fmt.Errorf` with `%w` verb for error wrapping:\n\n```go\n// CORRECT\nresp, err := client.Do(req)\nif err != nil {\n return nil, fmt.Errorf(\"sending request: %w\", err)\n}\n\n// INCORRECT - Breaks error chains\nif err != nil {\n return nil, fmt.Errorf(\"sending request: %v\", err)\n}\n```\n\n**Why This Matters:**\n- `%w` preserves error chain for `errors.Is()` and `errors.As()`\n- `%v` breaks the chain - root cause is lost\n- Error context adds debugging information\n\n### ⚠️ **Intentional Error Ignores**\n\nDocument why errors are intentionally ignored:\n\n```go\n// CORRECT\ndefer func() {\n _ = conn.Close() // nolint:errcheck - best effort cleanup\n}()\n\n// INCORRECT - Silent ignore\ndefer func() {\n _ = conn.Close()\n}()\n```\n\n**Validation:** Prescan pattern P13 detects undocumented ignores\n\n---\n\n## Interface Design\n\n### ✅ **Accept Interfaces, Return Structs**\n\n**Pattern:**\n```go\n// Define interface\ntype Agent interface {\n Initialize(ctx context.Context) error\n Invoke(ctx context.Context, req *Request) (*Response, error)\n}\n\n// Functions accept interface (flexible)\nfunc ProcessAgent(ctx context.Context, agent Agent) error {\n if err := agent.Initialize(ctx); err != nil {\n return fmt.Errorf(\"initialization failed: %w\", err)\n }\n // ...\n}\n\n// Constructors return struct (concrete)\nfunc NewRegistry() *Registry {\n return &Registry{\n agents: make(map[string]Agent),\n mu: sync.RWMutex{},\n }\n}\n```\n\n**Why This Matters:**\n- Callers can pass any implementation (testability)\n- Return type can add methods without breaking callers\n- Follows Go proverb: \"Be conservative in what you send, liberal in what you accept\"\n\n### ✅ **Small, Focused Interfaces**\n\n**Good Example:**\n```go\ntype Initializer interface {\n Initialize(ctx context.Context) error\n}\n\ntype Invoker interface {\n Invoke(ctx context.Context, req *Request) (*Response, error)\n}\n\n// Compose interfaces\ntype Agent interface {\n Initializer\n Invoker\n}\n```\n\n**Anti-Pattern (God Interface):**\n```go\ntype Agent interface {\n Initialize(ctx context.Context) error\n Invoke(ctx context.Context, req *Request) (*Response, error)\n Shutdown(ctx context.Context) error\n HealthCheck(ctx context.Context) error\n GetMetrics() *Metrics\n SetConfig(cfg *Config)\n // ... 20 more methods\n}\n```\n\n---\n\n## Concurrency Patterns\n\n### ✅ **Context Propagation** (Required)\n\nEvery I/O or long-running operation accepts `context.Context`:\n\n```go\n// HTTP Requests\nreq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body)\n\n// Database Operations\nrows, err := db.QueryContext(ctx, query)\n\n// Custom Functions\nfunc (c *Client) Invoke(ctx context.Context, req *Request) (*Response, error)\n```\n\n**Benefits:**\n- Timeout propagation\n- Cancellation support\n- Request-scoped values (tracing)\n\n### ✅ **Proper WaitGroup Usage**\n\n```go\nvar wg sync.WaitGroup\nfor name, agent := range agents {\n wg.Add(1)\n\n // Capture loop variables\n name := name\n agent := agent\n\n go func() {\n defer wg.Done() // Always defer, protects against panic\n\n if err := agent.Process(ctx); err != nil {\n mu.Lock()\n results[name] = err\n mu.Unlock()\n }\n }()\n}\nwg.Wait()\n```\n\n**Requirements:**\n- ✅ Variables captured before goroutine (avoids closure bug)\n- ✅ `defer wg.Done()` ensures decrement on panic\n- ✅ Mutex protects shared data structures\n- ✅ Context cancellation checked in each goroutine\n\n### ✅ **Thread-Safe Data Structures**\n\n```go\ntype Registry struct {\n items map[string]Item\n mu sync.RWMutex // Read-write mutex\n}\n\n// Read operations use RLock\nfunc (r *Registry) Get(key string) (Item, error) {\n r.mu.RLock()\n defer r.mu.RUnlock()\n // ...\n}\n\n// Write operations use Lock\nfunc (r *Registry) Set(key string, item Item) error {\n r.mu.Lock()\n defer r.mu.Unlock()\n // ...\n}\n```\n\n**Pattern Benefits:**\n- Multiple concurrent reads\n- Exclusive writes\n- Zero race conditions\n\n### ✅ **Backpressure in Streaming**\n\n```go\nselect {\ncase eventChan \u003c- event:\n // Event sent successfully\ncase \u003c-time.After(30 * time.Second):\n return fmt.Errorf(\"event channel blocked - consumer too slow (backpressure triggered)\")\ncase \u003c-ctx.Done():\n return ctx.Err()\n}\n```\n\n**Why This Matters:**\n- Prevents unbounded memory growth\n- Handles fast producer, slow consumer scenario\n- Explicit timeout for debugging\n\n---\n\n## Security Practices\n\n### ✅ **Constant-Time Comparison** (Timing Attack Prevention)\n\n```go\nimport \"crypto/subtle\"\n\n// CORRECT - Timing attack resistant\ntoken := r.Header.Get(\"Authorization\")\nif subtle.ConstantTimeCompare([]byte(token), []byte(expectedToken)) != 1 {\n return ErrUnauthorized\n}\n\n// INCORRECT - Vulnerable to timing attacks\nif token == expectedToken {\n // Attacker can brute-force byte-by-byte\n}\n```\n\n**Why This Matters:**\n- String comparison (`==`) leaks timing information\n- Attacker can brute-force secrets byte-by-byte\n- `subtle.ConstantTimeCompare()` runs in constant time\n- Critical for API keys, tokens, passwords\n\n### ✅ **HMAC Signature Validation**\n\n```go\nimport (\n \"crypto/hmac\"\n \"crypto/sha256\"\n \"encoding/hex\"\n)\n\nfunc validateHMAC(payload []byte, signature, secret string) bool {\n if !strings.HasPrefix(signature, \"sha256=\") {\n return false\n }\n\n expectedMAC := hmac.New(sha256.New, []byte(secret))\n expectedMAC.Write(payload)\n expected := \"sha256=\" + hex.EncodeToString(expectedMAC.Sum(nil))\n\n return hmac.Equal([]byte(expected), []byte(signature))\n}\n```\n\n**Security Features:**\n- ✅ HMAC prevents payload tampering\n- ✅ Uses `hmac.Equal()` (constant-time)\n- ✅ Verifies signature format first\n- ✅ SHA-256 (secure hash function)\n\n### ✅ **Replay Attack Prevention**\n\n```go\nfunc validateTimestamp(timestamp string, maxAge time.Duration) error {\n ts, err := time.Parse(time.RFC3339, timestamp)\n if err != nil {\n return fmt.Errorf(\"invalid timestamp format\")\n }\n\n age := time.Since(ts)\n if age > maxAge || age \u003c -1*time.Minute {\n return fmt.Errorf(\"request too old or in future: age=%v max=%v\", age, maxAge)\n }\n\n return nil\n}\n```\n\n**Protection Against:**\n- Replay attacks (old requests resubmitted)\n- Clock skew (1 minute tolerance for future timestamps)\n- DoS via timestamp manipulation\n\n### ✅ **TLS Configuration**\n\n```go\ntlsConfig := &tls.Config{\n MinVersion: tls.VersionTLS13, // Only TLS 1.3+\n // No InsecureSkipVerify - validates certificates\n}\n```\n\n---\n\n## Package Organization\n\n### ✅ **Layered Architecture**\n\n```\nproject/\n├── cmd/ # Binaries (main packages)\n│ ├── server/ # Server binary\n│ ├── worker/ # Worker binary\n│ └── cli/ # CLI tool\n├── internal/ # Private packages (cannot be imported externally)\n│ ├── domain/ # Business logic\n│ ├── handlers/ # HTTP handlers\n│ ├── repository/ # Data access\n│ └── sdk/ # External SDK clients\n├── pkg/ # Public packages (can be imported)\n│ ├── api/ # API types\n│ └── client/ # Client library\n└── tests/ # Test suites\n ├── e2e/ # End-to-end tests\n └── integration/ # Integration tests\n```\n\n**Principles:**\n- ✅ `cmd/` for binaries (no importable code)\n- ✅ `internal/` prevents external imports\n- ✅ `pkg/` for public APIs\n- ✅ Domain-driven structure\n- ✅ Tests at package level, e2e/integration separate\n\n### ✅ **Import Grouping** (Go Convention)\n\n```go\nimport (\n // Standard library\n \"context\"\n \"fmt\"\n \"time\"\n\n // External dependencies\n \"github.com/external/package\"\n\n // Internal packages\n \"myproject.com/internal/domain\"\n)\n```\n\n---\n\n## Testing Patterns\n\n### ✅ **Table-Driven Tests**\n\n```go\nfunc TestValidateEmail(t *testing.T) {\n tests := []struct {\n name string\n email string\n wantErr bool\n }{\n {\"valid\", \"[email protected]\", false},\n {\"missing @\", \"userexample.com\", true},\n {\"empty\", \"\", true},\n {\"no domain\", \"user@\", true},\n }\n\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n err := ValidateEmail(tt.email)\n if (err != nil) != tt.wantErr {\n t.Errorf(\"ValidateEmail(%q) error = %v, wantErr %v\",\n tt.email, err, tt.wantErr)\n }\n })\n }\n}\n```\n\n**Benefits:**\n- Easy to add test cases\n- Clear test names with `t.Run()`\n- DRY (Don't Repeat Yourself)\n\n### ✅ **Test Helpers with t.Helper()**\n\n```go\nfunc setupTestServer(t *testing.T) *httptest.Server {\n t.Helper() // Marks this as a helper function\n\n server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n // Mock responses\n }))\n\n t.Cleanup(func() {\n server.Close()\n })\n\n return server\n}\n\nfunc TestClient(t *testing.T) {\n server := setupTestServer(t) // Failures report this line, not inside helper\n // ... test code\n}\n```\n\n**Why t.Helper() Matters:**\n- Test failures report the *calling* line, not helper line\n- Makes test output more useful\n- Standard Go testing pattern\n\n### ✅ **Mock Interfaces**\n\n```go\n// Define mockable interface\ntype Invoker interface {\n Invoke(ctx context.Context, req *Request) (*Response, error)\n}\n\n// Create mock\ntype MockInvoker struct {\n InvokeFn func(ctx context.Context, req *Request) (*Response, error)\n}\n\nfunc (m *MockInvoker) Invoke(ctx context.Context, req *Request) (*Response, error) {\n if m.InvokeFn != nil {\n return m.InvokeFn(ctx, req)\n }\n return nil, nil\n}\n\n// Use in tests\nfunc TestProcessor(t *testing.T) {\n mock := &MockInvoker{\n InvokeFn: func(ctx context.Context, req *Request) (*Response, error) {\n return &Response{Status: \"success\"}, nil\n },\n }\n\n processor := NewProcessor(mock)\n // ... test with mock\n}\n```\n\n### Test Double Types\n\n| Type | Purpose | When to Use |\n|------|---------|-------------|\n| **Stub** | Returns canned data | Simple happy path |\n| **Mock** | Verifies interactions | Behavior verification |\n| **Fake** | Working implementation | Integration-like tests |\n| **Spy** | Records calls | Interaction counting |\n\n---\n\n## Documentation Standards\n\n### ✅ **Godoc Format**\n\nDocument all exported symbols with a comment directly above the declaration:\n\n```go\n// Registry manages agent lifecycle and discovery.\n// It is safe for concurrent use.\ntype Registry struct {\n agents map[string]Agent\n mu sync.RWMutex\n}\n\n// Get returns the agent registered under the given key.\n// It returns ErrNotFound if no agent is registered with that key.\nfunc (r *Registry) Get(key string) (Agent, error) {\n // ...\n}\n```\n\n**Rules:**\n- Comment starts with the name of the symbol\n- First sentence is a complete summary (used by `go doc -short`)\n- Use `//` comments, not `/* */` blocks (except for package-level docs)\n\n### ✅ **Package-Level Comments**\n\nFor packages with significant public API, use a `doc.go` file:\n\n```go\n// Package registry provides agent lifecycle management\n// including registration, discovery, and health monitoring.\n//\n// Basic usage:\n//\n//\treg := registry.New()\n//\treg.Register(\"my-agent\", agent)\n//\ta, err := reg.Get(\"my-agent\")\npackage registry\n```\n\n**When to use `doc.go`:**\n- Package has 3+ exported symbols\n- Package is part of a public API (`pkg/`)\n- Package needs usage examples beyond a single line\n\n### ✅ **Testable Examples**\n\nWrite `Example*` functions in `_test.go` files — they appear in generated docs and are compiled/run by `go test`:\n\n```go\nfunc ExampleRegistry_Get() {\n reg := registry.New()\n reg.Register(\"agent-1\", &MyAgent{Name: \"alpha\"})\n\n agent, err := reg.Get(\"agent-1\")\n if err != nil {\n log.Fatal(err)\n }\n fmt.Println(agent.Name)\n // Output: alpha\n}\n```\n\n**Naming Convention:**\n- `ExampleTypeName` — type-level example\n- `ExampleTypeName_MethodName` — method-level example\n- `Example` — package-level example\n\n### ✅ **Doc Generation**\n\n```bash\n# View docs in terminal\ngo doc ./pkg/registry\ngo doc ./pkg/registry.Registry.Get\n\n# Run local doc server (pkgsite)\ngo install golang.org/x/pkgsite/cmd/pkgsite@latest\npkgsite -open .\n```\n\n### ✅ **Interface Documentation**\n\nInterfaces define contracts — document the behavioral expectations, not just the signature:\n\n```go\n// Store persists agent state across restarts.\n//\n// Implementations must be safe for concurrent use.\n// All methods must respect context cancellation.\ntype Store interface {\n // Save persists the agent. It returns ErrConflict if the agent\n // was modified since it was last read (optimistic locking).\n Save(ctx context.Context, agent *Agent) error\n\n // Load retrieves an agent by ID. It returns ErrNotFound if\n // no agent exists with the given ID.\n Load(ctx context.Context, id string) (*Agent, error)\n}\n```\n\n**Guidelines:**\n- Document concurrency guarantees on the interface comment\n- Document error contracts on each method (which sentinel errors are returned)\n- Document preconditions and postconditions when non-obvious\n\n### ✅ **Internal Package Documentation**\n\n`internal/` packages cannot be imported outside the module, but still need documentation for team maintainability:\n\n```go\n// Package repository implements data access for agent storage.\n//\n// This is an internal package — it should not be imported outside\n// the module. Use pkg/client for the public API.\npackage repository\n```\n\n**Guidelines:**\n- Every `internal/` package needs a package comment explaining its role\n- Note the public alternative if one exists (e.g., `pkg/client`)\n- Document non-obvious design constraints (e.g., \"not safe for concurrent use\")\n\n### ✅ **Package README Files**\n\nFor packages with significant scope, include a `README.md` alongside the Go source:\n\n```\npkg/registry/\n├── README.md # Setup instructions, architecture notes\n├── doc.go # Godoc package comment\n├── registry.go # Implementation\n└── registry_test.go # Tests with examples\n```\n\n**When to include a README:**\n- Package requires setup steps (config, env vars, migrations)\n- Package has architecture or design decisions worth explaining\n- Package is a top-level entry point (`cmd/`, major `pkg/` packages)\n\n**README vs doc.go:**\n- `doc.go` → API usage shown in `go doc` output\n- `README.md` → Setup, architecture, diagrams, non-API context\n\n### ✅ **Comment Style**\n\nFollow Go's documentation conventions for consistent, tooling-friendly comments:\n\n```go\n// ProcessBatch sends all queued events to the remote collector.\n// It returns the number of events successfully delivered and\n// a non-nil error if the connection to the collector fails.\n//\n// ProcessBatch is safe for concurrent use. Each call acquires\n// a connection from the pool and releases it on return.\nfunc (c *Client) ProcessBatch(ctx context.Context) (int, error) {\n // ...\n}\n\n// ErrRateLimited is returned when the collector rejects a request\n// due to rate limiting. Callers should back off and retry.\nvar ErrRateLimited = errors.New(\"rate limited\")\n```\n\n**Rules:**\n- Write complete sentences with proper punctuation\n- First word is the name of the declared thing (`ProcessBatch sends...`, `ErrRateLimited is...`)\n- First sentence stands alone as a summary — `go doc -short` shows only this\n- Use third-person declarative (\"ProcessBatch sends...\") not imperative (\"Send...\")\n- Separate paragraphs with a blank `//` line\n- Use `[Registry.Get]` syntax (Go 1.19+) to link to other symbols in doc comments\n- Keep line length under 80 characters for readability in terminals\n\n**Anti-Patterns:**\n```go\n// BAD - Doesn't start with symbol name\n// This function processes a batch of events.\nfunc (c *Client) ProcessBatch(ctx context.Context) (int, error)\n\n// BAD - Not a complete sentence\n// process batch\nfunc (c *Client) ProcessBatch(ctx context.Context) (int, error)\n\n// BAD - Imperative instead of declarative\n// Send all queued events to the remote collector.\nfunc (c *Client) ProcessBatch(ctx context.Context) (int, error)\n```\n\n### ALWAYS / NEVER Rules\n\n| Rule | Rationale |\n|------|-----------|\n| **ALWAYS** document exported types, functions, and methods | Required by `revive` linter, enables `go doc` |\n| **ALWAYS** start doc comments with the symbol name | Standard godoc convention, enables tooling |\n| **ALWAYS** write doc comments as complete sentences | Consistent style, readable in `go doc` output |\n| **ALWAYS** include `// Output:` in Example functions | Makes examples testable by `go test` |\n| **ALWAYS** document interface contracts (thread-safety, errors, lifecycle) | Callers depend on the contract, not the implementation |\n| **NEVER** document unexported symbols unless logic is non-obvious | Noise — internal code changes frequently |\n| **NEVER** use `@param` / `@return` javadoc-style annotations | Not idiomatic Go — godoc ignores them |\n| **NEVER** duplicate the function signature in prose | Redundant — the signature is right below |\n| **NEVER** use imperative voice in doc comments | Go convention is declarative third-person |\n\n---\n\n## Structured Logging (slog)\n\n### ✅ **Use log/slog (Go 1.21+)**\n\n```go\nimport \"log/slog\"\n\nfunc main() {\n // Production: JSON handler for log aggregation\n logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{\n Level: slog.LevelInfo,\n }))\n slog.SetDefault(logger)\n\n // Include correlation IDs for tracing\n slog.Info(\"request processed\",\n \"request_id\", reqID,\n \"user_id\", userID,\n \"duration_ms\", duration.Milliseconds(),\n )\n}\n```\n\n### Handler Selection\n\n| Environment | Handler | Use Case |\n|-------------|---------|----------|\n| Production | `slog.JSONHandler` | Elasticsearch, Loki, CloudWatch |\n| Development | `slog.TextHandler` | Human-readable console output |\n\n### ❌ **Logging Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| `fmt.Println` in library | Not parseable, no levels | Use `slog.Info` |\n| `log.Printf` | No structure | Use `slog` with attributes |\n| Logging secrets | Security risk | Use `ReplaceAttr` to redact |\n| Missing correlation ID | Can't trace requests | Always include request_id |\n\n> **Talos check:** PRE-007 detects `fmt.Print*` debug statements in non-CLI code.\n\n---\n\n## Benchmarking and Profiling\n\n### ✅ **Writing Benchmarks**\n\n```go\nfunc BenchmarkProcess(b *testing.B) {\n data := setupTestData()\n b.ResetTimer() // Exclude setup from timing\n\n for i := 0; i \u003c b.N; i++ {\n Process(data)\n }\n}\n\n// Memory allocation benchmark\nfunc BenchmarkProcessAllocs(b *testing.B) {\n data := setupTestData()\n b.ResetTimer()\n b.ReportAllocs()\n for i := 0; i \u003c b.N; i++ {\n Process(data)\n }\n}\n```\n\n### Running Benchmarks\n\n```bash\n# Run benchmarks\ngo test -bench=. -benchmem ./...\n\n# Compare before/after\ngo test -bench=. -count=10 > old.txt\n# make changes\ngo test -bench=. -count=10 > new.txt\nbenchstat old.txt new.txt\n```\n\n### ✅ **Profiling with pprof**\n\n```go\nimport _ \"net/http/pprof\"\n\n// Profiles available at:\n// /debug/pprof/profile - CPU profile\n// /debug/pprof/heap - Memory profile\n// /debug/pprof/goroutine - Goroutine stacks\n```\n\n**Analyze Profiles:**\n```bash\n# CPU profile (30 seconds)\ngo tool pprof http://localhost:6060/debug/pprof/profile?seconds=30\n\n# Memory profile\ngo tool pprof http://localhost:6060/debug/pprof/heap\n\n# Interactive commands\n(pprof) top10 # Top 10 functions\n(pprof) web # Open flame graph in browser\n```\n\n---\n\n## Configuration Management\n\n### ✅ **Single Config Struct Pattern**\n\n```go\ntype Config struct {\n Server ServerConfig `yaml:\"server\"`\n Database DatabaseConfig `yaml:\"database\"`\n Log LogConfig `yaml:\"log\"`\n}\n\ntype ServerConfig struct {\n Port int `yaml:\"port\" env:\"PORT\"`\n ReadTimeout time.Duration `yaml:\"read_timeout\"`\n WriteTimeout time.Duration `yaml:\"write_timeout\"`\n}\n\n// Load with precedence: flags > env > file > defaults\nfunc Load() (*Config, error) {\n cfg := &Config{}\n setDefaults(cfg)\n if err := loadFromFile(cfg); err != nil {\n return nil, fmt.Errorf(\"load config file: %w\", err)\n }\n loadFromEnv(cfg)\n if err := cfg.Validate(); err != nil {\n return nil, fmt.Errorf(\"validate config: %w\", err)\n }\n return cfg, nil\n}\n```\n\n### ❌ **Configuration Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| Global config var | Hard to test | Pass as dependency |\n| Reading env in functions | Scattered config | Centralize in Load() |\n| No validation | Runtime errors | Validate at startup |\n| Secrets in config files | Security risk | Use env vars or vault |\n\n---\n\n## HTTP API Standards\n\n### ✅ **API Versioning**\n\n```go\nmux := http.NewServeMux()\n\n// Health endpoints (unversioned - K8s standard)\nmux.HandleFunc(\"/health\", healthHandler)\nmux.HandleFunc(\"/healthz\", healthHandler) // K8s liveness\nmux.HandleFunc(\"/readyz\", readyHandler) // K8s readiness\n\n// API v1\nmux.HandleFunc(\"/v1/webhook/gitlab\", handler.ServeHTTP)\n\n// API documentation\nmux.HandleFunc(\"/openapi.json\", openAPIHandler)\n```\n\n### ✅ **Health Endpoints**\n\n```go\nfunc healthHandler(w http.ResponseWriter, r *http.Request) {\n w.Header().Set(\"Content-Type\", \"application/json\")\n w.WriteHeader(http.StatusOK)\n w.Write([]byte(`{\"status\":\"healthy\"}`))\n}\n\nfunc readyHandler(w http.ResponseWriter, r *http.Request) {\n if !dependenciesReady() {\n w.WriteHeader(http.StatusServiceUnavailable)\n w.Write([]byte(`{\"status\":\"not ready\"}`))\n return\n }\n w.WriteHeader(http.StatusOK)\n w.Write([]byte(`{\"status\":\"ready\"}`))\n}\n```\n\n### ✅ **Server Configuration**\n\n```go\nserver := &http.Server{\n Addr: \":\" + port,\n Handler: loggingMiddleware(mux),\n ReadTimeout: 15 * time.Second,\n WriteTimeout: 15 * time.Second,\n IdleTimeout: 60 * time.Second,\n}\n\n// Graceful shutdown\nquit := make(chan os.Signal, 1)\nsignal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\ngo func() {\n if err := server.ListenAndServe(); err != http.ErrServerClosed {\n log.Fatalf(\"Server failed: %v\", err)\n }\n}()\n\n\u003c-quit\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\nserver.Shutdown(ctx)\n```\n\n### ❌ **HTTP API Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| Unversioned API | Breaking changes affect all | `/v1/webhook/gitlab` |\n| No Health Endpoint | K8s can't probe | Add `/health`, `/readyz` |\n| No OpenAPI Spec | Undocumented API | Serve OpenAPI 3.0 |\n| No Timeout Config | Slow clients block | Set Read/Write timeouts |\n| No Graceful Shutdown | Dropped requests | Catch signals, drain |\n\n---\n\n## Kubernetes Operator Patterns\n\n### ✅ **Controller Reconciliation**\n\n```go\nfunc (r *MyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n var resource myv1.MyResource\n if err := r.Get(ctx, req.NamespacedName, &resource); err != nil {\n return ctrl.Result{}, client.IgnoreNotFound(err)\n }\n\n // Handle deletion with finalizer\n if !resource.DeletionTimestamp.IsZero() {\n return r.handleDeletion(ctx, &resource)\n }\n\n // Add finalizer if not present\n if !controllerutil.ContainsFinalizer(&resource, myFinalizer) {\n controllerutil.AddFinalizer(&resource, myFinalizer)\n if err := r.Update(ctx, &resource); err != nil {\n return ctrl.Result{}, err\n }\n return ctrl.Result{Requeue: true}, nil\n }\n\n // State machine based on desired state\n switch resource.Spec.DesiredState {\n case myv1.StateActive:\n return r.ensureActive(ctx, &resource)\n case myv1.StateIdle:\n return r.ensureIdle(ctx, &resource)\n }\n return ctrl.Result{}, nil\n}\n```\n\n### Return Patterns\n\n| Result | Meaning |\n|--------|---------|\n| `ctrl.Result{}, nil` | Success, no requeue |\n| `ctrl.Result{Requeue: true}, nil` | Requeue immediately |\n| `ctrl.Result{RequeueAfter: time.Minute}, nil` | Requeue after duration |\n| `ctrl.Result{}, err` | Error, controller-runtime handles backoff |\n\n### ❌ **Operator Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| Status as Spec | Status is observed, not desired | Use Spec for desired |\n| Missing Finalizer | Orphaned external resources | Add finalizer first |\n| No Context Timeout | Hung operations | `context.WithTimeout` |\n| Condition Storms | Triggers unnecessary watches | Update only on change |\n| Direct Status Update | Conflicts with spec updates | Use `r.Status().Update()` |\n\n---\n\n## Code Quality Metrics\n\n> See `common-standards.md` for universal coverage targets and testing principles.\n\n### ✅ **golangci-lint Configuration**\n\nMinimum recommended linters:\n\n```yaml\n# .golangci.yml\nlinters:\n enable:\n - errcheck # Check error returns\n - govet # Go vet\n - staticcheck # Advanced static analysis\n - unused # Detect unused code\n - gosimple # Simplification suggestions\n - gocritic # Opinionated checks\n - misspell # Spell checking\n - errorlint # Error wrapping checks\n - goimports # Auto-organize imports\n - revive # Exported name checks\n\nlinters-settings:\n gocyclo:\n min-complexity: 10 # Cyclomatic complexity threshold\n```\n\n### 📊 **Complexity Thresholds**\n\n| Complexity Range | Status | Action |\n|-----------------|--------|--------|\n| CC 1-5 (Simple) | ✅ Excellent | Maintain |\n| CC 6-10 (OK) | ✅ Acceptable | Monitor |\n| CC 11-15 (High) | ⚠️ Warning | Refactor recommended |\n| CC 16+ (Very High) | ❌ Critical | Refactor required |\n\n**Refactoring Strategies:**\n- Strategy maps (replace switch statements)\n- Guard clauses (early returns)\n- Helper functions (extract validation)\n- Interface composition\n\n---\n\n## Anti-Patterns Avoided\n\n> See `common-standards.md` for universal anti-patterns across all languages.\n\n### ❌ **No Naked Returns**\n```go\n// BAD\nfunc bad() (err error) {\n err = doSomething()\n return // Naked return\n}\n\n// GOOD\nfunc good() error {\n err := doSomething()\n return err // Explicit return\n}\n```\n\n### ❌ **No init() Abuse**\n- No `init()` functions with side effects\n- Configuration via constructors\n- Explicit initialization with error handling\n\n### ❌ **No Panics in Library Code**\n- All errors returned via `error` interface\n- `panic` only used in tests for assertion failures\n- No `panic` in production paths\n\n### ❌ **No Global Mutable State**\n```go\n// BAD\nvar globalRegistry *Registry\n\n// GOOD\ntype Server struct {\n registry *Registry // Instance field\n}\n```\n\n### ❌ **No Pointer to Interface**\n```go\n// BAD\nfunc bad(agent *Agent) // Interface is already a reference\n\n// GOOD\nfunc good(agent Agent)\n```\n\n### ❌ **No Goroutine Leaks**\n```go\n// BAD - Goroutine never exits\ngo func() {\n for {\n work() // No way to stop\n }\n}()\n\n// GOOD - Context-based cancellation\ngo func() {\n for {\n select {\n case \u003c-ctx.Done():\n return\n default:\n work()\n }\n }\n}()\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n| Category | Assessment Criteria | Evidence Required |\n|----------|-------------------|-------------------|\n| Error Handling | Custom errors, %w wrapping, documented ignores | Count proper wrappings, undocumented ignores |\n| Interface Design | Accept interfaces, return structs, small interfaces | Count interfaces, methods per interface |\n| Concurrency | Context propagation, WaitGroups, mutexes | Activities with context, race condition count |\n| Security | Constant-time comparison, HMAC, replay prevention | Prescan P2 findings, hardcoded secrets count |\n| Code Organization | Layered architecture, import grouping | Package structure review, import violations |\n| Testing | Table-driven, helpers, mocks | Test pattern count, coverage percentage |\n\n**Grading Scale:**\n\n| Grade | Finding Threshold | Description |\n|-------|------------------|-------------|\n| A+ | 0-2 minor findings | Exemplary - industry best practices |\n| A | \u003c5 HIGH findings | Excellent - strong practices |\n| A- | 5-15 HIGH findings | Very Good - solid practices |\n| B+ | 15-25 HIGH findings | Good - acceptable practices |\n| B | 25-40 HIGH findings | Satisfactory - needs improvement |\n| C+ | 40-60 HIGH findings | Needs Improvement - multiple issues |\n| C | 60+ HIGH findings | Significant Issues - major refactoring |\n| D | 1+ CRITICAL findings | Major Problems - not production-ready |\n| F | Multiple CRITICAL | Critical Issues - complete rewrite |\n\n**Example Assessment:**\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Error Handling | A- | 131 proper %w wrappings, 5 undocumented ignores, 0 %v issues |\n| Interface Design | A+ | 9 small interfaces (avg 4 methods), proper composition |\n| Concurrency | A | 24/24 activities use context, 0 race conditions (go test -race) |\n| Security | A | 0 CRITICAL, 2 HIGH (P2 findings), timing-safe comparisons |\n| **OVERALL** | **A- (Excellent)** | **12 HIGH, 34 MEDIUM findings** |\n\n---\n\n## Vibe Integration\n\n### Prescan Patterns\n\n| Pattern | Severity | Detection |\n|---------|----------|-----------|\n| P13: Undocumented Error Ignores | HIGH | `_ =` without `nolint:errcheck` |\n| P14: Error Wrapping with %v | MEDIUM | `fmt.Errorf.*%v` with error args |\n| P15: golangci-lint Violations | HIGH | JSON output parsing |\n\n### Semantic Analysis\n\nDeep validation includes:\n- Error chain inspection (`errors.Is`, `errors.As` usage)\n- Interface segregation (ISP compliance)\n- Goroutine lifecycle analysis\n- Security vulnerability detection\n\n### JIT Loading\n\n**Tier 1 (Fast):** Load `~/.agents/skills/standards/references/go.md` (5KB)\n**Tier 2 (Deep):** Load this document (16KB) for comprehensive audit\n**Override:** Use `.agents/validation/GO_*.md` if project-specific standards exist\n\n---\n\n## Additional Resources\n\n- [Effective Go](https://go.dev/doc/effective_go)\n- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)\n- [Go Proverbs](https://go-proverbs.github.io/)\n- [golangci-lint Linters](https://golangci-lint.run/usage/linters/)\n- [OWASP Go Secure Coding](https://owasp.org/www-project-go-secure-coding-practices-guide/)\n\n---\n\n**Related:** `go-patterns.md` for quick reference examples\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":32329,"content_sha256":"77c1a437e3321ab7524862a340ce8e98172d9ef02730a6b3de3741de07ed6de4"},{"filename":"references/json-standards.md","content":"# JSON/JSONL Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical JSON/JSONL standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [JSON Formatting](#json-formatting)\n2. [JSONL Format](#jsonl-format)\n3. [Beads JSONL Schema](#beads-jsonl-schema)\n4. [Configuration Files](#configuration-files)\n5. [JSON Schema](#json-schema)\n6. [Tooling](#tooling)\n7. [Anti-Patterns](#anti-patterns)\n8. [Code Quality Metrics](#code-quality-metrics)\n9. [Prescan Patterns](#prescan-patterns)\n10. [Compliance Assessment](#compliance-assessment)\n\n---\n\n## JSON Formatting\n\n### Standard Format\n\n```json\n{\n \"name\": \"example\",\n \"version\": \"1.0.0\",\n \"config\": {\n \"timeout\": 30,\n \"retries\": 3,\n \"enabled\": true\n },\n \"items\": [\n \"first\",\n \"second\",\n \"third\"\n ]\n}\n```\n\n### Formatting Rules\n\n| Rule | Example | Why |\n|------|---------|-----|\n| 2-space indent | ` \"key\": \"value\"` | Readability |\n| Double quotes only | `\"key\"` not `'key'` | JSON spec |\n| No trailing commas | `[\"a\", \"b\"]` | JSON spec |\n| Trailing newline | File ends with `\\n` | POSIX, git diffs |\n| UTF-8 encoding | Always | Compatibility |\n\n### Key Naming Conventions\n\n| Convention | Use For | Example |\n|------------|---------|---------|\n| `camelCase` | JavaScript/TypeScript | `\"apiVersion\"` |\n| `snake_case` | Python, beads | `\"issue_type\"` |\n| `kebab-case` | Avoid | - |\n| `UPPER_CASE` | Environment vars | `\"DATABASE_URL\"` |\n\n**Rule:** Be consistent within a file. Match ecosystem convention.\n\n---\n\n## JSONL Format\n\n### What is JSONL?\n\nJSON Lines: one valid JSON object per line, newline-delimited.\n\n```jsonl\n{\"id\": \"abc-123\", \"status\": \"open\", \"title\": \"First issue\"}\n{\"id\": \"abc-124\", \"status\": \"closed\", \"title\": \"Second issue\"}\n{\"id\": \"abc-125\", \"status\": \"open\", \"title\": \"Third issue\"}\n```\n\n### When to Use\n\n| Use JSONL | Use JSON |\n|-----------|----------|\n| Append-only data | Single config |\n| Streaming ingestion | Nested data |\n| Line-by-line processing | Small datasets |\n| Beads issues | API responses |\n| Large datasets | Human-edited |\n\n### JSONL Rules\n\n| Rule | Rationale |\n|------|-----------|\n| One object per line | Enables grep/head/tail |\n| No trailing comma | Each line is complete |\n| No array wrapper | Not `[{...}, {...}]` |\n| Newline after last | Append-friendly |\n| UTF-8, no BOM | Compatibility |\n\n### Processing JSONL\n\n```bash\n# Count records\nwc -l issues.jsonl\n\n# Filter by field\njq -c 'select(.status == \"open\")' issues.jsonl\n\n# Extract field\njq -r '.title' issues.jsonl\n\n# Pretty-print one record\nhead -1 issues.jsonl | jq .\n\n# Append new record\necho '{\"id\": \"new\", \"status\": \"open\"}' >> issues.jsonl\n\n# Convert JSON array to JSONL\njq -c '.[]' array.json > data.jsonl\n\n# Convert JSONL to JSON array\njq -s '.' data.jsonl > array.json\n```\n\n---\n\n## Beads JSONL Schema\n\n### Issue Record Schema\n\n```json\n{\n \"id\": \"prefix-xxxx\",\n \"title\": \"Issue title\",\n \"status\": \"open\",\n \"priority\": 2,\n \"issue_type\": \"task\",\n \"owner\": \"[email protected]\",\n \"created_at\": \"2026-01-15T08:18:34.317984-05:00\",\n \"created_by\": \"User Name\",\n \"updated_at\": \"2026-01-15T08:42:39.253689-05:00\",\n \"closed_at\": null,\n \"close_reason\": null,\n \"dependencies\": []\n}\n```\n\n### Field Reference\n\n| Field | Type | Required | Values |\n|-------|------|----------|--------|\n| `id` | string | Yes | `prefix-xxxx` |\n| `title` | string | Yes | Brief description |\n| `status` | string | Yes | `open`, `in_progress`, `closed` |\n| `priority` | integer | Yes | 0-4 (0=critical) |\n| `issue_type` | string | Yes | `task`, `bug`, `feature`, `epic` |\n| `owner` | string | No | Email address |\n| `created_at` | string | Yes | ISO 8601 |\n| `updated_at` | string | Yes | ISO 8601 |\n| `closed_at` | string | No | ISO 8601 or null |\n| `dependencies` | array | No | Dependency objects |\n\n### Dependency Object\n\n```json\n{\n \"issue_id\": \"prefix-child\",\n \"depends_on_id\": \"prefix-parent\",\n \"type\": \"parent-child\",\n \"created_at\": \"2026-01-15T08:19:32.440350-05:00\"\n}\n```\n\n---\n\n## Configuration Files\n\n### tsconfig.json\n\n```json\n{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"NodeNext\",\n \"strict\": true,\n \"outDir\": \"./dist\"\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\"]\n}\n```\n\n### package.json\n\n```json\n{\n \"name\": \"package-name\",\n \"version\": \"1.0.0\",\n \"description\": \"Brief description\",\n \"main\": \"dist/index.js\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"test\": \"jest\",\n \"lint\": \"eslint .\"\n },\n \"dependencies\": {},\n \"devDependencies\": {}\n}\n```\n\n### VS Code settings.json\n\n```json\n{\n \"editor.formatOnSave\": true,\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"files.insertFinalNewline\": true,\n \"files.trimTrailingWhitespace\": true\n}\n```\n\n---\n\n## JSON Schema\n\n### Defining Schemas\n\n```json\n{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://example.com/config.schema.json\",\n \"title\": \"Configuration\",\n \"type\": \"object\",\n \"required\": [\"name\", \"version\"],\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Project name\",\n \"minLength\": 1\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\"\n },\n \"enabled\": {\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"additionalProperties\": false\n}\n```\n\n### Schema Validation\n\n```bash\n# Using ajv-cli\nnpx ajv validate -s schema.json -d config.json\n\n# Using Python jsonschema\npython -c \"\nimport json\nfrom jsonschema import validate\nwith open('schema.json') as s, open('config.json') as c:\n validate(json.load(c), json.load(s))\n\"\n```\n\n---\n\n## Tooling\n\n### Formatting\n\n```bash\n# jq - Format and validate\njq . config.json > formatted.json\n\n# Prettier - Format with config\nnpx prettier --write '**/*.json'\n\n# Python - Format\npython -m json.tool config.json\n```\n\n### Validation\n\n```bash\n# jq - Check valid JSON\njq empty config.json && echo \"Valid\"\n\n# Python - Check valid JSON\npython -c \"import json; json.load(open('config.json'))\"\n\n# Node - Check valid JSON\nnode -e \"require('./config.json')\"\n```\n\n### Editor Configuration\n\n**.editorconfig:**\n```ini\n[*.json]\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ncharset = utf-8\n\n[*.jsonl]\nindent_style = space\nindent_size = 0\ninsert_final_newline = true\n```\n\n**.prettierrc:**\n```json\n{\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"trailingComma\": \"none\",\n \"singleQuote\": false\n}\n```\n\n---\n\n## Anti-Patterns\n\n### Deeply Nested Objects\n\nNesting beyond 4 levels indicates missing abstraction or flattening opportunity.\n\n```json\n// BAD - 5 levels deep\n{\"config\": {\"server\": {\"auth\": {\"oauth\": {\"scopes\": [\"read\"]}}}}}\n\n// GOOD - flattened\n{\"auth_oauth_scopes\": [\"read\"]}\n```\n\n### Inconsistent Key Naming\n\nMixing `camelCase` and `snake_case` within a single file breaks grep-ability and signals multiple authors without review.\n\n### Missing Schema References\n\nJSON config files without a `$schema` field cannot be validated automatically. Always include `$schema` when a schema exists.\n\n### Magic Values Without Documentation\n\nUndocumented numeric or string constants embedded in JSON (e.g., `\"timeout\": 86400`) should use descriptive keys or adjacent comments in the referencing code.\n\n### Oversized Arrays or Objects\n\nArrays with >1000 elements or objects with >100 keys in a single file suggest the data belongs in JSONL or a database, not a monolithic JSON file.\n\n### Duplicate Keys\n\nJSON parsers silently drop earlier values when duplicate keys exist. This is always a bug.\n\n---\n\n## Code Quality Metrics\n\n### Validation Thresholds\n\n| Metric | Threshold | Severity |\n|--------|-----------|----------|\n| Schema coverage | 100% of config files have `$schema` | Warning |\n| Nesting depth | ≤4 levels | Error above 4 |\n| File size | ≤100KB per JSON file | Warning above 100KB |\n| Key consistency | Single naming convention per file | Error if mixed |\n| JSONL line validity | 100% lines parse | Error on any failure |\n| Duplicate keys | 0 per file | Error |\n\n### Grading Impact\n\n| Violation | Grade Impact |\n|-----------|-------------|\n| Parse failure | Automatic C |\n| Nesting >4 levels | Cap at B+ |\n| Mixed key naming | Cap at A- |\n| Missing schema ref | -0.5 grade step |\n| File >100KB | -0.5 grade step |\n\n---\n\n## Prescan Patterns\n\nAutomated detection commands for CI or pre-commit validation.\n\n### P01: Nesting Depth Check\n\n| Field | Value |\n|-------|-------|\n| **Pattern** | Nesting depth exceeds 4 levels |\n| **Detection** | `jq '[paths \\| length] \\| max' file.json` — fails if result >4 |\n| **Severity** | Error |\n\n### P02: Inconsistent Key Naming\n\n| Field | Value |\n|-------|-------|\n| **Pattern** | Mixed camelCase and snake_case keys in same file |\n| **Detection** | `jq '[paths \\| .[] \\| strings] \\| unique \\| map(test(\"_\")) \\| unique \\| length' file.json` — fails if result >1 |\n| **Severity** | Error |\n\n### P03: Duplicate Keys\n\n| Field | Value |\n|-------|-------|\n| **Pattern** | Same key appears twice in an object |\n| **Detection** | `python -c \"import json,sys; json.load(open(sys.argv[1]),object_pairs_hook=lambda p: (_ for k,v in p if sum(1 for k2,_ in p if k2==k)>1).__next__())\" file.json` or use `jq --jsonargs` strict mode |\n| **Severity** | Error |\n\n### P04: Missing Schema Reference\n\n| Field | Value |\n|-------|-------|\n| **Pattern** | Config file lacks `$schema` field |\n| **Detection** | `jq 'has(\"$schema\")' file.json` — fails if result is `false` |\n| **Severity** | Warning |\n\n### P05: Oversized Values\n\n| Field | Value |\n|-------|-------|\n| **Pattern** | File exceeds 100KB or arrays exceed 1000 elements |\n| **Detection** | `stat -f%z file.json` (macOS) or `stat -c%s file.json` (Linux) — fails if >102400; `jq '[.. \\| arrays \\| length] \\| max' file.json` — fails if >1000 |\n| **Severity** | Warning |\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Formatting** | jq validation, indentation, newlines |\n| **Schema** | Validation errors, required fields |\n| **Key Naming** | Consistency check |\n| **JSONL Integrity** | Line count = record count |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | All files validate, 2-space, UTF-8, schema valid |\n| A | Valid JSON, consistent formatting |\n| A- | Minor formatting inconsistencies |\n| B | Valid but poorly formatted |\n| C | Parse errors |\n\n### Validation Commands\n\n```bash\n# Validate JSON\nfind . -name '*.json' -exec jq empty {} \\; 2>&1 | grep -c \"parse error\"\n# Should be 0\n\n# Check indentation\njq . config.json | head -5\n\n# JSONL: validate line count\nwc -l data.jsonl\njq -c '.' data.jsonl | wc -l\n# Should match\n\n# JSONL: validate each line\nwhile IFS= read -r line; do echo \"$line\" | jq empty; done \u003c data.jsonl\n```\n\n### Example Assessment\n\n```markdown\n## JSON/JSONL Standards Compliance\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Formatting | A+ | 18/18 validate, 2-space |\n| Schema | A+ | 1247/1247 records pass |\n| Key Naming | A | Consistent snake_case |\n| JSONL | A+ | Line count matches |\n| **OVERALL** | **A+** | **0 findings** |\n```\n\n---\n\n## Additional Resources\n\n- [JSON Spec](https://www.json.org/)\n- [JSON Lines](https://jsonlines.org/)\n- [JSON Schema](https://json-schema.org/)\n- [jq Manual](https://stedolan.github.io/jq/manual/)\n\n---\n\n**Related:** Quick reference in Tier 1 `json.md`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11364,"content_sha256":"f4e4e064efc233105ac869ab5353f51e30e20b985aae9b1d1d42571b2c28f329"},{"filename":"references/markdown-standards.md","content":"# Markdown Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical Markdown standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [AI-Agent Optimization](#ai-agent-optimization)\n2. [Document Structure](#document-structure)\n3. [Heading Conventions](#heading-conventions)\n4. [Code Blocks](#code-blocks)\n5. [Tables](#tables)\n6. [Links](#links)\n7. [Lists](#lists)\n8. [Emphasis and Blockquotes](#emphasis-and-blockquotes)\n9. [Validation](#validation)\n10. [Compliance Assessment](#compliance-assessment)\n\n---\n\n## AI-Agent Optimization\n\n### Principles\n\n| Principle | Implementation | Why |\n|-----------|----------------|-----|\n| **Tables over prose** | Use tables for comparisons | Parallel parsing, scannable |\n| **Explicit rules** | ALWAYS/NEVER, not \"try to\" | Removes ambiguity |\n| **Decision trees** | If/then logic in lists | Executable reasoning |\n| **Named patterns** | Anti-patterns with names | Recognizable error states |\n| **Progressive disclosure** | Quick ref → details JIT | Context window efficiency |\n| **Copy-paste ready** | Complete examples | Reduces inference errors |\n\n---\n\n## Document Structure\n\n### SKILL.md Template\n\n```markdown\n# Skill Name\n\n> **Triggers:** \"phrase 1\", \"phrase 2\", \"phrase 3\"\n\n## Quick Reference\n\n| Action | Command | Notes |\n|--------|---------|-------|\n| ... | ... | ... |\n\n## When to Use\n\n| Scenario | Action |\n|----------|--------|\n| Condition A | Do X |\n| Condition B | Do Y |\n\n## Workflow\n\n1. Step one\n2. Step two\n3. Step three\n\n## Common Errors\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| Error message | Root cause | Solution |\n\n## References\n\n- [Reference 1](./references/detail1.md) - Load when needed\n- [Reference 2](./references/detail2.md) - Load when needed\n```\n\n### Reference Doc Template\n\n```markdown\n# Reference: Topic Name\n\n\u003c!-- Load JIT when skill needs deep context -->\n\n## Context\n\nBrief overview of when this reference applies.\n\n## Details\n\n### Section 1\n\n...\n\n## Decision Tree\n\n```text\nIs X true?\n├─ Yes → Do A\n│ └─ Did A fail? → Try B\n└─ No → Do C\n```\n\n## Anti-Patterns\n\n| Name | Pattern | Why Bad | Instead |\n|------|---------|---------|---------|\n| ... | ... | ... | ... |\n```\n\n---\n\n## Heading Conventions\n\n### Hierarchy Rules\n\n| Level | Use For | Example |\n|-------|---------|---------|\n| `#` | Document title (one per file) | `# Style Guide` |\n| `##` | Major sections | `## Installation` |\n| `###` | Subsections | `### macOS Setup` |\n| `####` | Minor divisions (sparingly) | `#### Homebrew` |\n\n**NEVER:**\n- Skip heading levels (`#` → `###`)\n- Use bold text as fake headings\n- Start with `##` (missing `#` title)\n\n### Heading Text\n\n```markdown\n# Good - Title Case for Title\n## Good - Sentence case for sections\n### Good - Sentence case continues\n\n# Bad - all lowercase title\n## Bad - ALL CAPS SECTION\n### Bad - Using: Colons: Everywhere\n```\n\n---\n\n## Code Blocks\n\n### Language Hints (Required)\n\nALWAYS specify language for syntax highlighting:\n\n````markdown\n```python\ndef hello():\n print(\"world\")\n```\n````\n\n### Common Language Hints\n\n| Language | Fence | Use For |\n|----------|-------|---------|\n| `bash` | ` ```bash ` | Shell commands |\n| `python` | ` ```python ` | Python code |\n| `go` | ` ```go ` | Go code |\n| `typescript` | ` ```typescript ` | TypeScript |\n| `yaml` | ` ```yaml ` | YAML config |\n| `json` | ` ```json ` | JSON data |\n| `text` | ` ```text ` | Plain text, diagrams |\n| `diff` | ` ```diff ` | Code diffs |\n\n### Command Output\n\n```markdown\n```bash\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nmy-pod 1/1 Running 0 5m\n```\n```\n\n---\n\n## Tables\n\n### When to Use\n\n| Situation | Use Table? | Alternative |\n|-----------|------------|-------------|\n| Comparing 3+ items | Yes | - |\n| Key-value mappings | Yes | - |\n| Command reference | Yes | - |\n| Step-by-step | No | Numbered list |\n| Narrative | No | Paragraphs |\n| Two items only | No | Inline comparison |\n\n### Table Formatting\n\n```markdown\n# Good - Aligned, readable\n| Column A | Column B | Column C |\n|----------|----------|----------|\n| Value 1 | Value 2 | Value 3 |\n\n# Bad - Misaligned\n|Column A|Column B|Column C|\n|-|-|-|\n|Value 1|Value 2|Value 3|\n```\n\n### Table Cell Content\n\n| Content Type | Formatting |\n|--------------|------------|\n| Code/commands | Backticks: `` `cmd` `` |\n| Emphasis | Bold: `**required**` |\n| Links | Inline: `[text](url)` |\n| Long text | Under 50 chars |\n\n---\n\n## Links\n\n### Internal Links\n\n```markdown\n# Good - Relative paths\n[Guide](./other-doc.md)\n\n# Good - Anchor links\n[Code Blocks](#code-blocks)\n\n# Bad - Absolute paths\n[Guide](/Users/me/project/docs/guide.md)\n```\n\n### Reference Links\n\nFor repeated URLs:\n\n```markdown\nSee the [official docs][k8s-docs] for more info.\nThe [Kubernetes documentation][k8s-docs] covers this.\n\n[k8s-docs]: https://kubernetes.io/docs/\n```\n\n---\n\n## Lists\n\n### Unordered Lists\n\nUse `-` consistently:\n\n```markdown\n# Good\n- Item one\n- Item two\n - Nested item\n\n# Bad - Mixed markers\n* Item one\n+ Item two\n- Item three\n```\n\n### Ordered Lists\n\nUse `1.` for all items:\n\n```markdown\n# Good - All 1s\n1. First step\n1. Second step\n1. Third step\n\n# Acceptable - Explicit numbering\n1. First step\n2. Second step\n3. Third step\n```\n\n### Task Lists\n\n```markdown\n- [ ] Incomplete task\n- [x] Completed task\n- [ ] Another incomplete\n```\n\n---\n\n## Emphasis and Blockquotes\n\n### Emphasis\n\n| Purpose | Syntax | Example |\n|---------|--------|---------|\n| Important terms | `**bold**` | **required** |\n| File names, commands | `` `backticks` `` | `config.yaml` |\n| Titles, emphasis | `*italic*` | *optional* |\n| Keyboard keys | `\u003ckbd>` | \u003ckbd>Ctrl\u003c/kbd>+\u003ckbd>C\u003c/kbd> |\n\n**NEVER use bold for:**\n- Entire paragraphs\n- Headings (use `#`)\n- Code (use backticks)\n\n### Callout Patterns\n\n```markdown\n> **Note:** Supplementary information.\n\n> **Warning:** Something that could cause issues.\n\n> **Important:** Critical information.\n\n> **Tip:** Helpful suggestion.\n```\n\n---\n\n## Validation\n\n### markdownlint Configuration\n\n```yaml\n# .markdownlint.yml\ndefault: true\n\nMD013:\n line_length: 100\n code_blocks: false\n tables: false\n\nMD033:\n allowed_elements:\n - kbd\n - br\n - details\n - summary\n\nMD034: false\n\nMD004:\n style: dash\n\nMD003:\n style: atx\n```\n\n### Validation Commands\n\n```bash\n# Lint Markdown files\nnpx markdownlint '**/*.md' --ignore node_modules\n\n# Check links\nnpx markdown-link-check README.md\n\n# Format with Prettier\nnpx prettier --write '**/*.md'\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Structure** | Heading hierarchy, single H1 |\n| **Formatting** | markdownlint violations, code fence hints |\n| **Links** | Broken link count, relative paths |\n| **AI Optimization** | Table usage, explicit rules |\n| **Accessibility** | Alt text, semantic markup |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | 0 errors, single H1, 100% code hints, 0 broken links |\n| A | \u003c5 warnings, good structure |\n| A- | \u003c15 warnings, mostly correct |\n| B | \u003c30 warnings |\n| C | Significant issues |\n\n### Validation Commands\n\n```bash\n# Lint Markdown\nnpx markdownlint '**/*.md' --ignore node_modules\n\n# Check heading hierarchy\ngrep -r \"^# \" docs/*.md | wc -l\nls docs/*.md | wc -l\n# Should match (1 H1 per file)\n\n# Code blocks without language\ngrep -rP '```\\s*

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

docs/ | wc -l\n# Should be 0\n\n# Check links\nnpx markdown-link-check docs/**/*.md\n```\n\n### Example Assessment\n\n```markdown\n## Markdown Standards Compliance\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Structure | A+ | 47/47 single H1, 0 skipped |\n| Formatting | A- | 18 warnings (MD013) |\n| Links | A | 0 broken, 93% relative |\n| AI Optimization | A | 85 tables, 23 decision trees |\n| **OVERALL** | **A** | **18 MEDIUM findings** |\n```\n\n---\n\n## Additional Resources\n\n- [CommonMark Spec](https://spec.commonmark.org/)\n- [markdownlint Rules](https://github.com/DavidAnson/markdownlint)\n- [GitHub Flavored Markdown](https://github.github.com/gfm/)\n\n---\n\n**Related:** Quick reference in Tier 1 `markdown.md`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8166,"content_sha256":"cd31533d268eda7f175f8d65c49bd9a45e9c7e19ce5fc1956d28772103af7e01"},{"filename":"references/patterns.md","content":"# Vibe Pattern Reference\n\nComprehensive pattern catalog for Talos validation.\n\n## Pattern Categories\n\n| Category | Prefix | Phase | Description |\n|----------|--------|-------|-------------|\n| Prescan | P1-P10 | Static | Fast, no LLM required |\n| Quality | QUAL-xxx | Semantic | Code smells, patterns |\n| Security | SEC-xxx | Semantic | OWASP, injection, auth |\n| Architecture | ARCH-xxx | Semantic | Boundaries, coupling |\n| Accessibility | A11Y-xxx | Semantic | WCAG, keyboard |\n| Complexity | CMPLX-xxx | Both | Cyclomatic, cognitive |\n| Semantic | SEM-xxx | Semantic | Names, docstrings |\n| Performance | PERF-xxx | Semantic | N+1, leaks |\n| Slop | SLOP-xxx | Semantic | AI artifacts |\n\n---\n\n## Prescan Patterns (Static Detection)\n\nFast static analysis - no LLM required.\n\n**Supported Languages:** Python, Go, Bash, TypeScript, JavaScript\n\n### P1: Phantom Modifications (CRITICAL)\n\n**What**: Committed lines that don't exist in current file.\n\n**Why Critical**: Indicates broken git workflow - changes were committed but then removed or lost.\n\n**Detection**: Compare `git show HEAD -- \u003cfile>` with actual file content.\n\n**Fix**: Re-commit or investigate git history.\n\n---\n\n### P2: Hardcoded Secrets (CRITICAL)\n\n**What**: API keys, passwords, tokens in source code.\n\n**Why Critical**: Credential exposure leads to immediate compromise.\n\n**Detection**:\n- gitleaks scan\n- Regex for common patterns (AWS keys, JWT, password=)\n\n**Patterns**:\n```regex\n(password|secret|api_key|token)\\s*[=:]\\s*[\"'][^\"']{8,}[\"']\nAKIA[0-9A-Z]{16}\neyJ[a-zA-Z0-9_-]+\\.eyJ[a-zA-Z0-9_-]+\n```\n\n**Fix**: Use environment variables or secrets manager.\n\n---\n\n### P3: SQL Injection Patterns (CRITICAL)\n\n**What**: String concatenation in SQL queries.\n\n**Why Critical**: Direct path to data breach.\n\n**Detection**:\n```regex\n(execute|query)\\s*\\(\\s*f?[\"'].*\\{.*\\}\ncursor\\.(execute|query)\\s*\\([^)]*%\n```\n\n**Fix**: Use parameterized queries.\n\n---\n\n### P4: TODO/FIXME/Commented Code (HIGH)\n\n**What**: TODO markers, FIXME, commented-out code blocks.\n\n**Why High**: Incomplete work or tech debt markers.\n\n**Detection**:\n```bash\ngrep -E \"TODO|FIXME|XXX|HACK|BUG\"\ngrep -E \"^\\s*#\\s*(def |class |if |for |while )\" # Commented code\n```\n\n**Fix**: Complete or remove with explanation.\n\n---\n\n### P5: Cyclomatic Complexity (HIGH)\n\n**What**: Functions with CC > 15.\n\n**Why High**: Too complex to maintain safely.\n\n**Detection by Language**:\n\n| Language | Tool | Command |\n|----------|------|---------|\n| Python | radon | `radon cc \u003cfile> -s -n E` |\n| Go | gocyclo | `gocyclo -over 15 \u003cfile>` |\n| TypeScript | escomplex | `escomplex \u003cfile>` |\n\n**Thresholds**:\n- CC > 10: Warning\n- CC > 15: Flag as complex\n- CC > 20: Critical\n\n**Fix**: Extract functions, simplify logic.\n\n---\n\n### P6: Long Functions (HIGH)\n\n**What**: Functions exceeding 50 lines.\n\n**Why High**: Long functions are hard to test and maintain.\n\n**Detection**: AST parsing, line counting.\n\n**Thresholds**:\n- Lines > 30: Warning\n- Lines > 50: Flag\n- Lines > 100: Critical\n\n**Fix**: Extract helper functions.\n\n---\n\n### P7: Cargo Cult Error Handling (HIGH)\n\n**What**: Empty except blocks, pass-only handlers, bare except.\n\n**Why High**: Swallowed errors hide bugs.\n\n**Detection by Language**:\n\n| Language | Pattern |\n|----------|---------|\n| Python | `except: pass`, `except Exception: pass` |\n| Go | `if err != nil { }` (empty block) |\n| Bash | shellcheck SC2181 |\n\n**Fix**: Handle or propagate errors explicitly.\n\n---\n\n### P8: Unused Imports/Functions (MEDIUM)\n\n**What**: Imported modules or defined functions never used.\n\n**Why Medium**: Dead code clutters codebase.\n\n**Detection**: AST analysis, import tracking.\n\n**Fix**: Remove unused code.\n\n---\n\n### P9: Docstring Mismatches (MEDIUM)\n\n**What**: Docstrings claiming behavior not implemented.\n\n**Why Medium**: False security from lying documentation.\n\n**Detection**: Match docstring claims vs implementation:\n- \"validates\" but no raise/ValueError\n- \"encrypts\" but no crypto imports\n- \"authenticates\" but no token handling\n\n**Fix**: Update docs or implement claimed behavior.\n\n---\n\n### P10: Missing Error Handling (MEDIUM)\n\n**What**: Operations that can fail without error handling.\n\n**Why Medium**: Silent failures cause hard-to-debug issues.\n\n**Detection**:\n- File operations without try/except\n- Network calls without timeout/retry\n- Parsing without validation\n\n**Fix**: Add appropriate error handling.\n\n---\n\n## Semantic Patterns (LLM-Powered)\n\nDeep analysis requiring semantic understanding.\n\n### Quality (QUAL-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| QUAL-001 | Dead code paths | MEDIUM |\n| QUAL-002 | Inconsistent naming | MEDIUM |\n| QUAL-003 | Magic numbers/strings | MEDIUM |\n| QUAL-004 | Missing tests for complex code | HIGH |\n| QUAL-005 | Copy-paste with variations | HIGH |\n| QUAL-006 | Feature envy (method uses another class more) | MEDIUM |\n| QUAL-007 | Primitive obsession | LOW |\n| QUAL-008 | Long parameter lists | MEDIUM |\n\n---\n\n### Security (SEC-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| SEC-001 | Injection (SQL, command, XSS, template) | CRITICAL |\n| SEC-002 | Authentication bypass | CRITICAL |\n| SEC-003 | Authorization missing/weak | CRITICAL |\n| SEC-004 | Cryptographic weakness | HIGH |\n| SEC-005 | Sensitive data exposure | HIGH |\n| SEC-006 | Security theater (looks secure, isn't) | HIGH |\n| SEC-007 | Insecure deserialization | HIGH |\n| SEC-008 | SSRF/path traversal | HIGH |\n| SEC-009 | Race conditions | MEDIUM |\n| SEC-010 | Debug mode in production | MEDIUM |\n\n---\n\n### Architecture (ARCH-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| ARCH-001 | Layer boundary violation | HIGH |\n| ARCH-002 | Circular dependency | HIGH |\n| ARCH-003 | God class/function | HIGH |\n| ARCH-004 | Missing abstraction | MEDIUM |\n| ARCH-005 | Inappropriate coupling | MEDIUM |\n| ARCH-006 | Scalability concern | MEDIUM |\n| ARCH-007 | Single point of failure | HIGH |\n| ARCH-008 | Hardcoded configuration | MEDIUM |\n| ARCH-009 | Missing retry/circuit breaker | MEDIUM |\n| ARCH-010 | Synchronous where async needed | MEDIUM |\n\n---\n\n### Accessibility (A11Y-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| A11Y-001 | Missing ARIA labels | HIGH |\n| A11Y-002 | Keyboard navigation broken | CRITICAL |\n| A11Y-003 | Color contrast insufficient | HIGH |\n| A11Y-004 | Missing alt text | HIGH |\n| A11Y-005 | Focus management issues | HIGH |\n| A11Y-006 | Missing skip links | MEDIUM |\n| A11Y-007 | Form labels missing | HIGH |\n| A11Y-008 | Dynamic content not announced | MEDIUM |\n| A11Y-009 | Touch target too small | MEDIUM |\n| A11Y-010 | Motion without reduced-motion support | LOW |\n\n---\n\n### Complexity (CMPLX-xxx)\n\n| Code | Pattern | Severity | Threshold |\n|------|---------|----------|-----------|\n| CMPLX-001 | Cyclomatic complexity | HIGH | CC > 10 |\n| CMPLX-002 | Cognitive complexity | HIGH | > 15 |\n| CMPLX-003 | Nesting depth | MEDIUM | > 4 |\n| CMPLX-004 | Parameter count | MEDIUM | > 5 |\n| CMPLX-005 | File too long | MEDIUM | > 500 lines |\n| CMPLX-006 | Class too large | MEDIUM | > 20 methods |\n| CMPLX-007 | Inheritance depth | LOW | > 3 |\n| CMPLX-008 | Fan-out too high | MEDIUM | > 10 dependencies |\n\n---\n\n### Semantic (SEM-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| SEM-001 | Docstring lies | HIGH |\n| SEM-002 | Misleading function name | HIGH |\n| SEM-003 | Misleading variable name | MEDIUM |\n| SEM-004 | Comment rot | MEDIUM |\n| SEM-005 | API contract violation | HIGH |\n| SEM-006 | Type annotation mismatch | MEDIUM |\n| SEM-007 | Inconsistent return types | MEDIUM |\n| SEM-008 | Side effects in getter | HIGH |\n\n---\n\n### Performance (PERF-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| PERF-001 | N+1 query | HIGH |\n| PERF-002 | Unbounded loop/recursion | CRITICAL |\n| PERF-003 | Missing pagination | HIGH |\n| PERF-004 | Resource leak | HIGH |\n| PERF-005 | Blocking in async context | HIGH |\n| PERF-006 | Inefficient algorithm | MEDIUM |\n| PERF-007 | Repeated computation | MEDIUM |\n| PERF-008 | Missing caching | LOW |\n| PERF-009 | Large object in memory | MEDIUM |\n| PERF-010 | Excessive logging | LOW |\n\n---\n\n### Slop (SLOP-xxx)\n\n| Code | Pattern | Severity |\n|------|---------|----------|\n| SLOP-001 | Hallucinated imports/APIs | CRITICAL |\n| SLOP-002 | Cargo cult patterns | HIGH |\n| SLOP-003 | Excessive boilerplate | MEDIUM |\n| SLOP-004 | AI conversation artifacts | HIGH |\n| SLOP-005 | Over-engineering | MEDIUM |\n| SLOP-006 | Unnecessary abstractions | MEDIUM |\n| SLOP-007 | Copy-paste from tutorials | MEDIUM |\n| SLOP-008 | Sycophantic comments | LOW |\n| SLOP-009 | Redundant type annotations | LOW |\n| SLOP-010 | Verbose where concise works | LOW |\n\n---\n\n## Severity Mapping\n\n| Level | Definition | Action | Exit Code |\n|-------|------------|--------|-----------|\n| **CRITICAL** | Security vuln, data loss, broken build | Block merge | 2 |\n| **HIGH** | Significant quality/security gap | Fix before merge | 3 |\n| **MEDIUM** | Technical debt, minor issues | Follow-up issue | 0 |\n| **LOW** | Nitpicks, style preferences | Optional | 0 |\n\n---\n\n## Tool Requirements\n\n| Tool | Languages | Install |\n|------|-----------|---------|\n| radon | Python | `pip install radon` |\n| gocyclo | Go | `go install github.com/fzipp/gocyclo/cmd/gocyclo@latest` |\n| shellcheck | Bash | `brew install shellcheck` |\n| gitleaks | All | `brew install gitleaks` |\n| eslint | JS/TS | `npm install eslint` |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9417,"content_sha256":"086bc630e7968681b6e7706acf6de4d1d1f04cb7f33fce37e6e9b834d131c22e"},{"filename":"references/post-verdict-actions.md","content":"# Post-Verdict Actions (Steps 9 & 9.5)\n\nProcedural detail extracted from SKILL.md so the billboard stays compact.\n\n## Step 9: Record Ratchet Progress\n\nAfter council verdict:\n1. If verdict is PASS or WARN:\n - Run: `ao ratchet record vibe --output \"\u003creport-path>\" 2>/dev/null || true`\n - Suggest: \"Run /post-mortem to capture learnings and complete the cycle.\"\n2. If verdict is FAIL:\n - Do NOT record ratchet progress.\n - Extract ALL findings from the council report for structured retry context (group by category if >20):\n ```\n Read the council report. For each finding, format as:\n FINDING: \u003cdescription> | FIX: \u003cfix or recommendation> | REF: \u003cref or location>\n\n Fallback for v1 findings (no fix/why/ref fields):\n fix = finding.fix || finding.recommendation || \"No fix specified\"\n ref = finding.ref || finding.location || \"No reference\"\n ```\n - Tell user to fix issues and re-run /vibe, including the formatted findings as actionable guidance.\n\n## Step 9.5: Feed Findings to Flywheel\n\n**If verdict is WARN or FAIL**, persist reusable findings to `.agents/findings/registry.jsonl` and optionally mirror the broader narrative to a learning file.\n\nRegistry write rules:\n\n- persist only reusable issues that should change future review or implementation behavior\n- require `dedup_key`, provenance, `pattern`, `detection_question`, `checklist_item`, `applicable_when`, and `confidence`\n- `applicable_when` must use the controlled vocabulary from the finding-registry contract\n- append or merge by `dedup_key`\n- use the contract's temp-file-plus-rename atomic write rule\n\nIf a broader prose summary still helps, also write the existing anti-pattern learning file to `.agents/learnings/YYYY-MM-DD-vibe-\u003ctarget>.md`. Skip both if verdict is PASS.\n\nAfter the registry update, if `hooks/finding-compiler.sh` exists, run:\n\n```bash\nbash hooks/finding-compiler.sh --quiet 2>/dev/null || true\n```\n\nThis keeps the same-session post-mortem path synchronized with the latest reusable findings. `session-end-maintenance.sh` remains the idempotent backstop.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2082,"content_sha256":"80f0e9d018abb511a06cf436563f69e01adf1a355ba310fce8cd769c081bb600"},{"filename":"references/python-standards.md","content":"# Python Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical Python standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [Project Structure](#project-structure)\n2. [Package Management](#package-management)\n3. [Code Formatting](#code-formatting)\n4. [Reducing Complexity](#reducing-complexity)\n5. [Type Hints](#type-hints)\n6. [Docstrings](#docstrings)\n7. [Error Handling](#error-handling)\n8. [Logging](#logging)\n9. [Testing](#testing)\n10. [CLI Script Template](#cli-script-template)\n11. [Code Quality Metrics](#code-quality-metrics)\n12. [Security Practices](#security-practices)\n13. [Anti-Patterns Avoided](#anti-patterns-avoided)\n14. [Compliance Assessment](#compliance-assessment)\n\n---\n\n## Project Structure\n\n### Standard Layout\n\n```text\nproject/\n├── pyproject.toml # Project metadata and dependencies\n├── uv.lock # Lock file (commit this!)\n├── src/\n│ └── mypackage/ # Source code\n│ ├── __init__.py\n│ ├── core.py\n│ └── utils.py\n├── scripts/ # CLI tools\n│ └── my_script.py\n├── tests/ # Test suite\n│ ├── __init__.py\n│ ├── conftest.py # Pytest fixtures\n│ ├── test_core.py\n│ └── e2e/ # End-to-end tests\n│ ├── conftest.py # Testcontainers fixtures\n│ └── test_integration.py\n└── docs/ # Documentation\n```\n\n**Key Principles:**\n- Use `src/` layout for packages (prevents import issues)\n- CLI scripts are standalone files in `scripts/`\n- Tests mirror source structure\n- Always commit `uv.lock` for reproducibility\n\n---\n\n## Package Management\n\n### uv - Project Dependencies\n\nUse `uv` for all project-level Python dependencies. It's 10-100x faster than pip and creates deterministic builds.\n\n```bash\n# Initialize a new project\nuv init my-project\ncd my-project\n\n# Add dependencies\nuv add requests pyyaml # Runtime deps\nuv add --dev pytest ruff # Dev deps\n\n# Install from existing pyproject.toml\nuv sync # Creates/updates uv.lock\n\n# Run a script with project deps\nuv run python my_script.py\n```\n\n### pipx - Global CLI Tools\n\nUse `pipx` for Python CLI tools you want available everywhere.\n\n```bash\n# Install CLI tools globally\npipx install ruff # Linter/formatter\npipx install radon # Complexity analysis\npipx install xenon # Complexity enforcement\npipx install pre-commit # Git hooks\n\n# Upgrade all\npipx upgrade-all\n\n# Run without installing\npipx run cowsay \"hello\"\n```\n\n### When to Use What\n\n| Need | Tool | Command |\n|------|------|---------|\n| Install project deps | uv | `uv sync` |\n| Add library to project | uv | `uv add requests` |\n| Install CLI globally | pipx | `pipx install ruff` |\n| Install system tool | brew | `brew install shellcheck` |\n| Quick script run | uv | `uv run script.py` |\n\n### What NOT to Do\n\n```python\n# DON'T use pip globally\npip install requests # Pollutes system Python\nsudo pip install anything # Even worse\n\n# DON'T mix package managers\npip install requests # Now you have pip AND uv deps\nuv add pyyaml # Conflicts likely\n\n# DON'T commit venv/\ngit add .venv/ # Use .gitignore\n```\n\n---\n\n## Code Formatting\n\n### ruff Configuration\n\n**Full recommended configuration:**\n\n```toml\n# pyproject.toml\n[tool.ruff]\nline-length = 100\ntarget-version = \"py312\"\nexclude = [\n \".git\",\n \".venv\",\n \"__pycache__\",\n \"build\",\n \"dist\",\n]\n\n[tool.ruff.lint]\nselect = [\n \"E\", # pycodestyle errors\n \"W\", # pycodestyle warnings\n \"F\", # pyflakes\n \"I\", # isort\n \"N\", # pep8-naming\n \"UP\", # pyupgrade\n \"B\", # flake8-bugbear\n \"C4\", # flake8-comprehensions\n \"SIM\", # flake8-simplify\n \"S\", # flake8-bandit (security)\n \"A\", # flake8-builtins\n \"PT\", # flake8-pytest-style\n]\nignore = [\n \"E501\", # line-too-long (handled by formatter)\n \"S101\", # assert (OK in tests)\n]\n\n[tool.ruff.lint.per-file-ignores]\n\"tests/**/*.py\" = [\"S101\"] # Allow assert in tests\n\n[tool.ruff.format]\nquote-style = \"double\"\nindent-style = \"space\"\n```\n\n### Usage\n\n```bash\n# Check linting\nruff check src/\n\n# Auto-fix issues\nruff check --fix src/\n\n# Format code\nruff format src/\n\n# Check formatting only\nruff format --check src/\n```\n\n---\n\n## Reducing Complexity\n\n**Target:** Maximum cyclomatic complexity of 10 (Grade B) per function\n\n### Why Complexity Matters\n\n- CC = number of independent paths through code\n- CC > 10 means exponentially more test cases for coverage\n- High complexity correlates with defect density\n- Humans (and LLMs) struggle with deeply nested logic\n\n### Pattern 1: Dispatch Pattern (Handler Registry)\n\n**When to use:** Functions with if/elif chains that dispatch based on mode or type.\n\n```python\n# Bad - if/elif chain (CC=18+)\ndef main():\n if args.patch:\n # 90 lines of patch logic\n elif args.read:\n # 20 lines of read logic\n else:\n # 100 lines of write logic\n\n# Good - Dispatch pattern (CC=6)\ndef _handle_patch_mode(args: Args, client: Client) -> None:\n \"\"\"Handle --patch mode.\"\"\"\n # Focused patch logic\n\ndef _handle_read_mode(args: Args, client: Client) -> None:\n \"\"\"Handle --read mode.\"\"\"\n # Focused read logic\n\ndef main() -> int:\n args = parse_args()\n client = build_client()\n\n handlers = {\n \"patch\": _handle_patch_mode,\n \"read\": _handle_read_mode,\n \"write\": _handle_write_mode,\n }\n\n handler = handlers.get(args.mode, _handle_write_mode)\n handler(args, client)\n return 0\n```\n\n### Pattern 2: Early Returns (Guard Clauses)\n\n```python\n# Bad - Deep nesting (CC=8)\ndef validate_document(doc: Document) -> bool:\n if doc:\n if doc.content:\n if len(doc.content) > 0:\n if doc.tenant:\n return True\n return False\n\n# Good - Guard clauses (CC=4)\ndef validate_document(doc: Document | None) -> bool:\n if not doc:\n return False\n if not doc.content:\n return False\n if len(doc.content) == 0:\n return False\n if not doc.tenant:\n return False\n return True\n```\n\n### Pattern 3: Lookup Tables\n\n```python\n# Bad - Each 'or' adds +1 CC\ndef normalize_field(key: str, value: str) -> str:\n if key == \"tls.crt\" or key == \"tls.key\" or key == \"ca\":\n return normalize_cert_field(value)\n elif key == \"config.json\":\n return normalize_pull_secret_json(value)\n else:\n return value\n\n# Good - O(1) lookup\nNORMALIZERS: dict[str, Callable[[str], str]] = {\n \"tls.crt\": normalize_cert_field,\n \"tls.key\": normalize_cert_field,\n \"ca\": normalize_cert_field,\n \"config.json\": normalize_pull_secret_json,\n}\n\ndef normalize_field(key: str, value: str) -> str:\n normalizer = NORMALIZERS.get(key)\n return normalizer(value) if normalizer else value\n```\n\n### Pattern 4: Strategy Pattern (Class-Based)\n\n```python\n# Bad - Type checking with isinstance\ndef process(item: Item) -> Result:\n if isinstance(item, TypeA):\n # TypeA logic\n elif isinstance(item, TypeB):\n # TypeB logic\n elif isinstance(item, TypeC):\n # TypeC logic\n # ... many more types\n\n# Good - Strategy pattern\nfrom abc import ABC, abstractmethod\n\nclass ItemProcessor(ABC):\n @abstractmethod\n def process(self, item: Item) -> Result:\n pass\n\nclass TypeAProcessor(ItemProcessor):\n def process(self, item: Item) -> Result:\n # TypeA logic\n\nclass TypeBProcessor(ItemProcessor):\n def process(self, item: Item) -> Result:\n # TypeB logic\n\n# Registry\nPROCESSORS: dict[type, ItemProcessor] = {\n TypeA: TypeAProcessor(),\n TypeB: TypeBProcessor(),\n}\n\ndef process(item: Item) -> Result:\n processor = PROCESSORS.get(type(item))\n if not processor:\n raise ValueError(f\"No processor for {type(item)}\")\n return processor.process(item)\n```\n\n### Helper Naming Convention\n\n| Prefix | Meaning | Example |\n|--------|---------|---------|\n| `_handle_` | Mode/dispatch handler | `_handle_patch_mode()` |\n| `_process_` | Processing helper | `_process_secret()` |\n| `_validate_` | Validation helper | `_validate_cert()` |\n| `_setup_` | Initialization helper | `_setup_mount_point()` |\n| `_normalize_` | Data normalization | `_normalize_cert_field()` |\n| `_build_` | Construction | `_build_audit_metadata()` |\n\n### Measuring Complexity\n\n```bash\n# Check specific file\nradon cc scripts/my_script.py -s -a\n\n# Fail if any function exceeds Grade B (CC > 10)\nxenon scripts/ --max-absolute B\n\n# Show only Grade C or worse\nradon cc scripts/ -s -n C\n```\n\n---\n\n## Type Hints\n\n### Modern Syntax (Python 3.12+)\n\n```python\nfrom __future__ import annotations\nfrom typing import Any, Callable, TypeVar\n\n# Basic types - use lowercase\nitems: list[str] = []\nmapping: dict[str, int] = {}\ncoords: tuple[int, int, int] = (0, 0, 0)\n\n# Union with pipe operator\nvalue: str | int = \"hello\"\noptional: str | None = None\n\n# Function signatures\ndef process(\n items: list[str],\n config: dict[str, Any] | None = None,\n callback: Callable[[str], bool] | None = None,\n) -> list[str]:\n \"\"\"Process items with optional config.\"\"\"\n ...\n\n# Generics\nT = TypeVar(\"T\")\n\ndef first(items: list[T]) -> T | None:\n return items[0] if items else None\n```\n\n### Type Hint Anti-Patterns\n\n| Anti-Pattern | Problem | Better |\n|--------------|---------|--------|\n| `Any` everywhere | Defeats type checking | Use generics or specific types |\n| `# type: ignore` without comment | Hides real issues | Add explanation |\n| Old syntax `List[str]` | Deprecated | Use `list[str]` |\n| Missing return type | Incomplete signature | Always add return type |\n\n---\n\n## Docstrings\n\n### Google Style (Required)\n\n```python\ndef verify_secret_after_write(\n client: hvac.Client,\n mount_point: str,\n name: str,\n expected_payload: dict[str, Any],\n) -> bool:\n \"\"\"Verify secret was written correctly.\n\n Args:\n client: Vault client connection.\n mount_point: KV v2 mount point path.\n name: Secret name/key.\n expected_payload: Expected secret data to verify against.\n\n Returns:\n True if verification passed, False if any check failed.\n\n Raises:\n hvac.exceptions.InvalidPath: If secret path is invalid.\n ConnectionError: If Vault connection fails.\n\n Example:\n >>> client = hvac.Client(url=\"http://localhost:8200\")\n >>> verify_secret_after_write(client, \"secret\", \"mykey\", {\"foo\": \"bar\"})\n True\n \"\"\"\n pass\n```\n\n### When to Include Each Section\n\n| Section | When to Include |\n|---------|-----------------|\n| **Args** | Always if function has parameters |\n| **Returns** | Always if function returns non-None |\n| **Raises** | If function can raise exceptions |\n| **Example** | For complex or non-obvious usage |\n| **Note** | For important caveats or warnings |\n\n---\n\n## Error Handling\n\n### Good Patterns\n\n```python\n# Good - Specific exception, logged\ntry:\n cert_info = validate_certificate(payload[\"tls.crt\"])\nexcept subprocess.CalledProcessError as exc:\n logging.warning(\"Certificate validation failed: %s\", exc)\n\n# Good - Multiple specific types for format detection\ntry:\n decoded = base64.b64decode(data)\nexcept (UnicodeDecodeError, base64.binascii.Error, ValueError) as exc:\n logging.debug(\"Not base64, assuming PEM format: %s\", exc)\n decoded = data\n\n# Good - Re-raise with context\ntry:\n result = subprocess.run(cmd, check=True, capture_output=True)\nexcept subprocess.CalledProcessError as exc:\n raise RuntimeError(f\"Command failed: {cmd}\") from exc\n\n# Good - Custom exception with context\nclass ConfigError(Exception):\n \"\"\"Configuration validation error.\"\"\"\n def __init__(self, key: str, message: str):\n self.key = key\n super().__init__(f\"Config '{key}': {message}\")\n```\n\n### Bad Patterns\n\n```python\n# Bad - Bare exception, swallowed\ntry:\n validate_something()\nexcept Exception:\n pass # Silent failure!\n\n# Bad - Catching Exception without re-raising\ntry:\n process_data()\nexcept Exception as e:\n logging.error(\"Error: %s\", e)\n return None # Hides the problem\n\n# Bad - Too broad, catches KeyboardInterrupt\ntry:\n long_running_task()\nexcept: # noqa: E722\n pass\n```\n\n### Exception Hierarchy for Custom Errors\n\n```python\nclass MyAppError(Exception):\n \"\"\"Base exception for application errors.\"\"\"\n\nclass ValidationError(MyAppError):\n \"\"\"Input validation failed.\"\"\"\n\nclass ConnectionError(MyAppError):\n \"\"\"External service connection failed.\"\"\"\n\nclass ConfigError(MyAppError):\n \"\"\"Configuration error.\"\"\"\n```\n\n---\n\n## Logging\n\n### Standard Setup\n\n```python\nimport logging\n\n# Basic setup for scripts\nlogging.basicConfig(\n format=\"%(asctime)s %(levelname)s %(message)s\",\n level=logging.INFO,\n)\n\n# Module logger for libraries\nlog = logging.getLogger(__name__)\n```\n\n### Log Levels\n\n| Level | When to Use |\n|-------|-------------|\n| `DEBUG` | Detailed diagnostic (development only) |\n| `INFO` | Key events, progress |\n| `WARNING` | Recoverable issues |\n| `ERROR` | Operation failed |\n| `CRITICAL` | Application cannot continue |\n\n### Good Patterns\n\n```python\n# Good - Use % formatting (lazy evaluation)\nlogging.info(\"Processing secret: %s\", secret_name)\nlogging.warning(\"Retry %d of %d: %s\", attempt, max_retries, error)\n\n# Good - Include context\nlogging.info(\"Prepared %s: %s\", secret_name, preview)\nlogging.warning(\"Security policy check failed for %s: %s\", key, exc)\n\n# Good - Structured for parsing\nlogging.info(\"event=secret_prepared name=%s preview=%s\", secret_name, preview)\n```\n\n### Bad Patterns\n\n```python\n# Bad - f-string (evaluated even if level disabled)\nlogging.info(f\"Processing {expensive_to_compute()}\")\n\n# Bad - No context\nlogging.info(\"Processing...\")\nlogging.error(str(e))\n\n# Bad - print() instead of logging\nprint(\"DEBUG: value is\", value)\n```\n\n---\n\n## Testing\n\n### Pytest Structure\n\n```text\ntests/\n├── conftest.py # Shared fixtures\n├── test_core.py # Unit tests for core module\n├── test_utils.py # Unit tests for utils\n└── e2e/ # End-to-end tests\n ├── conftest.py # Testcontainers fixtures\n └── test_integration.py\n```\n\n### Configuration\n\n```toml\n# pyproject.toml\n[tool.pytest.ini_options]\ntestpaths = [\"tests\"]\nmarkers = [\n \"e2e: marks tests as end-to-end (require Docker)\",\n \"slow: marks tests as slow\",\n]\naddopts = \"-v --tb=short\"\n\n[tool.coverage.run]\nsource = [\"src\"]\nbranch = true\n\n[tool.coverage.report]\nexclude_lines = [\n \"pragma: no cover\",\n \"if TYPE_CHECKING:\",\n \"raise NotImplementedError\",\n]\n```\n\n### Testcontainers for E2E Tests\n\nUse testcontainers for tests that need real infrastructure.\n\n```python\n# tests/e2e/conftest.py\nimport pytest\nfrom testcontainers.postgres import PostgresContainer\n\[email protected](scope=\"session\")\ndef postgres_container():\n \"\"\"Spin up PostgreSQL for E2E tests.\"\"\"\n with PostgresContainer(\"postgres:16\") as postgres:\n yield postgres\n # Container automatically cleaned up\n\[email protected]\ndef db_connection(postgres_container):\n \"\"\"Get connection to test database.\"\"\"\n import psycopg\n conn_str = postgres_container.get_connection_url()\n with psycopg.connect(conn_str) as conn:\n yield conn\n```\n\n### Test Patterns\n\n```python\n# Table-driven tests\nimport pytest\n\[email protected](\"input,expected\", [\n (\"[email protected]\", True),\n (\"invalid\", False),\n (\"\", False),\n (\"@nodomain\", False),\n])\ndef test_validate_email(input: str, expected: bool):\n assert validate_email(input) == expected\n\n# Fixtures for setup/teardown\[email protected]\ndef temp_config(tmp_path):\n \"\"\"Create temporary config file.\"\"\"\n config_file = tmp_path / \"config.yaml\"\n config_file.write_text(\"key: value\")\n return config_file\n\ndef test_load_config(temp_config):\n config = load_config(temp_config)\n assert config[\"key\"] == \"value\"\n\n# Mock external services\nfrom unittest.mock import patch, MagicMock\n\ndef test_api_call():\n with patch(\"mymodule.requests.get\") as mock_get:\n mock_get.return_value = MagicMock(status_code=200, json=lambda: {\"data\": \"test\"})\n result = my_api_function()\n assert result == {\"data\": \"test\"}\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run with coverage\npytest --cov=src --cov-report=term-missing\n\n# Run only E2E tests\npytest -m e2e\n\n# Run excluding slow tests\npytest -m \"not slow\"\n```\n\n---\n\n## CLI Script Template\n\n```python\n#!/usr/bin/env python3\n\"\"\"One-line description of what this script does.\n\nUsage:\n python3 script_name.py --config config.yaml --apply\n\nExit Codes:\n 0 - Success\n 1 - Argument/configuration error\n 2 - Runtime error\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport logging\nimport sys\nfrom pathlib import Path\nfrom typing import Any\n\nlogging.basicConfig(\n format=\"%(asctime)s %(levelname)s %(message)s\",\n level=logging.INFO,\n)\n\n\ndef die(message: str) -> None:\n \"\"\"Print error message and exit with code 1.\"\"\"\n logging.error(message)\n sys.exit(1)\n\n\ndef parse_args() -> argparse.Namespace:\n \"\"\"Parse command-line arguments.\"\"\"\n parser = argparse.ArgumentParser(\n description=__doc__,\n formatter_class=argparse.RawDescriptionHelpFormatter,\n )\n parser.add_argument(\n \"--config\",\n default=\"config.yaml\",\n type=Path,\n help=\"Path to config file (default: config.yaml)\",\n )\n parser.add_argument(\n \"--apply\",\n action=\"store_true\",\n help=\"Apply changes (default: dry-run)\",\n )\n parser.add_argument(\n \"-v\", \"--verbose\",\n action=\"store_true\",\n help=\"Enable debug logging\",\n )\n return parser.parse_args()\n\n\ndef main() -> int:\n \"\"\"Main entry point.\"\"\"\n args = parse_args()\n\n if args.verbose:\n logging.getLogger().setLevel(logging.DEBUG)\n\n if not args.apply:\n logging.info(\"Dry-run mode (use --apply to make changes)\")\n\n # Validate config exists\n if not args.config.exists():\n die(f\"Config file not found: {args.config}\")\n\n # Main logic here\n try:\n # ... implementation\n logging.info(\"Processing complete\")\n return 0\n except Exception as exc:\n logging.error(\"Failed: %s\", exc)\n return 2\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n```\n\n---\n\n## Code Quality Metrics\n\n> See `common-standards.md` for universal coverage targets and testing principles.\n\n### Complexity Thresholds\n\n| Grade | CC Range | Action |\n|-------|----------|--------|\n| A | 1-5 | Ideal - simple, low risk |\n| B | 6-10 | Acceptable - moderate complexity |\n| C | 11-20 | Refactor when touching |\n| D | 21-30 | Must refactor before merge |\n| F | 31+ | Block merge |\n\n### Validation Commands\n\n```bash\n# Code quality + style\nruff check src/ --statistics\n# Output: \"10 errors, 5 warnings\" → Count these\n\n# Complexity analysis\nradon cc src/ -s -a\n# Output includes per-function CC and average → Report both\n\n# Enforce complexity limit\nxenon src/ --max-absolute B\n# Fails if any function exceeds CC=10\n\n# Test coverage\npytest --cov=src --cov-report=term-missing\n# Output: \"87% line, 71% branch\" → Report both\n\n# Docstring coverage\ninterrogate src/\n# Output: \"85% (45/53 functions)\" → Report fraction + %\n```\n\n---\n\n## Security Practices\n\n### eval/exec Avoidance\n\nNever use `eval()` or `exec()` on user-controlled input:\n\n```python\n# DANGEROUS - Remote code execution\nuser_expr = request.args[\"expr\"]\nresult = eval(user_expr) # Attacker sends: __import__('os').system('rm -rf /')\n\n# SAFE - Use ast.literal_eval for data literals\nimport ast\nresult = ast.literal_eval(user_input) # Only parses strings, numbers, tuples, lists, dicts\n\n# SAFE - Use a mapping for dynamic dispatch\nOPERATIONS = {\"add\": operator.add, \"mul\": operator.mul}\nfunc = OPERATIONS.get(user_input)\nif func:\n result = func(a, b)\n```\n\n**Validation:** Prescan pattern P16 detects `eval(` and `exec(` calls\n\n### Pickle Safety\n\nNever unpickle untrusted data — `pickle.loads()` executes arbitrary code:\n\n```python\n# DANGEROUS - Arbitrary code execution on load\nimport pickle\ndata = pickle.loads(untrusted_bytes) # Attacker crafts payload to run code\n\n# SAFE - Use JSON for data interchange\nimport json\ndata = json.loads(untrusted_bytes)\n\n# SAFE - Use msgpack for binary efficiency\nimport msgpack\ndata = msgpack.unpackb(untrusted_bytes, raw=False)\n```\n\nIf pickle is unavoidable (e.g., ML model loading), load only from trusted, integrity-verified sources.\n\n### YAML Deserialization\n\n`yaml.load()` with the default loader executes arbitrary Python objects:\n\n```python\n# DANGEROUS - Arbitrary code execution\nimport yaml\ndata = yaml.load(untrusted_string) # Can execute __reduce__, !!python/object, etc.\n\n# SAFE - Use safe_load (only basic YAML types)\ndata = yaml.safe_load(untrusted_string)\n\n# SAFE - Explicit SafeLoader\ndata = yaml.load(untrusted_string, Loader=yaml.SafeLoader)\n```\n\n**Rule:** Always use `yaml.safe_load()` or `yaml.safe_load_all()`. Never use `yaml.load()` without `Loader=yaml.SafeLoader`.\n\n### SQL Injection Prevention\n\nAlways use parameterized queries:\n\n```python\n# DANGEROUS - SQL injection\ncursor.execute(f\"SELECT * FROM users WHERE name = '{user_input}'\")\n\n# SAFE - Parameterized query\ncursor.execute(\"SELECT * FROM users WHERE name = %s\", (user_input,))\n\n# SAFE - SQLAlchemy ORM\nuser = session.query(User).filter(User.name == user_input).first()\n\n# SAFE - SQLAlchemy text with bind params\nfrom sqlalchemy import text\nstmt = text(\"SELECT * FROM users WHERE name = :name\")\nresult = conn.execute(stmt, {\"name\": user_input})\n```\n\n### SSRF Prevention\n\nValidate URLs before making outbound requests:\n\n```python\n# DANGEROUS - Server-Side Request Forgery\nurl = request.args[\"url\"]\nresp = requests.get(url) # Attacker sends: http://169.254.169.254/metadata\n\n# SAFE - URL allowlist validation\nfrom urllib.parse import urlparse\n\nALLOWED_HOSTS = {\"api.example.com\", \"cdn.example.com\"}\n\ndef validate_url(url: str) -> bool:\n parsed = urlparse(url)\n if parsed.scheme not in (\"http\", \"https\"):\n return False\n if parsed.hostname not in ALLOWED_HOSTS:\n return False\n return True\n\nif validate_url(url):\n resp = requests.get(url, timeout=10)\n```\n\n### Path Traversal Prevention\n\nUser-controlled path components can escape intended directories:\n\n```python\n# DANGEROUS - Path traversal\nuser_file = request.args[\"filename\"]\npath = os.path.join(\"/data/uploads\", user_file) # \"../../../etc/passwd\" escapes!\ncontent = open(path).read()\n\n# SAFE - Resolve and check prefix\nfrom pathlib import Path\n\nUPLOAD_DIR = Path(\"/data/uploads\").resolve()\n\ndef safe_read(filename: str) -> str:\n target = (UPLOAD_DIR / filename).resolve()\n if not target.is_relative_to(UPLOAD_DIR):\n raise ValueError(f\"Path traversal blocked: {filename!r}\")\n return target.read_text()\n\n# SAFE - Strip directory components entirely\nfrom pathlib import PurePosixPath\n\ndef sanitize_filename(filename: str) -> str:\n \"\"\"Extract only the final filename component.\"\"\"\n return PurePosixPath(filename).name\n```\n\n**Key pitfalls:**\n- `os.path.join(\"/base\", \"/etc/passwd\")` returns `/etc/passwd` (absolute path overrides base)\n- Symlinks can bypass prefix checks — use `.resolve()` before comparison\n- Always use `pathlib.Path.is_relative_to()` (Python 3.9+) for containment checks\n- Never construct file paths from user input without validation\n\n### Input Validation\n\nValidate all external input at system boundaries:\n\n```python\n# Pydantic (recommended for structured data)\nfrom pydantic import BaseModel, Field, field_validator\n\nclass CreateUserRequest(BaseModel):\n name: str = Field(min_length=1, max_length=100)\n email: str = Field(pattern=r\"^[\\w.+-]+@[\\w-]+\\.[\\w.]+$\")\n age: int = Field(ge=0, le=150)\n\n @field_validator(\"name\")\n @classmethod\n def no_script_tags(cls, v: str) -> str:\n if \"\u003cscript\" in v.lower():\n raise ValueError(\"HTML not allowed in name\")\n return v.strip()\n\n# Manual validation for simple cases\ndef validate_port(port: str) -> int:\n try:\n p = int(port)\n except ValueError:\n raise ValueError(f\"Invalid port: {port!r}\")\n if not (1 \u003c= p \u003c= 65535):\n raise ValueError(f\"Port out of range: {p}\")\n return p\n```\n\n### Secrets Management\n\nNever hardcode secrets in source code:\n\n```python\n# DANGEROUS - Hardcoded secrets\nAPI_KEY = \"REDACTED\" # Leaked in git history forever\ndb_url = \"postgresql://user:REDACTED@prod-db:5432/app\"\n\n# SAFE - Environment variables\nimport os\nAPI_KEY = os.environ[\"API_KEY\"] # Fails loudly if missing\n\n# SAFE - With default for optional config\nDEBUG = os.environ.get(\"DEBUG\", \"false\").lower() == \"true\"\n\n# SAFE - Vault/secrets manager for production\nfrom hvac import Client\nvault = Client(url=os.environ[\"VAULT_ADDR\"])\nsecret = vault.secrets.kv.v2.read_secret_version(path=\"myapp/creds\")\n```\n\n**Validation:** Prescan pattern P17 detects common secret patterns (API keys, passwords in strings)\n\n### Subprocess Safety\n\nAvoid `shell=True` — it enables command injection:\n\n```python\n# DANGEROUS - Shell injection\nfilename = request.args[\"file\"]\nsubprocess.run(f\"cat {filename}\", shell=True) # Attacker sends: \"; rm -rf /\"\n\n# SAFE - List arguments, no shell\nsubprocess.run([\"cat\", filename], check=True, capture_output=True)\n\n# SAFE - For complex pipelines, use Python instead of shell\nfrom pathlib import Path\ncontent = Path(filename).read_text()\n\n# If shell=True is truly needed, validate input strictly\nimport shlex\nsafe_arg = shlex.quote(user_input)\n```\n\n### ALWAYS / NEVER Rules\n\n| Rule | Category | Detail |\n|------|----------|--------|\n| **ALWAYS** use parameterized queries | SQL | Never interpolate user input into SQL strings |\n| **ALWAYS** validate URLs before fetch | SSRF | Check scheme, hostname against allowlist |\n| **ALWAYS** resolve and check path prefix | Path Traversal | Use `pathlib.resolve()` + `is_relative_to()` |\n| **ALWAYS** use `secrets` module for tokens | Crypto | `secrets.token_urlsafe()`, not `random` |\n| **ALWAYS** set request timeouts | Network | `requests.get(url, timeout=10)` |\n| **NEVER** use `eval()`/`exec()` on user input | Injection | Use `ast.literal_eval` or dispatch maps |\n| **NEVER** unpickle untrusted data | Deserialization | Use JSON or msgpack instead |\n| **NEVER** use `shell=True` with user input | Command injection | Use list args with `subprocess.run` |\n| **NEVER** hardcode secrets | Secrets | Use env vars or vault |\n| **NEVER** disable TLS verification | TLS | No `verify=False` in production |\n| **NEVER** log secrets or tokens | Logging | Redact sensitive fields before logging |\n\n---\n\n## Anti-Patterns Avoided\n\n> See `common-standards.md` for universal anti-patterns across all languages.\n\n### No God Functions\n\n```python\n# Bad - Single function doing everything\ndef process_all(data):\n # 200+ lines of validation, transformation, saving, logging...\n pass\n\n# Good - Separated concerns\ndef validate(data: Data) -> ValidationResult:\n ...\n\ndef transform(data: Data) -> TransformedData:\n ...\n\ndef save(data: TransformedData) -> None:\n ...\n```\n\n### No Bare Except\n\n```python\n# Bad\ntry:\n risky_operation()\nexcept:\n pass\n\n# Good\ntry:\n risky_operation()\nexcept SpecificError as e:\n logging.warning(\"Operation failed: %s\", e)\n```\n\n### No Global Mutable State\n\n```python\n# Bad\nconfig = {} # Module-level mutable\n\ndef load_config(path):\n global config\n config = load_yaml(path)\n\n# Good\n@dataclass\nclass Config:\n setting_a: str\n setting_b: int\n\ndef load_config(path: Path) -> Config:\n data = load_yaml(path)\n return Config(**data)\n```\n\n### No Magic Strings\n\n```python\n# Bad\nif status == \"pending\":\n ...\nelif status == \"complete\":\n ...\n\n# Good\nclass Status(str, Enum):\n PENDING = \"pending\"\n COMPLETE = \"complete\"\n\nif status == Status.PENDING:\n ...\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Code Quality** | ruff violations count, auto-fixable count |\n| **Complexity** | radon cc output, functions >CC10 count |\n| **Type Safety** | % public functions with hints, missing count |\n| **Error Handling** | Bare except count, specific exception count |\n| **Testing** | pytest coverage (line/branch %), test count |\n| **Documentation** | Docstring coverage %, missing count |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | 0 ruff violations, 0 functions >CC10, 95%+ hints, 90%+ coverage |\n| A | \u003c5 ruff violations, \u003c3 functions >CC10, 85%+ hints, 80%+ coverage |\n| A- | \u003c15 ruff violations, \u003c8 functions >CC10, 75%+ hints, 70%+ coverage |\n| B+ | \u003c30 ruff violations, \u003c15 functions >CC10, 60%+ hints, 60%+ coverage |\n| B | \u003c50 ruff violations, \u003c25 functions >CC10, 50%+ hints, 50%+ coverage |\n| C | Significant issues, major refactoring needed |\n| D | Not production-ready |\n| F | Critical issues |\n\n### Example Assessment\n\n```markdown\n## Python Standards Compliance\n\n**Target:** src/\n**Date:** 2026-01-21\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Code Quality | A- | 8 ruff violations (6 fixable), 0 security |\n| Complexity | B+ | 12 functions >CC10, avg CC=6.8 (radon) |\n| Type Safety | A | 47/52 public functions typed (90%) |\n| Error Handling | A- | 0 bare except, 2 broad catches |\n| Testing | B | 73% line, 58% branch (pytest) |\n| Documentation | A | 48/52 documented (92%, interrogate) |\n| **OVERALL** | **A-** | **8 HIGH, 15 MEDIUM findings** |\n\n### High Priority Findings\n\n- **CMPLX-001** - `processor.py:89` CC=15 - Refactor dispatch\n- **TYPE-001** - `utils.py` - 5 functions missing hints\n```\n\n---\n\n## Vibe Integration\n\n### Prescan Patterns\n\n| Pattern | Severity | Detection |\n|---------|----------|-----------|\n| P04: Bare Except | HIGH | `except:` or `except Exception:` without re-raise |\n| P08: print() Debug | MEDIUM | `print(` in non-CLI modules |\n| P15: f-string Logging | LOW | `logging.*\\(f\"` pattern |\n\n### JIT Loading\n\n**Tier 1 (Fast):** Load `~/.agents/skills/standards/references/python.md` (5KB)\n**Tier 2 (Deep):** Load this document (20KB) for comprehensive audit\n\n---\n\n## Additional Resources\n\n- [PEP 8 - Style Guide](https://peps.python.org/pep-0008/)\n- [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html)\n- [ruff Documentation](https://docs.astral.sh/ruff/)\n- [radon Complexity](https://radon.readthedocs.io/)\n- [pytest Documentation](https://docs.pytest.org/)\n- [testcontainers-python](https://testcontainers-python.readthedocs.io/)\n\n---\n\n**Related:** `python-patterns.md` for quick reference examples (if needed)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":30711,"content_sha256":"c426c007af629c99ecd3c2604f1bdd3cb575196f575bb409661ded97f0e5dfb1"},{"filename":"references/report-format.md","content":"# Vibe Report Formats\n\n## Output Files\n\n| File | Purpose |\n|------|---------|\n| `reports/vibe-report.json` | Full JSON findings |\n| `reports/vibe-junit.xml` | CI integration (JUnit XML) |\n| `.agents/assessments/{date}-vibe-validate-{target}.md` | Knowledge artifact |\n\n---\n\n## Vibe Report Markdown Template\n\n> Used by Step 7 in SKILL.md. Write to `.agents/council/YYYY-MM-DD-vibe-\u003ctarget>.md`.\n\n```markdown\n---\nid: council-YYYY-MM-DD-vibe-\u003ctarget-slug>\ntype: council\ndate: YYYY-MM-DD\n---\n\n# Vibe Report: \u003cTarget>\n\n**Files Reviewed:** \u003ccount>\n\n## Complexity Analysis\n\n**Status:** Completed | Skipped (\u003creason>)\n\n| File | Score | Rating | Notes |\n|------|-------|--------|-------|\n| src/auth.py | 15 | C | Consider breaking up |\n| src/utils.py | 4 | A | Good |\n\n**Hotspots:** \u003clist files with C or worse>\n**Skipped reason:** \u003cif skipped, explain why - e.g., \"radon not installed\">\n\n## Council Verdict: PASS / WARN / FAIL\n\n| Judge | Verdict | Key Finding |\n|-------|---------|-------------|\n| Error-Paths | ... | ... (with spec — code-review preset) |\n| API-Surface | ... | ... (with spec — code-review preset) |\n| Spec-Compliance | ... | ... (with spec — code-review preset) |\n| Judge 1 | ... | ... (no spec — 2 independent judges) |\n| Judge 2 | ... | ... (no spec — 2 independent judges) |\n| Judge 3 | ... | ... (no spec — 2 independent judges) |\n\n## Shared Findings\n- ...\n\n## CRITICAL Findings (blocks ship)\n- ... (findings that indicate correctness, security, or data-safety issues)\n\n## INFORMATIONAL Findings (include in PR body)\n- ... (style suggestions, minor improvements, suppressed/downgraded items)\n\n## Concerns Raised\n- ...\n\n## All Findings\n\n> Included when `--deep` or `--sweep` produces a sweep manifest. Lists ALL findings\n> from explorer sweep + council adjudication. Grouped by category if >20 findings.\n\n| # | File | Line | Category | Severity | Description | Source |\n|---|------|------|----------|----------|-------------|--------|\n| 1 | ... | ... | ... | ... | ... | sweep / council |\n\n## Recommendation\n\nFor performance-sensitive code, run `/perf profile \u003ctarget>` to identify optimization opportunities.\n\n\u003ccouncil recommendation>\n\n## Decision\n\n[ ] SHIP - Complexity acceptable, council passed\n[ ] FIX - Address concerns before shipping\n[ ] REFACTOR - High complexity, needs rework\n```\n\n---\n\n## JSON Report Structure\n\n```json\n{\n \"summary\": {\n \"critical\": 0,\n \"high\": 2,\n \"medium\": 5,\n \"low\": 1,\n \"total\": 8\n },\n \"prescan\": [\n {\n \"id\": \"P4\",\n \"pattern\": \"Invisible Undone\",\n \"severity\": \"HIGH\",\n \"file\": \"services/auth/main.py\",\n \"line\": 42,\n \"message\": \"TODO marker\"\n }\n ],\n \"semantic\": [\n {\n \"id\": \"FAITH-001\",\n \"category\": \"docstrings\",\n \"severity\": \"HIGH\",\n \"file\": \"services/auth/main.py\",\n \"function\": \"validate_token\",\n \"message\": \"Docstring claims validation but no raise/return False\"\n }\n ]\n}\n```\n\n---\n\n## JUnit XML Format\n\nFor CI integration:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003ctestsuites name=\"vibe-validate\" tests=\"8\" failures=\"7\" errors=\"1\">\n \u003ctestsuite name=\"prescan\" tests=\"3\" failures=\"3\">\n \u003ctestcase name=\"P4-services/auth/main.py:42\" classname=\"prescan.invisible_undone\">\n \u003cfailure message=\"TODO marker\" type=\"HIGH\"/>\n \u003c/testcase>\n \u003c/testsuite>\n \u003ctestsuite name=\"semantic\" tests=\"5\" failures=\"4\">\n \u003ctestcase name=\"FAITH-001-validate_token\" classname=\"semantic.docstrings\">\n \u003cfailure message=\"Docstring mismatch\" type=\"HIGH\"/>\n \u003c/testcase>\n \u003c/testsuite>\n\u003c/testsuites>\n```\n\n---\n\n## Assessment Artifact Format\n\nSaved to `.agents/assessments/`:\n\n```yaml\n---\ndate: 2025-01-03\ntype: Assessment\nassessment_type: vibe-validate\nscope: recent\ntarget: HEAD~1..HEAD\nstatus: PASS_WITH_WARNINGS\nseverity: HIGH\nfindings:\n critical: 0\n high: 2\n medium: 5\n low: 1\n total: 8\ntags: [assessment, vibe-validate, validation, recent]\n---\n\n# Vibe Validation: recent\n\n## Summary\n\n| Severity | Count |\n|----------|-------|\n| CRITICAL | 0 |\n| HIGH | 2 |\n| MEDIUM | 5 |\n| LOW | 1 |\n\n## Critical Findings\n\nNone.\n\n## High Findings\n\n1. **P4** `services/auth/main.py:42` - TODO marker\n2. **FAITH-001** `validate_token()` - Docstring mismatch\n\n## Recommendations\n\n1. Complete or remove TODO at services/auth/main.py:42\n2. Update validate_token() docstring to match implementation\n```\n\n---\n\n## Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success, no CRITICAL findings |\n| 1 | Argument/usage error |\n| 2 | CRITICAL findings detected |\n| 3 | HIGH findings detected (no CRITICAL) |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4542,"content_sha256":"7a367f3ef71b6c1e8a2253b26c5330ab55fb89bf0620de72372bc68cb223220c"},{"filename":"references/rust-standards.md","content":"# Rust Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-02-09\n**Purpose:** Canonical Rust standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [Project Structure](#project-structure)\n2. [Cargo Configuration](#cargo-configuration)\n3. [Code Formatting](#code-formatting)\n4. [Ownership & Borrowing](#ownership--borrowing)\n5. [Error Handling Patterns](#error-handling-patterns)\n6. [Trait & Type System Design](#trait--type-system-design)\n7. [Concurrency Patterns](#concurrency-patterns)\n8. [Unsafe Code](#unsafe-code)\n9. [Testing Patterns](#testing-patterns)\n10. [Security Practices](#security-practices)\n11. [Documentation Standards](#documentation-standards)\n12. [Code Quality Metrics & Anti-Patterns](#code-quality-metrics--anti-patterns)\n\n---\n\n## Project Structure\n\n### ✅ **Standard Crate Layout**\n\n```\nmy-project/\n├── Cargo.toml # Package manifest\n├── Cargo.lock # Dependency lock (commit for binaries, .gitignore for libs)\n├── src/\n│ ├── lib.rs # Library root (public API surface)\n│ ├── main.rs # Binary entrypoint (or use src/bin/)\n│ ├── bin/\n│ │ ├── server.rs # Additional binary\n│ │ └── cli.rs # Additional binary\n│ ├── models/\n│ │ └── mod.rs # Domain types\n│ └── handlers/\n│ └── mod.rs # Request handlers\n├── tests/ # Integration tests (each file is a separate crate)\n│ ├── integration.rs\n│ └── e2e.rs\n├── examples/ # Runnable examples (`cargo run --example`)\n│ └── basic_usage.rs\n├── benches/ # Benchmarks (`cargo bench`)\n│ └── throughput.rs\n└── build.rs # Build script (optional)\n```\n\n**Principles:**\n- ✅ `src/lib.rs` defines the public API; `src/main.rs` consumes it\n- ✅ `src/bin/` for multiple binaries within one crate\n- ✅ `tests/` for integration tests (compiled as separate crates)\n- ✅ `examples/` for documentation-as-code\n- ✅ Commit `Cargo.lock` for binaries, omit for libraries\n\n### ⚠️ **Module Organization**\n\n```rust\n// GOOD - Explicit re-exports in lib.rs\npub mod config;\npub mod handlers;\npub mod models;\n\npub use config::Config;\npub use models::AppError;\n\n// BAD - Deep nesting with no re-exports\n// Forces users to write: my_crate::handlers::http::v1::webhook::process\n```\n\n**Module Size Thresholds:**\n\n| File Size | Status | Action |\n|-----------|--------|--------|\n| \u003c 300 lines | ✅ Excellent | Maintain |\n| 300-500 lines | ✅ Acceptable | Monitor |\n| 500-800 lines | ⚠️ Warning | Consider splitting |\n| 800+ lines | ❌ Critical | Split into submodules |\n\n---\n\n## Cargo Configuration\n\n### ✅ **Dependency Management**\n\n```toml\n[package]\nname = \"my-service\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.75\" # MSRV - minimum supported Rust version\n\n[dependencies]\ntokio = { version = \"1\", features = [\"full\"] }\nserde = { version = \"1\", features = [\"derive\"] }\nserde_json = \"1\"\nthiserror = \"2\"\ntracing = \"0.1\"\n\n[dev-dependencies]\ntokio = { version = \"1\", features = [\"test-util\", \"macros\"] }\nproptest = \"1\"\ncriterion = { version = \"0.5\", features = [\"html_reports\"] }\n\n[build-dependencies]\nprost-build = \"0.13\" # Only if needed at build time\n```\n\n**Requirements:**\n- ✅ Pin `edition` and `rust-version` for reproducibility\n- ✅ Use feature flags to minimize compile-time and binary size\n- ✅ Separate `dev-dependencies` from production deps\n- ✅ Never use wildcard versions (`*`)\n\n### ✅ **Feature Flags**\n\n```toml\n[features]\ndefault = [\"json\"]\njson = [\"dep:serde_json\"]\ntls = [\"dep:rustls\"]\nfull = [\"json\", \"tls\"]\n\n# Optional dependencies gated by feature\n[dependencies]\nserde_json = { version = \"1\", optional = true }\nrustls = { version = \"0.23\", optional = true }\n```\n\n**Why This Matters:**\n- Users opt into functionality they need\n- Reduces compile time and binary size\n- Avoids pulling transitive dependencies unnecessarily\n\n### ✅ **Profile Configuration**\n\n```toml\n[profile.release]\nlto = true # Link-time optimization\ncodegen-units = 1 # Single codegen unit for max optimization\nstrip = true # Strip debug symbols from binary\npanic = \"abort\" # Smaller binary, no unwinding\n\n[profile.dev]\nopt-level = 0 # Fast compile\ndebug = true # Full debug info\n\n[profile.test]\nopt-level = 1 # Slight optimization for faster test runs\n```\n\n### ✅ **Workspace Configuration**\n\n```toml\n# Root Cargo.toml\n[workspace]\nmembers = [\n \"crates/core\",\n \"crates/api\",\n \"crates/cli\",\n]\n\n[workspace.dependencies]\nserde = { version = \"1\", features = [\"derive\"] }\ntokio = { version = \"1\", features = [\"full\"] }\n\n# In member Cargo.toml\n[dependencies]\nserde = { workspace = true }\ntokio = { workspace = true }\n```\n\n**Benefits:**\n- Single lockfile across all crates\n- Unified dependency versions\n- `cargo test --workspace` runs all tests\n\n---\n\n## Code Formatting\n\n### ✅ **rustfmt Configuration**\n\n```toml\n# rustfmt.toml\nedition = \"2021\"\nmax_width = 100\ntab_spaces = 4\nuse_field_init_shorthand = true\nuse_try_shorthand = true\nimports_granularity = \"Module\"\ngroup_imports = \"StdExternalCrate\"\n```\n\n**Requirements:**\n- ✅ Run `cargo fmt --check` in CI (zero-tolerance for formatting drift)\n- ✅ `group_imports = \"StdExternalCrate\"` enforces import order: std, external, crate-local\n\n### ✅ **Import Grouping**\n\n```rust\n// GOOD - Grouped and ordered\nuse std::collections::HashMap;\nuse std::sync::Arc;\n\nuse serde::{Deserialize, Serialize};\nuse tokio::sync::Mutex;\n\nuse crate::config::Config;\nuse crate::models::AppError;\n\n// BAD - Unorganized imports\nuse crate::config::Config;\nuse std::collections::HashMap;\nuse serde::Serialize;\nuse std::sync::Arc;\nuse crate::models::AppError;\nuse tokio::sync::Mutex;\n```\n\n### ✅ **Naming Conventions**\n\n| Item | Convention | Example |\n|------|-----------|---------|\n| Types, Traits | `UpperCamelCase` | `HttpClient`, `Serialize` |\n| Functions, Methods | `snake_case` | `process_request` |\n| Local Variables | `snake_case` | `retry_count` |\n| Constants | `SCREAMING_SNAKE_CASE` | `MAX_RETRIES` |\n| Modules | `snake_case` | `error_handling` |\n| Type Parameters | Single uppercase or `CamelCase` | `T`, `Item` |\n| Lifetimes | Short lowercase | `'a`, `'ctx` |\n| Crate Names | `kebab-case` (Cargo.toml) | `my-service` |\n| Feature Flags | `kebab-case` | `full-json` |\n\n### ⚠️ **Naming Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| `get_` prefix on getters | Redundant in Rust | `fn name(&self)` not `fn get_name(&self)` |\n| `FooStruct` suffix | Redundant | `Foo` |\n| `IFoo` prefix on traits | Not idiomatic Rust | `Foo` trait, `FooImpl` if needed |\n| Single-letter variable names | Unreadable (except in closures/iterators) | Descriptive names |\n\n---\n\n## Ownership & Borrowing\n\n### ✅ **Prefer Borrowing Over Ownership**\n\n```rust\n// GOOD - Borrows the string, caller retains ownership\nfn validate_email(email: &str) -> bool {\n email.contains('@') && email.contains('.')\n}\n\n// BAD - Takes ownership unnecessarily\nfn validate_email(email: String) -> bool {\n email.contains('@') && email.contains('.')\n}\n```\n\n**Why This Matters:**\n- Borrowing avoids unnecessary allocations and clones\n- Caller retains ownership for reuse\n- `&str` accepts both `String` and `&str` via deref coercion\n\n### ✅ **Lifetime Annotations**\n\n```rust\n// GOOD - Explicit lifetime ties output to input\nfn first_word(s: &str) -> &str {\n s.split_whitespace().next().unwrap_or(\"\")\n}\n\n// GOOD - Multiple lifetimes when inputs have different scopes\nfn longest\u003c'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\n\n// GOOD - Struct borrowing data\nstruct Config\u003c'a> {\n name: &'a str,\n version: &'a str,\n}\n```\n\n**Lifetime Elision Rules (when annotations are NOT needed):**\n1. Each reference parameter gets its own lifetime\n2. If exactly one input lifetime, it applies to all output lifetimes\n3. If `&self` or `&mut self`, its lifetime applies to all output lifetimes\n\n### ✅ **Copy vs Clone**\n\n```rust\n// GOOD - Small, stack-only types implement Copy\n#[derive(Debug, Clone, Copy, PartialEq)]\nstruct Point {\n x: f64,\n y: f64,\n}\n\n// GOOD - Types with heap data implement Clone only\n#[derive(Debug, Clone)]\nstruct Config {\n name: String, // String is Clone but NOT Copy\n retries: u32,\n}\n```\n\n| Trait | Behavior | Use When |\n|-------|----------|----------|\n| `Copy` | Implicit bitwise copy | Small stack-only types (integers, bools, tuples of Copy types) |\n| `Clone` | Explicit `.clone()` | Heap-allocated or expensive-to-copy types |\n| Neither | Move semantics | Unique resources (file handles, connections) |\n\n### ⚠️ **Common Ownership Mistakes**\n\n```rust\n// BAD - Unnecessary clone to satisfy borrow checker\nlet name = config.name.clone();\nprocess(&name);\nprocess2(&config.name); // Could have borrowed directly\n\n// GOOD - Borrow instead of clone\nprocess(&config.name);\nprocess2(&config.name);\n\n// BAD - Moving out of a shared reference\nfn take_name(config: &Config) -> String {\n config.name // ERROR: cannot move out of borrowed content\n}\n\n// GOOD - Clone when you truly need ownership from a borrow\nfn take_name(config: &Config) -> String {\n config.name.clone()\n}\n```\n\n---\n\n## Error Handling Patterns\n\n### ✅ **Custom Error Types with thiserror**\n\n```rust\nuse thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum AppError {\n #[error(\"configuration error: {0}\")]\n Config(String),\n\n #[error(\"database query failed: {source}\")]\n Database {\n #[source]\n source: sqlx::Error,\n },\n\n #[error(\"HTTP request failed: {url}\")]\n Http {\n url: String,\n #[source]\n source: reqwest::Error,\n },\n\n #[error(\"not found: {entity} with id {id}\")]\n NotFound { entity: &'static str, id: String },\n\n #[error(transparent)]\n Unexpected(#[from] anyhow::Error),\n}\n```\n\n**Requirements:**\n- ✅ Use `thiserror` for library error types (structured, matchable)\n- ✅ Use `anyhow` for application-level errors (ergonomic, context-rich)\n- ✅ Implement `#[source]` for error chain inspection\n- ✅ Implement `#[from]` for automatic conversion via `?`\n- ✅ Human-readable display messages\n\n### ✅ **The ? Operator and Error Propagation**\n\n```rust\n// GOOD - Clean error propagation with context\nuse anyhow::{Context, Result};\n\nfn load_config(path: &str) -> Result\u003cConfig> {\n let contents = std::fs::read_to_string(path)\n .with_context(|| format!(\"failed to read config from {path}\"))?;\n\n let config: Config = toml::from_str(&contents)\n .with_context(|| format!(\"failed to parse config from {path}\"))?;\n\n config.validate()\n .context(\"config validation failed\")?;\n\n Ok(config)\n}\n\n// BAD - Manual match on every error\nfn load_config(path: &str) -> Result\u003cConfig, Box\u003cdyn std::error::Error>> {\n let contents = match std::fs::read_to_string(path) {\n Ok(c) => c,\n Err(e) => return Err(Box::new(e)),\n };\n // ... tedious repetition\n}\n```\n\n### ✅ **Result Type Aliases**\n\n```rust\n// GOOD - Crate-level Result alias\npub type Result\u003cT> = std::result::Result\u003cT, AppError>;\n\n// Usage throughout the crate\npub fn get_user(id: u64) -> Result\u003cUser> {\n // AppError is the implicit error type\n Ok(User { id, name: \"Alice\".into() })\n}\n```\n\n### ⚠️ **Error Handling Anti-Patterns**\n\n| Pattern | Problem | Instead |\n|---------|---------|---------|\n| `.unwrap()` in production | Panics on None/Err | Use `?`, `.unwrap_or()`, or match |\n| `Box\u003cdyn Error>` everywhere | Loses type info | Use `thiserror` enums |\n| String errors | Not matchable | Use typed errors |\n| Swallowing errors silently | Hides bugs | Log or propagate |\n| `panic!()` for expected failures | Crashes the process | Return `Result` |\n\n**Unwrap Threshold:**\n\n| Context | `.unwrap()` Allowed? |\n|---------|---------------------|\n| Tests | ✅ Yes |\n| Examples | ✅ Yes |\n| Build scripts | ⚠️ Acceptable with comment |\n| Library code | ❌ Never |\n| Binary (main) | ⚠️ Only after validation |\n\n---\n\n## Trait & Type System Design\n\n### ✅ **Trait Design**\n\n```rust\n// GOOD - Small, focused traits\npub trait Validate {\n fn validate(&self) -> Result\u003c(), ValidationError>;\n}\n\npub trait Persist {\n fn save(&self, store: &dyn Store) -> Result\u003c()>;\n fn load(id: &str, store: &dyn Store) -> Result\u003cSelf>\n where\n Self: Sized;\n}\n\n// Compose traits via supertraits\npub trait Entity: Validate + Persist + std::fmt::Debug {}\n```\n\n**Anti-Pattern (God Trait):**\n```rust\n// BAD - Too many methods, forces implementors to define everything\npub trait Service {\n fn start(&self) -> Result\u003c()>;\n fn stop(&self) -> Result\u003c()>;\n fn health(&self) -> HealthStatus;\n fn metrics(&self) -> Metrics;\n fn configure(&mut self, config: Config);\n fn validate(&self) -> Result\u003c()>;\n // ... 15 more methods\n}\n```\n\n### ✅ **Generics vs Trait Objects**\n\n```rust\n// GOOD - Static dispatch (monomorphized, zero-cost abstraction)\nfn process\u003cT: Serialize + Send>(item: T) -> Result\u003c()> {\n let json = serde_json::to_string(&item)?;\n send_to_queue(&json)\n}\n\n// GOOD - Dynamic dispatch (runtime polymorphism, smaller binary)\nfn process_any(item: &dyn Serialize) -> Result\u003c()> {\n let json = serde_json::to_value(item)?;\n send_to_queue(&json.to_string())\n}\n```\n\n| Approach | Binary Size | Performance | Use When |\n|----------|------------|-------------|----------|\n| Generics (`T: Trait`) | Larger (monomorphized) | Faster (inlined) | Hot paths, known types at compile time |\n| Trait Objects (`dyn Trait`) | Smaller | Vtable overhead | Collections of mixed types, plugin systems |\n| `impl Trait` (return) | Smaller | Inlined | Returning closures or iterators |\n\n### ✅ **Associated Types vs Generics**\n\n```rust\n// GOOD - Associated type when there's ONE natural choice per impl\npub trait Iterator {\n type Item;\n fn next(&mut self) -> Option\u003cSelf::Item>;\n}\n\n// GOOD - Generic parameter when impl can work with MANY types\npub trait From\u003cT> {\n fn from(value: T) -> Self;\n}\n```\n\n### ✅ **Derive Macros**\n\n```rust\n// GOOD - Derive common traits\n#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]\npub struct User {\n pub id: u64,\n pub name: String,\n pub email: String,\n}\n```\n\n**Standard Derive Order:**\n\n| Priority | Traits | Purpose |\n|----------|--------|---------|\n| 1 | `Debug` | Always derive for debugging |\n| 2 | `Clone`, `Copy` | If semantically appropriate |\n| 3 | `PartialEq`, `Eq` | If comparison is needed |\n| 4 | `Hash` | If used as HashMap key |\n| 5 | `Serialize`, `Deserialize` | If serialized |\n| 6 | `Default` | If zero-value makes sense |\n\n---\n\n## Concurrency Patterns\n\n### ✅ **Shared State with Arc\u003cMutex\u003cT>>**\n\n```rust\nuse std::sync::Arc;\nuse tokio::sync::Mutex;\n\n#[derive(Clone)]\nstruct AppState {\n db: Arc\u003cMutex\u003cDatabase>>,\n cache: Arc\u003cdashmap::DashMap\u003cString, String>>,\n}\n\n// GOOD - Lock scope is minimal\nasync fn get_user(state: &AppState, id: u64) -> Result\u003cUser> {\n let db = state.db.lock().await;\n let user = db.query_user(id).await?;\n drop(db); // Explicit drop releases lock before further processing\n Ok(user)\n}\n\n// BAD - Holding lock across await points\nasync fn bad_get_user(state: &AppState, id: u64) -> Result\u003cUser> {\n let db = state.db.lock().await;\n let user = db.query_user(id).await?; // Lock held across .await!\n let enriched = enrich_user(user).await; // Still holding lock!\n Ok(enriched)\n}\n```\n\n**Lock Duration Thresholds:**\n\n| Duration | Status | Action |\n|----------|--------|--------|\n| \u003c 1 ms | ✅ Excellent | Maintain |\n| 1-10 ms | ⚠️ Warning | Review scope |\n| > 10 ms | ❌ Critical | Refactor (clone-and-release pattern) |\n\n### ✅ **Channel Patterns**\n\n```rust\nuse tokio::sync::mpsc;\n\n// GOOD - Bounded channel with backpressure\nlet (tx, mut rx) = mpsc::channel::\u003cEvent>(100);\n\n// Producer\ntokio::spawn(async move {\n for event in events {\n if tx.send(event).await.is_err() {\n tracing::warn!(\"receiver dropped, stopping producer\");\n break;\n }\n }\n});\n\n// Consumer\ntokio::spawn(async move {\n while let Some(event) = rx.recv().await {\n process_event(event).await;\n }\n});\n```\n\n### ✅ **Send and Sync Bounds**\n\n```rust\n// GOOD - Explicit Send + Sync bounds for spawned futures\nfn spawn_worker\u003cF>(task: F) -> tokio::task::JoinHandle\u003c()>\nwhere\n F: Future\u003cOutput = ()> + Send + 'static,\n{\n tokio::spawn(task)\n}\n\n// GOOD - Ensure types are thread-safe\nstruct SharedConfig {\n data: Arc\u003cRwLock\u003cHashMap\u003cString, String>>>, // Send + Sync\n}\n```\n\n| Marker | Meaning | NOT Send/Sync |\n|--------|---------|---------------|\n| `Send` | Can be transferred across threads | `Rc\u003cT>`, `*const T` |\n| `Sync` | Can be shared between threads via `&T` | `Cell\u003cT>`, `RefCell\u003cT>` |\n| Both | Safe for concurrent access | `Arc\u003cMutex\u003cT>>` is both |\n\n### ✅ **Async/Await Best Practices**\n\n```rust\n// GOOD - Select for racing multiple futures\ntokio::select! {\n result = process_request(&req) => {\n handle_response(result).await;\n }\n _ = tokio::time::sleep(Duration::from_secs(30)) => {\n return Err(AppError::Timeout);\n }\n _ = shutdown_signal.recv() => {\n tracing::info!(\"shutting down gracefully\");\n return Ok(());\n }\n}\n\n// GOOD - Spawn blocking work off the async runtime\nlet hash = tokio::task::spawn_blocking(move || {\n argon2::hash_encoded(password.as_bytes(), &salt, &config)\n}).await??;\n```\n\n---\n\n## Unsafe Code\n\n### ✅ **SAFETY Comments (Required)**\n\n```rust\n// GOOD - Every unsafe block has a SAFETY comment\nlet value = unsafe {\n // SAFETY: We verified that `ptr` is non-null and properly aligned\n // in the check above (line 42). The pointed-to data is initialized\n // by `init_buffer()` called on line 38 and has not been freed.\n *ptr\n};\n\n// BAD - Unsafe with no justification\nlet value = unsafe { *ptr };\n```\n\n**Requirements:**\n- ✅ Every `unsafe` block must have a `// SAFETY:` comment\n- ✅ Comment must explain WHY the invariants are upheld\n- ✅ Reference the specific preconditions being satisfied\n\n### ✅ **Minimizing Unsafe Scope**\n\n```rust\n// GOOD - Minimal unsafe block, safe wrapper\npub fn get_element(slice: &[u8], index: usize) -> Option\u003cu8> {\n if index \u003c slice.len() {\n // SAFETY: We just verified index is within bounds\n Some(unsafe { *slice.get_unchecked(index) })\n } else {\n None\n }\n}\n\n// BAD - Entire function is unsafe when only one operation needs it\npub unsafe fn get_element(slice: &[u8], index: usize) -> u8 {\n let ptr = slice.as_ptr().add(index);\n let extra = compute_offset(ptr); // This doesn't need unsafe!\n let result = *ptr;\n log_access(result); // This doesn't need unsafe!\n result\n}\n```\n\n### ✅ **FFI (Foreign Function Interface)**\n\n```rust\n// GOOD - Safe wrapper around FFI\nmod ffi {\n extern \"C\" {\n fn c_process(data: *const u8, len: usize) -> i32;\n }\n}\n\n/// Process data using the C library.\n///\n/// # Errors\n/// Returns `Err` if the C function returns a non-zero exit code.\npub fn process(data: &[u8]) -> Result\u003c(), FfiError> {\n // SAFETY: `data.as_ptr()` is valid for `data.len()` bytes.\n // The C function does not retain the pointer after returning.\n let result = unsafe { ffi::c_process(data.as_ptr(), data.len()) };\n if result == 0 {\n Ok(())\n } else {\n Err(FfiError::ExitCode(result))\n }\n}\n```\n\n### ⚠️ **Unsafe Code Thresholds**\n\n| Metric | Status | Action |\n|--------|--------|--------|\n| 0 unsafe blocks | ✅ Ideal | Maintain |\n| 1-5 with SAFETY comments | ✅ Acceptable | Audit quarterly |\n| 6-15 with SAFETY comments | ⚠️ Warning | Justify each, seek safe alternatives |\n| Any without SAFETY comments | ❌ Critical | Add comments immediately |\n| `#[allow(unsafe_code)]` crate-wide | ❌ Critical | Remove, audit all unsafe |\n\n---\n\n## Testing Patterns\n\n### ✅ **Unit Tests (Inline Modules)**\n\n```rust\npub fn calculate_discount(price: f64, tier: &str) -> f64 {\n match tier {\n \"gold\" => price * 0.20,\n \"silver\" => price * 0.10,\n _ => 0.0,\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn gold_tier_gets_twenty_percent() {\n let discount = calculate_discount(100.0, \"gold\");\n assert!((discount - 20.0).abs() \u003c f64::EPSILON);\n }\n\n #[test]\n fn unknown_tier_gets_no_discount() {\n assert_eq!(calculate_discount(100.0, \"bronze\"), 0.0);\n }\n\n #[test]\n fn zero_price_returns_zero() {\n assert_eq!(calculate_discount(0.0, \"gold\"), 0.0);\n }\n}\n```\n\n**Requirements:**\n- ✅ `#[cfg(test)]` module in the same file as the code\n- ✅ Test names describe the expected behavior\n- ✅ `use super::*` imports the parent module\n\n### ✅ **Integration Tests**\n\n```rust\n// tests/api_integration.rs\n// Each file in tests/ is compiled as a separate crate\n\nuse my_service::{Config, Server};\n\n#[tokio::test]\nasync fn server_responds_to_health_check() {\n let config = Config::test_default();\n let server = Server::start(config).await.unwrap();\n\n let resp = reqwest::get(&format!(\"{}/health\", server.url()))\n .await\n .unwrap();\n\n assert_eq!(resp.status(), 200);\n server.shutdown().await;\n}\n```\n\n### ✅ **Doc Tests**\n\n```rust\n/// Parses a duration string like \"5s\", \"100ms\", \"2m\".\n///\n/// # Examples\n///\n/// ```\n/// use my_crate::parse_duration;\n///\n/// let d = parse_duration(\"5s\").unwrap();\n/// assert_eq!(d, std::time::Duration::from_secs(5));\n///\n/// let d = parse_duration(\"100ms\").unwrap();\n/// assert_eq!(d, std::time::Duration::from_millis(100));\n/// ```\n///\n/// # Errors\n///\n/// Returns `Err` if the string is not a valid duration format.\npub fn parse_duration(s: &str) -> Result\u003cDuration, ParseError> {\n // ...\n}\n```\n\n**Why Doc Tests Matter:**\n- Examples in documentation are compiled and tested\n- Guarantees documentation stays accurate\n- `cargo test` runs doc tests by default\n\n### ✅ **Property-Based Testing with proptest**\n\n```rust\nuse proptest::prelude::*;\n\nproptest! {\n #[test]\n fn roundtrip_serialization(input in \"\\\\PC{1,100}\") {\n let serialized = serde_json::to_string(&input).unwrap();\n let deserialized: String = serde_json::from_str(&serialized).unwrap();\n prop_assert_eq!(input, deserialized);\n }\n\n #[test]\n fn discount_never_exceeds_price(price in 0.0f64..10000.0, tier in \"gold|silver|bronze\") {\n let discount = calculate_discount(price, &tier);\n prop_assert!(discount \u003c= price);\n prop_assert!(discount >= 0.0);\n }\n}\n```\n\n### ✅ **Benchmarks with Criterion**\n\n```rust\n// benches/throughput.rs\nuse criterion::{black_box, criterion_group, criterion_main, Criterion};\nuse my_service::process;\n\nfn benchmark_process(c: &mut Criterion) {\n let data = setup_test_data();\n\n c.bench_function(\"process_1000_items\", |b| {\n b.iter(|| process(black_box(&data)))\n });\n}\n\ncriterion_group!(benches, benchmark_process);\ncriterion_main!(benches);\n```\n\n**Running:**\n```bash\ncargo bench # Run all benchmarks\ncargo bench -- process # Run matching benchmarks\n```\n\n### Test Type Summary\n\n| Type | Location | Runs With | Purpose |\n|------|----------|-----------|---------|\n| Unit | `#[cfg(test)]` inline | `cargo test` | Test private functions |\n| Integration | `tests/` directory | `cargo test` | Test public API |\n| Doc | `///` comments | `cargo test` | Verify examples |\n| Property | Inline or `tests/` | `cargo test` | Fuzz invariants |\n| Benchmark | `benches/` | `cargo bench` | Performance regression |\n\n---\n\n## Security Practices\n\n### ✅ **Minimize Unsafe Code**\n\n```rust\n// CORRECT — isolate unsafe behind a safe API\npub fn read_buffer(ptr: *const u8, len: usize) -> &[u8] {\n // SAFETY: caller guarantees ptr is valid for `len` bytes,\n // properly aligned, and the memory won't be mutated during\n // the lifetime of the returned slice.\n unsafe { std::slice::from_raw_parts(ptr, len) }\n}\n\n// INCORRECT — unsafe scattered through business logic\npub fn process(data: *const u8) {\n unsafe {\n // Multiple unsafe operations without justification\n let val = *data;\n let next = *data.add(1);\n }\n}\n```\n\n**Unsafe Audit Criteria:**\n- Every `unsafe` block MUST have a `// SAFETY:` comment explaining the invariant\n- Minimize the scope of `unsafe` — wrap in safe abstractions\n- Prefer safe alternatives: `Vec`, `Box`, `Rc`/`Arc` over raw pointers\n- Audit all `unsafe impl Send` and `unsafe impl Sync` for correctness\n\n### ✅ **FFI Safety**\n\n```rust\n// CORRECT — safe wrapper around FFI\nextern \"C\" {\n fn c_process(data: *const u8, len: usize) -> i32;\n}\n\n/// Process data through the C library.\n///\n/// # Panics\n/// Panics if `data` is empty.\npub fn process(data: &[u8]) -> Result\u003c(), FfiError> {\n assert!(!data.is_empty(), \"data must not be empty\");\n // SAFETY: data.as_ptr() is valid for data.len() bytes,\n // and c_process does not retain the pointer.\n let result = unsafe { c_process(data.as_ptr(), data.len()) };\n match result {\n 0 => Ok(()),\n code => Err(FfiError::ReturnCode(code)),\n }\n}\n```\n\n**FFI Rules:**\n- Always validate inputs before crossing the FFI boundary\n- Wrap every `extern \"C\"` function in a safe Rust API\n- Never expose raw pointers in public APIs\n- Use `CStr`/`CString` for string interchange, never cast directly\n\n### ✅ **Integer Overflow**\n\n```rust\n// CORRECT — use checked arithmetic for untrusted inputs\nfn allocate_buffer(count: usize, item_size: usize) -> Result\u003cVec\u003cu8>, AllocError> {\n let total = count.checked_mul(item_size)\n .ok_or(AllocError::Overflow)?;\n Ok(vec![0u8; total])\n}\n\n// CORRECT — use saturating arithmetic for counters/metrics\nfn increment_retry(count: u32) -> u32 {\n count.saturating_add(1) // Caps at u32::MAX instead of wrapping\n}\n\n// INCORRECT — silent wrapping in release mode\nfn total_size(count: usize, item_size: usize) -> usize {\n count * item_size // Wraps silently in release, panics in debug\n}\n```\n\n**Integer Overflow Rules:**\n\n| Context | Strategy | Method |\n|---------|----------|--------|\n| Untrusted input | Checked | `checked_add`, `checked_mul` — returns `None` on overflow |\n| Counters / metrics | Saturating | `saturating_add` — caps at MAX |\n| Bit manipulation | Wrapping | `wrapping_add` — intentional modular arithmetic |\n| Debug assertions | Default | Panics in debug, wraps in release |\n\n- Prefer `checked_*` for any arithmetic involving external data\n- Use `saturating_*` when capping is acceptable (progress bars, counters)\n- Use `wrapping_*` only for intentional modular arithmetic (hashing, crypto)\n- Add `#[deny(clippy::arithmetic_side_effects)]` for high-assurance modules\n\n### ✅ **Panic Handling**\n\n```rust\n// CORRECT — catch_unwind at FFI and thread boundaries\nuse std::panic;\n\npub extern \"C\" fn ffi_entry_point(input: *const u8, len: usize) -> i32 {\n let result = panic::catch_unwind(|| {\n // SAFETY: caller guarantees valid pointer and length\n let data = unsafe { std::slice::from_raw_parts(input, len) };\n process(data)\n });\n match result {\n Ok(Ok(())) => 0,\n Ok(Err(_)) => -1,\n Err(_panic) => -2, // Caught a panic — do not unwind into C\n }\n}\n\n// CORRECT — prefer Result over panic for recoverable errors\npub fn parse_port(s: &str) -> Result\u003cu16, ParseError> {\n let port: u16 = s.parse().map_err(|_| ParseError::InvalidPort)?;\n if port == 0 {\n return Err(ParseError::PortZero);\n }\n Ok(port)\n}\n\n// INCORRECT — panic for expected failure\npub fn parse_port(s: &str) -> u16 {\n s.parse().expect(\"invalid port\") // Crashes on bad input\n}\n```\n\n**Panic Rules:**\n- Use `catch_unwind` at FFI boundaries to prevent unwinding into C/C++\n- Use `catch_unwind` in thread pool workers to prevent poisoning the pool\n- Return `Result` for all recoverable errors — reserve `panic!` for programmer bugs\n- Set `panic = \"abort\"` in release profile if unwinding is not needed (smaller binary)\n- Use `assert!` only for invariants that indicate a bug if violated\n\n### ✅ **Input Validation**\n\n```rust\nuse std::net::IpAddr;\n\npub fn parse_config(input: &str) -> Result\u003cConfig, ConfigError> {\n let config: Config = toml::from_str(input)\n .map_err(ConfigError::Parse)?;\n\n // Validate bounds after deserialization\n if config.port == 0 || config.port > 65535 {\n return Err(ConfigError::InvalidPort(config.port));\n }\n if config.max_connections > 10_000 {\n return Err(ConfigError::ExceedsLimit(\"max_connections\", 10_000));\n }\n\n Ok(config)\n}\n```\n\n**Validation Rules:**\n- Validate all external data at system boundaries (CLI args, env vars, files, network)\n- Use newtypes to enforce invariants at the type level\n- Prefer `TryFrom` over unchecked conversions\n\n### ✅ **Dependency Auditing**\n\n```bash\n# Audit for known vulnerabilities\ncargo audit\n\n# Check for unmaintained or yanked crates\ncargo audit --deny warnings\n\n# In CI, fail the build on any advisory\ncargo audit --deny vulnerability --deny unmaintained --deny yanked\n```\n\n**Dependency Rules:**\n- Run `cargo audit` in CI on every PR\n- Pin major versions in `Cargo.toml` (e.g., `serde = \"1\"`)\n- Review new dependencies for `unsafe` usage and maintenance status\n- Prefer crates from the RustSec-reviewed ecosystem\n\n### Security ALWAYS / NEVER\n\n| ALWAYS | NEVER |\n|--------|-------|\n| Add `// SAFETY:` comment on every `unsafe` block | Use `unsafe` without documenting the invariant |\n| Wrap FFI calls in safe Rust abstractions | Expose raw pointers in public APIs |\n| Validate external inputs at system boundaries | Trust deserialized data without bounds checks |\n| Run `cargo audit` in CI | Ignore advisory warnings on dependencies |\n| Use `CStr`/`CString` for C string interchange | Cast `*const u8` to `&str` without validation |\n| Minimize `unsafe` block scope | Scatter `unsafe` through business logic |\n\n---\n\n## Documentation Standards\n\n### ✅ **Rustdoc Conventions**\n\n```rust\n//! # mycrate\n//!\n//! A library for processing widgets efficiently.\n//!\n//! ## Quick Start\n//!\n//! ```rust\n//! use mycrate::Widget;\n//! let w = Widget::new(\"example\");\n//! assert!(w.is_valid());\n//! ```\n\n/// A widget that can be processed.\n///\n/// Widgets are the core data type. They must be created\n/// via [`Widget::new`] to ensure invariants are upheld.\n///\n/// # Examples\n///\n/// ```\n/// use mycrate::Widget;\n///\n/// let widget = Widget::new(\"test\");\n/// assert_eq!(widget.name(), \"test\");\n/// ```\npub struct Widget {\n name: String,\n}\n\nimpl Widget {\n /// Creates a new widget with the given name.\n ///\n /// # Panics\n ///\n /// Panics if `name` is empty.\n ///\n /// # Examples\n ///\n /// ```\n /// use mycrate::Widget;\n /// let w = Widget::new(\"example\");\n /// ```\n pub fn new(name: &str) -> Self {\n assert!(!name.is_empty(), \"name must not be empty\");\n Self { name: name.to_string() }\n }\n}\n```\n\n### ✅ **Doc Test Patterns**\n\n```rust\n/// Parses a duration string like \"5s\", \"100ms\".\n///\n/// # Examples\n///\n/// ```\n/// # use mycrate::parse_duration;\n/// assert_eq!(parse_duration(\"5s\").unwrap().as_secs(), 5);\n/// assert_eq!(parse_duration(\"100ms\").unwrap().as_millis(), 100);\n/// ```\n///\n/// # Errors\n///\n/// Returns [`ParseError`] if the format is unrecognized.\n///\n/// ```\n/// # use mycrate::parse_duration;\n/// assert!(parse_duration(\"invalid\").is_err());\n/// ```\npub fn parse_duration(s: &str) -> Result\u003cDuration, ParseError> {\n // ...\n}\n```\n\n**Doc Test Rules:**\n- Doc tests compile and run with `cargo test` — treat them as real tests\n- Use `# ` prefix to hide setup lines (imports, boilerplate)\n- Use `no_run` for examples that need network/filesystem\n- Use `should_panic` for examples demonstrating failure\n\n### ✅ **Module Documentation**\n\n```rust\n//! # handlers\n//!\n//! HTTP request handlers for the API.\n//!\n//! Each handler follows the pattern:\n//! 1. Parse and validate input\n//! 2. Call domain logic\n//! 3. Map result to HTTP response\n//!\n//! See [`crate::domain`] for business logic.\n```\n\n### ✅ **`#[doc(hidden)]` Usage**\n\n```rust\n// Hide implementation details from public docs\n#[doc(hidden)]\npub mod __internal {\n // Used by macros, not part of public API\n}\n\n// Hide trait impls that are required but not user-facing\n#[doc(hidden)]\npub fn __macro_helper() {}\n```\n\n**When to use `#[doc(hidden)]`:**\n- Macro support functions that must be `pub` but are not API\n- Trait implementations required by the compiler but meaningless to users\n- Never hide things to avoid documenting them\n\n### ✅ **README Integration**\n\n```bash\n# Generate README.md from lib.rs module-level docs\ncargo install cargo-readme\ncargo readme > README.md\n\n# Verify README stays in sync (CI check)\ncargo readme | diff - README.md\n```\n\n```rust\n// src/lib.rs — module-level docs become README content\n//! # mycrate\n//!\n//! A fast, safe widget processor.\n//!\n//! ## Features\n//!\n//! - Zero-copy parsing\n//! - Async support via tokio\n//! - Type-safe configuration\n//!\n//! ## Usage\n//!\n//! ```rust\n//! use mycrate::process;\n//!\n//! let result = process(\"input\").unwrap();\n//! assert!(!result.is_empty());\n//! ```\n```\n\n**README Rules:**\n- Use `cargo-readme` to generate README.md from `//!` docs in `src/lib.rs`\n- Keep the single source of truth in `lib.rs` — README is a derived artifact\n- Add a CI step to verify README stays in sync with `lib.rs` docs\n- Include: crate purpose, features, usage example, MSRV, license\n\n### Documentation ALWAYS / NEVER\n\n| ALWAYS | NEVER |\n|--------|-------|\n| Use `///` for public items, `//!` for module-level docs | Leave public API items undocumented |\n| Include `# Examples` section on public functions | Write doc tests that don't actually assert behavior |\n| Document `# Panics`, `# Errors`, `# Safety` sections | Use `#[doc(hidden)]` to avoid writing documentation |\n| Run `cargo test` to verify doc examples compile | Assume doc examples stay correct without CI |\n| Link to related items with [`ident`] syntax | Duplicate information already in type signatures |\n| Use `# ` to hide boilerplate in doc tests | Write doc tests that require external services |\n\n---\n\n## Code Quality Metrics & Anti-Patterns\n\n> See `common-standards.md` for universal coverage targets, testing principles, and anti-patterns across all languages.\n\n### ✅ **Clippy Lint Levels**\n\n```toml\n# Cargo.toml or clippy.toml\n[lints.clippy]\n# Deny — treat as errors\nunwrap_used = \"deny\"\nexpect_used = \"deny\"\npanic = \"deny\"\ntodo = \"deny\"\n\n# Warn — flag for review\nclone_on_ref_ptr = \"warn\"\nlarge_enum_variant = \"warn\"\nneedless_pass_by_value = \"warn\"\nimplicit_clone = \"warn\"\nmissing_errors_doc = \"warn\"\nmissing_panics_doc = \"warn\"\n```\n\n**Recommended CI Command:**\n```bash\ncargo clippy --all-targets --all-features -- -D warnings\n```\n\n### ✅ **Lint Category Enforcement**\n\n| Category | CI Policy | Rationale |\n|----------|-----------|-----------|\n| `clippy::correctness` | ❌ Deny (fail build) | Likely bugs |\n| `clippy::suspicious` | ❌ Deny (fail build) | Probably wrong |\n| `clippy::pedantic` | ⚠️ Warn | Style improvements |\n| `clippy::nursery` | ⚠️ Optional | Experimental lints |\n| `clippy::cargo` | ⚠️ Warn | Cargo.toml hygiene |\n\n### 📊 **Complexity Thresholds**\n\n| Complexity Range | Status | Action |\n|-----------------|--------|--------|\n| CC 1-5 (Simple) | ✅ Excellent | Maintain |\n| CC 6-10 (OK) | ✅ Acceptable | Monitor |\n| CC 11-15 (High) | ⚠️ Warning | Refactor recommended |\n| CC 16+ (Very High) | ❌ Critical | Refactor required |\n\n**Coverage Targets:**\n\n| Metric | Minimum | Target |\n|--------|---------|--------|\n| Line coverage | 60% | 80%+ |\n| Branch coverage | 50% | 70%+ |\n| Critical path coverage | 90% | 100% |\n\n### ❌ **Named Anti-Patterns**\n\n**1. Stringly-Typed Code**\n```rust\n// BAD - Strings for everything\nfn set_status(status: &str) { /* \"active\", \"idle\", \"error\" */ }\n\n// GOOD - Enums encode valid states\nenum Status { Active, Idle, Error }\nfn set_status(status: Status) { /* ... */ }\n```\n\n**2. Clone-Happy Code**\n```rust\n// BAD - Cloning to avoid borrow checker fights\nfn process(data: &Data) {\n let owned = data.clone(); // Unnecessary allocation\n compute(&owned);\n}\n\n// GOOD - Work with references\nfn process(data: &Data) {\n compute(data);\n}\n```\n\n**3. Typestate Neglect**\n```rust\n// BAD - Runtime checks for compile-time invariants\nstruct Connection { is_authenticated: bool }\nfn query(conn: &Connection) {\n assert!(conn.is_authenticated); // Runtime panic\n}\n\n// GOOD - Typestate pattern enforces at compile time\nstruct Unauthenticated;\nstruct Authenticated;\nstruct Connection\u003cState> { _state: std::marker::PhantomData\u003cState> }\n\nimpl Connection\u003cUnauthenticated> {\n fn authenticate(self, creds: &Credentials) -> Result\u003cConnection\u003cAuthenticated>> {\n // ...\n }\n}\n\nimpl Connection\u003cAuthenticated> {\n fn query(&self, sql: &str) -> Result\u003cRows> {\n // Can only be called on authenticated connections\n }\n}\n```\n\n**4. Arc\u003cMutex\u003cT>> Everywhere**\n```rust\n// BAD - Mutex when only reads happen\nlet config = Arc::new(Mutex::new(load_config()));\n\n// GOOD - Use RwLock for read-heavy workloads\nlet config = Arc::new(RwLock::new(load_config()));\n\n// BETTER - Use Arc\u003cT> if config is immutable after init\nlet config = Arc::new(load_config());\n```\n\n**5. Ignoring Must-Use Types**\n```rust\n// BAD - Ignoring a Result\nfn fire_and_forget() {\n send_notification(); // Warning: unused Result\n}\n\n// GOOD - Explicitly acknowledge\nfn fire_and_forget() {\n let _ = send_notification(); // Intentional ignore\n}\n```\n\n**6. Unbounded Collections**\n```rust\n// BAD - No size limit on cache\nlet mut cache: HashMap\u003cString, Data> = HashMap::new();\n// Grows forever...\n\n// GOOD - Bounded with eviction\nlet cache = lru::LruCache::new(NonZeroUsize::new(10_000).unwrap());\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n| Category | Assessment Criteria | Evidence Required |\n|----------|-------------------|-------------------|\n| Project Structure | Standard layout, module sizes, re-exports | File count per module, module line counts |\n| Cargo Config | MSRV set, features used, profiles configured | Cargo.toml audit, dep count |\n| Code Formatting | rustfmt clean, naming conventions followed | `cargo fmt --check` output, naming violations |\n| Ownership & Borrowing | Minimal clones, correct lifetimes, no unnecessary ownership | Clone count, borrow checker workarounds |\n| Error Handling | thiserror/anyhow usage, no unwrap in prod, context added | Unwrap count, error type audit |\n| Traits & Types | Small traits, appropriate dispatch, derive usage | Methods per trait, dyn vs generic ratio |\n| Concurrency | Minimal lock scope, bounded channels, Send/Sync correct | Lock duration, channel audit |\n| Unsafe Code | SAFETY comments, minimal scope, safe wrappers | Unsafe block count, comment coverage |\n| Testing | Unit + integration + doc tests, property tests | Coverage %, test type distribution |\n| Security | Unsafe minimized, FFI wrapped, inputs validated, deps audited | Unsafe count, audit output, overflow handling |\n| Documentation | Rustdoc on public API, doc tests, module docs, README sync | `cargo doc` warnings, doc test count, README freshness |\n| Code Quality | Clippy clean, low complexity, no named anti-patterns | Clippy findings, CC distribution |\n\n**Grading Scale:**\n\n| Grade | Finding Threshold | Description |\n|-------|------------------|-------------|\n| A+ | 0-2 minor findings | Exemplary - industry best practices |\n| A | \u003c5 HIGH findings | Excellent - strong practices |\n| A- | 5-15 HIGH findings | Very Good - solid practices |\n| B+ | 15-25 HIGH findings | Good - acceptable practices |\n| B | 25-40 HIGH findings | Satisfactory - needs improvement |\n| C+ | 40-60 HIGH findings | Needs Improvement - multiple issues |\n| C | 60+ HIGH findings | Significant Issues - major refactoring |\n| D | 1+ CRITICAL findings | Major Problems - not production-ready |\n| F | Multiple CRITICAL | Critical Issues - complete rewrite |\n\n**Example Assessment:**\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Error Handling | A | 0 unwraps in lib code, 45 proper `?` propagations, thiserror enums |\n| Ownership | A- | 3 unnecessary clones flagged, all lifetimes correct |\n| Concurrency | A+ | All locks \u003c 1ms scope, bounded channels, no deadlock paths |\n| Unsafe Code | A+ | 0 unsafe blocks in application code |\n| Testing | B+ | 72% line coverage, doc tests on public API, no property tests |\n| **OVERALL** | **A- (Excellent)** | **8 HIGH, 22 MEDIUM findings** |\n\n---\n\n## Vibe Integration\n\n### Prescan Patterns\n\n| Pattern | Severity | Detection |\n|---------|----------|-----------|\n| PR-01: `.unwrap()` in library code | HIGH | grep for `.unwrap()` outside `#[cfg(test)]` |\n| PR-02: Missing SAFETY comments | CRITICAL | `unsafe` blocks without `// SAFETY:` |\n| PR-03: Clippy warnings | HIGH | `cargo clippy` JSON output parsing |\n| PR-04: Unformatted code | MEDIUM | `cargo fmt --check` exit code |\n| PR-05: Unused dependencies | LOW | `cargo machete` output |\n\n### Semantic Analysis\n\nDeep validation includes:\n- Ownership pattern analysis (clone frequency, lifetime correctness)\n- Trait design review (ISP compliance, dispatch appropriateness)\n- Concurrency safety audit (lock scope, Send/Sync bounds)\n- Unsafe code audit (SAFETY comments, scope minimization)\n\n### JIT Loading\n\n**Tier 1 (Fast):** Load `~/.agents/skills/standards/references/rust.md` (5KB)\n**Tier 2 (Deep):** Load this document (~20KB) for comprehensive audit\n**Override:** Use `.agents/validation/RUST_*.md` if project-specific standards exist\n\n---\n\n## Additional Resources\n\n- [The Rust Programming Language](https://doc.rust-lang.org/book/)\n- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)\n- [Rust Design Patterns](https://rust-unofficial.github.io/patterns/)\n- [Clippy Lints](https://rust-lang.github.io/rust-clippy/master/)\n- [Rust Performance Book](https://nnethercote.github.io/perf-book/)\n- [The Rustonomicon](https://doc.rust-lang.org/nomicon/) (unsafe Rust)\n\n---\n\n**Related:** `rust-patterns.md` for quick reference examples\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":42186,"content_sha256":"367caff1b85ed655f0abd22d88b61f3ae6876b1e3663431620d2d91c1b02df3a"},{"filename":"references/shell-standards.md","content":"# Shell Script Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical shell scripting standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [Required Patterns](#required-patterns)\n2. [Shellcheck Integration](#shellcheck-integration)\n3. [Error Handling](#error-handling)\n4. [Logging Functions](#logging-functions)\n5. [Script Organization](#script-organization)\n6. [Security](#security)\n7. [Common Patterns](#common-patterns)\n8. [Testing](#testing)\n9. [Documentation Standards](#documentation-standards)\n10. [Code Quality Metrics](#code-quality-metrics)\n11. [Anti-Patterns Avoided](#anti-patterns-avoided)\n12. [Compliance Assessment](#compliance-assessment)\n\n---\n\n## Required Patterns\n\n### Shebang and Flags\n\nEvery shell script MUST start with:\n\n```bash\n#!/usr/bin/env bash\nset -eEuo pipefail\n```\n\n**Flag explanation:**\n\n| Flag | Effect | Failure without |\n|------|--------|-----------------|\n| `-e` | Exit on error | Silent failures, continued execution |\n| `-E` | ERR trap inherited | Traps don't fire in functions |\n| `-u` | Exit on undefined | Empty variables cause silent bugs |\n| `-o pipefail` | Pipe fails propagate | `false \\| true` returns 0 |\n\n### Variable Quoting\n\nAlways quote variables to prevent word splitting and globbing:\n\n```bash\n# GOOD - Quoted variables, safe defaults\nnamespace=\"${NAMESPACE:-default}\"\nkubectl get pods -n \"${namespace}\"\n\n# GOOD - Array expansion\nfiles=(\"file with spaces.txt\" \"another file.txt\")\ncat \"${files[@]}\"\n\n# BAD - Unquoted variables (word splitting, globbing risks)\nkubectl get pods -n $namespace\ncat $files\n```\n\n### Safe Defaults\n\n```bash\n# Pattern: ${VAR:-default}\nnamespace=\"${NAMESPACE:-default}\"\ntimeout=\"${TIMEOUT:-300}\"\nlog_level=\"${LOG_LEVEL:-INFO}\"\n\n# Pattern: ${VAR:?error message}\napi_key=\"${API_KEY:?API_KEY must be set}\"\n```\n\n---\n\n## Shellcheck Integration\n\n### Repository Configuration\n\nCreate `.shellcheckrc` at repo root:\n\n```ini\n# .shellcheckrc\n# Shell variant\nshell=bash\n\n# Can't follow non-constant source\ndisable=SC1090\n# Not following sourced files\ndisable=SC1091\n# Consider invoking separately (pipefail handles this)\ndisable=SC2312\n```\n\n### Common Shellcheck Fixes\n\n| Code | Issue | Fix |\n|------|-------|-----|\n| SC2086 | Word splitting | Quote: `\"$var\"` |\n| SC2164 | cd can fail | `cd /path \\|\\| exit 1` |\n| SC2046 | Word splitting in $() | Quote: `\"$(command)\"` |\n| SC2181 | Checking $? | Use `if command; then` |\n| SC2155 | declare/local hides exit | Split: `local x; x=$(cmd)` |\n| SC2034 | Unused variable | Remove or use |\n| SC2206 | Word splitting in array | `read -ra arr \u003c\u003c\u003c \"$var\"` |\n\n### Disable Rules Sparingly\n\n```bash\n# Only disable when truly necessary\n# shellcheck disable=SC2086\n# Reason: Word splitting is intentional for flag array\n$tool_cmd $flags_array \"$input_file\"\n```\n\n---\n\n## Error Handling\n\n### ERR Trap for Debug Context\n\n```bash\n#!/usr/bin/env bash\nset -eEuo pipefail\n\non_error() {\n local exit_code=$?\n local line_no=$1\n echo \"ERROR: Script failed on line $line_no with exit code $exit_code\" >&2\n echo \"Command: ${BASH_COMMAND}\" >&2\n exit \"$exit_code\"\n}\ntrap 'on_error $LINENO' ERR\n```\n\n### Exit Code Documentation\n\nDocument exit codes in script headers:\n\n```bash\n#!/usr/bin/env bash\n# ===================================================================\n# Script: deploy.sh\n# Purpose: Deploy application to Kubernetes cluster\n# Usage: ./deploy.sh \u003cnamespace> [--dry-run]\n#\n# Exit Codes:\n# 0 - Success\n# 1 - Argument error\n# 2 - Missing dependency\n# 3 - Configuration error\n# 4 - Validation failed\n# 5 - User cancelled\n# 6 - Deployment failed\n# ===================================================================\n\nset -eEuo pipefail\n```\n\n### Cleanup Pattern\n\n```bash\n#!/usr/bin/env bash\nset -eEuo pipefail\n\n# Create temp directory\nTMPDIR=$(mktemp -d)\n\ncleanup() {\n local exit_code=$?\n rm -rf \"$TMPDIR\" 2>/dev/null || true\n exit \"$exit_code\"\n}\ntrap cleanup EXIT\n\n# Your code here - cleanup runs on exit or error\n```\n\n### Checking Command Success\n\n```bash\n# GOOD - Direct conditional\nif kubectl get namespace \"$ns\" &>/dev/null; then\n echo \"Namespace exists\"\nelse\n echo \"Creating namespace\"\n kubectl create namespace \"$ns\"\nfi\n\n# GOOD - Negation\nif ! kubectl get namespace \"$ns\" &>/dev/null; then\n kubectl create namespace \"$ns\"\nfi\n\n# BAD - Capturing exit code (unnecessary)\nkubectl get namespace \"$ns\" &>/dev/null\nresult=$?\nif [[ $result -eq 0 ]]; then\n ...\nfi\n```\n\n---\n\n## Logging Functions\n\n### Standard Logging\n\n```bash\n# Logging functions\nlog() { echo \"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"; }\nwarn() { echo \"[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $*\" >&2; }\nerr() { echo \"[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*\" >&2; }\ndie() { err \"$*\"; exit 1; }\n\n# Debug logging (controlled by variable)\ndebug() {\n [[ \"${DEBUG:-false}\" == \"true\" ]] && echo \"[DEBUG] $*\" >&2\n}\n\n# Usage\nlog \"Processing namespace: ${NAMESPACE}\"\nwarn \"Timeout exceeded, retrying...\"\ndie \"Required tool 'kubectl' not found\"\ndebug \"Variable state: foo=$foo\"\n```\n\n### Colored Output (Optional)\n\n```bash\n# Color codes (check if terminal supports colors)\nif [[ -t 1 ]]; then\n RED='\\033[0;31m'\n GREEN='\\033[0;32m'\n YELLOW='\\033[1;33m'\n NC='\\033[0m' # No Color\nelse\n RED=''\n GREEN=''\n YELLOW=''\n NC=''\nfi\n\nlog_success() { echo -e \"${GREEN}[OK]${NC} $*\"; }\nlog_warning() { echo -e \"${YELLOW}[WARN]${NC} $*\" >&2; }\nlog_error() { echo -e \"${RED}[ERR]${NC} $*\" >&2; }\n```\n\n---\n\n## Script Organization\n\n### Full Template\n\n```bash\n#!/usr/bin/env bash\n# ===================================================================\n# Script: \u003cname>.sh\n# Purpose: \u003cone-line description>\n# Usage: ./\u003cscript>.sh [args]\n#\n# Environment Variables:\n# NAMESPACE - Target namespace (default: default)\n# DRY_RUN - If \"true\", don't make changes (default: false)\n#\n# Exit Codes:\n# 0 - Success\n# 1 - Argument error\n# 2 - Missing dependency\n# ===================================================================\n\nset -eEuo pipefail\n\n# -------------------------------------------------------------------\n# Configuration\n# -------------------------------------------------------------------\n\nreadonly SCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nreadonly SCRIPT_NAME=\"$(basename \"${BASH_SOURCE[0]}\")\"\n\nNAMESPACE=\"${NAMESPACE:-default}\"\nDRY_RUN=\"${DRY_RUN:-false}\"\nTIMEOUT=\"${TIMEOUT:-300}\"\n\n# -------------------------------------------------------------------\n# Functions\n# -------------------------------------------------------------------\n\nlog() { echo \"[$(date '+%H:%M:%S')] $*\"; }\nwarn() { echo \"[$(date '+%H:%M:%S')] WARNING: $*\" >&2; }\nerr() { echo \"[$(date '+%H:%M:%S')] ERROR: $*\" >&2; }\ndie() { err \"$*\"; exit 1; }\n\non_error() {\n local exit_code=$?\n err \"Script failed on line $1 with exit code $exit_code\"\n exit \"$exit_code\"\n}\ntrap 'on_error $LINENO' ERR\n\ncleanup() {\n rm -rf \"${TMPDIR:-}\" 2>/dev/null || true\n}\ntrap cleanup EXIT\n\nusage() {\n cat \u003c\u003cEOF\nUsage: $SCRIPT_NAME [options] \u003crequired-arg>\n\nOptions:\n -h, --help Show this help message\n -n, --namespace Kubernetes namespace (default: $NAMESPACE)\n --dry-run Don't make changes, just show what would happen\n\nEnvironment:\n NAMESPACE Same as --namespace\n DRY_RUN Same as --dry-run (set to \"true\")\nEOF\n}\n\nvalidate_args() {\n if [[ $# -lt 1 ]]; then\n usage\n exit 1\n fi\n}\n\ncheck_dependencies() {\n local missing=()\n for cmd in kubectl jq; do\n if ! command -v \"$cmd\" &>/dev/null; then\n missing+=(\"$cmd\")\n fi\n done\n if [[ ${#missing[@]} -gt 0 ]]; then\n die \"Missing dependencies: ${missing[*]}\"\n fi\n}\n\n# -------------------------------------------------------------------\n# Main\n# -------------------------------------------------------------------\n\nmain() {\n local required_arg=\"\"\n\n # Parse arguments\n while [[ $# -gt 0 ]]; do\n case \"$1\" in\n -h|--help)\n usage\n exit 0\n ;;\n -n|--namespace)\n NAMESPACE=\"$2\"\n shift 2\n ;;\n --dry-run)\n DRY_RUN=\"true\"\n shift\n ;;\n -*)\n die \"Unknown option: $1\"\n ;;\n *)\n required_arg=\"$1\"\n shift\n ;;\n esac\n done\n\n validate_args \"${required_arg:-}\"\n check_dependencies\n\n log \"Starting with namespace: $NAMESPACE\"\n [[ \"$DRY_RUN\" == \"true\" ]] && log \"DRY RUN MODE - no changes will be made\"\n\n # Main logic here\n}\n\n# Setup\nTMPDIR=$(mktemp -d)\n\n# Run\nmain \"$@\"\n```\n\n---\n\n## Security\n\n### Secret Handling\n\n**Never pass secrets as CLI arguments** - they're visible in `ps aux`:\n\n```bash\n# BAD - Secrets visible in process list\nkubectl create secret generic my-secret --from-literal=token=\"$TOKEN\"\n\n# GOOD - Pass via stdin\nkubectl create secret generic my-secret --from-literal=token=- \u003c\u003c\u003c \"$TOKEN\"\n\n# GOOD - Use file-based approach\necho \"$SECRET\" > \"$TMPDIR/secret\"\nchmod 600 \"$TMPDIR/secret\"\nkubectl create secret generic my-secret --from-file=token=\"$TMPDIR/secret\"\n\n# GOOD - Environment variable (some tools support this)\nexport TOKEN\nsome_tool --token-env=TOKEN\n```\n\n### Input Validation\n\n#### Kubernetes Resource Names (RFC 1123)\n\n```bash\nvalidate_namespace() {\n local ns=\"$1\"\n # RFC 1123: lowercase alphanumeric, hyphens, max 63 chars\n if [[ ! \"$ns\" =~ ^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$ ]] && \\\n [[ ! \"$ns\" =~ ^[a-z0-9]$ ]]; then\n die \"Invalid namespace format: $ns (must be RFC 1123 label)\"\n fi\n}\n```\n\n#### Path Traversal Prevention\n\n```bash\nvalidate_path() {\n local path=\"$1\"\n # Block path traversal\n case \"$path\" in\n *..*)\n die \"Path traversal detected: $path\"\n ;;\n esac\n # Optionally ensure path is under allowed directory\n local resolved\n resolved=$(realpath -m \"$path\" 2>/dev/null) || die \"Invalid path: $path\"\n if [[ \"$resolved\" != \"$ALLOWED_DIR\"/* ]]; then\n die \"Path outside allowed directory: $path\"\n fi\n}\n```\n\n### Sed Injection Prevention\n\n```bash\n# User input in sed can have special meaning\n# BAD - Injection possible\nNAME=\"test&id\" # & inserts matched text\nsed \"s/{{NAME}}/$NAME/g\" template.txt # & causes issues\n\n# GOOD - Escape special characters\nescape_sed_replacement() {\n printf '%s' \"$1\" | sed -e 's/[&/\\]/\\\\&/g'\n}\n\nescaped_name=$(escape_sed_replacement \"$NAME\")\nsed \"s/{{NAME}}/$escaped_name/g\" template.txt\n```\n\n### JSON Construction\n\n```bash\n# BAD - String interpolation (injection risk, quoting issues)\njson=\"{\\\"name\\\": \\\"$NAME\\\", \\\"value\\\": \\\"$VALUE\\\"}\"\n\n# GOOD - Use jq for proper escaping\njson=$(jq -n --arg name \"$NAME\" --arg value \"$VALUE\" \\\n '{name: $name, value: $value}')\n\n# GOOD - Building complex JSON\njson=$(jq -n \\\n --arg name \"$NAME\" \\\n --arg ns \"$NAMESPACE\" \\\n --argjson replicas \"$REPLICAS\" \\\n '{\n metadata: {name: $name, namespace: $ns},\n spec: {replicas: $replicas}\n }')\n```\n\n---\n\n## Common Patterns\n\n### Polling with Timeout\n\n> **SECURITY WARNING:** The pattern below uses `eval` which can lead to command injection\n> if `condition_cmd` contains unsanitized user input. **Never pass untrusted input to this function.**\n> For safer alternatives, use bash functions instead of string evaluation:\n> ```bash\n> # SAFER: Pass a function name instead of a command string\n> wait_for_condition 300 10 check_pod_running\n> ```\n\n```bash\nwait_for_condition() {\n local timeout=${1:-300}\n local interval=${2:-10}\n local condition_cmd=\"$3\"\n\n # WARNING: eval is dangerous with untrusted input - see security note above\n local elapsed=0\n while ! eval \"$condition_cmd\" &>/dev/null; do\n if [[ $elapsed -ge $timeout ]]; then\n err \"Timeout waiting for condition after ${timeout}s\"\n return 1\n fi\n log \"Waiting... (${elapsed}s/${timeout}s)\"\n sleep \"$interval\"\n elapsed=$((elapsed + interval))\n done\n return 0\n}\n\n# Usage\nwait_for_condition 300 10 \\\n \"kubectl get pod my-pod -o jsonpath='{.status.phase}' | grep -q Running\"\n```\n\n### Parallel Execution\n\n```bash\nrun_parallel() {\n local pids=()\n local failures=()\n\n for item in \"$@\"; do\n process_item \"$item\" &\n pids+=($!)\n done\n\n for pid in \"${pids[@]}\"; do\n if ! wait \"$pid\"; then\n failures+=(\"$pid\")\n fi\n done\n\n if [[ ${#failures[@]} -gt 0 ]]; then\n err \"Failed jobs: ${#failures[@]}\"\n return 1\n fi\n}\n```\n\n### Kubernetes Resource Checks\n\n```bash\nresource_exists() {\n local kind=\"$1\"\n local name=\"$2\"\n local ns=\"${3:-}\"\n\n local ns_flag=\"\"\n [[ -n \"$ns\" ]] && ns_flag=\"-n $ns\"\n\n # shellcheck disable=SC2086\n kubectl get \"$kind\" \"$name\" $ns_flag &>/dev/null\n}\n\n# Usage\nif resource_exists deployment my-app my-namespace; then\n log \"Deployment exists\"\nfi\n```\n\n### Retry Pattern\n\n```bash\nretry() {\n local max_attempts=${1:-3}\n local delay=${2:-5}\n shift 2\n local cmd=(\"$@\")\n\n local attempt=1\n while [[ $attempt -le $max_attempts ]]; do\n if \"${cmd[@]}\"; then\n return 0\n fi\n warn \"Attempt $attempt/$max_attempts failed, retrying in ${delay}s...\"\n sleep \"$delay\"\n attempt=$((attempt + 1))\n done\n\n err \"All $max_attempts attempts failed\"\n return 1\n}\n\n# Usage\nretry 3 5 kubectl apply -f manifest.yaml\n```\n\n---\n\n## Testing\n\n### Manual Testing\n\n```bash\n# Test with shellcheck\nshellcheck ./script.sh\n\n# Test with bash\nbash ./script.sh --help\n\n# Test with debug output\nbash -x ./script.sh\n\n# Test with verbose mode\nbash -v ./script.sh\n```\n\n### BATS Framework\n\nFor complex scripts, use [BATS](https://github.com/bats-core/bats-core):\n\n```bash\n# test/test_script.bats\n#!/usr/bin/env bats\n\nsetup() {\n load 'test_helper/bats-support/load'\n load 'test_helper/bats-assert/load'\n SCRIPT=\"$BATS_TEST_DIRNAME/../script.sh\"\n}\n\n@test \"script requires argument\" {\n run bash \"$SCRIPT\"\n assert_failure 1\n assert_output --partial \"Usage:\"\n}\n\n@test \"script validates namespace format\" {\n run bash \"$SCRIPT\" --namespace \"INVALID_NS\"\n assert_failure\n assert_output --partial \"Invalid namespace\"\n}\n\n@test \"script succeeds with valid input\" {\n run bash \"$SCRIPT\" valid-namespace\n assert_success\n}\n```\n\n---\n\n## Documentation Standards\n\n### Header Comments\n\nEvery script MUST have a header block describing purpose, usage, and exit codes:\n\n```bash\n#!/usr/bin/env bash\n# ===================================================================\n# Script: deploy.sh\n# Purpose: Deploy application to target Kubernetes cluster\n# Usage: ./deploy.sh [options] \u003cnamespace>\n#\n# Options:\n# -h, --help Show this help message\n# -n, --namespace Target namespace (default: default)\n# --dry-run Preview changes without applying\n#\n# Environment Variables:\n# NAMESPACE - Target namespace (default: default)\n# DRY_RUN - If \"true\", don't make changes\n#\n# Exit Codes:\n# 0 - Success\n# 1 - Argument error\n# 2 - Missing dependency\n# ===================================================================\n```\n\n### Inline Help (--help / -h)\n\nEvery user-facing script MUST support `--help` and `-h` flags:\n\n```bash\nusage() {\n cat \u003c\u003cEOF\nUsage: ${SCRIPT_NAME} [options] \u003crequired-arg>\n\nOptions:\n -h, --help Show this help message\n -v, --verbose Enable verbose output\n --dry-run Preview mode\n\nExamples:\n ${SCRIPT_NAME} my-namespace\n ${SCRIPT_NAME} --dry-run my-namespace\nEOF\n}\n```\n\n**Requirements:**\n- Print to stdout (not stderr) so output is pipeable\n- Exit 0 on `--help`, exit 1 on missing/invalid args\n- Include at least one usage example\n\n### Function Documentation\n\nDocument non-trivial functions with a comment above the declaration:\n\n```bash\n# Wait for a Kubernetes resource to reach the desired state.\n# Arguments:\n# $1 - Resource kind (e.g., deployment, pod)\n# $2 - Resource name\n# $3 - Desired condition (e.g., Available, Ready)\n# $4 - Timeout in seconds (default: 300)\n# Returns: 0 on success, 1 on timeout\nwait_for_resource() {\n local kind=\"$1\" name=\"$2\" condition=\"$3\" timeout=\"${4:-300}\"\n # ...\n}\n```\n\n### ALWAYS / NEVER Rules\n\n| Rule | Rationale |\n|------|-----------|\n| **ALWAYS** include a header block with Purpose, Usage, Exit Codes | First thing a reader sees — orients them |\n| **ALWAYS** support `--help` / `-h` in user-facing scripts | Discoverability — no need to read source |\n| **ALWAYS** document functions with 3+ parameters | Prevents misuse of positional args |\n| **ALWAYS** document non-obvious exit codes (beyond 0/1) | Callers need to handle specific failures |\n| **NEVER** omit the shebang line (`#!/usr/bin/env bash`) | Portability — don't assume `/bin/bash` |\n| **NEVER** put usage info only in comments (not in `--help`) | Users shouldn't need to read source |\n\n---\n\n## Code Quality Metrics\n\n> See `common-standards.md` for universal coverage targets and testing principles.\n\n### Validation Commands\n\n```bash\n# Shellcheck all scripts\nshellcheck scripts/*.sh\n# Output: \"X issues\" → Count by severity\n\n# Check set flags\ngrep -r \"^set -\" scripts/ | grep -c \"eEuo pipefail\"\n# Compare to total script count\n\n# Count unquoted variables (SC2086)\nshellcheck scripts/*.sh -f json | jq '[.[] | select(.code == 2086)] | length'\n\n# Check ERR trap presence\ngrep -r \"trap.*ERR\" scripts/ | wc -l\n\n# Check exit code documentation\ngrep -r \"# Exit Codes:\" scripts/ | wc -l\n\n# Security: Check for secrets in args\ngrep -rE \"\\-\\-(password|token|secret)=\" scripts/\n# Should return nothing\n```\n\n---\n\n## Anti-Patterns Avoided\n\n> See `common-standards.md` for universal anti-patterns across all languages.\n\n### No Parsing ls Output\n\n```bash\n# Bad\nfor f in $(ls); do\n echo \"$f\"\ndone\n\n# Good\nfor f in *; do\n [[ -e \"$f\" ]] || continue\n echo \"$f\"\ndone\n\n# Good - find with null separator\nwhile IFS= read -r -d '' f; do\n echo \"$f\"\ndone \u003c \u003c(find . -type f -print0)\n```\n\n### No Useless Cat\n\n```bash\n# Bad\ncat file.txt | grep pattern\n\n# Good\ngrep pattern file.txt\n```\n\n### No Backticks\n\n```bash\n# Bad\nresult=`command`\n\n# Good\nresult=$(command)\n\n# Good - nested\nresult=$(echo $(date))\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Safety** | set flags count, SC2086 violations |\n| **Code Quality** | shellcheck total violations, function count |\n| **Security** | Secrets in CLI, input validation |\n| **Error Handling** | ERR trap, exit code docs |\n| **Logging** | Log function usage |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | 0 shellcheck errors, set flags, ERR trap, 0 security issues |\n| A | \u003c5 shellcheck warnings, set flags, ERR trap, quoted vars |\n| A- | \u003c15 shellcheck warnings, set flags, mostly quoted |\n| B+ | \u003c30 shellcheck warnings, set flags present |\n| B | \u003c50 shellcheck warnings, some flags |\n| C | Significant safety issues |\n| D | Not production-ready |\n| F | Critical issues |\n\n### Example Assessment\n\n```markdown\n## Shell Script Standards Compliance\n\n**Target:** scripts/\n**Date:** 2026-01-21\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Safety | A+ | 12/12 have set -eEuo pipefail, 0 SC2086 |\n| Code Quality | A- | 8 shellcheck warnings (SC2312), 15 functions |\n| Security | A | 0 secrets in CLI, 8/8 inputs validated |\n| Error Handling | A | 12/12 ERR trap, 11/12 exit codes |\n| **OVERALL** | **A** | **5 MEDIUM findings** |\n```\n\n---\n\n## Vibe Integration\n\n### Prescan Patterns\n\n| Pattern | Severity | Detection |\n|---------|----------|-----------|\n| P05: Missing set flags | HIGH | No `set -eEuo pipefail` |\n| P06: Unquoted variables | MEDIUM | SC2086 violations |\n| P09: Secrets in CLI | CRITICAL | `--password=` patterns |\n\n### JIT Loading\n\n**Tier 1 (Fast):** Load `~/.agents/skills/standards/references/shell.md` (5KB)\n**Tier 2 (Deep):** Load this document (18KB) for comprehensive audit\n\n---\n\n## Additional Resources\n\n- [Bash Manual](https://www.gnu.org/software/bash/manual/)\n- [ShellCheck Wiki](https://www.shellcheck.net/wiki/)\n- [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html)\n- [BATS Testing Framework](https://github.com/bats-core/bats-core)\n\n---\n\n**Related:** Quick reference in Tier 1 `shell.md`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":20380,"content_sha256":"fe682a2f0b14d205e197293642f305989dc40b09f20dcda6225575f76d78c54c"},{"filename":"references/test-pyramid-inventory.md","content":"# Test Pyramid Inventory (Step 2g, MANDATORY)\n\nAssess test coverage against the test pyramid standard (the test pyramid standard (loaded via `/standards`)).\n\nRead `skills/vibe/references/test-pyramid-weighting.md` for test pyramid weighting — L3+ tests found all production bugs, weight them 5x.\n\n**Test Pyramid Weighting:** Weight test coverage by level: L0–L1 at 1x, L2 at 3x, L3+ at 5x. Unit-only coverage is a WARN signal, not a PASS. See `references/test-pyramid-weighting.md`.\n\n**Run even in `--quick` mode** — this is cheap (file existence checks) and high-signal.\n\n1. **Identify changed modules** from git diff or target scope\n2. **For each changed module, check coverage pyramid (L0–L3):**\n - L0: Does a contract/spec enforcement test cover this module?\n - L1: Does a unit test file exist for this module?\n - L2: If module crosses boundaries, does an integration test exist?\n3. **For boundary-touching code, check bug-finding pyramid (BF1–BF5):**\n - BF4 (Chaos): Do external call sites have failure injection tests?\n - BF1 (Property): Do data transformations have property tests?\n - BF2 (Golden): Do output generators have golden file tests?\n4. **Compute weighted pyramid score** for changed code paths:\n\n **Formula:**\n ```\n weighted_score = (L0_count x 1 + L1_count x 1 + L2_count x 3 + L3_count x 5 + L4_count x 5) / max_possible\n ```\n Where `max_possible = total_test_count x 5` (the score if every test were L3+).\n\n Count tests at each level for changed code paths:\n - L0: Build/compile checks (weight 1)\n - L1: Unit tests (weight 1)\n - L2: Integration tests (weight 3)\n - L3: E2E/system tests (weight 5)\n - L4: Smoke/fresh-context tests (weight 5)\n\n **Interpretation:**\n - `weighted_score >= 0.6` — strong pyramid, L2+ tests present\n - `0.3 \u003c= weighted_score \u003c 0.6` — acceptable, but recommend more integration tests\n - `weighted_score \u003c 0.3` AND all tests are L0-L1 only — **WARN: unit-only test coverage** (feeds into vibe verdict as a WARN signal, not a separate gate)\n\n **Satisfaction exposure:** The `weighted_score` is also exposed as `satisfaction_score` (with source `\"test-pyramid-weighted\"`) in the test_pyramid output block AND promoted to the top-level verdict JSON as `satisfaction_score` (verdict schema field, `skills/council/schemas/verdict.json`: number 0.0-1.0, \"Probabilistic satisfaction score (0.0 = unsatisfied, 1.0 = fully satisfied). Optional — absent means not computed.\"). Downstream consumers (e.g., `/validation` STEP 1.8 holdout evaluation) can use `satisfaction_score` as a normalized quality signal.\n\n **Include in council packet and vibe report output:**\n ```\n ## Test Pyramid Score\n | Level | Count | Weight | Contribution |\n |-------|-------|--------|--------------|\n | L0 | 2 | 1x | 2 |\n | L1 | 8 | 1x | 8 |\n | L2 | 0 | 3x | 0 |\n | L3 | 0 | 5x | 0 |\n | L4 | 0 | 5x | 0 |\n | **Total** | **10** | | **10 / 50 = 0.20** |\n WARN: weighted_score 0.20 \u003c 0.3 and all tests are L0-L1 only\n ```\n\n5. **Build coverage table** and include in council packet as `context.test_pyramid`:\n\n```json\n\"test_pyramid\": {\n \"coverage\": {\n \"L0\": {\"status\": \"pass\", \"files\": [\"test_spec_enforcement.py\"]},\n \"L1\": {\"status\": \"pass\", \"files\": [\"test_module.py\"]},\n \"L2\": {\"status\": \"gap\", \"reason\": \"crosses subsystem boundary, no integration test\"}\n },\n \"bug_finding\": {\n \"BF4_chaos\": {\"status\": \"gap\", \"reason\": \"external API calls without failure injection\"},\n \"BF1_property\": {\"status\": \"na\", \"reason\": \"no data transformations in scope\"}\n },\n \"weighted_score\": 0.20,\n \"satisfaction_score\": 0.20,\n \"satisfaction_source\": \"test-pyramid-weighted\",\n \"score_breakdown\": {\"L0\": 2, \"L1\": 8, \"L2\": 0, \"L3\": 0, \"L4\": 0},\n \"max_possible\": 50,\n \"warn_unit_only\": true,\n \"verdict\": \"WARN: weighted_score 0.20 \u003c 0.3, all tests L0-L1 only\"\n}\n```\n\n**Verdict rules:**\n- `weighted_score \u003c 0.3` AND all tests L0-L1 only — **WARN: unit-only coverage** (include in council findings)\n- Missing L1 on feature code — **WARN** (include in council findings)\n- Missing L0 on spec-changing code — **WARN**\n- Missing BF4 on boundary code — **WARN** (advisory, not blocking)\n- All levels covered with `weighted_score >= 0.6` — no mention needed\n\nWhen coverage gaps are found, run `/test \u003cmodule>` to generate test candidates for uncovered code.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4475,"content_sha256":"902ff3ebdb814ea041dc0e351f4be668eebc509eaf88f545c645598fd037c40e"},{"filename":"references/test-pyramid-weighting.md","content":"# AI-Native Test Shape Weighting\n\n> From analysis of 946 council verdicts: unit tests (L0–L1) found zero production bugs. L2+ tests (integration, E2E, smoke) found ALL real bugs.\n> Vibe scoring must weight higher-level coverage proportionally. This is the empirical basis for the AI-native test shape (see `skills/standards/references/test-pyramid.md`).\n\n## The Evidence\n\nAcross 14,753 analyzed sessions:\n- **L0 (build):** Catches syntax errors only. No bugs found that weren't immediately obvious.\n- **L1 (unit):** Zero production bugs caught. Useful for regression prevention but NOT for bug discovery.\n- **L2 (integration):** Moderate bug discovery. Catches component interaction failures.\n- **L3 (E2E/system):** Found the majority of real bugs. Tests full workflows.\n- **L4 (smoke/zero-context):** 3–5x more issues found than self-review. Fresh-eye validation is the highest-value test.\n\n## Scoring Weights\n\nWhen computing the test coverage component of a vibe score:\n\n| Level | Weight | Rationale |\n|-------|--------|-----------|\n| L0: Build passes | 1x | Table stakes — not a quality signal |\n| L1: Unit tests pass | 1x | Regression prevention, not discovery |\n| L2: Integration tests pass | 3x | Real interaction bugs caught here |\n| L3: E2E tests pass | 5x | Highest bug-discovery rate |\n| L4: Smoke/fresh-context | 5x | Catches what familiarity blinds |\n\n## Impact on Vibe Verdicts\n\n### PASS Requirements\n- L0 + L1 passing is NECESSARY but NOT SUFFICIENT\n- At least one L2+ test must exist for changed code paths\n- If L3+ tests exist and pass, this is a strong positive signal\n\n### WARN Triggers\n- All tests are L0–L1 only (no integration or higher)\n- Changed code paths have no dedicated test at any level\n- Test count is high but all tests are trivial assertions (`!= nil`, `!= \"\"`)\n\n### FAIL Triggers\n- L2+ tests exist and are failing\n- Changed code has zero test coverage at any level\n- Test suite is entirely coverage-padding (no behavioral assertions)\n\n## Recommendations to Judges\n\nWhen reviewing test coverage in a vibe check:\n\n1. **Count tests by level, not just total.** 50 unit tests and 0 integration tests is worse than 10 unit tests and 5 integration tests.\n\n2. **Check test quality, not just quantity.** Trivial assertions (`!= nil`, `!= \"\"`) are banned per project rules. Each test must assert behavioral correctness.\n\n3. **Prioritize coverage gaps at L2+.** If suggesting test improvements, suggest integration or E2E tests first, not more unit tests.\n\n4. **Fresh-context validation is high-value.** A zero-context reviewer (different agent, fresh session) catching issues is worth more than the implementer's self-review.\n\n## Integration with /test Skill\n\nWhen vibe detects insufficient L2+ coverage:\n- Recommend running `/test` with explicit level targeting\n- Suggest specific integration test scenarios based on changed code paths\n- Flag if the project has no integration test infrastructure at all\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2936,"content_sha256":"6243377a947787f2131d8716a886d5541a59859c2dde805c19c892003f0fba68"},{"filename":"references/typescript-standards.md","content":"# TypeScript Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical TypeScript standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [Strict Configuration](#strict-configuration)\n2. [ESLint Configuration](#eslint-configuration)\n3. [Type System Patterns](#type-system-patterns)\n4. [Generic Constraints](#generic-constraints)\n5. [Utility Types](#utility-types)\n6. [Conditional Types](#conditional-types)\n7. [Error Handling](#error-handling)\n8. [Module Template](#module-template)\n9. [Code Quality Metrics](#code-quality-metrics)\n10. [Testing Patterns](#testing-patterns)\n - [Test Frameworks](#test-frameworks)\n - [Test Organization](#test-organization)\n - [React Testing Library Patterns](#react-testing-library-patterns)\n - [MSW (Mock Service Worker)](#msw-mock-service-worker-for-api-mocking)\n - [Mocking](#mocking)\n - [Async Testing](#async-testing)\n - [Type-safe Testing](#type-safe-testing)\n - [Snapshot Testing](#snapshot-testing)\n - [Coverage Expectations](#coverage-expectations)\n11. [Anti-Patterns Avoided](#anti-patterns-avoided)\n12. [Compliance Assessment](#compliance-assessment)\n\n---\n\n## Strict Configuration\n\n### Full tsconfig.json\n\nEvery TypeScript project MUST use strict mode:\n\n```json\n{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"NodeNext\",\n \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\"],\n \"outDir\": \"./dist\",\n \"rootDir\": \"./src\",\n\n \"strict\": true,\n \"noUncheckedIndexedAccess\": true,\n \"noImplicitReturns\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"exactOptionalPropertyTypes\": true,\n\n \"declaration\": true,\n \"declarationMap\": true,\n \"sourceMap\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"forceConsistentCasingInFileNames\": true\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n```\n\n### Why Strict Matters\n\n| Option | Effect |\n|--------|--------|\n| `strict: true` | Enables all strict type-checking options |\n| `noUncheckedIndexedAccess` | Adds `undefined` to index signatures |\n| `exactOptionalPropertyTypes` | Distinguishes `undefined` from missing |\n| `noImplicitReturns` | All code paths must return |\n| `noFallthroughCasesInSwitch` | Prevents accidental case fallthrough |\n\n---\n\n## ESLint Configuration\n\n### eslint.config.js (Flat Config)\n\n```javascript\nimport eslint from '@eslint/js';\nimport tseslint from 'typescript-eslint';\n\nexport default tseslint.config(\n eslint.configs.recommended,\n ...tseslint.configs.strictTypeChecked,\n ...tseslint.configs.stylisticTypeChecked,\n {\n languageOptions: {\n parserOptions: {\n project: true,\n tsconfigRootDir: import.meta.dirname,\n },\n },\n rules: {\n '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],\n '@typescript-eslint/explicit-function-return-type': 'error',\n '@typescript-eslint/no-explicit-any': 'error',\n '@typescript-eslint/prefer-nullish-coalescing': 'error',\n '@typescript-eslint/prefer-optional-chain': 'error',\n '@typescript-eslint/no-floating-promises': 'error',\n '@typescript-eslint/await-thenable': 'error',\n },\n },\n {\n ignores: ['dist/', 'node_modules/', '*.js'],\n }\n);\n```\n\n### Usage\n\n```bash\n# Lint check\nnpx eslint . --ext .ts,.tsx\n\n# Fix auto-fixable issues\nnpx eslint . --ext .ts,.tsx --fix\n\n# Type check only (no emit)\nnpx tsc --noEmit\n```\n\n---\n\n## Type System Patterns\n\n### Prefer Type Inference\n\nLet TypeScript infer types when obvious:\n\n```typescript\n// Good - inference is clear\nconst users = ['alice', 'bob'];\nconst count = users.length;\n\n// Good - explicit when non-obvious or API boundary\nfunction getUser(id: string): User | undefined {\n return userMap.get(id);\n}\n\n// Bad - redundant annotation\nconst name: string = 'alice';\n```\n\n### Discriminated Unions\n\nUse discriminated unions for state modeling:\n\n```typescript\n// Good - exhaustive pattern matching\ntype Result\u003cT, E> =\n | { status: 'success'; data: T }\n | { status: 'error'; error: E };\n\nfunction handleResult\u003cT, E>(result: Result\u003cT, E>): void {\n switch (result.status) {\n case 'success':\n console.log(result.data);\n break;\n case 'error':\n console.error(result.error);\n break;\n // TypeScript enforces exhaustiveness\n }\n}\n```\n\n### Const Assertions\n\nUse `as const` for literal types:\n\n```typescript\n// Good - preserves literal types\nconst CONFIG = {\n apiVersion: 'v1',\n retries: 3,\n endpoints: ['primary', 'fallback'],\n} as const;\n\n// Type: { readonly apiVersion: \"v1\"; readonly retries: 3; ... }\n```\n\n### Branded Types\n\nUse branded types for type-safe IDs:\n\n```typescript\ntype UserId = string & { readonly __brand: 'UserId' };\ntype OrderId = string & { readonly __brand: 'OrderId' };\n\nfunction createUserId(id: string): UserId {\n return id as UserId;\n}\n\nfunction getUser(id: UserId): User { ... }\nfunction getOrder(id: OrderId): Order { ... }\n\n// Type error: can't pass UserId where OrderId expected\nconst user = getUser(createUserId('123'));\nconst order = getOrder(createUserId('123')); // Error!\n```\n\n---\n\n## Generic Constraints\n\n### Constrained Generics\n\nAlways constrain generics when possible:\n\n```typescript\n// Good - constrained generic\nfunction getProperty\u003cT, K extends keyof T>(obj: T, key: K): T[K] {\n return obj[key];\n}\n\n// Good - multiple constraints\nfunction merge\u003cT extends object, U extends object>(a: T, b: U): T & U {\n return { ...a, ...b };\n}\n\n// Bad - unconstrained (allows any)\nfunction unsafe\u003cT>(value: T): T {\n return value;\n}\n```\n\n### Generic Defaults\n\nProvide defaults for optional type parameters:\n\n```typescript\ninterface ApiResponse\u003cT = unknown, E = Error> {\n data?: T;\n error?: E;\n status: number;\n}\n\n// Uses defaults\nconst response: ApiResponse = { status: 200 };\n\n// Override defaults\nconst typed: ApiResponse\u003cUser, ApiError> = { status: 200 };\n```\n\n### Generic Inference\n\nLet TypeScript infer generic types when possible:\n\n```typescript\n// Good - infers T from argument\nfunction identity\u003cT>(value: T): T {\n return value;\n}\n\nconst str = identity('hello'); // T inferred as string\nconst num = identity(42); // T inferred as number\n\n// Bad - unnecessary explicit type\nconst str2 = identity\u003cstring>('hello'); // Redundant\n```\n\n---\n\n## Utility Types\n\n### Built-in Utilities\n\nUse built-in utility types over manual definitions:\n\n```typescript\n// Partial - all properties optional\ntype PartialUser = Partial\u003cUser>;\n\n// Required - all properties required\ntype RequiredConfig = Required\u003cConfig>;\n\n// Pick - select properties\ntype UserPreview = Pick\u003cUser, 'id' | 'name'>;\n\n// Omit - exclude properties\ntype UserWithoutPassword = Omit\u003cUser, 'password'>;\n\n// Record - typed object\ntype UserMap = Record\u003cstring, User>;\n\n// Extract/Exclude - union manipulation\ntype StringOrNumber = Extract\u003cstring | number | boolean, string | number>;\n```\n\n### Custom Type Helpers\n\nCreate reusable type utilities:\n\n```typescript\n// Deep partial\ntype DeepPartial\u003cT> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial\u003cT[P]> : T[P];\n};\n\n// Non-nullable object values\ntype NonNullableValues\u003cT> = {\n [K in keyof T]: NonNullable\u003cT[K]>;\n};\n\n// Extract function return types from object\ntype ReturnTypes\u003cT extends Record\u003cstring, (...args: never[]) => unknown>> = {\n [K in keyof T]: ReturnType\u003cT[K]>;\n};\n\n// Make specific keys required\ntype WithRequired\u003cT, K extends keyof T> = T & Required\u003cPick\u003cT, K>>;\n```\n\n---\n\n## Conditional Types\n\n### Type-Level Logic\n\nUse conditional types for dynamic typing:\n\n```typescript\n// Infer array element type\ntype ElementOf\u003cT> = T extends readonly (infer E)[] ? E : never;\n\n// Flatten promise type\ntype Awaited\u003cT> = T extends Promise\u003cinfer U> ? Awaited\u003cU> : T;\n\n// Function parameter extraction\ntype FirstParam\u003cT> = T extends (first: infer P, ...args: never[]) => unknown\n ? P\n : never;\n\n// Conditional return type\ntype ApiResult\u003cT> = T extends 'user'\n ? User\n : T extends 'order'\n ? Order\n : never;\n```\n\n### Template Literal Types\n\nUse template literals for string manipulation:\n\n```typescript\n// Event handler naming\ntype EventName = 'click' | 'change' | 'submit';\ntype HandlerName = `on${Capitalize\u003cEventName>}`;\n// Result: \"onClick\" | \"onChange\" | \"onSubmit\"\n\n// Path building\ntype ApiPath\u003cT extends string> = `/api/v1/${T}`;\ntype UserPath = ApiPath\u003c'users'>; // \"/api/v1/users\"\n\n// Property getters/setters\ntype Getters\u003cT> = {\n [K in keyof T as `get${Capitalize\u003cstring & K>}`]: () => T[K];\n};\n```\n\n---\n\n## Error Handling\n\n### Result Pattern\n\nPrefer explicit error handling over exceptions:\n\n```typescript\ntype Result\u003cT, E = Error> =\n | { ok: true; value: T }\n | { ok: false; error: E };\n\nfunction parseJson\u003cT>(json: string): Result\u003cT, SyntaxError> {\n try {\n return { ok: true, value: JSON.parse(json) as T };\n } catch (e) {\n return { ok: false, error: e as SyntaxError };\n }\n}\n\n// Usage\nconst result = parseJson\u003cUser>(input);\nif (result.ok) {\n console.log(result.value.name);\n} else {\n console.error(result.error.message);\n}\n```\n\n### Type Guards\n\nUse type guards for runtime type narrowing:\n\n```typescript\n// User-defined type guard\nfunction isUser(value: unknown): value is User {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value\n );\n}\n\n// Assertion function\nfunction assertUser(value: unknown): asserts value is User {\n if (!isUser(value)) {\n throw new Error('Invalid user');\n }\n}\n\n// Usage\nfunction processData(data: unknown): void {\n if (isUser(data)) {\n // data is User here\n console.log(data.name);\n }\n\n // Or with assertion\n assertUser(data);\n // data is User from here on\n console.log(data.id);\n}\n```\n\n### Error Classes\n\nCreate typed error classes:\n\n```typescript\nclass AppError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = 'AppError';\n }\n}\n\nclass ValidationError extends AppError {\n constructor(\n message: string,\n public readonly field: string,\n ) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\n// Type guard for error handling\nfunction isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n```\n\n---\n\n## Module Template\n\nStandard template for TypeScript modules:\n\n```typescript\n/**\n * Module description.\n * @module module-name\n */\n\n// Types first\nexport interface Config {\n readonly apiUrl: string;\n readonly timeout: number;\n}\n\nexport type Handler\u003cT> = (data: T) => Promise\u003cvoid>;\n\n// Type guards\nexport function isConfig(value: unknown): value is Config {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'apiUrl' in value &&\n 'timeout' in value\n );\n}\n\n// Constants\nconst DEFAULT_TIMEOUT = 5000;\n\n// Private helpers (not exported)\nfunction validateConfig(config: Config): void {\n if (!config.apiUrl) {\n throw new Error('apiUrl is required');\n }\n}\n\n// Public API\nexport function createClient(config: Config): Client {\n validateConfig(config);\n return new Client(config);\n}\n\nexport class Client {\n readonly #config: Config;\n\n constructor(config: Config) {\n this.#config = config;\n }\n\n async fetch\u003cT>(path: string): Promise\u003cT> {\n const response = await fetch(`${this.#config.apiUrl}${path}`);\n return response.json() as Promise\u003cT>;\n }\n}\n```\n\n---\n\n## Code Quality Metrics\n\n> See `common-standards.md` for universal coverage targets and testing principles.\n\n### Type Coverage Metrics\n\n| Metric | Target | Validation |\n|--------|--------|------------|\n| tsc errors | 0 | `tsc --noEmit` |\n| any types | 0 | `grep -r \": any\"` |\n| Explicit returns | 100% on exports | `grep \"^export function\"` |\n| Type-only imports | 100% | Check `import type` usage |\n\n### Validation Commands\n\n```bash\n# Type check (no emit)\ntsc --noEmit\n# Output: \"Found X errors\" → Count these\n\n# ESLint violations\nnpx eslint . --ext .ts,.tsx\n# Output: \"X problems (Y errors, Z warnings)\" → Report all\n\n# Count any types\ngrep -r \": any\" src/ | wc -l\n# Report: \"5 any types found\"\n\n# Count explicit return types on exports\ngrep -r \"^export function\" src/ | grep -c \": .* {\"\n# Compare to total export function count\n\n# Type-only imports check\ngrep -r \"^import {\" src/ | grep -vc \"import type\"\n# Report: \"12 value imports (should be type-only)\"\n```\n\n---\n\n## Testing Patterns\n\n### Test Frameworks\n\n#### Vitest (Preferred)\n\nVitest is the recommended test runner for TypeScript projects. It shares Vite's config and transform pipeline, supports ESM natively, and runs significantly faster than Jest for TypeScript codebases.\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environment: 'jsdom', // For React; use 'node' for backend\n setupFiles: ['./src/test/setup.ts'],\n coverage: {\n provider: 'v8',\n reporter: ['text', 'lcov'],\n exclude: ['**/*.d.ts', '**/*.test.ts', '**/test/**'],\n },\n typecheck: {\n enabled: true, // Run type-level tests via expect-type\n },\n },\n});\n```\n\n#### Jest 29+ with ts-jest\n\nWhen Vitest is not an option (legacy codebase, specific CI constraints):\n\n```typescript\n// jest.config.ts\nimport type { Config } from 'jest';\n\nconst config: Config = {\n preset: 'ts-jest',\n testEnvironment: 'node',\n roots: ['\u003crootDir>/src'],\n moduleNameMapper: {\n '^@/(.*)

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

: '\u003crootDir>/src/$1',\n },\n collectCoverageFrom: [\n 'src/**/*.ts',\n '!src/**/*.d.ts',\n '!src/**/*.test.ts',\n ],\n};\n\nexport default config;\n```\n\n| Setting | Recommendation |\n|---------|---------------|\n| Runner | Vitest (preferred) or Jest 29+ with ts-jest |\n| Environment | `jsdom` for UI, `node` for backend/CLI |\n| Globals | `true` — avoids `import { describe, it }` boilerplate |\n| Coverage provider | `v8` (fast) or `istanbul` (precise) |\n| Transform | Vitest uses esbuild (fast); Jest uses ts-jest or `@swc/jest` |\n\n### Test Organization\n\n```typescript\ndescribe('UserService', () => {\n // Group by method\n describe('createUser', () => {\n it('creates user with valid data', async () => { /* ... */ });\n it('throws ValidationError for duplicate email', async () => { /* ... */ });\n it('hashes password before storing', async () => { /* ... */ });\n });\n\n describe('deleteUser', () => {\n it('soft-deletes user by setting deletedAt', async () => { /* ... */ });\n it('throws NotFoundError for unknown id', async () => { /* ... */ });\n });\n});\n```\n\n**Nesting guidelines:**\n\n- Top-level `describe` = class or module name\n- Second-level `describe` = method or function name\n- `it` blocks = single behavior, stated as expected outcome\n- Limit nesting to 3 levels maximum — deeper nesting signals the unit under test is too complex\n\n**File naming and placement:**\n\n| Convention | Example |\n|-----------|---------|\n| Co-located tests (preferred) | `user-service.test.ts` next to `user-service.ts` |\n| Test directory | `__tests__/user-service.test.ts` (when co-location is impractical) |\n| Test utilities | `src/test/setup.ts` for global setup, `src/test/factories.ts` for test data |\n| Integration tests | `tests/integration/` at project root |\n| E2E tests | `tests/e2e/` at project root |\n| Describe blocks | Class/module name: `describe('UserService', ...)` |\n| Test names | Behavior: `it('throws ValidationError for duplicate email')` |\n\n### React Testing Library Patterns\n\nTest components by user behavior, not implementation:\n\n```typescript\n// Good - tests user-visible behavior\nimport { render, screen } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\ntest('submits form with valid data', async () => {\n const onSubmit = vi.fn();\n const user = userEvent.setup();\n\n render(\u003cLoginForm onSubmit={onSubmit} />);\n\n await user.type(screen.getByLabelText('Email'), '[email protected]');\n await user.type(screen.getByLabelText('Password'), 'secret123');\n await user.click(screen.getByRole('button', { name: /sign in/i }));\n\n expect(onSubmit).toHaveBeenCalledWith({\n email: '[email protected]',\n password: 'secret123',\n });\n});\n\n// Bad - tests implementation details\ntest('sets state on input change', () => {\n const { container } = render(\u003cLoginForm />);\n const input = container.querySelector('input[name=\"email\"]')!;\n fireEvent.change(input, { target: { value: '[email protected]' } });\n // Brittle: relies on DOM structure and internal state\n});\n```\n\n**Query Priority (prefer top to bottom):**\n\n| Priority | Query | When |\n|----------|-------|------|\n| 1 | `getByRole` | Interactive elements (buttons, inputs, headings) |\n| 2 | `getByLabelText` | Form fields |\n| 3 | `getByText` | Non-interactive text content |\n| 4 | `getByTestId` | Last resort — no accessible selector available |\n\n### MSW (Mock Service Worker) for API Mocking\n\nMock API calls at the network level, not the implementation level:\n\n```typescript\nimport { http, HttpResponse } from 'msw';\nimport { setupServer } from 'msw/node';\n\nconst handlers = [\n http.get('/api/users/:id', ({ params }) => {\n return HttpResponse.json({\n id: params.id,\n name: 'Alice',\n email: '[email protected]',\n });\n }),\n\n http.post('/api/users', async ({ request }) => {\n const body = await request.json();\n return HttpResponse.json(body, { status: 201 });\n }),\n];\n\nconst server = setupServer(...handlers);\n\nbeforeAll(() => server.listen({ onUnhandledRequest: 'error' }));\nafterEach(() => server.resetHandlers());\nafterAll(() => server.close());\n\n// Override for specific test\ntest('handles server error', async () => {\n server.use(\n http.get('/api/users/:id', () => {\n return HttpResponse.json({ message: 'Internal error' }, { status: 500 });\n }),\n );\n // ... test error handling\n});\n```\n\n### Async Testing Patterns\n\nUse `waitFor` and async queries for asynchronous UI updates:\n\n```typescript\n// Good - waits for async state updates\nimport { render, screen, waitFor } from '@testing-library/react';\n\ntest('loads and displays user data', async () => {\n render(\u003cUserProfile userId=\"123\" />);\n\n // findBy* waits for element to appear (combines getBy + waitFor)\n const name = await screen.findByText('Alice');\n expect(name).toBeInTheDocument();\n\n // waitFor for assertions on async state\n await waitFor(() => {\n expect(screen.getByRole('status')).toHaveTextContent('Active');\n });\n});\n\n// Bad - manual timers and arbitrary delays\ntest('loads data', async () => {\n render(\u003cUserProfile userId=\"123\" />);\n await new Promise((r) => setTimeout(r, 1000)); // Flaky!\n expect(screen.getByText('Alice')).toBeInTheDocument();\n});\n```\n\n### Snapshot Testing\n\n| Use Snapshots For | Avoid Snapshots For |\n|-------------------|---------------------|\n| Serialized data structures (API responses, configs) | Full component trees (too brittle) |\n| Error message formatting | Styled components (CSS changes break snapshots) |\n| CLI output strings | Large objects (unreadable diffs) |\n\n```typescript\n// Good - small, focused snapshot\ntest('formats error response', () => {\n const error = formatApiError(404, 'User not found');\n expect(error).toMatchInlineSnapshot(`\n {\n \"code\": 404,\n \"message\": \"User not found\",\n \"type\": \"NOT_FOUND\",\n }\n `);\n});\n\n// Bad - entire component tree snapshot\ntest('renders dashboard', () => {\n const { container } = render(\u003cDashboard />);\n expect(container).toMatchSnapshot(); // 500+ line snapshot nobody reviews\n});\n```\n\n### Mocking\n\n#### Function Mocks (`vi.fn` / `jest.fn`)\n\nUse function mocks to verify interactions and control return values:\n\n```typescript\n// Basic function mock\nconst onSave = vi.fn();\nrender(\u003cForm onSave={onSave} />);\nawait user.click(screen.getByRole('button', { name: /save/i }));\nexpect(onSave).toHaveBeenCalledOnce();\nexpect(onSave).toHaveBeenCalledWith({ name: 'Alice', email: '[email protected]' });\n\n// Mock with return value\nconst fetchUser = vi.fn().mockResolvedValue({ id: '1', name: 'Alice' });\n\n// Mock with implementation\nconst hash = vi.fn((input: string) => `hashed_${input}`);\n\n// Spy on existing method (preserves original by default)\nconst consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});\n// ... test code ...\nexpect(consoleSpy).toHaveBeenCalledWith('Connection failed');\nconsoleSpy.mockRestore();\n```\n\n#### Module Mocks\n\nMock entire modules when you need to replace dependencies:\n\n```typescript\n// Vitest — mock a module\nvi.mock('./database', () => ({\n getConnection: vi.fn().mockReturnValue({\n query: vi.fn().mockResolvedValue([]),\n close: vi.fn(),\n }),\n}));\n\n// Jest — mock a module\njest.mock('./database', () => ({\n getConnection: jest.fn().mockReturnValue({\n query: jest.fn().mockResolvedValue([]),\n close: jest.fn(),\n }),\n}));\n\n// Import after mock declaration — the import gets the mocked version\nimport { getConnection } from './database';\n```\n\n#### Manual Mocks (`__mocks__/`)\n\nUse manual mocks for complex dependencies shared across many test files:\n\n```\nsrc/\n services/\n __mocks__/\n email-service.ts # Manual mock — auto-used when vi.mock('./email-service') is called\n email-service.ts # Real implementation\n email-service.test.ts\n```\n\n```typescript\n// src/services/__mocks__/email-service.ts\nexport const sendEmail = vi.fn().mockResolvedValue({ messageId: 'mock-id' });\nexport const validateAddress = vi.fn().mockReturnValue(true);\n\n// In test file — just declare the mock, implementation comes from __mocks__/\nvi.mock('./email-service');\n```\n\n**When to use each mocking approach:**\n\n| Approach | When |\n|----------|------|\n| `vi.fn()` / `jest.fn()` | Callbacks, event handlers, simple dependency injection |\n| `vi.spyOn()` / `jest.spyOn()` | Observing calls without replacing behavior (or with `mockImplementation`) |\n| `vi.mock()` / `jest.mock()` | Replacing an imported module for a single test file |\n| Manual mocks (`__mocks__/`) | Shared mock used by 3+ test files |\n| MSW | HTTP/API calls — always prefer over mocking `fetch`/`axios` directly |\n\n### Async Testing\n\n#### Promises and Async/Await\n\n```typescript\n// Good — async/await with proper assertion\nit('fetches user by id', async () => {\n const user = await userService.getById('123');\n expect(user).toEqual({ id: '123', name: 'Alice' });\n});\n\n// Good — testing rejected promises\nit('throws NotFoundError for missing user', async () => {\n await expect(userService.getById('nonexistent')).rejects.toThrow(NotFoundError);\n});\n\n// Good — testing promise resolution value\nit('resolves with created user', async () => {\n await expect(userService.create({ name: 'Bob' })).resolves.toMatchObject({\n name: 'Bob',\n id: expect.any(String),\n });\n});\n```\n\n#### Fake Timers\n\n```typescript\n// Vitest\nbeforeEach(() => {\n vi.useFakeTimers();\n});\n\nafterEach(() => {\n vi.useRealTimers();\n});\n\nit('retries after delay', async () => {\n const fetchData = vi.fn()\n .mockRejectedValueOnce(new Error('timeout'))\n .mockResolvedValue({ data: 'ok' });\n\n const promise = retryWithDelay(fetchData, { delay: 1000, retries: 2 });\n\n // Advance past the retry delay\n await vi.advanceTimersByTimeAsync(1000);\n\n const result = await promise;\n expect(result).toEqual({ data: 'ok' });\n expect(fetchData).toHaveBeenCalledTimes(2);\n});\n\nit('debounces input handler', async () => {\n const handler = vi.fn();\n const debounced = debounce(handler, 300);\n\n debounced('a');\n debounced('ab');\n debounced('abc');\n\n expect(handler).not.toHaveBeenCalled();\n\n await vi.advanceTimersByTimeAsync(300);\n\n expect(handler).toHaveBeenCalledOnce();\n expect(handler).toHaveBeenCalledWith('abc');\n});\n```\n\n#### React `act()` and Async State Updates\n\n```typescript\nimport { act, render, screen } from '@testing-library/react';\n\n// act() is needed when triggering state updates outside of RTL helpers\nit('updates count on external event', async () => {\n const eventBus = new EventEmitter();\n render(\u003cCounter eventBus={eventBus} />);\n\n await act(async () => {\n eventBus.emit('increment');\n });\n\n expect(screen.getByText('Count: 1')).toBeInTheDocument();\n});\n\n// RTL's userEvent and findBy* wrap act() automatically — prefer those\n// Only use act() directly when dealing with non-RTL async triggers\n```\n\n### Type-safe Testing\n\n#### Typed Mocks\n\n```typescript\n// Type-safe mock function\nconst onSubmit = vi.fn\u003c[FormData], Promise\u003cvoid>>();\n\n// Type-safe mock of an interface\ninterface UserRepository {\n findById(id: string): Promise\u003cUser | null>;\n save(user: User): Promise\u003cUser>;\n delete(id: string): Promise\u003cvoid>;\n}\n\nfunction createMockRepository(): { [K in keyof UserRepository]: ReturnType\u003ctypeof vi.fn> } & UserRepository {\n return {\n findById: vi.fn\u003c[string], Promise\u003cUser | null>>().mockResolvedValue(null),\n save: vi.fn\u003c[User], Promise\u003cUser>>().mockImplementation(async (user) => user),\n delete: vi.fn\u003c[string], Promise\u003cvoid>>().mockResolvedValue(undefined),\n };\n}\n\nit('returns null for unknown user', async () => {\n const repo = createMockRepository();\n const service = new UserService(repo);\n\n const result = await service.getById('unknown');\n expect(result).toBeNull();\n expect(repo.findById).toHaveBeenCalledWith('unknown');\n});\n```\n\n#### Assertion Helpers and Custom Matchers\n\n```typescript\n// Custom matcher for domain-specific assertions\nexpect.extend({\n toBeValidEmail(received: string) {\n const pass = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(received);\n return {\n pass,\n message: () => `expected ${received} ${pass ? 'not ' : ''}to be a valid email`,\n };\n },\n});\n\n// Declare the matcher type\ndeclare module 'vitest' {\n interface Assertion\u003cT> {\n toBeValidEmail(): T;\n }\n}\n\n// Usage\nit('generates valid email for new user', () => {\n const user = createUser({ name: 'Alice' });\n expect(user.email).toBeValidEmail();\n});\n```\n\n#### Type-level Testing with `expect-type`\n\n```typescript\nimport { expectTypeOf } from 'vitest';\n\nit('returns correct types', () => {\n // Verify function signature types\n expectTypeOf(getUser).parameter(0).toBeString();\n expectTypeOf(getUser).returns.resolves.toMatchTypeOf\u003cUser>();\n\n // Verify discriminated union exhaustiveness\n expectTypeOf\u003cResult\u003cstring>>().toMatchTypeOf\u003c\n { ok: true; value: string } | { ok: false; error: Error }\n >();\n\n // Verify type utilities produce correct types\n expectTypeOf\u003cWithRequired\u003cPartial\u003cUser>, 'id'>>().toHaveProperty('id');\n});\n```\n\n### Snapshot Testing\n\n| Use Snapshots For | Avoid Snapshots For |\n|-------------------|---------------------|\n| Serialized data structures (API responses, configs) | Full component trees (too brittle) |\n| Error message formatting | Styled components (CSS changes break snapshots) |\n| CLI output strings | Large objects (unreadable diffs) |\n\n```typescript\n// Good - small, focused snapshot\ntest('formats error response', () => {\n const error = formatApiError(404, 'User not found');\n expect(error).toMatchInlineSnapshot(`\n {\n \"code\": 404,\n \"message\": \"User not found\",\n \"type\": \"NOT_FOUND\",\n }\n `);\n});\n\n// Bad - entire component tree snapshot\ntest('renders dashboard', () => {\n const { container } = render(\u003cDashboard />);\n expect(container).toMatchSnapshot(); // 500+ line snapshot nobody reviews\n});\n```\n\n### Coverage Expectations\n\n| Level | Minimum | Target | Notes |\n|-------|---------|--------|-------|\n| Overall | 60% | 80% | Enforced in CI |\n| Critical paths | 80% | 90% | Auth, payments, data mutations |\n| Utility functions | 80% | 95% | Pure functions are easy to test |\n| Type guards | 100% | 100% | Runtime type safety boundary |\n\n```bash\n# Run tests with coverage\nnpx vitest run --coverage\n\n# Check coverage thresholds (in vitest.config.ts)\n# coverage.thresholds: { lines: 60, branches: 60, functions: 60 }\n```\n\n**What to cover vs. what to skip:**\n\n| Cover | Skip |\n|-------|------|\n| Business logic and domain rules | Generated code (protobuf, GraphQL types) |\n| Error handling paths | Third-party library internals |\n| Type guards (runtime boundary) | Trivial getters/setters |\n| State transitions | Framework boilerplate (module re-exports) |\n| Edge cases in parsing/validation | Static configuration objects |\n\n### ALWAYS / NEVER Rules\n\n| Rule | Type | Rationale |\n|------|------|-----------|\n| ALWAYS use `userEvent` over `fireEvent` | ALWAYS | `userEvent` simulates real browser behavior (focus, hover, keystrokes) |\n| ALWAYS use `findBy*` for async elements | ALWAYS | Avoids race conditions; auto-retries until timeout |\n| ALWAYS set `onUnhandledRequest: 'error'` in MSW | ALWAYS | Catches unmocked API calls that indicate missing test setup |\n| ALWAYS co-locate test files with source | ALWAYS | Easier navigation; test dies when source is deleted |\n| ALWAYS type your mock functions | ALWAYS | Catches incorrect call signatures at compile time |\n| ALWAYS clean up mocks in `afterEach` | ALWAYS | Prevents test pollution; use `vi.restoreAllMocks()` or `jest.restoreAllMocks()` |\n| NEVER use `container.querySelector` in RTL tests | NEVER | Bypasses accessibility queries; tests implementation not behavior |\n| NEVER use `setTimeout` / manual delays in tests | NEVER | Flaky; use `waitFor` or `findBy*` instead |\n| NEVER snapshot full component trees | NEVER | Unreadable diffs; nobody reviews 500-line snapshots |\n| NEVER mock what you don't own without MSW | NEVER | Direct `jest.mock('axios')` couples tests to HTTP library choice |\n| NEVER use `as any` to silence mock type errors | NEVER | Hides real type mismatches; use proper typed mocks instead |\n\n---\n\n## Anti-Patterns Avoided\n\n> See `common-standards.md` for universal anti-patterns across all languages.\n\n### No Any Escape\n\n```typescript\n// Bad - defeats type safety\nconst data = response as any;\nconst typed = data as User;\n\n// Good - use unknown + type guard\nconst data: unknown = response;\nif (isUser(data)) {\n const typed: User = data;\n}\n```\n\n### No Non-null Assertion Spam\n\n```typescript\n// Bad - runtime errors if assumption wrong\nconst name = user!.profile!.displayName!;\n\n// Good - proper null handling\nconst name = user?.profile?.displayName ?? 'Anonymous';\n```\n\n### No Index Signature Abuse\n\n```typescript\n// Bad - no type safety\ninterface Config {\n [key: string]: any;\n}\n\n// Good - explicit properties\ninterface Config {\n apiUrl: string;\n timeout: number;\n features: string[];\n}\n\n// Or generic when truly dynamic\ntype Config\u003cT extends string> = Record\u003cT, string>;\n```\n\n### No Enum for Strings\n\n```typescript\n// Bad - verbose, poor tree-shaking\nenum Color {\n Red = 'RED',\n Blue = 'BLUE',\n}\n\n// Good - union type\ntype Color = 'RED' | 'BLUE';\n\n// Or const object for runtime values\nconst Color = {\n Red: 'RED',\n Blue: 'BLUE',\n} as const;\ntype Color = typeof Color[keyof typeof Color];\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Type Safety** | tsc error count, any usage count, strict mode enabled |\n| **Code Quality** | ESLint violations count, unused variables |\n| **Type Coverage** | Explicit return types on exports (count), any/unknown ratio |\n| **Best Practices** | Discriminated union usage, type guard count |\n| **Testing** | Test file count, coverage % |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | 0 tsc errors, 0 any types, strict mode, 0 ESLint errors, 100% return types |\n| A | 0 tsc errors, \u003c3 any types (justified), \u003c5 ESLint errors, 95%+ return types |\n| A- | \u003c5 tsc errors, \u003c10 any types, \u003c15 ESLint errors, 85%+ return types |\n| B+ | \u003c15 tsc errors, \u003c20 any types, \u003c30 ESLint errors, 75%+ return types |\n| B | \u003c30 tsc errors, \u003c40 any types, \u003c50 ESLint errors, 60%+ return types |\n| C | Significant type safety issues |\n| D | Not production-ready |\n| F | Critical issues |\n\n### Example Assessment\n\n```markdown\n## TypeScript Standards Compliance\n\n**Target:** src/\n**Date:** 2026-01-21\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Type Safety | A+ | 0 tsc errors, 0 any types, strict mode |\n| Code Quality | A- | 8 ESLint violations (6 auto-fixable) |\n| Type Coverage | A | 48/52 exports typed (92%) |\n| Best Practices | A | 12 discriminated unions, 8 type guards |\n| **OVERALL** | **A** | **2 HIGH, 6 MEDIUM findings** |\n```\n\n---\n\n## Vibe Integration\n\n### Prescan Patterns\n\n| Pattern | Severity | Detection |\n|---------|----------|-----------|\n| P10: any type usage | HIGH | `: any` without justification |\n| P11: Non-null assertion spam | MEDIUM | Multiple `!` in chain |\n| P12: Missing import type | LOW | `import {` for type-only |\n\n### JIT Loading\n\n**Tier 1 (Fast):** Load `~/.agents/skills/standards/references/typescript.md` (5KB)\n**Tier 2 (Deep):** Load this document (18KB) for comprehensive audit\n\n---\n\n## Additional Resources\n\n- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/)\n- [typescript-eslint](https://typescript-eslint.io/)\n- [Total TypeScript](https://www.totaltypescript.com/)\n- [Type Challenges](https://github.com/type-challenges/type-challenges)\n\n---\n\n**Related:** Quick reference in Tier 1 `typescript.md`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":33117,"content_sha256":"6f02a105fb13cb294f76f6465db8a24d89eb802870e060f4cc6cc551d088cd63"},{"filename":"references/verification-report.md","content":"# Structured Verification Report Format\n\n> Inspired by verification-loop patterns. Use with `/vibe --structured` or as pre-PR gate.\n\n## When to Use\n\n- Before any PR submission\n- After `/crank` wave completion\n- As `/post-mortem` pre-check\n- When `--structured` flag is passed to `/vibe`\n\n## Report Template\n\n```\nVERIFICATION REPORT — \u003ctarget>\nDate: \u003cYYYY-MM-DD>\nScope: \u003cfiles or directories reviewed>\n\nBuild: [PASS/FAIL] \u003cdetails>\nTypes: [PASS/FAIL] (\u003cN> errors)\nLint: [PASS/FAIL] (\u003cN> warnings)\nTests: [PASS/FAIL] (\u003cN>/\u003cM> passed, \u003cZ>% coverage)\nSecurity: [PASS/FAIL] (\u003cN> issues)\nDiff: [\u003cN> files changed, +\u003cA>/-\u003cR> lines]\n\nOverall: [READY/NOT READY] for PR\n\nIssues to Fix:\n1. \u003cseverity> — \u003cfile:line> — \u003cdescription>\n2. ...\n\nRecommendations:\n- ...\n```\n\n## Phase Execution\n\n### Phase 1: Build Gate (fail-fast)\n```bash\n# Go\ncd cli && go build ./...\n\n# Python\npython -m py_compile \u003cchanged-files>\n\n# Node\nnpm run build 2>&1 | tail -20\n```\nIf build fails, STOP. Report failure. Do not proceed.\n\n### Phase 2: Type Check\n```bash\n# Go\ngo vet ./...\n\n# Python\nmypy \u003cchanged-files> --ignore-missing-imports\n\n# TypeScript\nnpx tsc --noEmit\n```\n\n### Phase 3: Lint\n```bash\n# Go\ngolangci-lint run ./...\n\n# Python\nruff check \u003cchanged-files>\n\n# Shell\nshellcheck \u003cchanged-scripts>\n```\n\n### Phase 4: Tests\n```bash\n# Go\ngo test ./... -count=1\n\n# Python\npytest \u003ctest-files> -v --tb=short\n```\nReport coverage if available.\n\n### Phase 5: Security Scan\n```bash\n# Secrets in changed files\ngrep -rn 'password\\|secret\\|api_key\\|token' \u003cchanged-files> | grep -v test | grep -v '_test'\n\n# Hardcoded values\ngrep -rn 'http://\\|localhost:\\|127.0.0.1' \u003cchanged-files> | grep -v test\n\n# Console/debug statements\ngrep -rn 'console\\.log\\|print(\\|fmt\\.Print' \u003cchanged-files> | grep -v test\n```\n\n### Phase 6: Diff Review\n```bash\ngit diff --stat HEAD~1\ngit diff HEAD~1 -- \u003cchanged-files>\n```\nReview for: unintended changes, leftover debug code, TODO comments, missing error handling.\n\n## Severity Classification\n\n| Severity | Definition | Action |\n|----------|-----------|--------|\n| CRITICAL | Build breaks, security vuln, data loss risk | Must fix before merge |\n| HIGH | Test failure, type error, missing validation | Should fix before merge |\n| MEDIUM | Lint warning, missing docs, style violation | Fix or document exception |\n| LOW | Suggestion, minor improvement | Optional |\n\n## Integration Points\n\n- `/vibe --structured` triggers this report format\n- `/crank` Step 7 can use this as wave-end gate\n- `/post-mortem` uses this as pre-check before council\n- `/pr-prep` includes this in PR body\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2594,"content_sha256":"a80e8f16334b20fe4fc0f6bb3f2b4d06e8ea13f2b7f038e60f4e8c3b84115f66"},{"filename":"references/vibe-coding.md","content":"# Vibe-Coding Science Reference\n\n**JIT-loaded by /vibe skill and validation agents**\n\n---\n\n## Vibe Levels (Trust Calibration)\n\n| Level | Trust | Verify | Use For | Tracer Test |\n|:-----:|:-----:|:------:|---------|-------------|\n| **5** | 95% | Final only | Format, lint, imports | Smoke (2m) |\n| **4** | 80% | Spot check | Boilerplate, renames | Environment (5m) |\n| **3** | 60% | Key outputs | CRUD, tests, known patterns | Integration (10m) |\n| **2** | 40% | Every change | New features, integrations | Components (15m) |\n| **1** | 20% | Every line | Architecture, security | All assumptions (30m) |\n| **0** | 0% | N/A | Novel research | Feasibility (15m) |\n\n**Most tasks are L3.** When in doubt, go lower.\n\n---\n\n## The 5 Core Metrics\n\n| Metric | Target | Red Flag | What It Means |\n|--------|:------:|:--------:|---------------|\n| **Iteration Velocity** | >3/hr | \u003c1/hr | Feedback loop frequency |\n| **Rework Ratio** | \u003c30% | >50% | Building vs debugging |\n| **Trust Pass Rate** | >80% | \u003c60% | Code acceptance rate |\n| **Debug Spiral Duration** | \u003c30m | >60m | Time stuck on issues |\n| **Flow Efficiency** | >75% | \u003c50% | Productive time ratio |\n\n**The key number:** Trust Pass Rate. If >80%, building. If \u003c60%, debugging.\n\n---\n\n## Rating Thresholds\n\n| Metric | ELITE | HIGH | MEDIUM | LOW |\n|--------|:-----:|:----:|:------:|:---:|\n| Velocity | >5 | ≥3 | ≥1 | \u003c1 |\n| Rework | \u003c30% | \u003c50% | \u003c70% | ≥70% |\n| Trust Pass | >95% | ≥80% | ≥60% | \u003c60% |\n| Spiral | \u003c15m | \u003c30m | \u003c60m | ≥60m |\n| Flow | >90% | ≥75% | ≥50% | \u003c50% |\n\n---\n\n## PDC Framework\n\n| Phase | Question | Actions |\n|-------|----------|---------|\n| **Prevent** | Could we have avoided this? | Specs, checkpoints, tests, 40% rule |\n| **Detect** | How did we catch it? | TDD, verify claims, monitor |\n| **Correct** | How do we fix it? | Fresh session, rollback, modularize |\n\n**Investment ratio:** Prevention (1x) > Detection (10x) > Correction (100x)\n\n---\n\n## The 12 Failure Patterns\n\n### Inner Loop (Seconds-Minutes)\n\n| # | Pattern | Symptom | Fix |\n|:-:|---------|---------|-----|\n| 1 | **Tests Lie** | AI says \"pass\" but broken | Run tests yourself |\n| 2 | **Amnesia** | Forgets constraints | Fresh session (>40%) |\n| 3 | **Drift** | \"Improving\" undirected | Smaller tasks |\n| 4 | **Debug Spiral** | 3rd log, no fix | Real debugger |\n\n### Middle Loop (Hours-Days)\n\n| # | Pattern | Symptom | Fix |\n|:-:|---------|---------|-----|\n| 5 | **Eldritch Horror** | 3000-line function | Test. Modularize |\n| 6 | **Collision** | Same files | Clear territories |\n| 7 | **Memory Decay** | Re-solving | Bundle maintenance |\n| 8 | **Deadlock** | Agents waiting | Break cycle |\n\n### Outer Loop (Weeks-Months)\n\n| # | Pattern | Symptom | Fix |\n|:-:|---------|---------|-----|\n| 9 | **Bridge Torch** | API broke downstream | Roll back |\n| 10 | **Deletion** | \"Unused\" removed | Approval required |\n| 11 | **Gridlock** | PRs backed up | Fast lane |\n| 12 | **Stewnami** | Half-done pile | Limit WIP |\n\n---\n\n## Code Review Calibration\n\n| Task | Max Level | Notes |\n|------|:---------:|-------|\n| Generate review comments | L4 | Suggestions only |\n| Apply review suggestions | L3 | Verify applies |\n| Security review findings | L2 | Higher risk |\n| Automated linting | L5 | Fully automated |\n\n---\n\n## Grade Mapping\n\n| Vibe Grade | Trust Pass | Verdict |\n|:----------:|:----------:|---------|\n| **A** | >95% | ELITE - ship it |\n| **B** | ≥80% | HIGH - minor fixes |\n| **C** | ≥60% | MEDIUM - needs work |\n| **D** | \u003c60% | LOW - significant issues |\n| **F** | \u003c40% | BLOCK - systemic problems |\n\n---\n\n## 40% Context Rule\n\n| Utilization | Effect | Action |\n|:-----------:|--------|--------|\n| 0-40% | Optimal | Continue |\n| 40-60% | Degradation | Checkpoint |\n| 60-80% | Instruction loss | Save state |\n| 80-100% | Confabulation | STOP |\n\n---\n\n**Source:** gitops/docs/methodology/vibe-ecosystem/vibe-coding/\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3873,"content_sha256":"31045aacc85d81e9ee29dd4242bb6f4a2261522c683097b44dd18fc86f143935"},{"filename":"references/vibe-suppressions.md","content":"# Vibe Suppressions\n\n> Default suppression list for `/vibe` findings. Load before council invocation to filter noise.\n\n## Purpose\n\nSuppressions prevent known false-positive patterns from cluttering vibe reports. A suppressed finding is **omitted from CRITICAL** and downgraded to INFORMATIONAL (or dropped entirely if marked `drop`).\n\n## Default Suppressions\n\n### Category: Redundant Findings\n\n| Pattern | Reason | Action |\n|---------|--------|--------|\n| \"X is redundant with Y\" | Two findings flag the same root cause | Keep the more specific one, suppress the other |\n| Duplicate across judges | Multiple judges report identical finding | Deduplicate — keep first occurrence with highest severity |\n| Finding already addressed in reviewed code | Code already contains the fix or guard | Suppress entirely |\n\n### Category: Tuning Noise\n\n| Pattern | Reason | Action |\n|---------|--------|--------|\n| Eval threshold changes tuned empirically | Threshold values chosen by measurement, not convention | Suppress — not a code quality issue |\n| \"Add a comment explaining why\" for tuned values | Thresholds change during tuning; comments go stale | Downgrade to INFORMATIONAL |\n| Magic number in config/constants file | Constants files exist to hold these values | Suppress if value is in a dedicated constants/config file |\n\n### Category: Style-Only\n\n| Pattern | Reason | Action |\n|---------|--------|--------|\n| Style suggestion when behavior is correct | Formatting, naming preference, import ordering | Downgrade to INFORMATIONAL |\n| \"Consider renaming\" with no correctness impact | Subjective naming preference | Downgrade to INFORMATIONAL |\n| Line length warnings in generated files | Generated code is not hand-maintained | Suppress entirely |\n\n### Category: Known Safe Patterns\n\n| Pattern | Reason | Action |\n|---------|--------|--------|\n| `//nolint` or `# noqa` with documented reason | Intentional suppression with justification | Suppress — already reviewed |\n| Test files using hardcoded values | Test fixtures are expected to have literals | Suppress in `*_test.go`, `test_*.py`, `*.test.ts` |\n| Error handling in CLI `main()` with `os.Exit` | CLI entry points legitimately exit on error | Suppress if in `main.go` or equivalent entry point |\n\n## Custom Suppressions\n\nProjects can extend this list by creating `.agents/vibe-suppressions.jsonl` with one entry per line:\n\n```jsonl\n{\"pattern\": \"regex or substring\", \"reason\": \"why this is suppressed\", \"action\": \"suppress|downgrade\"}\n```\n\n- `suppress` — omit from report entirely\n- `downgrade` — move from CRITICAL to INFORMATIONAL\n\n## How Suppressions Are Applied\n\n1. Load default suppressions (this file) before council invocation\n2. Load project suppressions from `.agents/vibe-suppressions.jsonl` if present\n3. After council verdict, match each finding against suppression patterns\n4. Apply action (suppress or downgrade) and note in report: \"N findings suppressed (see vibe-suppressions.md)\"\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2963,"content_sha256":"9ae1cf7a394742f45ed7ed577a89d9049a0419095774edd03d91cd7c431e7496"},{"filename":"references/write-time-quality.md","content":"# Write-Time Quality Enforcement\n\n> Catch code quality issues at edit time, not review time. Hook-based, zero-config.\n\n## Problem\n\nCurrent quality enforcement happens at `/vibe` time (review). This means:\n- Workers produce 100 lines of code before learning the style is wrong\n- Agents disable linter rules instead of fixing violations\n- Formatting inconsistencies accumulate across a wave\n- Debug logging makes it to commit\n\n## Solution: PostToolUse Quality Hooks\n\nRun lightweight quality checks after every file edit, format automatically when possible, and block config tampering.\n\n### Architecture\n\n```\nAgent edits file.go\n │\n ├── PostToolUse hook fires\n │ ├── Auto-format (gofmt, black, prettier)\n │ ├── Fast lint check (go vet, ruff check --select=E)\n │ └── Config protection (block linter config edits)\n │\n ├── If violations found:\n │ ├── WARN: \"3 lint issues in file.go: \u003csummary>\"\n │ └── Agent fixes before continuing\n │\n └── If config tampered:\n ├── BLOCK (exit 2): \"Blocked: editing linter config\"\n └── Agent must fix code, not config\n```\n\n### What to Auto-Fix (No Blocking)\n- **Formatting**: gofmt, black, prettier — run silently, rewrite file\n- **Import sorting**: goimports, isort — run silently\n- **Trailing whitespace**: strip on save\n\n### What to Warn (Non-Blocking)\n- **Lint violations**: Show inline, let agent fix\n- **Debug logging**: Flag `fmt.Println`, `console.log`, `print(` in non-test files\n- **TODO comments**: Flag, suggest `bd create` instead\n\n### What to Block (Exit 2)\n- **Linter config edits**: `.golangci.yml`, `.eslintrc`, `ruff.toml`, `pyproject.toml` lint sections\n- **Test disabling**: Commenting out test functions, adding `t.Skip()` without justification\n- **CI config weakening**: Removing checks from CI pipeline files\n\n### Config Protection Rules\n\nAgents sometimes \"fix\" lint violations by weakening the linter:\n\n```yaml\n# BLOCKED: Agent tried to add this to .golangci.yml\nlinters:\n disable:\n - errcheck # \u003c- This disables a critical check\n```\n\n**Rule:** If an agent edits a linter/formatter config file, the hook blocks with:\n```\n\"Blocked: Editing linter configuration. Fix the code instead of disabling the rule.\nIf the rule is genuinely wrong, explain why and the user can approve.\"\n```\n\n### Model-Tiered Delegation\n\nWhen a lint violation is too complex for the current worker:\n\n| Violation Type | Tier | Action |\n|---------------|------|--------|\n| Formatting | Auto-fix | Just run formatter |\n| Import organization | Auto-fix | Just run import sorter |\n| Simple lint (unused var) | Haiku | Quick inline fix |\n| Logic lint (error handling) | Sonnet | Contextual fix |\n| Type system issue | Opus | Deep reasoning fix |\n\n### Implementation Notes\n\nThis pattern is documented as a reference for future hook implementation. Current AgentOps hooks (`hooks/hooks.json`) can implement this via:\n\n1. **PreToolUse:Edit** — Check if target file is a config file → block if linter config\n2. **PostToolUse:Edit** — Run formatter on edited file → warn on lint violations\n3. **PostToolUse:Write** — Same as Edit, plus check for debug logging patterns\n\n### Integration with /vibe\n\nWrite-time quality reduces `/vibe` review burden:\n- Formatting violations: eliminated (auto-fixed at write time)\n- Simple lint: mostly eliminated (fixed or blocked at write time)\n- Complex logic: still caught by `/vibe` council (appropriate level)\n\nTarget: reduce vibe findings by 40-60% through write-time enforcement.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3557,"content_sha256":"fcbfd93939819330c0c7a1f7330b69f298c3ba0a68d0b48faa72072cb52c271c"},{"filename":"references/yaml-standards.md","content":"# YAML/Helm Standards Catalog - Vibe Canonical Reference\n\n**Version:** 1.0.0\n**Last Updated:** 2026-01-21\n**Purpose:** Canonical YAML/Helm standards for vibe skill validation\n\n---\n\n## Table of Contents\n\n1. [yamllint Configuration](#yamllint-configuration)\n2. [Formatting Rules](#formatting-rules)\n3. [Helm Chart Conventions](#helm-chart-conventions)\n4. [Kustomize Patterns](#kustomize-patterns)\n5. [Template Best Practices](#template-best-practices)\n6. [Validation Workflow](#validation-workflow)\n7. [Compliance Assessment](#compliance-assessment)\n8. [Anti-Patterns Avoided](#anti-patterns-avoided)\n9. [Code Quality Metrics](#code-quality-metrics)\n10. [Prescan Patterns](#prescan-patterns)\n\n---\n\n## yamllint Configuration\n\n### Full Configuration\n\n```yaml\n# .yamllint.yml\nextends: default\nrules:\n line-length:\n max: 120\n allow-non-breakable-inline-mappings: true\n indentation:\n spaces: 2\n indent-sequences: consistent\n truthy:\n check-keys: false\n comments:\n min-spaces-from-content: 1\n document-start: disable\n empty-lines:\n max: 2\n brackets:\n min-spaces-inside: 0\n max-spaces-inside: 0\n colons:\n max-spaces-before: 0\n max-spaces-after: 1\n commas:\n max-spaces-before: 0\n min-spaces-after: 1\n hyphens:\n max-spaces-after: 1\n```\n\n### Usage\n\n```bash\n# Lint all YAML files\nyamllint .\n\n# Lint specific directory\nyamllint apps/\n\n# Lint with format output\nyamllint -f parsable .\n```\n\n---\n\n## Formatting Rules\n\n### Quoting Strings\n\n```yaml\n# Quote strings that look like other types\nenabled: \"true\" # String, not boolean\nport: \"8080\" # String, not integer\nversion: \"1.0\" # String, not float\n\n# No quotes for actual typed values\nenabled: true # Boolean\nport: 8080 # Integer\nreplicas: 3 # Integer\n```\n\n### Multi-line Strings\n\n```yaml\n# Literal block scalar (preserves newlines)\nscript: |\n #!/bin/bash\n set -euo pipefail\n echo \"Hello\"\n\n# Folded block scalar (folds newlines to spaces)\ndescription: >\n This is a long description that will be\n folded into a single line with spaces.\n\n# BAD - Escaped newlines (hard to read)\nscript: \"#!/bin/bash\\nset -euo pipefail\\necho \\\"Hello\\\"\"\n```\n\n### Comments\n\n```yaml\n# Section header (full line)\n# =============================================================================\n# Database Configuration\n# =============================================================================\n\ndatabase:\n host: localhost # Inline comment (1 space before #)\n port: 5432\n # Subsection comment\n credentials:\n username: admin\n```\n\n---\n\n## Helm Chart Conventions\n\n### Chart Structure\n\n```text\ncharts/\u003cchart-name>/\n├── Chart.yaml\n├── values.yaml\n├── values.schema.json # Optional: JSON Schema for values\n├── templates/\n│ ├── _helpers.tpl\n│ ├── deployment.yaml\n│ ├── service.yaml\n│ └── ...\n└── charts/ # Nested charts (if needed)\n```\n\n### Chart.yaml\n\n```yaml\napiVersion: v2\nname: my-app\ndescription: A Helm chart for my application\ntype: application\nversion: 1.0.0\nappVersion: \"2.0.0\"\n\ndependencies:\n - name: postgresql\n version: \"12.x.x\"\n repository: https://charts.bitnami.com/bitnami\n condition: postgresql.enabled\n```\n\n### values.yaml Conventions\n\n```yaml\n# =============================================================================\n# Application Configuration\n# =============================================================================\n\napp:\n name: my-app\n replicas: 3\n\n# Resource limits (adjust for environment)\nresources:\n requests:\n cpu: 100m\n memory: 128Mi\n limits:\n cpu: 500m\n memory: 512Mi\n\n# =============================================================================\n# Image Configuration\n# =============================================================================\n\nimage:\n repository: myregistry/my-app\n tag: \"\" # Defaults to appVersion\n pullPolicy: IfNotPresent\n```\n\n### Validation Commands\n\n```bash\n# Lint chart\nhelm lint charts/\u003cchart-name>/\n\n# Template with values (dry-run)\nhelm template \u003crelease> charts/\u003cchart-name>/ -f values.yaml\n\n# Validate rendered output\nhelm template \u003crelease> charts/\u003cchart-name>/ | kubectl apply --dry-run=client -f -\n\n# Debug template rendering\nhelm template \u003crelease> charts/\u003cchart-name>/ --debug\n```\n\n---\n\n## Kustomize Patterns\n\n### Overlay Structure\n\n```text\napps/\u003capp>/\n├── base/\n│ ├── kustomization.yaml\n│ ├── deployment.yaml\n│ └── service.yaml\n└── overlays/\n ├── dev/\n │ └── kustomization.yaml\n ├── staging/\n │ └── kustomization.yaml\n └── prod/\n └── kustomization.yaml\n```\n\n### kustomization.yaml Template\n\n```yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n - deployment.yaml\n - service.yaml\n\n# Environment-specific patches\npatches:\n - path: ./patches/replicas.yaml\n target:\n kind: Deployment\n name: my-app\n```\n\n### Patch Types\n\n**Strategic Merge Patch:**\n```yaml\n# patches/extend-rbac.yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: my-role\nrules:\n - apiGroups: [\"custom.io\"]\n resources: [\"widgets\"]\n verbs: [\"get\", \"list\"]\n```\n\n**JSON Patch:**\n```yaml\n# patches/add-annotation.yaml\n- op: add\n path: /metadata/annotations/custom.io~1managed\n value: \"true\"\n```\n\n**Delete Patch:**\n```yaml\n# patches/delete-resource.yaml\n$patch: delete\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: unused-config\n```\n\n---\n\n## Template Best Practices\n\n### Use include for Reusable Snippets\n\n```yaml\n# templates/_helpers.tpl\n{{- define \"app.labels\" -}}\napp.kubernetes.io/name: {{ .Chart.Name }}\napp.kubernetes.io/instance: {{ .Release.Name }}\napp.kubernetes.io/version: {{ .Chart.AppVersion | quote }}\n{{- end }}\n\n# templates/deployment.yaml\nmetadata:\n labels:\n {{- include \"app.labels\" . | nindent 4 }}\n```\n\n### Whitespace Control\n\n```yaml\n# GOOD - Use {{- and -}} to control whitespace\n{{- if .Values.enabled }}\napiVersion: v1\nkind: ConfigMap\n{{- end }}\n\n# BAD - Extra blank lines in output\n{{ if .Values.enabled }}\n\napiVersion: v1\n\n{{ end }}\n```\n\n### Required Values\n\n```yaml\n# Fail fast if required value missing\nimage: {{ required \"image.repository is required\" .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}\n```\n\n### Default Values\n\n```yaml\n# Safe defaults\nreplicas: {{ .Values.replicas | default 1 }}\n\n# Nested defaults\nresources:\n {{- with .Values.resources }}\n {{- toYaml . | nindent 2 }}\n {{- else }}\n requests:\n cpu: 100m\n memory: 128Mi\n {{- end }}\n```\n\n---\n\n## Validation Workflow\n\n### Pre-commit Checks\n\n```bash\n# 1. Lint YAML\nyamllint .\n\n# 2. Lint Helm charts\nfor chart in charts/*/Chart.yaml; do\n helm lint \"$(dirname \"$chart\")\"\ndone\n\n# 3. Build Kustomize overlays\nkustomize build apps/\u003capp>/ --enable-helm > /dev/null\n```\n\n### CI Pipeline Example\n\n```yaml\n# .github/workflows/validate.yaml\n- name: Lint YAML\n run: yamllint .\n\n- name: Lint Helm\n run: |\n for chart in charts/*/Chart.yaml; do\n helm lint \"$(dirname \"$chart\")\"\n done\n\n- name: Validate Kustomize\n run: |\n for kust in apps/*/kustomization.yaml; do\n kustomize build \"$(dirname \"$kust\")\" --enable-helm > /dev/null\n done\n```\n\n---\n\n## Compliance Assessment\n\n**Use letter grades + evidence, NOT numeric scores.**\n\n### Assessment Categories\n\n| Category | Evidence Required |\n|----------|------------------|\n| **Formatting** | yamllint violations, tab count, indentation |\n| **Helm Charts** | helm lint output, template rendering |\n| **Kustomize** | kustomize build success, patch correctness |\n| **Documentation** | values.yaml comments, section headers |\n| **Security** | Hardcoded secrets, external secret refs |\n\n### Grading Scale\n\n| Grade | Criteria |\n|-------|----------|\n| A+ | 0 yamllint errors, 0 helm lint errors, documented, 0 secrets |\n| A | \u003c3 yamllint warnings, \u003c3 helm lint warnings, documented |\n| A- | \u003c10 warnings, partial docs |\n| B+ | \u003c20 warnings |\n| B | \u003c40 warnings, templates render |\n| C | Significant issues |\n\n### Validation Commands\n\n```bash\n# Lint YAML\nyamllint .\n# Output: \"X error(s), Y warning(s)\"\n\n# Check for tabs\ngrep -rP '\\t' --include='*.yaml' --include='*.yml' . | wc -l\n# Should be 0\n\n# Helm lint\nfor chart in charts/*/Chart.yaml; do\n helm lint \"$(dirname \"$chart\")\"\ndone\n\n# Check for hardcoded secrets\ngrep -r \"password:\\|secret:\\|token:\" --include='*.yaml' apps/\n# Should only return external references\n```\n\n### Example Assessment\n\n```markdown\n## YAML/Helm Standards Compliance\n\n| Category | Grade | Evidence |\n|----------|-------|----------|\n| Formatting | A+ | 0 yamllint errors, 0 tabs |\n| Helm Charts | A- | 3 lint warnings (docs) |\n| Kustomize | A | All overlays build |\n| Security | A | 0 hardcoded secrets |\n| **OVERALL** | **A** | **3 MEDIUM findings** |\n```\n\n---\n\n## Anti-Patterns Avoided\n\n### ❌ **Implicit Typing Traps (Norway Problem)**\n\nUnquoted values silently coerced to unexpected types:\n\n```yaml\n# BAD - These become booleans (false, true)\ncountry: NO # false\nfeature: YES # true\nenabled: on # true\ndisabled: off # false\n\n# GOOD - Quote ambiguous strings\ncountry: \"NO\"\nfeature: \"YES\"\nenabled: \"on\"\ndisabled: \"off\"\n```\n\n### ❌ **Anchor/Alias Abuse**\n\nOveruse of `&` anchors and `*` aliases creates unreadable configs:\n\n```yaml\n# BAD - Excessive aliasing obscures intent\ndefaults: &defaults\n timeout: 30\n retries: 3\n\nservice_a:\n \u003c\u003c: *defaults\n name: a\n\nservice_b:\n \u003c\u003c: *defaults\n name: b\n\n# GOOD - Explicit values for clarity (or use Kustomize overlays)\nservice_a:\n timeout: 30\n retries: 3\n name: a\n```\n\n**Rule:** Anchors acceptable for DRY in 2-3 references. Beyond that, use templating (Helm, Kustomize).\n\n### ❌ **Deeply Nested Configs**\n\nNesting beyond 6 levels signals structural problems:\n\n```yaml\n# BAD - 7+ levels deep\napp:\n server:\n routes:\n api:\n v1:\n users:\n endpoints:\n list:\n timeout: 30\n\n# GOOD - Flatten with dotted keys or restructure\napp:\n server:\n routes:\n api-v1-users-list:\n timeout: 30\n```\n\n### ❌ **Missing Document Markers**\n\nMulti-document YAML files without `---` separators cause parse failures:\n\n```yaml\n# BAD - Two documents, no separator\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: config-a\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: config-b\n\n# GOOD - Explicit document markers\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: config-a\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: config-b\n```\n\n### ❌ **Mixed Indentation**\n\nTabs or inconsistent indent widths cause silent parse errors:\n\n```yaml\n# BAD - Tabs mixed with spaces (invisible breakage)\napp:\n\tname: broken # Tab character\n\n# BAD - Inconsistent indent width\napp:\n name: my-app # 2 spaces\n config:\n port: 8080 # 4 spaces\n\n# GOOD - Consistent 2-space indentation throughout\napp:\n name: my-app\n config:\n port: 8080\n```\n\n---\n\n## Code Quality Metrics\n\n### Validation Thresholds\n\n| Metric | Threshold | Status | Action |\n|--------|-----------|--------|--------|\n| yamllint errors | 0 | ✅ Required | Fix before merge |\n| yamllint warnings | \u003c5 | ✅ Acceptable | Fix in next PR |\n| yamllint warnings | 5-20 | ⚠️ Warning | Refactor recommended |\n| yamllint warnings | 20+ | ❌ Critical | Block merge |\n| Nesting depth | ≤6 levels | ✅ Acceptable | Flatten if deeper |\n| Line length | ≤256 chars | ✅ Maximum | Prefer ≤120 |\n| Helm lint errors | 0 | ✅ Required | Fix before merge |\n| Kustomize build | Pass | ✅ Required | All overlays must build |\n| Hardcoded secrets | 0 | ✅ Required | Use external refs |\n\n### Tool Commands\n\n```bash\n# Full validation pass\nyamllint -f parsable . | wc -l # Total findings\nyamllint -f parsable . | grep error # Errors only\nhelm lint charts/*/ # Helm validation\ngrep -rP '\\t' --include='*.yaml' . | wc -l # Tab detection\n```\n\n---\n\n## Prescan Patterns\n\n| ID | Pattern | Detection Command | Severity |\n|----|---------|-------------------|----------|\n| P01 | Implicit boolean detection | `yamllint -d '{extends: default, rules: {truthy: {check-keys: true}}}' .` | HIGH |\n| P02 | Duplicate keys | `yamllint -d '{extends: default, rules: {key-duplicates: enable}}' .` | HIGH |\n| P03 | Excessive nesting (>6 levels) | `awk '/^( ){14}[^ ]/' *.yaml` | MEDIUM |\n| P04 | Long lines (>256 chars) | `yamllint -d '{extends: default, rules: {line-length: {max: 256}}}' .` | MEDIUM |\n| P05 | Missing document marker | `grep -rL '^---' --include='*.yaml' .` | LOW |\n\n### Pattern Details\n\n**P01: Implicit Boolean Detection**\nCatches the Norway problem — unquoted values like `NO`, `YES`, `on`, `off` silently become booleans. The `truthy` rule with `check-keys: true` flags these in both keys and values.\n\n**P02: Duplicate Keys**\nDuplicate keys in the same mapping silently overwrite earlier values. YAML spec allows it but most parsers keep only the last value, causing hard-to-debug configuration drift.\n\n**P03: Excessive Nesting**\nDetects indentation at 14+ spaces (7+ levels at 2-space indent). Deep nesting indicates config structure should be flattened or split into overlays.\n\n**P04: Long Lines**\nLines beyond 256 characters indicate inline lists or values that should use block scalars. Default yamllint threshold is 120; 256 is the hard maximum.\n\n**P05: Missing Document Marker**\nMulti-resource YAML files (common in Kubernetes) require `---` separators. Missing markers cause concatenation errors during apply.\n\n---\n\n## Additional Resources\n\n- [YAML Spec](https://yaml.org/spec/)\n- [Helm Documentation](https://helm.sh/docs/)\n- [Kustomize Documentation](https://kustomize.io/)\n- [yamllint Documentation](https://yamllint.readthedocs.io/)\n\n---\n\n**Related:** Quick reference in Tier 1 `yaml.md`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13806,"content_sha256":"a6fd84907fa87cfb944e195092bf1b1c6f02a0644411c17265dee12869fe4c6f"},{"filename":"scripts/prescan.sh","content":"#!/usr/bin/env bash\n# Vibe Pre-Scan: Fast static detection for 7 failure patterns\n# Usage: prescan.sh \u003ctarget>\n# target: recent | all | \u003cdirectory> | \u003cfile>\n\nset -euo pipefail\n\nTARGET=\"${1:-recent}\"\n\n# Validate TARGET to prevent argument injection\nif [[ \"$TARGET\" =~ ^- ]]; then\n echo \"Error: TARGET cannot start with a dash (prevents argument injection)\" >&2\n exit 1\nfi\nif [[ \"$TARGET\" != \"recent\" && \"$TARGET\" != \"all\" && ! -e \"$TARGET\" ]]; then\n echo \"Error: TARGET '$TARGET' does not exist\" >&2\n exit 1\nfi\n\n# File filtering (exclude generated code, build artifacts, test fixtures)\nfilter_files() {\n grep -v '__pycache__\\|\\.venv\\|venv/\\|node_modules\\|\\.git/\\|test_fixtures\\|/fixtures/\\|\\.eggs\\|egg-info\\|/dist/\\|/build/\\|\\.tox\\|\\.mypy_cache\\|\\.pytest_cache' \\\n | grep -v '\\.gen\\.go$\\|zz_generated\\|_generated\\.go$\\|\\.pb\\.go$\\|mock_.*\\.go$\\|/generated/\\|/gen/\\|deepcopy'\n}\n\n# Resolve target to file lists (Python, Go, Bash)\ncase \"$TARGET\" in\n recent)\n PY_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '\\.py

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

| filter_files || true)\n GO_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '\\.go

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

| filter_files || true)\n SH_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '\\.sh

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

| filter_files || true)\n MODE=\"Recent\"\n ;;\n all)\n PY_FILES=$(find . -name \"*.py\" -type f 2>/dev/null | filter_files | grep -v 'test_' || true)\n GO_FILES=$(find . -name \"*.go\" -type f 2>/dev/null | filter_files | grep -v '_test\\.go

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

|| true)\n SH_FILES=$(find . -name \"*.sh\" -type f 2>/dev/null | filter_files || true)\n MODE=\"All\"\n ;;\n *)\n if [ -d \"$TARGET\" ]; then\n PY_FILES=$(find \"$TARGET\" -name \"*.py\" -type f 2>/dev/null | filter_files || true)\n GO_FILES=$(find \"$TARGET\" -name \"*.go\" -type f 2>/dev/null | filter_files || true)\n SH_FILES=$(find \"$TARGET\" -name \"*.sh\" -type f 2>/dev/null | filter_files || true)\n MODE=\"Dir\"\n elif [ -f \"$TARGET\" ]; then\n case \"$TARGET\" in\n *.py) PY_FILES=\"$TARGET\"; GO_FILES=\"\"; SH_FILES=\"\" ;;\n *.go) GO_FILES=\"$TARGET\"; PY_FILES=\"\"; SH_FILES=\"\" ;;\n *.sh) SH_FILES=\"$TARGET\"; PY_FILES=\"\"; GO_FILES=\"\" ;;\n *) PY_FILES=\"$TARGET\"; GO_FILES=\"\"; SH_FILES=\"\" ;;\n esac\n MODE=\"File\"\n else\n echo \"ERROR: Target not found: $TARGET\" >&2\n exit 1\n fi\n ;;\nesac\n\n# Combine for backwards compatibility\nFILES=\"$PY_FILES\"\n[ -n \"$GO_FILES\" ] && FILES=$(printf \"%s\\n%s\" \"$FILES\" \"$GO_FILES\")\n[ -n \"$SH_FILES\" ] && FILES=$(printf \"%s\\n%s\" \"$FILES\" \"$SH_FILES\")\n\n# Count files (handle empty strings properly)\ncount_lines() {\n local input=\"$1\"\n [ -z \"$input\" ] && echo 0 && return\n echo \"$input\" | wc -l | tr -d ' '\n}\nPY_COUNT=$(count_lines \"$PY_FILES\")\nGO_COUNT=$(count_lines \"$GO_FILES\")\nSH_COUNT=$(count_lines \"$SH_FILES\")\nFILE_COUNT=$((PY_COUNT + GO_COUNT + SH_COUNT))\nif [ \"$FILE_COUNT\" -eq 0 ]; then\n echo \"No files found for target: $TARGET\"\n exit 0\nfi\n\necho \"Pre-Scan Target: $TARGET\"\necho \"Mode: $MODE | Files: $FILE_COUNT (py:$PY_COUNT go:$GO_COUNT sh:$SH_COUNT)\"\necho \"\"\n\n# Initialize counters\nP1_COUNT=0\nP2_COUNT=0\nP4_COUNT=0\nP5_COUNT=0\nP8_COUNT=0\nP9_COUNT=0\nP12_COUNT=0\n\n# P1: Phantom Modifications (CRITICAL)\n# Committed lines not in current file\necho \"[P1] Phantom Modifications\"\nif [ \"$TARGET\" = \"recent\" ]; then\n for file in $FILES; do\n [ -f \"$file\" ] || continue\n while IFS= read -r line; do\n clean=$(echo \"$line\" | sed 's/^+//' | xargs)\n if [ ${#clean} -gt 10 ] && ! grep -qF \"$clean\" \"$file\" 2>/dev/null; then\n echo \" - $file: Committed line missing: \\\"${clean:0:50}...\\\"\"\n P1_COUNT=$((P1_COUNT + 1))\n fi\n done \u003c \u003c(git show HEAD -- \"$file\" 2>/dev/null | grep '^+[^+]' || true)\n done\nfi\necho \" $P1_COUNT findings\"\n\n# P2: Hardcoded Secrets (CRITICAL)\n# Uses path-based filtering to exclude test directories\necho \"\"\necho \"[P2] Hardcoded Secrets\"\nfor file in $FILES; do\n [ -f \"$file\" ] || continue\n # Skip test directories\n case \"$file\" in\n */test/*|*/tests/*|*_test.*|*/example/*|*/examples/*|*.example.*) continue ;;\n esac\n while IFS= read -r match; do\n line_num=$(echo \"$match\" | cut -d: -f1)\n echo \" - $file:$line_num: Possible hardcoded secret\"\n P2_COUNT=$((P2_COUNT + 1))\n done \u003c \u003c(grep -n -E \"(password|secret|api_key|apikey|token)\\s*=\\s*['\\\"][^'\\\"]+['\\\"]\" \"$file\" 2>/dev/null | head -5 || true)\ndone\necho \" $P2_COUNT findings\"\n\n# P4: Invisible Undone (HIGH)\n# Detects: unfinished work markers, commented-out code\necho \"\"\necho \"[P4] Invisible Undone\"\nfor file in $FILES; do\n [ -f \"$file\" ] || continue\n # TODO/FIXME markers\n while IFS= read -r match; do\n line_num=$(echo \"$match\" | cut -d: -f1)\n echo \" - $file:$line_num: TODO marker\"\n P4_COUNT=$((P4_COUNT + 1))\n done \u003c \u003c(grep -n \"TODO\\|FIXME\\|XXX\\|HACK\" \"$file\" 2>/dev/null | head -3 || true)\n # Commented code\n while IFS= read -r match; do\n line_num=$(echo \"$match\" | cut -d: -f1)\n echo \" - $file:$line_num: Commented code\"\n P4_COUNT=$((P4_COUNT + 1))\n done \u003c \u003c(grep -n \"^\\s*#\\s*\\(def \\|class \\|if \\|for \\)\" \"$file\" 2>/dev/null | head -2 || true)\ndone\necho \" $P4_COUNT findings\"\n\n# P5: Eldritch Horror (HIGH)\n# Complexity CC > 15 or function > 50 lines\necho \"\"\necho \"[P5] Eldritch Horror\"\n\n# Python: radon for cyclomatic complexity\nif [ -n \"$PY_FILES\" ]; then\n if command -v radon &>/dev/null; then\n for file in $PY_FILES; do\n [ -f \"$file\" ] || continue\n while IFS= read -r line; do\n cc=$(echo \"$line\" | grep -oE '\\([0-9]+\\)' | tr -d '()')\n if [ -n \"$cc\" ] && [ \"$cc\" -gt 15 ]; then\n func=$(echo \"$line\" | awk '{print $3}')\n echo \" - $file: $func CC=$cc (py)\"\n P5_COUNT=$((P5_COUNT + 1))\n fi\n done \u003c \u003c(radon cc \"$file\" -s -n E 2>/dev/null | grep -E \"^\\s*[EF]\\s+[0-9]+\" || true)\n done\n else\n echo \" WARNING: radon not installed (Python CC skipped)\"\n fi\nfi\n\n# Go: gocyclo for cyclomatic complexity\nif [ -n \"$GO_FILES\" ]; then\n if command -v gocyclo &>/dev/null; then\n for file in $GO_FILES; do\n [ -f \"$file\" ] || continue\n while IFS= read -r line; do\n # gocyclo output: \"15 pkg funcName file.go:42:1\"\n cc=$(echo \"$line\" | awk '{print $1}')\n func=$(echo \"$line\" | awk '{print $3}')\n loc=$(echo \"$line\" | awk '{print $4}')\n if [ -n \"$cc\" ] && [ \"$cc\" -gt 15 ]; then\n echo \" - $loc: $func CC=$cc (go)\"\n P5_COUNT=$((P5_COUNT + 1))\n fi\n done \u003c \u003c(gocyclo -over 15 \"$file\" 2>/dev/null || true)\n done\n else\n echo \" WARNING: gocyclo not installed (Go CC skipped)\"\n fi\nfi\n\n# Python: Function length > 50 lines\nfor file in $PY_FILES; do\n [ -f \"$file\" ] || continue\n python3 -c '\nimport ast, sys\nfname = sys.argv[1]\ntry:\n with open(fname) as f: tree = ast.parse(f.read())\n for n in ast.walk(tree):\n if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)) and hasattr(n, \"end_lineno\"):\n lines = n.end_lineno - n.lineno + 1\n if lines > 50: print(f\" - {fname}:{n.lineno}: {n.name}() is {lines} lines (py)\")\nexcept: pass\n' \"$file\" 2>/dev/null || true\ndone\n\n# Go: Function length > 50 lines (simple heuristic)\n# Limitation: This awk-based parser only detects `func ` at line start and `}` alone on a line.\n# Multi-line signatures, nested braces, or unusual formatting may cause false positives/negatives.\n# For production Go codebases, consider using gocyclo or go/ast for accurate metrics.\nfor file in $GO_FILES; do\n [ -f \"$file\" ] || continue\n awk '\n /^func / { fname=$0; start=NR; in_func=1 }\n in_func && /^}$/ {\n lines = NR - start + 1\n if (lines > 50) {\n # Extract function name\n match(fname, /func[[:space:]]+(\\([^)]+\\)[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_]*)/, arr)\n print \" - '\"$file\"':\" start \": \" arr[2] \"() is \" lines \" lines (go)\"\n }\n in_func=0\n }\n ' \"$file\" 2>/dev/null || true\ndone\necho \" $P5_COUNT findings\"\n\n# P8: Cargo Cult Error Handling (HIGH)\n# Empty except, pass-only handlers, bare except\necho \"\"\necho \"[P8] Cargo Cult Error Handling\"\n\n# Python: except:pass, bare except\nfor file in $PY_FILES; do\n [ -f \"$file\" ] || continue\n python3 -c '\nimport ast, sys\nfname = sys.argv[1]\ntry:\n with open(fname) as f: tree = ast.parse(f.read())\n for n in ast.walk(tree):\n if isinstance(n, ast.Try):\n for h in n.handlers:\n if len(h.body) == 1 and isinstance(h.body[0], ast.Pass):\n print(f\" - {fname}:{h.lineno}: except: pass (swallowed) (py)\")\n if h.type is None:\n print(f\" - {fname}:{h.lineno}: bare except (catches SystemExit) (py)\")\nexcept: pass\n' \"$file\" 2>/dev/null || true\ndone\n\n# Bash: shellcheck for error handling issues\nif [ -n \"$SH_FILES\" ]; then\n if command -v shellcheck &>/dev/null; then\n for file in $SH_FILES; do\n [ -f \"$file\" ] || continue\n # SC2181: Check exit code directly, not via $?\n # SC2086: Double quote to prevent globbing/splitting\n # SC2046: Quote to prevent word splitting\n # SC2155: Declare and assign separately to avoid masking return values\n while IFS= read -r line; do\n echo \" - $line (sh)\"\n P8_COUNT=$((P8_COUNT + 1))\n done \u003c \u003c(shellcheck -f gcc -S warning \"$file\" 2>/dev/null | head -5 || true)\n done\n else\n echo \" WARNING: shellcheck not installed (Bash checks skipped)\"\n fi\nfi\necho \" $P8_COUNT findings\"\n\n# P9: Documentation Phantom (MEDIUM)\n# Docstrings claiming behavior not implemented (Python only)\necho \"\"\necho \"[P9] Documentation Phantom\"\nfor file in $PY_FILES; do\n [ -f \"$file\" ] || continue\n python3 -c '\nimport ast, re, sys\nfname = sys.argv[1]\ntry:\n with open(fname) as f: src = f.read()\n tree = ast.parse(src)\n PATTERNS = [\n (r\"\\bvalidates?\\b\", [\"raise\", \"ValueError\", \"return False\"]),\n (r\"\\bensures?\\b\", [\"assert\", \"raise\"]),\n (r\"\\bencrypts?\\b\", [\"crypto\", \"cipher\"]),\n (r\"\\bauthenticat\", [\"token\", \"password\"]),\n (r\"\\bsanitiz\", [\"escape\", \"strip\"])\n ]\n for n in ast.walk(tree):\n if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)):\n if n.body and isinstance(n.body[0], ast.Expr) and isinstance(getattr(n.body[0], \"value\", None), ast.Constant):\n doc = str(n.body[0].value.value).lower()\n fsrc = (ast.get_source_segment(src, n) or \"\").lower()\n for pat, impl in PATTERNS:\n if re.search(pat, doc) and not any(i in fsrc for i in impl):\n print(f\" - {fname}:{n.lineno}: {n.name}() docstring mismatch\")\n break\nexcept: pass\n' \"$file\" 2>/dev/null || true\ndone\necho \" $P9_COUNT findings\"\n\n# P12: Zombie Code (MEDIUM)\n# Unused functions, unreachable code after return (Python only)\necho \"\"\necho \"[P12] Zombie Code\"\nfor file in $PY_FILES; do\n [ -f \"$file\" ] || continue\n python3 -c '\nimport ast, sys\nfname = sys.argv[1]\ntry:\n with open(fname) as f: src = f.read()\n tree = ast.parse(src)\n defined, called = set(), set()\n for n in ast.walk(tree):\n if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)) and not n.name.startswith(\"_\"):\n defined.add(n.name)\n if isinstance(n, ast.Call):\n if isinstance(n.func, ast.Name): called.add(n.func.id)\n elif isinstance(n.func, ast.Attribute): called.add(n.func.attr)\n for fn in (defined - called):\n if fn not in (\"main\", \"setup\", \"teardown\") and not fn.startswith(\"test_\"):\n print(f\" - {fname}: {fn}() may be unused\")\n # Unreachable code\n for n in ast.walk(tree):\n if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)):\n for i, s in enumerate(n.body[:-1]):\n if isinstance(s, (ast.Return, ast.Raise)) and n.body[i+1:]:\n nxt = n.body[i+1]\n if not (isinstance(nxt, ast.Expr) and isinstance(getattr(nxt, \"value\", None), ast.Constant)):\n print(f\" - {fname}:{nxt.lineno}: Unreachable after return/raise\")\nexcept: pass\n' \"$file\" 2>/dev/null || true\ndone\necho \" $P12_COUNT findings\"\n\n# Summary\necho \"\"\necho \"==============================================\"\necho \"Pre-Scan Results:\"\nCRITICAL=$((P1_COUNT + P2_COUNT))\nHIGH=$((P4_COUNT + P5_COUNT + P8_COUNT))\nMEDIUM=$((P9_COUNT + P12_COUNT))\nTOTAL=$((CRITICAL + HIGH + MEDIUM))\n\necho \"[P1] Phantom Modifications: $P1_COUNT findings\"\necho \"[P2] Hardcoded Secrets: $P2_COUNT findings\"\necho \"[P4] Invisible Undone: $P4_COUNT findings\"\necho \"[P5] Eldritch Horror: $P5_COUNT findings\"\necho \"[P8] Cargo Cult Error Handling: $P8_COUNT findings\"\necho \"[P9] Documentation Phantom: $P9_COUNT findings\"\necho \"[P12] Zombie Code: $P12_COUNT findings\"\necho \"----------------------------------------------\"\necho \"Summary: $TOTAL findings ($CRITICAL CRITICAL, $HIGH HIGH, $MEDIUM MEDIUM)\"\necho \"\"\n\n[ \"$CRITICAL\" -gt 0 ] && echo \"CRITICAL: Fix P1, P2 immediately\"\n[ \"$HIGH\" -gt 0 ] && echo \"HIGH: Review P4, P5, P8\"\n[ \"$MEDIUM\" -gt 0 ] && echo \"MEDIUM: Consider P9, P12\"\n[ \"$TOTAL\" -eq 0 ] && echo \"All clear - no violations\"\necho \"==============================================\"\n\n# Exit code based on findings\n[ \"$CRITICAL\" -gt 0 ] && exit 2\n[ \"$HIGH\" -gt 0 ] && exit 3\nexit 0\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":13202,"content_sha256":"d34f8fb93974b8ea8880d5cfc7757639d6292f7e55c99bbae168c9aeb8036439"},{"filename":"scripts/validate.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\nSKILL_DIR=\"$(cd \"$(dirname \"$0\")/..\" && pwd)\"\nPASS=0; FAIL=0\n\ncheck() { if bash -c \"$2\"; then echo \"PASS: $1\"; PASS=$((PASS + 1)); else echo \"FAIL: $1\"; FAIL=$((FAIL + 1)); fi; }\n\ncheck \"SKILL.md exists\" \"[ -f '$SKILL_DIR/SKILL.md' ]\"\ncheck \"SKILL.md has YAML frontmatter\" \"head -1 '$SKILL_DIR/SKILL.md' | grep -q '^---

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…

\"\ncheck \"SKILL.md has name: vibe\" \"grep -q '^name: vibe' '$SKILL_DIR/SKILL.md'\"\ncheck \"references/ has at least 5 files\" \"[ \\$(ls '$SKILL_DIR/references/' | wc -l) -ge 5 ]\"\ncheck \"scripts/prescan.sh exists\" \"[ -f '$SKILL_DIR/scripts/prescan.sh' ]\"\ncheck \"scripts/prescan.sh is executable\" \"[ -x '$SKILL_DIR/scripts/prescan.sh' ]\"\ncheck \"SKILL.md mentions complexity\" \"grep -qi 'complexity' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md mentions council\" \"grep -qi 'council' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md mentions compiled prevention inputs\" \"grep -q '\\.agents/pre-mortem-checks/\\|\\.agents/planning-rules/' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md mentions finding registry fallback\" \"grep -q 'registry.jsonl' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md mentions known_risks\" \"grep -q 'known_risks' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md mentions dedup_key\" \"grep -q 'dedup_key' '$SKILL_DIR/SKILL.md'\"\ncheck \"SKILL.md refreshes finding compiler after writes\" \"grep -q 'finding-compiler.sh' '$SKILL_DIR/SKILL.md'\"\ncheck \"deep-audit-protocol.md exists\" \"[ -f '$SKILL_DIR/references/deep-audit-protocol.md' ]\"\ncheck \"SKILL.md references --sweep flag\" \"grep -q '\\-\\-sweep' '$SKILL_DIR/SKILL.md'\"\n\necho \"\"; echo \"Results: $PASS passed, $FAIL failed\"\n[ $FAIL -eq 0 ] && exit 0 || exit 1\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1634,"content_sha256":"c8b83ec5f121792d136879dc2fc0b7c6af9d777f6b77fe0a0dd564631a3b10e7"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Vibe Skill","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Is this code ready to ship?","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Loop position","type":"text"}]},{"type":"paragraph","content":[{"text":"Per-slice quality gate within move ","type":"text"},{"text":"6 (close the bead by proving acceptance)","type":"text","marks":[{"type":"strong"}]},{"text":" of the ","type":"text"},{"text":"operating loop","type":"text","marks":[{"type":"link","attrs":{"href":"../../docs/architecture/operating-loop.md","title":null}}]},{"text":". Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers \"is this slice ready to be counted against the ","type":"text"},{"text":"slice-validation roll-up","type":"text","marks":[{"type":"link","attrs":{"href":"../../docs/templates/slice-validation.md","title":null}}]},{"text":"?\" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there).","type":"text"}]},{"type":"paragraph","content":[{"text":"Three steps:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complexity analysis","type":"text","marks":[{"type":"strong"}]},{"text":" — Find hotspots (radon, gocyclo)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bug hunt audit","type":"text","marks":[{"type":"strong"}]},{"text":" — Systematic sweep for concrete bugs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Council validation","type":"text","marks":[{"type":"strong"}]},{"text":" — Multi-model judgment","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Start","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe # validates recent changes\n/vibe recent # same as above\n/vibe src/auth/ # validates specific path\n/vibe --quick recent # fast inline check, no agent spawning\n/vibe --structured recent # 6-phase verification report (build→types→lint→tests→security→diff)\n/vibe --deep recent # 3 judges instead of 2\n/vibe --sweep recent # deep audit: per-file explorers + council\n/vibe --mixed recent # cross-vendor (Claude + Codex)\n/vibe --preset=security-audit src/auth/ # security-focused review\n/vibe --explorers=2 recent # judges with explorer sub-agents\n/vibe --debate recent # two-round adversarial review\n/vibe --tier=quality recent # use quality tier for council calls","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Execution Steps","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 0: Load Prior Review Context","type":"text"}]},{"type":"paragraph","content":[{"text":"Before reviewing, pull relevant learnings from prior code reviews and known patterns:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"if command -v ao &>/dev/null; then\n ao lookup --query \"\u003ctarget-scope> code review patterns\" --limit 3 2>/dev/null || true\nfi","type":"text"}]},{"type":"paragraph","content":[{"text":"Apply retrieved knowledge (mandatory when results returned):","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"If learnings or patterns are returned, do NOT just load them as passive context. For each returned item:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check: does this learning apply to the code under review? (answer yes/no)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If yes: include it as a ","type":"text"},{"text":"known_risk","type":"text","marks":[{"type":"code_inline"}]},{"text":" in your review — state the pattern, what to look for, and whether the code exhibits it","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cite the learning by filename in your review output when it influences a finding","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"After applying, record the citation:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"ao metrics cite \"\u003clearning-path>\" --type applied 2>/dev/null || true","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip silently if ao is unavailable or returns no results.","type":"text"}]},{"type":"paragraph","content":[{"text":"Project reviewer config:","type":"text","marks":[{"type":"strong"}]},{"text":" If ","type":"text"},{"text":".agents/reviewer-config.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists, its full config (","type":"text"},{"text":"reviewers","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"plan_reviewers","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"skip_reviewers","type":"text","marks":[{"type":"code_inline"}]},{"text":") is passed to council for judge selection. See ","type":"text"},{"text":"skills/council/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" Step 1b.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Crank Checkpoint Detection","type":"text"}]},{"type":"paragraph","content":[{"text":"Before scanning for changed files via git diff, check if a crank checkpoint exists:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"if [ -f .agents/vibe-context/latest-crank-wave.json ]; then\n echo \"Crank checkpoint found — using files_changed from checkpoint\"\n FILES_CHANGED=$(jq -r '.files_changed[]' .agents/vibe-context/latest-crank-wave.json 2>/dev/null)\n WAVE_COUNT=$(jq -r '.wave' .agents/vibe-context/latest-crank-wave.json 2>/dev/null)\n echo \"Wave $WAVE_COUNT checkpoint: $(echo \"$FILES_CHANGED\" | wc -l | tr -d ' ') files changed\"\nfi","type":"text"}]},{"type":"paragraph","content":[{"text":"When a crank checkpoint is available, use its ","type":"text"},{"text":"files_changed","type":"text","marks":[{"type":"code_inline"}]},{"text":" list instead of re-detecting via ","type":"text"},{"text":"git diff","type":"text","marks":[{"type":"code_inline"}]},{"text":". This ensures vibe validates exactly the files that crank modified.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Determine Target","type":"text"}]},{"type":"paragraph","content":[{"text":"If target provided:","type":"text","marks":[{"type":"strong"}]},{"text":" Use it directly.","type":"text"}]},{"type":"paragraph","content":[{"text":"If no target or \"recent\":","type":"text","marks":[{"type":"strong"}]},{"text":" Auto-detect from git:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check recent commits\ngit diff --name-only HEAD~3 2>/dev/null | head -20","type":"text"}]},{"type":"paragraph","content":[{"text":"If nothing found, ask user.","type":"text"}]},{"type":"paragraph","content":[{"text":"Pre-flight: If no files found:","type":"text","marks":[{"type":"strong"}]},{"text":" Return immediately with: \"PASS (no changes to review) — no modified files detected.\" Do NOT spawn agents for empty file lists.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5a: Structured Verification Path (--structured mode)","type":"text"}]},{"type":"paragraph","content":[{"text":"If ","type":"text","marks":[{"type":"strong"}]},{"text":"--structured","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" flag is set","type":"text","marks":[{"type":"strong"}]},{"text":", run a 6-phase mechanical verification pipeline instead of the council flow. This produces a machine-readable verification report suitable for PR gates and CI integration.","type":"text"}]},{"type":"paragraph","content":[{"text":"Phases: Build → Types → Lint → Tests → Security → Diff Review.","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/verification-report.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full report template and per-phase commands. Each phase is fail-fast — if Build fails, skip remaining phases and report NOT READY.","type":"text"}]},{"type":"paragraph","content":[{"text":"After all phases complete, write the structured report to ","type":"text"},{"text":".agents/council/YYYY-MM-DD-verification-\u003ctarget>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" and output the summary table to the user.","type":"text"}]},{"type":"paragraph","content":[{"text":"When to use:","type":"text","marks":[{"type":"strong"}]},{"text":" Pre-PR gate, CI integration, when you need a mechanical pass/fail rather than judgment-based review.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5: Fast Path (--quick mode)","type":"text"}]},{"type":"paragraph","content":[{"text":"If ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" flag is set","type":"text","marks":[{"type":"strong"}]},{"text":", skip Steps 2a through 2e as heavy pre-processing, plus 2.5 and 2f, and jump to Step 4 with inline council after Steps 2.3, 2.4, 2g, and Step 3. Domain checklists, compiled-prevention loading, test-pyramid inventory, and inline product context are cheap and high-value, so they still run in quick mode. Complexity analysis (Step 2) still runs — it's cheap and informative.","type":"text"}]},{"type":"paragraph","content":[{"text":"Why:","type":"text","marks":[{"type":"strong"}]},{"text":" Steps 2.5 and 2a–2f add 30–90 seconds of pre-processing that mainly feed multi-judge council packets. In --quick mode (single inline agent), those inputs are not worth the cost, but test-pyramid and product-context checks still shape the inline review meaningfully.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Run Complexity Analysis","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/complexity-analysis.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/complexity-analysis.md","title":null}}]},{"text":" when you need the language-detection preflight, per-language analyzer commands (radon/gocyclo), and the score interpretation table. Filter by language present in the diff before running any analyzer.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.3: Load Domain-Specific Checklists","type":"text"}]},{"type":"paragraph","content":[{"text":"Detect code patterns in the target files and load matching domain-specific checklists from ","type":"text"},{"text":"standards/references/","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trigger","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Checklist","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Detection","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"SQL/ORM code","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"sql-safety-checklist.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Files contain SQL queries, ORM imports (","type":"text"},{"text":"database/sql","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"sqlalchemy","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"prisma","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"activerecord","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"gorm","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"knex","type":"text","marks":[{"type":"code_inline"}]},{"text":"), or migration files in changeset","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LLM/AI code","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"llm-trust-boundary-checklist.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Files import ","type":"text"},{"text":"anthropic","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"openai","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"google.generativeai","type":"text","marks":[{"type":"code_inline"}]},{"text":", or match ","type":"text"},{"text":"*llm*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"*prompt*","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"*completion*","type":"text","marks":[{"type":"code_inline"}]},{"text":" patterns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Concurrent code","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"race-condition-checklist.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Files use goroutines, ","type":"text"},{"text":"threading","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"asyncio","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"multiprocessing","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"sync.Mutex","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"concurrent.futures","type":"text","marks":[{"type":"code_inline"}]},{"text":", or shared file I/O patterns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Codex skills","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"codex-skill.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Files under ","type":"text"},{"text":"skills-codex/","type":"text","marks":[{"type":"code_inline"}]},{"text":", or files matching ","type":"text"},{"text":"*codex*SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"convert.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"skills-codex-overrides/","type":"text","marks":[{"type":"code_inline"}]},{"text":", or converter scripts","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"For each matched checklist, load it via the Read tool and include relevant items in the council packet as ","type":"text"},{"text":"context.domain_checklists","type":"text","marks":[{"type":"code_inline"}]},{"text":". Multiple checklists can be loaded simultaneously.","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip silently if no patterns match. This step runs in both ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" and full modes (domain checklists are cheap to load and high-value).","type":"text"}]},{"type":"paragraph","content":[{"text":"Steps 2.4-2f, 2h, 3-3.6 (Deep Checks & Pre-Council Prep):","type":"text","marks":[{"type":"strong"}]},{"text":" Read ","type":"text"},{"text":"references/deep-checks.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for compiled prevention, prior findings, pre-council deep analysis checks, product context, spec loading, suppressions, pre-mortem correlation, and model cost tiers. Loaded automatically unless ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" mode is set. In ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" mode, skip directly to Step 2g.","type":"text"}]},{"type":"paragraph","content":[{"text":"Compiled prevention inputs:","type":"text","marks":[{"type":"strong"}]},{"text":" Load ","type":"text"},{"text":".agents/pre-mortem-checks/","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":".agents/planning-rules/","type":"text","marks":[{"type":"code_inline"}]},{"text":" when available. These compiled artifacts contain known_risks from prior findings that inform the review — carry matched finding IDs into council context so judges can assess whether the flywheel prevented rediscovery.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2a: Prior Findings Check","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Load prior findings from ","type":"text"},{"text":".agents/findings/registry.jsonl","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2b: Constraint Tests","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Run compiled constraint tests from ","type":"text"},{"text":".agents/constraints/","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2c: Metadata Checks","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Verify file metadata consistency.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.5: OL Validation","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Run organizational-lint checks.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2d: Knowledge Search","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Search for relevant prior learnings via ","type":"text"},{"text":"ao lookup","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2e: Bug Hunt or Deep Audit Sweep","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"Path A — Deep Audit Sweep (","type":"text","marks":[{"type":"strong"}]},{"text":"--deep","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" or ","type":"text","marks":[{"type":"strong"}]},{"text":"--sweep","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":"):","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/deep-audit-protocol.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full protocol. In summary:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Chunk target files into batches of 3-5 by line count","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Dispatch up to 8 Explore agents in parallel, each with a mandatory 8-category checklist per file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Merge all explorer findings into a sweep manifest at ","type":"text"},{"text":".agents/council/sweep-manifest.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Include sweep manifest in the council packet so judges shift to adjudication mode","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Why:","type":"text","marks":[{"type":"strong"}]},{"text":" Generalist judges exhibit satisfaction bias — they stop after a small number of findings regardless of actual issue count. Per-file explorers with category checklists reduce that bias and surface concrete line-level issues before council adjudication.","type":"text"}]},{"type":"paragraph","content":[{"text":"Path B — Lightweight Bug Hunt (default, no ","type":"text","marks":[{"type":"strong"}]},{"text":"--deep","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":"/","type":"text","marks":[{"type":"strong"}]},{"text":"--sweep","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":"):","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"Run proactive bug-hunt audit on target files.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2f: Codex Review","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" When ","type":"text"},{"text":"--mixed","type":"text","marks":[{"type":"code_inline"}]},{"text":" is passed and Codex CLI is available, send the first 2000 chars of the diff to Codex for a parallel review. Cap input at 2000 chars to stay within Codex context budgets.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Product Context","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if ","type":"text","marks":[{"type":"strong"}]},{"text":"--quick","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" as a separate judge-fanout step.","type":"text","marks":[{"type":"strong"}]},{"text":" When ","type":"text"},{"text":"PRODUCT.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists and the user did not pass an explicit ","type":"text"},{"text":"--preset","type":"text","marks":[{"type":"code_inline"}]},{"text":" override, quick mode still loads DX expectations inline in the single-agent review. In non-quick modes, add a DX (developer experience) judge: 2 independent + 1 DX judge (3 judges total). The DX judge evaluates whether the code aligns with the product's stated personas and value propositions.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2g: Test Pyramid Inventory (MANDATORY)","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/test-pyramid-inventory.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/test-pyramid-inventory.md","title":null}}]},{"text":" when you need the full inventory procedure: per-module L0–L3 coverage checks, BF1–BF5 boundary checks, the ","type":"text"},{"text":"weighted_score","type":"text","marks":[{"type":"code_inline"}]},{"text":" formula, satisfaction-score exposure, the council-packet ","type":"text"},{"text":"test_pyramid","type":"text","marks":[{"type":"code_inline"}]},{"text":" JSON shape, and verdict rules. Runs in both ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" and full modes — file existence checks are cheap. Weight L0–L1 at 1x, L2 at 3x, L3+ at 5x; ","type":"text"},{"text":"weighted_score \u003c 0.3","type":"text","marks":[{"type":"code_inline"}]},{"text":" with L0–L1 only is a WARN.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Run Council Validation","type":"text"}]},{"type":"paragraph","content":[{"text":"With spec found — use code-review preset:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"/council --preset=code-review validate \u003ctarget>","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"error-paths","type":"text","marks":[{"type":"code_inline"}]},{"text":": Trace every error handling path. What's uncaught? What fails silently?","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"api-surface","type":"text","marks":[{"type":"code_inline"}]},{"text":": Review every public interface. Is the contract clear? Breaking changes?","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"spec-compliance","type":"text","marks":[{"type":"code_inline"}]},{"text":": Compare implementation against the spec. What's missing? What diverges?","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The spec content is injected into the council packet context so the ","type":"text"},{"text":"spec-compliance","type":"text","marks":[{"type":"code_inline"}]},{"text":" judge can compare implementation against it.","type":"text"}]},{"type":"paragraph","content":[{"text":"Without spec — 2 independent judges (no perspectives):","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"/council validate \u003ctarget>","type":"text"}]},{"type":"paragraph","content":[{"text":"2 independent judges (no perspective labels). Use ","type":"text"},{"text":"--deep","type":"text","marks":[{"type":"code_inline"}]},{"text":" for 3 judges on high-stakes reviews. Override with ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" (inline single-agent check) or ","type":"text"},{"text":"--mixed","type":"text","marks":[{"type":"code_inline"}]},{"text":" (cross-vendor with Codex).","type":"text"}]},{"type":"paragraph","content":[{"text":"Council receives:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Files to review","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complexity hotspots (from Step 2)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Git diff context","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Spec content (when found, in ","type":"text"},{"text":"context.spec","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sweep manifest (when ","type":"text"},{"text":"--deep","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"--sweep","type":"text","marks":[{"type":"code_inline"}]},{"text":", in ","type":"text"},{"text":"context.sweep_manifest","type":"text","marks":[{"type":"code_inline"}]},{"text":" — judges shift to adjudication mode, see ","type":"text"},{"text":"references/deep-audit-protocol.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"All council flags pass through: ","type":"text"},{"text":"--quick","type":"text","marks":[{"type":"code_inline"}]},{"text":" (inline), ","type":"text"},{"text":"--mixed","type":"text","marks":[{"type":"code_inline"}]},{"text":" (cross-vendor), ","type":"text"},{"text":"--preset=\u003cname>","type":"text","marks":[{"type":"code_inline"}]},{"text":" (override perspectives), ","type":"text"},{"text":"--explorers=N","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--debate","type":"text","marks":[{"type":"code_inline"}]},{"text":" (adversarial 2-round), ","type":"text"},{"text":"--tier=\u003cname>","type":"text","marks":[{"type":"code_inline"}]},{"text":" (model cost tier: quality/balanced/budget). See Quick Start examples and ","type":"text"},{"text":"/council","type":"text","marks":[{"type":"code_inline"}]},{"text":" docs.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 5: Council Checks","type":"text"}]},{"type":"paragraph","content":[{"text":"Each judge reviews for:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Aspect","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What to Look For","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Correctness","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Does code do what it claims?","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Security","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Injection, auth issues, secrets","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Edge Cases","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Null handling, boundaries, errors","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Quality","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dead code, duplication, clarity","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Complexity","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High cyclomatic scores, deep nesting","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Architecture","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Coupling, abstractions, patterns","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 6: Interpret Verdict","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Council Verdict:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Council Verdict","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Vibe Result","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Action","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PASS","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ready to ship","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Merge/deploy","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WARN","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Review concerns","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Address or accept risk","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FAIL","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Not ready","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fix issues","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 7: Write Vibe Report","type":"text"}]},{"type":"paragraph","content":[{"text":"Write to:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":".agents/council/YYYY-MM-DD-vibe-\u003ctarget>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (use ","type":"text"},{"text":"date +%Y-%m-%d","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/report-format.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full vibe report markdown template. The report includes: complexity analysis, council verdict table, shared/critical/informational findings, all findings (when ","type":"text"},{"text":"--deep","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"--sweep","type":"text","marks":[{"type":"code_inline"}]},{"text":"), recommendation, and decision checkboxes.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 8: Report to User","type":"text"}]},{"type":"paragraph","content":[{"text":"Tell the user:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complexity hotspots (if any)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Council verdict (PASS/WARN/FAIL)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Key concerns","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Location of vibe report","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 9: Record Ratchet Progress & Step 9.5: Feed Findings to Flywheel","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/post-verdict-actions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/post-verdict-actions.md","title":null}}]},{"text":" when you need the PASS/WARN/FAIL ratchet recording rules, the failure-retry finding extraction format, and the ","type":"text"},{"text":".agents/findings/registry.jsonl","type":"text","marks":[{"type":"code_inline"}]},{"text":" write contract (dedup_key, applicable_when vocabulary, atomic-rename rule) plus the ","type":"text"},{"text":"hooks/finding-compiler.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" follow-up.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 10: Test Bead Cleanup","type":"text"}]},{"type":"paragraph","content":[{"text":"After validation completes, clean up stale test beads (","type":"text"},{"text":"bd list --status=open | grep -iE \"test bead|test quest\"","type":"text","marks":[{"type":"code_inline"}]},{"text":") via ","type":"text"},{"text":"bd close","type":"text","marks":[{"type":"code_inline"}]},{"text":" to prevent bead pollution. Skip if ","type":"text"},{"text":"bd","type":"text","marks":[{"type":"code_inline"}]},{"text":" unavailable.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Integration with Workflow","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"/implement issue-123\n │\n ▼\n(coding, quick lint/test as you go)\n │\n ▼\n/vibe ← You are here\n │\n ├── Complexity analysis (find hotspots)\n ├── Bug hunt audit (find concrete bugs)\n └── Council validation (multi-model judgment)\n │\n ├── PASS → ship it\n ├── WARN → review, then ship or fix\n └── FAIL → fix, re-run /vibe","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"paragraph","content":[{"text":"User says:","type":"text","marks":[{"type":"strong"}]},{"text":" \"Run a quick validation on the latest changes.\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Do:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe recent","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Validate Recent Changes","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe recent","type":"text"}]},{"type":"paragraph","content":[{"text":"Runs complexity on recent changes, then council reviews.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Validate Specific Directory","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe src/auth/","type":"text"}]},{"type":"paragraph","content":[{"text":"Complexity + council on auth directory.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Deep Review","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe --deep recent","type":"text"}]},{"type":"paragraph","content":[{"text":"Complexity + 3 judges for thorough review.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cross-Vendor Consensus","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/vibe --mixed recent","type":"text"}]},{"type":"paragraph","content":[{"text":"Complexity + Claude + Codex judges.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/examples.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for additional examples: security audit with spec compliance, developer-experience code review with PRODUCT.md, and fast inline checks.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Problem","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cause","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Solution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"COMPLEXITY SKIPPED: radon not installed\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python complexity analyzer missing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Install with ","type":"text"},{"text":"pip install radon","type":"text","marks":[{"type":"code_inline"}]},{"text":" or skip complexity (council still runs).","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"COMPLEXITY SKIPPED: gocyclo not installed\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Go complexity analyzer missing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Install with ","type":"text"},{"text":"go install github.com/fzipp/gocyclo/cmd/gocyclo@latest","type":"text","marks":[{"type":"code_inline"}]},{"text":" or skip.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Vibe returns PASS but constraint tests fail","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Council LLMs miss mechanical violations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":".agents/council/\u003ctimestamp>-vibe-*.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for constraint test results. Failed constraints override council PASS. Fix violations and re-run.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Codex review skipped","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--mixed","type":"text","marks":[{"type":"code_inline"}]},{"text":" not passed, Codex CLI not on PATH, or no uncommitted changes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Codex review is opt-in — pass ","type":"text"},{"text":"--mixed","type":"text","marks":[{"type":"code_inline"}]},{"text":" to enable. Also requires Codex CLI on PATH and uncommitted changes.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"No modified files detected\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Clean working tree, no recent commits","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Make changes or specify target path explicitly: ","type":"text"},{"text":"/vibe src/auth/","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Spec-compliance judge not spawned","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No spec found in beads/plans","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reference bead ID in commit message or create plan doc in ","type":"text"},{"text":".agents/plans/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Without spec, vibe uses 2 independent judges (3 with ","type":"text"},{"text":"--deep","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Write-Time Quality Hook","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"hooks/write-time-quality.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" PostToolUse hook runs automatically after every Write/Edit tool call, catching common anti-patterns at edit time rather than review time. It checks:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Go:","type":"text","marks":[{"type":"strong"}]},{"text":" unchecked errors, ","type":"text"},{"text":"fmt.Print","type":"text","marks":[{"type":"code_inline"}]},{"text":" in library code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python:","type":"text","marks":[{"type":"strong"}]},{"text":" bare ","type":"text"},{"text":"except:","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"eval","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"exec","type":"text","marks":[{"type":"code_inline"}]},{"text":", missing type hints on public functions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Shell:","type":"text","marks":[{"type":"strong"}]},{"text":" missing ","type":"text"},{"text":"set -euo pipefail","type":"text","marks":[{"type":"code_inline"}]},{"text":", unquoted variables","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The hook is non-blocking (always exits 0) and outputs warnings via JSON. See ","type":"text"},{"text":"references/write-time-quality.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/write-time-quality.md","title":null}}]},{"text":" for the full design.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"See Also","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"skills/council/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Multi-model validation council","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"skills/complexity/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Standalone complexity analysis","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"skills/bug-hunt/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Proactive code audit and bug investigation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":".agents/specs/conflict-resolution-algorithm.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Conflict resolution between agent findings","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"test","type":"text","marks":[{"type":"link","attrs":{"href":"../test/SKILL.md","title":null}}]},{"text":" — Test generation and coverage analysis","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"perf","type":"text","marks":[{"type":"link","attrs":{"href":"../perf/SKILL.md","title":null}}]},{"text":" — Performance profiling and benchmarking","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Reference Documents","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/vibe.feature","type":"text","marks":[{"type":"link","attrs":{"href":"references/vibe.feature","title":null}}]},{"text":" — Executable spec: council verdict (complexity/architecture/security/intent-fit), block-on-CRITICAL, verdict.json (soc-qk4b)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/complexity-analysis.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/complexity-analysis.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/deep-checks.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/deep-checks.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/post-verdict-actions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/post-verdict-actions.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/test-pyramid-inventory.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/test-pyramid-inventory.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/verification-report.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/verification-report.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/write-time-quality.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/write-time-quality.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/deep-audit-protocol.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/deep-audit-protocol.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/examples.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/examples.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/go-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/go-patterns.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/go-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/go-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/json-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/json-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/markdown-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/markdown-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/patterns.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/python-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/python-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/report-format.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/report-format.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/rust-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/rust-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/shell-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/shell-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/typescript-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/typescript-standards.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/vibe-coding.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/vibe-coding.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/vibe-suppressions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/vibe-suppressions.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/test-pyramid-weighting.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/test-pyramid-weighting.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/yaml-standards.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/yaml-standards.md","title":null}}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"vibe","author":"@skillopedia","source":{"stars":375,"repo_name":"agentops","origin_url":"https://github.com/boshu2/agentops/blob/HEAD/skills/vibe/SKILL.md","repo_owner":"boshu2","body_sha256":"ea99721011bf985cb9d80611df74e2244b74be42cff3a70b3b8e78c460764580","cluster_key":"482e364ed90df91dc443f582521d0629459a6c334f6b1fe5517ce68f1cafc5a0","clean_bundle":{"format":"clean-skill-bundle-v1","source":"boshu2/agentops/skills/vibe/SKILL.md","attachments":[{"id":"79c1409b-9998-5422-93fe-66cc1916758e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/79c1409b-9998-5422-93fe-66cc1916758e/attachment.md","path":"references/complexity-analysis.md","size":2300,"sha256":"95129e01d3547c1ad795bb6f806c7109c5cbf49dc241491bbf18c143a2fe01ed","contentType":"text/markdown; charset=utf-8"},{"id":"69189280-83cd-5ff4-97e1-006dff1aa3d7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/69189280-83cd-5ff4-97e1-006dff1aa3d7/attachment.md","path":"references/deep-audit-protocol.md","size":9165,"sha256":"05e863d4d85e9cf02cf74bf2d65c078d651a55f57a6d18a55102a98571f01b3a","contentType":"text/markdown; charset=utf-8"},{"id":"c41ad3d3-1b4d-5d7e-80db-2d456e965c6a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c41ad3d3-1b4d-5d7e-80db-2d456e965c6a/attachment.md","path":"references/deep-checks.md","size":11494,"sha256":"6a5c17b3452cee808cba8372ae57432e99f17307ad3e3d1f88f54685d5f0bd62","contentType":"text/markdown; charset=utf-8"},{"id":"813a401f-848c-5987-9b03-703d8ef111ef","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/813a401f-848c-5987-9b03-703d8ef111ef/attachment.md","path":"references/examples.md","size":1883,"sha256":"6affcb5b27828830a50eca58503df51d1320a03665ae60a2dae515fd6b757d27","contentType":"text/markdown; charset=utf-8"},{"id":"83f41845-1395-5db3-bf5b-ac4197eca971","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/83f41845-1395-5db3-bf5b-ac4197eca971/attachment.md","path":"references/go-patterns.md","size":13788,"sha256":"51a007e2dccdd09c5d598b8cdcd61d467d3538bf0188ec6d448b1d9fa7e1cf40","contentType":"text/markdown; charset=utf-8"},{"id":"a811ef52-5872-56b9-8151-a41f3d1a911d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a811ef52-5872-56b9-8151-a41f3d1a911d/attachment.md","path":"references/go-standards.md","size":32329,"sha256":"77c1a437e3321ab7524862a340ce8e98172d9ef02730a6b3de3741de07ed6de4","contentType":"text/markdown; charset=utf-8"},{"id":"ed556683-e713-51bd-b39a-f40944cb26b1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ed556683-e713-51bd-b39a-f40944cb26b1/attachment.md","path":"references/json-standards.md","size":11364,"sha256":"f4e4e064efc233105ac869ab5353f51e30e20b985aae9b1d1d42571b2c28f329","contentType":"text/markdown; charset=utf-8"},{"id":"9e2eb1b2-c9d2-50a7-8952-4896abcd347d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9e2eb1b2-c9d2-50a7-8952-4896abcd347d/attachment.md","path":"references/markdown-standards.md","size":8166,"sha256":"cd31533d268eda7f175f8d65c49bd9a45e9c7e19ce5fc1956d28772103af7e01","contentType":"text/markdown; charset=utf-8"},{"id":"e611cb6f-24bf-50c6-8faf-fa6c1a66dfed","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e611cb6f-24bf-50c6-8faf-fa6c1a66dfed/attachment.md","path":"references/patterns.md","size":9417,"sha256":"086bc630e7968681b6e7706acf6de4d1d1f04cb7f33fce37e6e9b834d131c22e","contentType":"text/markdown; charset=utf-8"},{"id":"88c7a77b-ff12-5c02-82d8-be357b5cd095","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/88c7a77b-ff12-5c02-82d8-be357b5cd095/attachment.md","path":"references/post-verdict-actions.md","size":2082,"sha256":"80f0e9d018abb511a06cf436563f69e01adf1a355ba310fce8cd769c081bb600","contentType":"text/markdown; charset=utf-8"},{"id":"ca4004bf-65bc-5877-b165-952693b535f0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ca4004bf-65bc-5877-b165-952693b535f0/attachment.md","path":"references/python-standards.md","size":30711,"sha256":"c426c007af629c99ecd3c2604f1bdd3cb575196f575bb409661ded97f0e5dfb1","contentType":"text/markdown; charset=utf-8"},{"id":"3af581c4-3e87-5595-8002-d0f296af885b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3af581c4-3e87-5595-8002-d0f296af885b/attachment.md","path":"references/report-format.md","size":4542,"sha256":"7a367f3ef71b6c1e8a2253b26c5330ab55fb89bf0620de72372bc68cb223220c","contentType":"text/markdown; charset=utf-8"},{"id":"dfa303a6-36ee-5fb2-98b0-f008ae30f63d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dfa303a6-36ee-5fb2-98b0-f008ae30f63d/attachment.md","path":"references/rust-standards.md","size":42186,"sha256":"367caff1b85ed655f0abd22d88b61f3ae6876b1e3663431620d2d91c1b02df3a","contentType":"text/markdown; charset=utf-8"},{"id":"15e6336d-5f9e-5806-bf9e-450526e75eaf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/15e6336d-5f9e-5806-bf9e-450526e75eaf/attachment.md","path":"references/shell-standards.md","size":20380,"sha256":"fe682a2f0b14d205e197293642f305989dc40b09f20dcda6225575f76d78c54c","contentType":"text/markdown; charset=utf-8"},{"id":"ebebece7-1c33-5886-b8c0-1d95c9d826d9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ebebece7-1c33-5886-b8c0-1d95c9d826d9/attachment.md","path":"references/test-pyramid-inventory.md","size":4475,"sha256":"902ff3ebdb814ea041dc0e351f4be668eebc509eaf88f545c645598fd037c40e","contentType":"text/markdown; charset=utf-8"},{"id":"3481ef3f-3d90-538d-89b6-6784a30584dd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3481ef3f-3d90-538d-89b6-6784a30584dd/attachment.md","path":"references/test-pyramid-weighting.md","size":2936,"sha256":"6243377a947787f2131d8716a886d5541a59859c2dde805c19c892003f0fba68","contentType":"text/markdown; charset=utf-8"},{"id":"f4d6195e-2c7a-5ea9-99dd-d0c3b7f0e4d7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f4d6195e-2c7a-5ea9-99dd-d0c3b7f0e4d7/attachment.md","path":"references/typescript-standards.md","size":33117,"sha256":"6f02a105fb13cb294f76f6465db8a24d89eb802870e060f4cc6cc551d088cd63","contentType":"text/markdown; charset=utf-8"},{"id":"fd087941-368a-50e8-8eb4-f8b96929373a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd087941-368a-50e8-8eb4-f8b96929373a/attachment.md","path":"references/verification-report.md","size":2594,"sha256":"a80e8f16334b20fe4fc0f6bb3f2b4d06e8ea13f2b7f038e60f4e8c3b84115f66","contentType":"text/markdown; charset=utf-8"},{"id":"734f27b4-79b7-559a-a0ac-f4432e625331","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/734f27b4-79b7-559a-a0ac-f4432e625331/attachment.md","path":"references/vibe-coding.md","size":3873,"sha256":"31045aacc85d81e9ee29dd4242bb6f4a2261522c683097b44dd18fc86f143935","contentType":"text/markdown; charset=utf-8"},{"id":"e809aed9-74b8-5d3d-b23a-9def4fd62a67","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e809aed9-74b8-5d3d-b23a-9def4fd62a67/attachment.md","path":"references/vibe-suppressions.md","size":2963,"sha256":"9ae1cf7a394742f45ed7ed577a89d9049a0419095774edd03d91cd7c431e7496","contentType":"text/markdown; charset=utf-8"},{"id":"7b32b5cf-503c-5ad9-b763-c53faab76aca","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7b32b5cf-503c-5ad9-b763-c53faab76aca/attachment.feature","path":"references/vibe.feature","size":1571,"sha256":"5a8012a0bdbd4353eb1a4a8c8cf5bfcb376691f43b8bd205a7032b4d73886b43","contentType":"text/plain; charset=utf-8"},{"id":"c420bbf9-5961-50c2-b394-00b9bb3f051f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c420bbf9-5961-50c2-b394-00b9bb3f051f/attachment.md","path":"references/write-time-quality.md","size":3557,"sha256":"fcbfd93939819330c0c7a1f7330b69f298c3ba0a68d0b48faa72072cb52c271c","contentType":"text/markdown; charset=utf-8"},{"id":"32101111-ab04-5774-9c84-068b505770d7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/32101111-ab04-5774-9c84-068b505770d7/attachment.md","path":"references/yaml-standards.md","size":13806,"sha256":"a6fd84907fa87cfb944e195092bf1b1c6f02a0644411c17265dee12869fe4c6f","contentType":"text/markdown; charset=utf-8"},{"id":"59c18e0f-1795-5048-8321-70b8f6c64c2e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/59c18e0f-1795-5048-8321-70b8f6c64c2e/attachment.sh","path":"scripts/prescan.sh","size":13202,"sha256":"d34f8fb93974b8ea8880d5cfc7757639d6292f7e55c99bbae168c9aeb8036439","contentType":"application/x-sh; charset=utf-8"},{"id":"2c2ffaf1-cb75-5bcb-92f2-76e1b23e53e1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2c2ffaf1-cb75-5bcb-92f2-76e1b23e53e1/attachment.sh","path":"scripts/validate.sh","size":1634,"sha256":"c8b83ec5f121792d136879dc2fc0b7c6af9d777f6b77fe0a0dd564631a3b10e7","contentType":"application/x-sh; charset=utf-8"}],"bundle_sha256":"455d62133c8894812c0df5145ca149650da954c8760b5bf37f77d77df280b6c5","attachment_count":25,"text_attachments":24,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":1,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/vibe/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"software-engineering","category_label":"Engineering"},"exact_dupes_collapsed_into_this":0},"context":{"intent":{"mode":"task"},"window":"fork","sections":{"exclude":["HISTORY"]},"intel_scope":"full"},"version":"v1","category":"software-engineering","consumes":["standards"],"metadata":{"tier":"judgment","dependencies":["council","complexity","bug-hunt","standards"]},"produces":["result.json","verdict.json"],"practices":["ai-assisted-dev","llm-eval-harness","code-complete","pragmatic-programmer"],"import_tag":"clean-skills-v1","context_rel":[{"kind":"shared-kernel","with":"standards"}],"description":"Validate code readiness.","hexagonal_role":"domain","output_contract":"skills/council/schemas/verdict.json","skill_api_version":1}},"renderedAt":1782980418477}

Vibe Skill Purpose: Is this code ready to ship? Loop position Per-slice quality gate within move 6 (close the bead by proving acceptance) of the operating loop. Consumes a slice's changes; produces PASS/WARN/FAIL on complexity, architecture, security, intent fit. Vibe answers "is this slice ready to be counted against the slice-validation roll-up?" — it is not a substitute for the slice's first failing test (the test proves behavior; vibe judges the code that gets there). Three steps: 1. Complexity analysis — Find hotspots (radon, gocyclo) 2. Bug hunt audit — Systematic sweep for concrete bug…