{"id":"ab0c162a-3a04-4020-b5d4-b477e114f993","entityType":"agent","slug":"clawhub-athola-nm-sanctum-pr-review","name":"pr-review","canonicalUrl":"https://www.xpersona.co/agent/clawhub-athola-nm-sanctum-pr-review","canonicalPath":"/agent/clawhub-athola-nm-sanctum-pr-review","generatedAt":"2026-10-10T11:00:22.799Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":null},"description":"Reviews pull requests with scope validation, requirements compliance, and line comments Skill: pr-review Owner: athola Summary: Reviews pull requests with scope validation, requirements compliance, and line comments Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:20:39.575Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:40:42.486Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:57:35.890Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:05:27.217Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.6K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17emme0e2m3cpf7k2jvp3a84984b8z9:nm-sanctum-pr-review","sourceUrl":"https://clawhub.ai/athola/nm-sanctum-pr-review","homepage":"https://clawhub.ai/athola/skills/nm-sanctum-pr-review","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/athola/nm-sanctum-pr-review","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/athola/skills/nm-sanctum-pr-review","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Reviews pull requests with scope validation, requirements compliance, and line comments Skill: pr-review Owner: athola Summary: Reviews pull requests with scope"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":null},"stars":null,"forks":null,"downloads":1560,"packageName":null,"latestVersion":"1.9.19","tractionLabel":"1.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:23:56.377Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T08:23:56.378Z","lastCrawledAt":"2026-10-10T08:23:56.377Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T08:23:56.377Z","lastVerifiedAt":null,"highlights":[{"version":"1.9.19","createdAt":"2026-08-26T13:20:39.575Z","changelog":"Release v1.9.19","fileCount":10,"zipByteSize":30203},{"version":"1.9.17","createdAt":"2026-07-30T05:40:42.486Z","changelog":"Release v1.9.17","fileCount":10,"zipByteSize":30119},{"version":"1.9.16","createdAt":"2026-07-14T19:57:35.890Z","changelog":"Release v1.9.16","fileCount":10,"zipByteSize":30248},{"version":"1.9.14","createdAt":"2026-06-30T18:05:27.217Z","changelog":"Release v1.9.14","fileCount":10,"zipByteSize":30216},{"version":"1.9.13","createdAt":"2026-06-27T16:23:19.123Z","changelog":"Release v1.9.13","fileCount":10,"zipByteSize":30127},{"version":"1.9.12","createdAt":"2026-06-19T03:18:44.521Z","changelog":"Release v1.9.12","fileCount":10,"zipByteSize":30161},{"version":"1.0.3","createdAt":"2026-06-18T15:20:30.331Z","changelog":"Release v1.9.12","fileCount":10,"zipByteSize":30120},{"version":"1.0.2","createdAt":"2026-05-09T02:19:57.935Z","changelog":"Release v1.9.5","fileCount":9,"zipByteSize":27575}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17emme0e2m3cpf7k2jvp3a84984b8z9:nm-sanctum-pr-review","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T11:00:22.796Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-sanctum-pr-review/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":null},"readme":"Skill: pr-review\n\nOwner: athola\n\nSummary: Reviews pull requests with scope validation, requirements compliance, and line comments\n\nTags: latest:1.9.19\n\nVersion history:\n\nv1.9.19 | 2026-08-26T13:20:39.575Z | user\n\nRelease v1.9.19\n\nv1.9.17 | 2026-07-30T05:40:42.486Z | user\n\nRelease v1.9.17\n\nv1.9.16 | 2026-07-14T19:57:35.890Z | user\n\nRelease v1.9.16\n\nv1.9.14 | 2026-06-30T18:05:27.217Z | user\n\nRelease v1.9.14\n\nv1.9.13 | 2026-06-27T16:23:19.123Z | user\n\nRelease v1.9.13\n\nv1.9.12 | 2026-06-19T03:18:44.521Z | user\n\nRelease v1.9.12\n\nv1.0.3 | 2026-06-18T15:20:30.331Z | user\n\nRelease v1.9.12\n\nv1.0.2 | 2026-05-09T02:19:57.935Z | user\n\nRelease v1.9.5\n\nv1.0.1 | 2026-05-06T14:21:21.624Z | user\n\nRelease v1.9.4\n\nv1.0.0 | 2026-04-15T19:02:01.732Z | auto\n\nInitial release of the scope-focused PR review skill.\n\n- Provides structured pull/merge request review focused on requirements validation and backlog triage.\n- Includes a scope classification framework to categorize findings: BLOCKING, IN-SCOPE, SUGGESTION, BACKLOG, IGNORE.\n- Outlines a detailed, phase-based review workflow: establish scope, gather changes, validate requirements, check versions, review code, triage backlog, and capture knowledge.\n- Automatically detects and integrates with GitHub or GitLab for platform-specific actions.\n- Emphasizes preventing scope creep and routing out-of-scope issues to the backlog.\n\nArchive index:\n\nArchive v1.9.19: 10 files, 30203 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2453b), SKILL.md (21009b), _meta.json (140b)\n\nFile v1.9.19:SKILL.md\n\n---\nname: pr-review\ndescription: |\n  Reviews pull requests with scope validation, requirements compliance, and line comments\nversion: 1.9.8\ntriggers:\n  - pr\n  - review\n  - scope\n  - github\n  - gitlab\n  - code-quality\n  - knowledge-capture\n  - cross-platform\n  - reviewing GitHub or GitLab PRs\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/sanctum\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.leyline:git-platform\", \"night-market.sanctum:shared\", \"night-market.sanctum:git-workspace-review\", \"night-market.sanctum:version-updates\", \"night-market.pensive:unified-review\", \"night-market.imbue:proof-of-work\", \"night-market.imbue:justify\", \"night-market.memory-palace:review-chamber\", \"night-market.scribe:slop-detector\", \"night-market.scribe:doc-generator\"]}}}\nsource: claude-night-market\nsource_plugin: sanctum\n---\n\n> **Night Market Skill** — ported from [claude-night-market/sanctum](https://github.com/athola/claude-night-market/tree/master/plugins/sanctum). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Core Principle](#core-principle)\n- [When to Use](#when-to-use)\n- [Scope Classification Framework](#scope-classification-framework)\n- [Classification Examples](#classification-examples)\n- [Workflow](#workflow)\n- [Phase 1: Establish Scope Baseline](#phase-1-establish-scope-baseline)\n- [Phase 2: Gather Changes](#phase-2-gather-changes)\n- [Phase 3: Requirements Validation](#phase-3-requirements-validation)\n- [Phase 1.5: Version Validation (MANDATORY)](#phase-15-version-validation-mandatory)\n- [Phase 4: Code Review with Scope Context](#phase-4-code-review-with-scope-context)\n- [Phase 4.5: Additive Bias Audit](#phase-45-additive-bias-audit)\n- [Phase 5: Backlog Triage](#phase-5-backlog-triage)\n- [Phase 6: Generate Report](#phase-6-generate-report)\n- [Phase 7: Knowledge Capture](#phase-7-knowledge-capture)\n- [Quality Gates](#quality-gates)\n- [Anti-Patterns to Avoid](#anti-patterns-to-avoid)\n- [Don't: Scope Creep Review](#dont-scope-creep-review)\n- [Don't: Perfect is Enemy of Good](#dont-perfect-is-enemy-of-good)\n- [Don't: Blocking on Style](#dont-blocking-on-style)\n- [Don't: Reviewing Unchanged Code](#dont-reviewing-unchanged-code)\n- [Integration with Other Tools](#integration-with-other-tools)\n- [Exit Criteria](#exit-criteria)\n\n\n# Scope-Focused PR Review\n\nReview pull/merge requests with discipline: validate against original requirements, prevent scope creep, and route out-of-scope findings to issues on the detected platform.\n\n**Platform detection is automatic** via `leyline:git-platform`. Use `gh` for GitHub, `glab` for GitLab. Check session context for `git_platform:`.\n\n## Core Principle\n\n**A PR review validates scope compliance, not code perfection.**\n\nThe goal is to validate the implementation meets its stated requirements without introducing regressions. Improvements beyond the scope belong in future PRs.\n\n## When To Use\n\n- Before merging any feature branch\n- When reviewing PRs from teammates\n- To validate your own work before requesting review\n- To generate a backlog of improvements discovered during review\n\n## When NOT To Use\n\n- Preparing PRs - use pr-prep instead\n- Deep code\n  review - use pensive:unified-review\n- Preparing PRs - use pr-prep instead\n- Deep code\n  review - use pensive:unified-review\n\n## Scope Classification Framework\n\nEvery finding must be classified:\n\n| Category | Definition | Action |\n|----------|------------|--------|\n| **BLOCKING** | Bug, security issue, or regression introduced by this change | Must fix before merge |\n| **IN-SCOPE** | Issue directly related to stated requirements | Should address in this PR |\n| **SUGGESTION** | Improvement within changed code, not required | Author decides |\n| **BACKLOG** | Good idea but outside PR scope | Create GitHub issue |\n| **IGNORE** | Nitpick, style preference, or not worth tracking | Skip entirely |\n\n### Classification Examples\n\n**BLOCKING:**\n- Null pointer exception in new code path\n- SQL injection in new endpoint\n- Breaking change to public API without migration\n- Test that was passing now fails\n\n**IN-SCOPE:**\n- Missing error handling specified in requirements\n- Feature doesn't match spec behavior\n- Incomplete implementation of planned functionality\n\n**SUGGESTION:**\n- Better variable name in changed function\n- Slightly more efficient algorithm\n- Additional edge case test\n\n**BACKLOG:**\n- Refactoring opportunity in adjacent code\n- \"While we're here\" improvements\n- Technical debt in files touched but not changed\n- Features sparked by seeing the code\n\n**IGNORE:**\n- Personal style preferences\n- Theoretical improvements with no practical impact\n- Premature optimization suggestions\n\n## Workflow\n\n### Phase 1: Establish Scope Baseline\n\nBefore looking at ANY code, understand what this PR is supposed to accomplish.\n\n**Note:** Version validation (Phase 1.5) runs AFTER scope establishment but BEFORE code review. See `modules/version-validation.md` for details.\n\n**Search for scope artifacts in order:**\n\n1. **Plan file**: Most authoritative (check spec-kit locations first, then root)\n   ```bash\n   # Spec-kit feature plans (preferred - structured implementation blueprints)\n   find specs -name \"plan.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   # Legacy/alternative locations\n   ls docs/plans/ 2>/dev/null\n   # Root plan.md (may be Claude Plan Mode artifact from v2.0.51+)\n   cat plan.md 2>/dev/null | head -100\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n2. **Spec file**: Requirements definition (check spec-kit locations first)\n   ```bash\n   find specs -name \"spec.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   cat spec.md 2>/dev/null | head -100\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n3. **Tasks file**: Implementation checklist (check spec-kit locations first)\n   ```bash\n   find specs -name \"tasks.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null\n   cat tasks.md 2>/dev/null\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n4. **PR/MR description**: Author's intent\n   ```bash\n   # GitHub\n   gh pr view <number> --json body --jq '.body'\n   # GitLab\n   glab mr view <number> --json description --jq '.description'\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n5. **Commit messages**: Incremental decisions\n   ```bash\n   # GitHub\n   gh pr view <number> --json commits --jq '.commits[].messageHeadline'\n   # GitLab\n   glab mr view <number> --json commits\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n**Output:** A clear statement of scope:\n> \"This PR implements [feature X] as specified in plan.md. The requirements are:\n> 1. [requirement]\n> 2. [requirement]\n> 3. [requirement]\"\n\nIf no scope artifacts exist, flag this as a process issue but continue with PR description as the baseline.\n\n### Phase 2: Gather Changes\n\n```bash\n# GitHub\ngh pr diff <number> --name-only\ngh pr diff <number>\ngh pr view <number> --json additions,deletions,changedFiles,commits\n\n# GitLab\nglab mr diff <number>\nglab mr view <number>\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n### Phase 3: Requirements Validation\n\nBefore detailed code review, check scope coverage:\n\n- [ ] Each requirement has corresponding implementation\n- [ ] No requirements are missing\n- [ ] Implementation doesn't exceed requirements (overengineering signal)\n\n### Phase 1.5: Version Validation (MANDATORY)\n\n**Run version validation checks BEFORE code review.**\n\nSee `modules/version-validation.md` for detailed validation procedures.\n\n**Quick reference:**\n1. Check if bypass requested (`--skip-version-check`, label, or PR marker)\n2. Detect if version files changed in PR diff\n3. If changed, run project-specific validations:\n   - Claude marketplace: Check marketplace.json vs plugin.json versions\n   - Python: Check pyproject.toml vs __version__\n   - Node: Check package.json vs package-lock.json\n   - Rust: Check Cargo.toml vs Cargo.lock\n4. Validate CHANGELOG has entry for new version\n5. Check README/docs for version references\n6. Classify findings as BLOCKING (or WAIVED if bypassed)\n\n**All version mismatches are BLOCKING unless explicitly waived by maintainer.**\n\n### Phase 3.5: PR Hygiene Checks\n\nBefore diving into code, run the PR hygiene checks from\n`modules/pr-hygiene.md`:\n\n1. **Atomicity check**: Does this PR contain one logical\n   change? Flag mixed commit types (feat, refactor, and fix),\n   formatting commits bundled with logic, or changes spanning\n   unrelated subsystems. Large PRs get 30% defect detection\n   vs 75% for focused ones.\n\n2. **Agent curation check**: Does the code show signs of\n   iterative AI generation without a cleanup pass? Look for\n   redundant implementations, premature abstractions, incomplete\n   refactors, and scope drift.\n\n3. **Self-review signals**: Are there unsquashed fixup commits,\n   debug statements, or commented-out code that suggest the\n   author did not read their own diff before sending?\n\nClassify findings per `modules/pr-hygiene.md` severity tables.\n\n### Phase 4: Code Review with Scope Context\n\nUse `pensive:unified-review` on the changed files. For comment quality assessment, see `modules/comment-guidelines.md`.\n\n**Critical:** Evaluate each finding against the scope baseline:\n\n```text\n**Verification:** Run the command with `--help` flag to verify availability.\nFinding: \"Function X lacks input validation\"\nScope check: Is input validation mentioned in requirements?\n  - YES → IN-SCOPE\n  - NO, but it's a security issue → BLOCKING\n  - NO, and it's a nice-to-have → BACKLOG\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n### Phase 4.5: Additive Bias Audit\n\nRun `Skill(imbue:justify)` on the PR changes to detect\nAI additive bias, test-logic tampering, and unnecessary\ncomplexity.\n\n**Key checks:**\n\n1. **Additive bias score** -- flag changes with high\n   add/delete ratio (>5:1) that lack justification\n2. **Iron Law compliance** -- verify test assertions were\n   not weakened to match broken implementations\n3. **Minimal intervention** -- confirm each changed file\n   was necessary and the change was the smallest fix\n\n**Classify justify findings using the scope framework:**\n\n| Justify Signal | Likely Classification |\n|---------------|----------------------|\n| Test logic tampered | BLOCKING |\n| High additive bias, no justification | IN-SCOPE |\n| Premature abstraction | SUGGESTION |\n| Compatibility shim | BACKLOG |\n\nInclude the additive bias score and Iron Law status in\nthe Phase 6 report.\n\n### Phase 4.6: Invariant Conflict Detection\n\nCheck whether the PR touches existing design invariants.\nThis is a judgment problem that models get wrong far too\noften — surface conflicts for human review rather than\nsilently accepting or rejecting them.\n\n**Quick detection heuristic:**\n\n1. Do changed files cross module boundaries that\n   previously didn't interact?\n2. Do changes introduce a new pattern alongside an\n   existing one (two ways to do the same thing)?\n3. Do interface/type/schema files change shape?\n4. Do data flow directions change?\n5. Are ADR-documented decisions being contradicted?\n\n```bash\n# Check for structural pattern changes\ngit diff --name-only HEAD...origin/master 2>/dev/null \\\n  | rg \"(interface|types|schema|model|base|core|contract)\" \\\n  || git diff --name-only HEAD...origin/master 2>/dev/null \\\n  | grep -E \"(interface|types|schema|model|base|core|contract)\"\n```\n\n**When a conflict is detected:**\n\nDo NOT resolve it. Add to the report as a special\ncategory:\n\n| Category | Definition | Action |\n|----------|------------|--------|\n| **INVARIANT** | Change conflicts with an existing design decision | Escalate to human with 3-option analysis |\n\n**For each invariant conflict, present:**\n\n1. **The invariant**: Name the design decision and why\n   it was made (reference ADRs if available)\n2. **The conflict**: What this PR does that clashes\n3. **Option A — Preserve**: Don't merge this change;\n   the invariant pays dividends elsewhere\n4. **Option B — Layer**: Merge as-is, accepting\n   inelegance; not every feature must be elegant\n5. **Option C — Revise**: The invariant is wrong;\n   here's what a redesign would look like\n\n**Classification:** INVARIANT findings are always\nBLOCKING — not because the code is wrong, but because\nthe judgment call requires human input. Only the human\nreviewer can decide which of the three options is right.\n\n**Why this matters:** Bad invariant decisions compound.\nA few wrong calls and the codebase becomes unsalvageable.\nThis is not a context problem solvable with better\ndocumentation — it is a judgment problem that requires\nhuman wisdom.\n\n### Phase 5: Backlog Triage\n\nFor each BACKLOG item, create an issue on the detected platform:\n\n```bash\n# GitHub\ngh issue create \\\n  --title \"[Tech Debt] Brief description\" \\\n  --body \"## Context\nIdentified during PR #<number> review.\n...\" \\\n  --label \"tech-debt\"\n\n# GitLab\nglab issue create \\\n  --title \"[Tech Debt] Brief description\" \\\n  --description \"## Context\nIdentified during MR !<number> review.\n...\" \\\n  --label \"tech-debt\"\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n**Ask user before creating:** \"I found N backlog items. Create issues? [y/n/select]\"\n\n### Phase 6: Generate Report\n\nStructure the report by classification. Every BLOCKING and\nIN-SCOPE finding MUST include educational insights per\n`modules/educational-insights.md`: **Why** (the principle),\n**Proof** (link to best practice), and a **Teachable Moment**\n(generalized lesson). SUGGESTION findings include Why and\noptionally Proof. BACKLOG items need only a brief rationale.\n\n```markdown\n## PR #X: Title\n\n### Scope Compliance\n**Requirements:** (from plan/spec)\n1. [x] Requirement A - Implemented\n2. [x] Requirement B - Implemented\n3. [ ] Requirement C - **Missing**\n\n### Blocking (1)\n1. [B1] SQL injection via string concatenation\n   - **Location**: `db/queries.py:89`\n   - **Issue**: User input interpolated directly into SQL\n   - **Why**: String-interpolated SQL allows attackers to\n     execute arbitrary queries (CWE-89). This is the #1\n     web application vulnerability per OWASP Top 10.\n   - **Proof**: [OWASP SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)\n   - **Teachable Moment**: Always use parameterized queries\n     or an ORM. This applies everywhere user input reaches\n     a database, cache, or search engine query.\n   - **Fix**: Use parameterized query:\n     `cursor.execute(\"SELECT * FROM t WHERE id = ?\", (uid,))`\n\n### In-Scope (1)\n1. [S1] Missing validation for edge case\n   - **Location**: `api.py:45`\n   - **Issue**: Empty input not handled per requirement\n   - **Why**: Defensive validation at API boundaries\n     prevents cascading failures in downstream logic.\n   - **Proof**: [Postel's Law](https://en.wikipedia.org/wiki/Robustness_principle)\n   - **Teachable Moment**: Validate inputs at system\n     boundaries (API handlers, CLI args, file parsers)\n     but trust internal function contracts.\n\n### Suggestions (1)\n1. [G1] Consider extracting helper function\n   - **Why**: The repeated pattern on lines 30-35 and\n     72-77 violates DRY. Extracting it reduces future\n     bug surface.\n   - Author's discretion\n\n### Backlog → GitHub Issues (3)\n1. #142 - Refactor authentication module\n2. #143 - Add caching layer\n3. #144 - Update deprecated dependency\n\n### Recommendation\n**APPROVE WITH CHANGES**\nAddress B1 and S1 before merge.\n```\n\n### Local Output (`--local`)\n\nWhen `--local [path]` is passed, write the Phase 6 report to a\nlocal `.md` file instead of posting via API. Default path:\n`.pr-review/pr-<number>-review.md`. The file includes the\nreview summary, test plan, and backlog items in a single\ndocument. Issue creation and PR description updates are skipped.\nKnowledge capture (Phase 7) still runs.\n\n### Phase 7: Knowledge Capture\n\nAfter generating the report, evaluate findings for knowledge capture into the project's review chamber.\n\n**Trigger:** Automatically for findings scoring ≥60 on evaluation criteria.\n\n```bash\n# Capture significant findings to review-chamber\n# Uses memory-palace:review-chamber evaluation framework\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n**Candidates for capture:**\n- BLOCKING findings with architectural context → `decisions/`\n- Recurring patterns seen in multiple PRs → `patterns/`\n- Quality standards and conventions → `standards/`\n- Post-mortem insights and learnings → `lessons/`\n\n**Output:** Add to report:\n```markdown\n### Knowledge Captured 📚\n\n| Entry ID | Title | Room |\n|----------|-------|------|\n| abc123 | JWT over sessions | decisions/ |\n| def456 | Token refresh pattern | patterns/ |\n\nView: `/review-room list --palace <project>`\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nSee `modules/knowledge-capture.md` for full workflow.\n\n## Quality Gates\n\nA PR should be approved when:\n- [ ] All stated requirements are implemented\n- [ ] No BLOCKING issues remain\n- [ ] IN-SCOPE issues are resolved or acknowledged\n- [ ] BACKLOG items are tracked as GitHub issues\n- [ ] Tests cover new code paths\n- [ ] Tests would fail if the fix were reverted (the revert test)\n- [ ] No obvious agent-generated code left uncurated\n- [ ] Author can explain how each changed section works and how\n      it could fail (understanding check, not just \"tests pass\")\n\n## Anti-Patterns to Avoid\n\n### Don't: Scope Creep Review\n> \"While you're here, you should also refactor X, add feature Y, and fix Z in adjacent files.\"\n\n**Do:** Create backlog issues, keep PR focused.\n\n### Don't: Perfect is Enemy of Good\n> \"This works but could be 5% more efficient with different approach.\"\n\n**Do:** If it meets requirements and has no bugs, it's ready.\n\n### Don't: Blocking on Style\n> \"I prefer tabs over spaces.\"\n\n**Do:** Use linters for style, reserve review for logic.\n\n### Don't: Reviewing Unchanged Code\n> \"The file you imported from has some issues...\"\n\n**Do:** That's a separate PR. Create an issue if important.\n\n### Don't: Tests That Prove Old Code Was Bad\n> \"Here's a test showing the old behavior was wrong.\"\n\n**Do:** Write tests that break if your fix is reverted.\nTests should protect against regressions in *your* code,\nnot document why the change was needed. See\n`modules/pr-hygiene.md` Principle 4.\n\n### Don't: Bundling Unrelated Changes\n> \"I also reformatted the file and fixed a typo in another module.\"\n\n**Do:** One PR = one logical change. Formatting, refactors,\nand unrelated fixes belong in separate PRs. See\n`modules/pr-hygiene.md` Principle 2.\n\n### Don't: Merge Code You Cannot Explain\n\n> \"It works and the tests pass.\"\n\nA PR where the author cannot explain how each changed section\nworks and how it might fail is not ready to merge. This is\nespecially true for AI-assisted code: generation speed creates\nthe illusion of understanding.\n\n**Do:** Before marking a PR ready, ask the reviewing agent to\nquestion you about the changed code — how each part works, what\nassumptions it makes, and what inputs would break it. Continue\nuntil you can answer without hesitation. Only merge code you\nown front-to-back.\n\nThis applies to self-reviews: run the same probe before\nrequesting external review. Do not submit a PR for review that\nyou yourself do not fully understand.\n\n## Integration with Other Tools\n\n- **`/fix-pr`**: After review identifies issues, use this to address them\n- **`/pr`**: To prepare a PR before review\n- **`pensive:unified-review`**: For the actual code analysis\n- **`pensive:bug-review`**: For deeper bug hunting if needed\n- **`scribe:slop-detector`**: For documentation AND commit message quality analysis\n- **`scribe:doc-generator`**: For PR description writing guidelines (slop-free)\n\n## Slop Detection Integration\n\n### Documentation Review\nFor all changed `.md` files, invoke `Skill(scribe:slop-detector)`:\n- Score ≥ 3.0: Flag as IN-SCOPE (should remediate)\n- Score ≥ 5.0: Flag as BLOCKING if `--strict` mode\n\n### Commit Message Review\nScan all PR commit messages for slop markers:\n```bash\ngh pr view <number> --json commits --jq '.commits[].messageBody' | \\\n  grep -iE 'leverage|seamless|comprehensive|delve|robust|utilize|facilitate'\n```\nIf slop found in commits: Add to SUGGESTION category with remediation guidance.\n\n### PR Description Review\nApply `scribe:slop-detector` to PR body:\n- Tier 1 words in description → SUGGESTION to rephrase\n- Marketing phrases (\"unlock potential\") → Flag for removal\n\n## Exit Criteria\n\n- Scope baseline established\n- All changes reviewed against scope\n- Findings classified correctly\n- Backlog items tracked as issues\n- Clear recommendation provided\n\n## Supporting Modules\n\n- [GitHub PR comment patterns](modules/github-comments.md) - `gh api` patterns for inline and summary PR comments\n\nFile v1.9.19:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-sanctum-pr-review\",\n  \"version\": \"1.9.19\",\n  \"publishedAt\": 1787750439575\n}\n\nFile v1.9.19:modules/comment-guidelines.md\n\n# Code Comment Quality Guidelines\n\nGuidance on when and how to write effective code comments that add value without bloat.\n\n## Core Philosophy: Why, Not What\n\nGood comments explain **why** code exists, not **what** it does. The code already shows what it does.\n\n| Comment Type | Value | Example |\n|--------------|-------|---------|\n| **Why** | High | \"Use exponential backoff to handle transient API failures\" |\n| **What** | Low | \"Loop through the array\" |\n| **Context** | High | \"AWS Lambda has 15-min timeout, so max 3 retries\" |\n| **Obvious** | Negative | \"Increment counter by 1\" |\n\n## When Comments Are Warranted\n\n### Require Comments For\n\n| Scenario | Reason | Example |\n|----------|--------|---------|\n| **Non-obvious behavior** | Future readers will wonder why | Edge case handling |\n| **Business logic decisions** | Domain knowledge not in code | \"Tax calculated per 2024 regulations\" |\n| **Performance optimizations** | Why this approach over simpler one | \"O(1) lookup vs O(n) iteration\" |\n| **Workarounds** | Temporary fixes need context | \"TODO: Remove after #123 fixed\" |\n| **Algorithm complexity** | Complex logic needs explanation | Mathematical formulas |\n| **External constraints** | Dependencies, APIs, limits | \"API rate limit: 100 req/min\" |\n\n### Don't Require Comments For\n\n| Scenario | Alternative |\n|----------|-------------|\n| Self-explanatory code | Good naming |\n| Simple CRUD operations | Patterns speak |\n| Well-named functions | Function name = documentation |\n| Standard patterns | Convention over comment |\n\n## Examples\n\n### Good Comments (Explain Why)\n\n```python\ndef retry_with_backoff(max_attempts=3):\n    \"\"\"Retry with exponential backoff for transient failures.\n\n    AWS Lambda has a 15-minute timeout, so max_attempts=3 prevents\n    exceeding this limit with our 1s/2s/4s backoff strategy.\n    \"\"\"\n    ...\n\n# Use set for O(1) membership testing instead of list O(n)\n# Critical for processing 100k+ items in batch jobs\nseen_ids = set()\n```\n\n### Bad Comments (Explain What - Avoid These)\n\n```python\n# Bad: Restates code\ni = 0  # Set i to 0\n\n# Bad: Obvious from code\nif user_input == \"\":  # Check if user_input is empty string\n    return DEFAULT_VALUE\n\n# Bad: Redundant docstring\ndef add(a, b):\n    \"\"\"Add two numbers and return the result.\"\"\"\n    return a + b\n```\n\n## Anti-Patterns\n\n### Over-Commenting (Bloat)\n\n**Problem**: Too many comments obscure code and become maintenance burden.\n\n**Symptoms**:\n- Comment-to-code ratio > 1:3\n- Comments on every line\n- Comments restating variable names\n\n**Solution**: Improve code clarity instead. Better names, smaller functions.\n\n### Stale Comments (Out of Sync)\n\n**Problem**: Comments that don't match current code behavior are worse than no comments.\n\n**Symptoms**:\n- Function behavior changed, comment didn't\n- TODO comments for completed work\n- References to deleted code\n\n**Solution**: Update comments with code changes. Delete outdated TODOs.\n\n### Commented-Out Code\n\n**Problem**: Dead code clutters codebase and confuses readers.\n\n**Solution**: Delete it. Git preserves history.\n\n## Docstring Conventions\n\n### When Required\n\n- Public functions/methods\n- Classes with non-obvious purpose\n- Modules with significant complexity\n\n### Format (Python)\n\n```python\ndef process_order(order: Order, apply_discount: bool = False) -> Receipt:\n    \"\"\"Process an order and generate a receipt.\n\n    Validates inventory, applies pricing rules, and records transaction.\n\n    Args:\n        order: The order to process.\n        apply_discount: Whether to apply member discount (default: False).\n\n    Returns:\n        Receipt with itemized charges and total.\n\n    Raises:\n        InsufficientStockError: If any item is out of stock.\n        PaymentFailedError: If payment processing fails.\n    \"\"\"\n```\n\n### Format (TypeScript)\n\n```typescript\n/**\n * Process an order and generate a receipt.\n *\n * Validates inventory, applies pricing rules, and records transaction.\n *\n * @param order - The order to process\n * @param applyDiscount - Whether to apply member discount\n * @returns Receipt with itemized charges and total\n * @throws InsufficientStockError if any item is out of stock\n */\nfunction processOrder(order: Order, applyDiscount = false): Receipt {\n```\n\n## Review Checklist\n\nWhen reviewing code comments:\n\n- [ ] Comments explain WHY, not WHAT\n- [ ] No redundant comments restating code\n- [ ] Complex logic is documented\n- [ ] Business rules have context\n- [ ] No stale/outdated comments\n- [ ] No commented-out code\n- [ ] Public APIs have docstrings\n- [ ] TODOs have issue references\n\n## Integration with KISS/YAGNI\n\nFrom `conserve:code-quality-principles`:\n\n- **KISS**: If code needs extensive comments to understand, simplify the code\n- **YAGNI**: Don't comment for hypothetical future readers - comment for current needs\n\n## Summary\n\n| Situation | Action |\n|-----------|--------|\n| Simple, clear code | No comment needed |\n| Non-obvious behavior | Comment the WHY |\n| Business logic | Document the rule source |\n| Complex algorithm | Explain approach/tradeoffs |\n| Workaround | Note why and when to remove |\n| Dead code | Delete, don't comment out |\n\nFile v1.9.19:modules/educational-insights.md\n\n---\nname: educational-insights\ndescription: >-\n  Enrich PR review findings with educational context:\n  why the fix matters, proof via best-practice links,\n  and teachable moments that grow the implementer.\nparent_skill: sanctum:pr-review\ncategory: review-infrastructure\ntags: [education, insights, best-practices, teaching]\nestimated_tokens: 300\n---\n\n# Educational Insights for PR Review Findings\n\nEvery finding in a PR review is a learning opportunity.\nEach reported issue, suggestion, or error MUST include\neducational context so the review improves both the code\nand the person who wrote it.\n\n## The Three Pillars\n\nEach finding includes three educational elements:\n\n| Pillar | Purpose | Content |\n|--------|---------|---------|\n| **Why It Matters** | Explain the principle | 1-2 sentences on the underlying concept |\n| **Proof** | Link to authoritative source | URL to docs, standard, or guide |\n| **Teachable Moment** | Generalize the lesson | How this pattern applies beyond this PR |\n\n## Enriched Finding Format\n\nEvery finding entry (BLOCKING, IN-SCOPE, SUGGESTION)\nMUST use this extended format:\n\n```markdown\n1. [S1] Missing input validation on user-supplied path\n   - **Location**: `api/handlers.py:45`\n   - **Issue**: Path traversal possible via `../` in filename\n   - **Why**: Unsanitized file paths allow directory traversal\n     attacks (CWE-22). An attacker can read or overwrite\n     files outside the intended directory.\n   - **Proof**: [OWASP Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal)\n   - **Teachable Moment**: Always normalize paths with\n     `os.path.realpath()` and verify they stay within the\n     expected root. This applies to any function accepting\n     file paths from external input.\n   - **Fix**:\n     ```python\n     real = os.path.realpath(user_path)\n     if not real.startswith(allowed_root):\n         raise ValueError(\"Path outside allowed directory\")\n     ```\n```\n\n## How to Source Proof Links\n\nUse authoritative references in this priority order:\n\n1. **Language/framework docs** (python.org, docs.rs,\n   developer.mozilla.org)\n2. **Security standards** (OWASP, CWE, NIST)\n3. **Style guides** (PEP 8, Google Style Guide, Effective Go)\n4. **Well-known articles** (Martin Fowler, Dan Abramov,\n   Kent Beck)\n5. **RFCs and specifications** (IETF RFCs, W3C specs)\n\nWhen no authoritative URL exists, cite the principle by\nname (e.g., \"Liskov Substitution Principle\") and briefly\nexplain it inline.\n\n## Insight Depth by Classification\n\n| Classification | Insight Depth | Proof Required |\n|---------------|--------------|----------------|\n| **BLOCKING** | Full (why, impact, and fix) | Yes, with link |\n| **IN-SCOPE** | Standard (why and fix) | Yes, with link |\n| **SUGGESTION** | Brief (why and alternative) | Optional |\n| **BACKLOG** | One-liner rationale | No |\n\nBLOCKING and IN-SCOPE findings always include proof links.\nSUGGESTION findings include them when a well-known source\nexists. BACKLOG items need only a brief rationale since\nthey become separate issues with their own context.\n\n## Anti-Patterns\n\n### Don't: Lecture Without Context\n> \"You should use `pathlib` instead of `os.path`.\"\n\n**Do:** Explain why:\n> \"`pathlib` provides object-oriented path handling that\n> prevents string concatenation bugs (PEP 428). It also\n> makes path operations cross-platform by default.\"\n\n### Don't: Link Without Explaining\n> \"See https://owasp.org/...\"\n\n**Do:** Summarize what the link teaches:\n> \"OWASP classifies this as CWE-22 (Path Traversal).\n> The linked guide shows three defense layers:\n> canonicalization, allowlisting, and sandboxing.\"\n\n### Don't: Over-Teach on Trivial Findings\n> [Three paragraphs explaining why a typo matters]\n\n**Do:** Match depth to severity. A typo fix needs one line,\nnot a lecture.\n\n## Integration with Phase 6 Report\n\nThe Phase 6 report template already groups findings by\nclassification. Educational insights are embedded inline\nwithin each finding, not in a separate section. This\nkeeps the insight next to the code it explains, making\nthe review scannable and the lessons immediately visible.\n\n## Exit Criteria\n\n- [ ] Every BLOCKING finding has Why + Proof + Teachable Moment\n- [ ] Every IN-SCOPE finding has Why + Proof\n- [ ] SUGGESTION findings have Why (Proof if available)\n- [ ] Proof links are to authoritative, stable URLs\n- [ ] Insights explain the principle, not just the symptom\n\nFile v1.9.19:modules/github-comments.md\n\n# GitHub PR Comment Patterns\n\nReusable patterns for posting comments to GitHub PRs via the `gh` CLI.\n\n## Key API Differences\n\n| Endpoint | Use Case | Notes |\n|----------|----------|-------|\n| `gh pr comment` | General PR comments | Simple, always works |\n| `gh api .../reviews` | Inline comments on diff lines | Use `-F` for integers |\n| `gh pr review` | Summary with approve/request changes | Final submission |\n\n## Common Mistakes\n\n### Wrong: Individual Comments Endpoint with `line` parameter\n```bash\n# This will FAIL with HTTP 422\ngh api repos/{owner}/{repo}/pulls/{pr}/comments \\\n  -X POST \\\n  -f path='file.rs' \\\n  -f line=63 \\  # ERROR: \"line\" is not a permitted key\n  -f body='Comment'\n```\n\n### Right: Reviews Endpoint with Comments Array\n```bash\n# This works correctly\ngh api repos/{owner}/{repo}/pulls/{pr}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"Review summary\" \\\n  -f 'comments[][path]=file.rs' \\\n  -F 'comments[][line]=63' \\  # Use -F for integers!\n  -f 'comments[][body]=Inline comment text'\n```\n\n## Pattern: Single Inline Comment\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"See inline comment.\" \\\n  -f 'comments[][path]=src/auth/jwt.rs' \\\n  -F 'comments[][line]=63' \\\n  -f 'comments[][side]=RIGHT' \\\n  -f 'comments[][body]=**[IN-SCOPE]** JWT secondary secret\n\nThis fallback secret poses a security risk.\n\n**Recommendation:** Fail-fast on missing JWT_SECRET.'\n```\n\n## Pattern: Multiple Inline Comments\n\nFor multiple comments, use JSON input via `--input -`:\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  --input - <<'EOF'\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Review with inline comments\",\n  \"comments\": [\n    {\n      \"path\": \"src/auth.rs\",\n      \"line\": 26,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[IN-SCOPE]** Basic email validation\"\n    },\n    {\n      \"path\": \"src/routes.rs\",\n      \"line\": 45,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[SUGGESTION]** Consider rate limiting\"\n    }\n  ]\n}\nEOF\n```\n\n**Note:** The indexed array syntax (`comments[0][path]`) does NOT work with `gh api` - it creates an object instead of an array. Always use JSON input for multiple comments.\n\n## Pattern: General PR Comment (Not Inline)\n\nFor findings not on diff lines or when inline fails:\n\n```bash\ngh pr comment $PR_NUMBER --body '## Detailed Findings\n\n### IN-SCOPE (Should fix before merge)\n\n#### 1. JWT Fallback Secret (`src/auth/jwt.rs:62-63`)\n**Risk**: If deployed without `JWT_SECRET`, tokens use known secret.\n**Fix**: Fail-fast on missing secret.\n\n#### 2. Basic Email Validation (`src/routes/auth.rs:26`)\n**Risk**: Accepts invalid emails like `@@` or `test@`.\n**Fix**: Use proper email validation.'\n```\n\n## Pattern: Submit Review with Summary\n\n```bash\n# Determine event based on findings\nEVENT=\"COMMENT\"  # or \"REQUEST_CHANGES\" or \"APPROVE\"\n\ngh pr review $PR_NUMBER \\\n  --event $EVENT \\\n  --body \"$(cat <<'EOF'\n## PR Review Summary\n\n### Blocking Issues (2)\n- [B1] Missing token validation (auth.py:45)\n- [B2] SQL injection risk (models.py:123)\n\n### Suggestions (3)\n- See inline comments for details\n\n**Action Required:** Address blocking issues before merge.\nEOF\n)\"\n```\n\n## Secondary Strategy\n\nWhen inline comments fail (line not in diff, API issues):\n\n1. **Try inline first** via reviews API\n2. **On failure, fall back to PR comment** with file:line reference in body\n3. **Always post a summary comment** with all findings aggregated\n\n```bash\n# Secondary: Post as regular comment with location reference\ngh pr comment $PR_NUMBER --body \"**[B1] Issue at src/auth.rs:45**\n\nThis line was not in the PR diff, but the issue was identified during review.\n\nIssue: Missing validation\nSeverity: BLOCKING\nFix: Add input sanitization\"\n```\n\n## Extracting Owner/Repo\n\n```bash\n# From remote URL\nREMOTE_URL=$(git remote get-url origin)\nOWNER_REPO=$(echo \"$REMOTE_URL\" | sed -E 's/.*github\\.com[:/]([^/]+\\/[^/.]+).*/\\1/')\nOWNER=$(echo \"$OWNER_REPO\" | cut -d'/' -f1)\nREPO=$(echo \"$OWNER_REPO\" | cut -d'/' -f2)\n\n# Or from gh CLI\ngh repo view --json owner,name --jq '\"\\(.owner.login)/\\(.name)\"'\n```\n\n## Getting Commit SHA for Comments\n\n```bash\n# Get HEAD commit of the PR\nCOMMIT_SHA=$(gh pr view $PR_NUMBER --json headRefOid --jq '.headRefOid')\n\n# Or get the latest commit\nCOMMIT_SHA=$(gh pr view $PR_NUMBER --json commits --jq '.commits[-1].oid')\n```\n\nFile v1.9.19:modules/insight-generation.md\n\n---\nname: insight-generation\ndescription: Post PR-scoped insights to GitHub Discussions\n---\n\n## PR Insight Generation\n\nAfter completing the PR review analysis, generate insights\nfrom the review findings and post them to Discussions.\n\n### When to Run\n\nRun this module AFTER the main review is complete and\nfindings have been documented. Only generate insights for\nfindings with severity \"high\" or \"medium\".\n\n### Process\n\n1. Collect review findings from the current PR analysis\n2. For each high/medium finding, create a Finding object:\n\n```bash\ncd /home/alext/claude-night-market\npython3 -c \"\nimport sys, json\nsys.path.insert(0, 'plugins/abstract/scripts')\nfrom insight_types import Finding\nfrom post_insights_to_discussions import post_findings\n\nfindings = [\n    Finding(\n        type='PR Finding',\n        severity='$SEVERITY',\n        skill='',\n        summary='PR #$PR_NUMBER: $FINDING_SUMMARY',\n        evidence='$EVIDENCE',\n        recommendation='$RECOMMENDATION',\n        source='pr-review',\n        related_files=$CHANGED_FILES,\n    )\n]\nurls = post_findings(findings)\nfor url in urls:\n    print(f'Posted: {url}')\n\"\n```\n\n3. The posting script handles all dedup automatically\n4. Report posted URLs in the review summary\n\n### Finding Types\n\nMap review categories to insight types:\n\n| Review Category | Insight Type |\n|----------------|-------------|\n| Security issue | `[Bug Alert]` |\n| Logic error | `[Bug Alert]` |\n| Performance concern | `[Optimization]` |\n| Code quality | `[Improvement]` |\n| Test gap | `[PR Finding]` |\n| Architecture issue | `[PR Finding]` |\n\nFile v1.9.19:modules/knowledge-capture.md\n\n# Knowledge Capture Module\n\nCapture significant PR review findings into the project's review chamber.\n\n## Integration Point\n\nThis module executes **after Phase 6 (Generate Report)** and **before posting to GitHub**.\n\n```\nPhase 6: Generate Report\n    ↓\n[KNOWLEDGE CAPTURE MODULE]\n    ↓\nPhase 7: Post to GitHub\n```\n\n## Trigger Conditions\n\nEvaluate knowledge capture when:\n\n1. Review contains BLOCKING findings with architectural context\n2. Review contains recurring patterns (seen in 2+ PRs)\n3. Review establishes new conventions or standards\n4. Review documents a significant decision with rationale\n\n## Capture Workflow\n\n### Step 1: Extract Capture Candidates\n\nFrom the review findings, identify candidates for knowledge capture:\n\n```python\ndef extract_candidates(findings, pr_info):\n    \"\"\"Identify findings worth capturing.\"\"\"\n    candidates = []\n\n    for finding in findings:\n        # Score using evaluation criteria\n        score = evaluate_finding(finding, pr_info)\n\n        if score >= 60:\n            candidates.append({\n                \"finding\": finding,\n                \"score\": score,\n                \"room_type\": classify_room_type(finding),\n            })\n\n    return candidates\n```\n\n### Step 2: Classify Room Type\n\nRoute each candidate to the appropriate review-chamber room:\n\n| Finding Characteristics | Target Room |\n|------------------------|-------------|\n| Architectural decision with rationale | `decisions/` |\n| Recurring pattern or solution | `patterns/` |\n| Quality standard or convention | `standards/` |\n| Post-mortem insight or learning | `lessons/` |\n\n### Step 3: Create Review Entries\n\nFor each approved candidate:\n\n```yaml\n---\nsource_pr: \"#42 - Add authentication\"\ndate: 2025-01-15\nparticipants: [author, reviewers...]\npalace_location: review-chamber/decisions\ntags: [authentication, jwt, security]\n---\n\n## Decision Title\n\n### Decision\n[What was decided]\n\n### Context\n[Discussion that led to decision]\n\n### Captured Knowledge\n- Pattern: [reusable pattern]\n- Tradeoff: [key tradeoffs]\n- Application: [where to apply]\n\n### Connected\n- [[related-room]] - connection type\n```\n\n### Step 4: User Confirmation\n\nBefore capturing, present candidates to user:\n\n```markdown\n## 📚 Knowledge Capture\n\nFound **3** findings worth capturing to review-chamber:\n\n| # | Title | Score | Room | Action |\n|---|-------|-------|------|--------|\n| 1 | JWT over sessions | 95 | decisions | Capture |\n| 2 | API error format | 77 | standards | Capture |\n| 3 | Missing null check | 25 | - | Skip |\n\n**Options:**\n- [Y] Capture all (2 findings)\n- [S] Select which to capture\n- [N] Skip knowledge capture\n- [E] Edit before capture\n```\n\n### Step 5: Store in Project Palace\n\n```python\nfrom memory_palace.project_palace import (\n    ProjectPalaceManager,\n    ReviewEntry,\n    capture_pr_review_knowledge,\n)\n\ndef store_findings(findings, pr_info):\n    \"\"\"Store findings in project palace.\"\"\"\n\n    # Get or create project palace\n    manager = ProjectPalaceManager()\n    palace = manager.get_or_create_project_palace(\n        repo_name=pr_info.repo,\n        repo_url=pr_info.repo_url,\n    )\n\n    # Create entries for each finding\n    created = []\n    for finding in findings:\n        entry = ReviewEntry(\n            source_pr=f\"#{pr_info.number} - {pr_info.title}\",\n            title=finding.title,\n            room_type=finding.room_type,\n            content={\n                \"decision\": finding.description,\n                \"context\": finding.context,\n                \"captured_knowledge\": {\n                    \"severity\": finding.severity,\n                    \"category\": finding.category,\n                    \"file\": finding.file,\n                    \"line\": finding.line,\n                },\n                \"connected_concepts\": finding.related,\n            },\n            participants=pr_info.participants,\n            tags=finding.tags,\n        )\n\n        if manager.add_review_entry(palace[\"id\"], entry):\n            created.append(entry.id)\n\n    return created\n```\n\n## Output Integration\n\nAdd knowledge capture summary to the review report:\n\n```markdown\n## PR #42: Add Authentication\n\n### Scope Compliance\n...\n\n### Blocking Issues\n...\n\n### In-Scope Issues\n...\n\n### Knowledge Captured 📚\n\nThe following findings were stored in the project's review chamber:\n\n| Entry ID | Title | Room |\n|----------|-------|------|\n| abc123 | JWT over sessions | decisions/ |\n| def456 | Token refresh pattern | patterns/ |\n\nView in palace: `python scripts/palace_manager.py list-reviews --palace project-id`\n```\n\n## CLI Integration\n\n### Automatic (Default)\n\nWhen running `/pr-review`, knowledge capture triggers automatically for high-scoring findings:\n\n```bash\n/pr-review 42\n# ... review output ...\n# → Knowledge Capture: Captured 2 findings to review-chamber\n```\n\n### Manual Override\n\n```bash\n# Skip knowledge capture\n/pr-review 42 --no-capture\n\n# Force capture all findings\n/pr-review 42 --capture-all\n\n# Review and select interactively\n/pr-review 42 --capture-interactive\n```\n\n### Retroactive Capture\n\nCapture knowledge from a past review:\n\n```bash\n/review-room capture 42\n# Fetches PR #42 review comments and extracts knowledge\n```\n\n## Configuration\n\nIn `memory-palace/config/settings.json`:\n\n```json\n{\n  \"review_chamber\": {\n    \"auto_capture\": true,\n    \"capture_threshold\": 60,\n    \"require_confirmation\": true,\n    \"default_rooms\": [\"decisions\", \"patterns\", \"standards\", \"lessons\"],\n    \"excluded_categories\": [\"typo\", \"formatting\", \"style\"]\n  }\n}\n```\n\n## Evaluation Criteria\n\nUses `memory-palace:review-chamber` evaluation framework:\n\n| Criterion | Weight | Description |\n|-----------|--------|-------------|\n| Novelty | 25% | Is this new knowledge? |\n| Applicability | 30% | Will this affect future PRs? |\n| Durability | 20% | Architectural vs tactical? |\n| Connectivity | 15% | Links to existing knowledge? |\n| Authority | 10% | Expert reviewer involved? |\n\n**Threshold:** Score ≥ 60 triggers capture consideration.\n\n## Dependencies\n\n- `memory-palace:project-palace` - Project palace management\n- `memory-palace:review-chamber` - Room structure and evaluation\n- `memory-palace:knowledge-intake` - Evaluation framework\n\nFile v1.9.19:modules/pr-hygiene.md\n\n# PR Hygiene: Four Principles\n\nResearch-backed practices for PR quality that apply to\nevery review. These checks run during scope establishment\n(Phase 1) and code quality analysis (Phase 2.5).\n\n> **See Also**: [Main Skill](../SKILL.md) |\n> [Review Framework](../../../commands/pr-review/modules/review-framework.md)\n\n## Principle 1: Self-Review Before Sending\n\nOpen your own PR in the diff view and read it as if you\nare a reviewer seeing it for the first time. This catches\nscope creep, formatting commits, and unclear changes\nbefore anyone else spends time on them.\n\n### Detection (during `/pr-review`)\n\nWhen reviewing a PR, check for signs the author skipped\nself-review:\n\n```bash\n# Check for formatting-only commits mixed with feature work\ngh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -iE '(fmt|format|lint|style|whitespace|cleanup)' \\\n  && echo \"WARNING: Formatting commits mixed with feature work\"\n\n# Check for fixup/amend commits that should have been squashed\ngh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -iE '(fixup|fix typo|oops|wip|forgot|actually)' \\\n  && echo \"WARNING: Unsquashed fixup commits suggest no self-review\"\n```\n\n### Classification\n\n| Signal | Severity | Action |\n|--------|----------|--------|\n| Formatting-only commits mixed with feature work | SUGGESTION | Recommend squash or split |\n| 3+ fixup/typo commits | SUGGESTION | Recommend self-review pass |\n| Debug code left in (`console.log`, `print()`, `TODO`) | IN-SCOPE | Should remove before review |\n| Commented-out code blocks | IN-SCOPE | Should clean up |\n\n### Guidance for `/pr-prep` (Self-Review Checklist)\n\nBefore sending the PR, the author should verify:\n\n- [ ] Read the diff as a reviewer would\n- [ ] No debug statements left in\n- [ ] No commented-out code\n- [ ] No formatting-only commits mixed with logic changes\n- [ ] No fixup commits that should be squashed\n- [ ] Changes are limited to what the PR description promises\n\n## Principle 2: One PR = One Logical Change\n\nThe Single Responsibility Principle for PRs. Small,\nfocused PRs get reviewed faster, get reviewed more\nthoroughly (75%+ defect detection vs 30% for large PRs),\nand are easier to revert if something goes wrong.\n\n### Detection (during Phase 1: Scope Establishment)\n\nAnalyze commit messages and changed files for mixed\nconcerns:\n\n```bash\n# Count distinct conventional commit types\nCOMMIT_TYPES=$(gh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -oE '^(feat|fix|refactor|docs|test|chore|style|perf)' | \\\n  sort -u | wc -l)\n\nif [[ \"$COMMIT_TYPES\" -gt 2 ]]; then\n  echo \"WARNING: $COMMIT_TYPES distinct commit types - possible mixed concerns\"\nfi\n\n# Check for unrelated directory changes\nCHANGED_DIRS=$(gh pr diff $PR_NUMBER --name-only | \\\n  awk -F/ '{print $1\"/\"$2}' | sort -u | wc -l)\n\n# Large PRs with many unrelated directories\nCHANGED_FILES=$(gh pr view $PR_NUMBER --json changedFiles \\\n  --jq '.changedFiles')\n\nif [[ \"$CHANGED_FILES\" -gt 30 ]]; then\n  echo \"WARNING: $CHANGED_FILES files changed - consider splitting\"\nfi\n```\n\n### Atomicity Signals\n\n| Signal | Severity | Threshold |\n|--------|----------|-----------|\n| Mixed commit types (feat, refactor, and fix) | SUGGESTION | >2 distinct types |\n| Large file count | SUGGESTION | >30 files |\n| Mixed concerns across unrelated subsystems | IN-SCOPE | Subjective, reviewer judgment |\n| Refactor bundled with feature | SUGGESTION | Any occurrence |\n| Formatting changes bundled with logic | SUGGESTION | Any occurrence |\n\n### Classification\n\n- **BLOCKING**: Never. Splitting a PR is the author's\n  judgment call, not a gate.\n- **IN-SCOPE**: When mixed concerns are obvious and the\n  split would be straightforward (e.g., a `cargo fmt`\n  commit bundled with a feature).\n- **SUGGESTION**: When the PR is large but logically\n  coherent, note the size for awareness.\n\n### Recommendation Template\n\nWhen atomicity concerns are found:\n\n```markdown\n**[G-ATOMICITY] Consider splitting this PR**\n\nThis PR contains N distinct concerns:\n1. [concern A] (files: ...)\n2. [concern B] (files: ...)\n\nSmaller PRs get reviewed more thoroughly (75%+ defect\ndetection rate vs 30% for large PRs) and are easier to\nrevert. Consider splitting into:\n- PR 1: [concern A]\n- PR 2: [concern B]\n\nAuthor's discretion - this is a suggestion, not a blocker.\n```\n\n## Principle 3: Agent-Generated Code Needs Human Curation\n\nAI coding tools produce code quickly, but the output\nneeds careful review for: redundant code, unnecessary\ncomplexity, incomplete refactors, and scope drift.\nFormatting commits and mixed-concern refactors are\ntelltale signs of iterative AI generation without a\nfinal cleanup pass.\n\n### Detection (during Phase 2.5: Code Quality)\n\nLook for patterns characteristic of AI-generated code\nthat was not curated by a human before submission.\n\n#### Tier 1: Structural checks (always run)\n\n```bash\n# 1. Wrapper functions (function body is a single call)\n# Agent pattern: create_user() just calls _do_create_user()\ngh pr diff $PR_NUMBER | \\\n  awk '/^\\+.*def |^\\+.*fn |^\\+.*function /{name=$0; getline; \\\n  if(/^\\+\\s*(return |self\\.)/ && !/^\\+\\s*$/) print name \" -> WRAPPER?\"}' \\\n  2>/dev/null || true\n\n# 2. Redundant implementations (same logic, different names)\ngh pr diff $PR_NUMBER | \\\n  grep -E '^\\+.*(def |fn |function |func )' | \\\n  awk '{print $NF}' | sort | uniq -d\n\n# 3. Over-abstraction signals\n# New interfaces/traits/protocols with single implementations\nNEW_ABSTRACTIONS=$(gh pr diff $PR_NUMBER | \\\n  grep -cE '^\\+.*(trait |interface |protocol |abstract class )' || true)\nif [[ \"$NEW_ABSTRACTIONS\" -gt 0 ]]; then\n  echo \"CHECK: $NEW_ABSTRACTIONS new abstractions - verify each has 2+ implementations\"\nfi\n\n# 4. Incomplete refactors\n# Old function still called after new replacement added\nNEW_FUNCS=$(gh pr diff $PR_NUMBER | \\\n  grep -E '^\\+.*(def |fn |function )' | \\\n  sed 's/.*\\(def\\|fn\\|function\\) \\+\\([a-zA-Z_]*\\).*/\\2/' | head -10)\nfor func in $NEW_FUNCS; do\n  OLD_VARIANT=$(echo \"$func\" | sed 's/new_//;s/_v2$//;s/_updated$//')\n  if [[ \"$OLD_VARIANT\" != \"$func\" ]]; then\n    STILL_CALLED=$(gh pr diff $PR_NUMBER | grep -c \"$OLD_VARIANT\" || true)\n    if [[ \"$STILL_CALLED\" -gt 0 ]]; then\n      echo \"INCOMPLETE REFACTOR? $func replaces $OLD_VARIANT but old version still referenced\"\n    fi\n  fi\ndone\n```\n\n#### Tier 2: Diff-ratio checks (run for PRs > 10 files)\n\n```bash\n# 5. Addition-heavy ratio (agents add more than they remove)\nSTATS=$(gh pr view $PR_NUMBER --json additions,deletions \\\n  --jq '\"\\(.additions) \\(.deletions)\"')\nADDITIONS=$(echo $STATS | cut -d' ' -f1)\nDELETIONS=$(echo $STATS | cut -d' ' -f2)\n\nif [[ \"$DELETIONS\" -gt 0 ]]; then\n  RATIO=$((ADDITIONS / DELETIONS))\n  if [[ \"$RATIO\" -gt 5 ]]; then\n    echo \"CHECK: Add/delete ratio $RATIO:1 - agents tend to add without removing\"\n  fi\nfi\n\n# 6. Import bloat (new imports that may be unused)\nADDED_IMPORTS=$(gh pr diff $PR_NUMBER | \\\n  grep -cE '^\\+.*(^import |^from .* import |^use |require\\()' || true)\nif [[ \"$ADDED_IMPORTS\" -gt 10 ]]; then\n  echo \"CHECK: $ADDED_IMPORTS new imports - verify none are unused\"\nfi\n\n# 7. Scope drift via directory spread\nCHANGED_DIRS=$(gh pr diff $PR_NUMBER --name-only | \\\n  awk -F/ 'NF>1{print $1\"/\"$2}' | sort -u)\nDIR_COUNT=$(echo \"$CHANGED_DIRS\" | wc -l)\nif [[ \"$DIR_COUNT\" -gt 5 ]]; then\n  echo \"CHECK: Changes span $DIR_COUNT directories:\"\n  echo \"$CHANGED_DIRS\"\nfi\n```\n\n#### Tier 3: Content-level checks (reviewer judgment)\n\nThese cannot be fully automated. The reviewer should\nmanually check for:\n\n- **Boilerplate inflation**: Does the PR add config\n  files, CI changes, or documentation that is not\n  required by the stated goal?\n- **Defensive over-engineering**: Are there error\n  handlers for conditions that cannot happen? Try/catch\n  blocks wrapping infallible operations?\n- **Naming inconsistency**: Do new functions follow\n  existing naming conventions, or do they introduce a\n  different style (camelCase vs snake_case, different\n  prefix patterns)?\n- **Comment density spike**: Agent-generated code\n  often has more comments per line than human code.\n  If the PR's comment density is notably higher than\n  the surrounding code, flag it.\n\n### Agent Code Curation Signals\n\n| Signal | What to look for | Severity |\n|--------|-----------------|----------|\n| Redundant implementations | Functions doing the same thing with different names | IN-SCOPE |\n| Premature abstraction | New trait/interface with exactly one implementation | SUGGESTION |\n| Incomplete refactor | Old code path still exists alongside the new one | IN-SCOPE |\n| Over-engineered error handling | Catch-all handlers, unnecessary Result wrapping | SUGGESTION |\n| Unnecessary wrapper functions | Function that just calls another function | SUGGESTION |\n| Scope drift | Changes to files unrelated to the stated goal | IN-SCOPE |\n| Formatting commit bundled with logic | `cargo fmt` or `ruff format` in same PR as feature | SUGGESTION |\n| Config/boilerplate bloat | New config files, CI changes unrelated to feature | SUGGESTION |\n\n### Recommendation Template\n\nWhen agent curation issues are found:\n\n```markdown\n**[G-CURATION] Agent-generated code needs cleanup pass**\n\nThis PR shows signs of iterative AI generation without\na final curation pass:\n\n- [specific finding 1]\n- [specific finding 2]\n\nRecommendation: Review the PR with fresh eyes, asking\n\"does every change here serve the stated goal?\" Remove\nredundant code, collapse unnecessary abstractions, and\nsplit unrelated changes into separate PRs.\n```\n\n### Integration with Anti-Slop (Phase 1.7)\n\nAgent curation overlaps with slop detection but targets\n*structural* issues rather than *prose* issues:\n\n- **Slop detection** (Phase 1.7): AI markers in prose,\n  documentation, and commit messages\n- **Agent curation** (Phase 2.5): AI patterns in code\n  structure, architecture, and implementation choices\n\nBoth should run. Slop detection catches the writing;\nagent curation catches the engineering.\n\n## Principle 4: Tests Should Test Your Code\n\nTests should break if someone reverts your fix, not\ndemonstrate why the fix was needed. Assertion blocks\nshowing unrelated functionality are documentation,\nnot regression protection.\n\n### Detection (during Phase 2.5 and Test Plan)\n\nAnalyze test files changed in the PR:\n\n```bash\n# Get test files in the PR\nTEST_FILES=$(gh pr diff $PR_NUMBER --name-only | \\\n  grep -E '(test_|_test\\.|\\.test\\.|\\.spec\\.)')\n\n# Check for tests that only assert existing behavior\n# without connecting to the changed code\nfor file in $TEST_FILES; do\n  # Look for assertions about code NOT changed in this PR\n  gh pr diff $PR_NUMBER -- \"$file\" | \\\n    grep -E '^\\+.*assert' | head -10\ndone\n```\n\n### Test Quality Signals\n\n| Signal | What it means | Severity |\n|--------|--------------|----------|\n| Tests only assert pre-existing behavior | Demonstrating the problem, not protecting the fix | IN-SCOPE |\n| No tests touch code changed in this PR | Tests don't protect against regression | IN-SCOPE |\n| Tests pass with the fix reverted | Tests don't actually verify the fix | BLOCKING |\n| Test names describe old behavior, not new | Naming suggests documentation, not verification | SUGGESTION |\n| Assertion count >> code change size | Over-testing existing behavior | SUGGESTION |\n\n### The Revert Test\n\nThe gold standard for test quality: if someone reverts\nthe fix, at least one test should fail. If no test\nfails on revert, the tests are documentation, not\nprotection.\n\n```bash\n# Mental model for each test:\n# 1. Does this test touch code changed in this PR?\n# 2. Would reverting the PR changes cause this test to fail?\n# 3. If not, what regression does this test actually prevent?\n```\n\n### Classification\n\n- **BLOCKING**: Tests that pass even when the fix is\n  reverted (they test nothing about the new code)\n- **IN-SCOPE**: Tests that only assert old behavior\n  without covering the new code path\n- **SUGGESTION**: Tests that work but could be more\n  targeted or better named\n\n### Recommendation Template\n\nWhen test quality issues are found:\n\n```markdown\n**[S-TESTS] Tests should protect against regressions**\n\nThe following tests don't break if someone reverts this\nPR's changes:\n\n- `test_existing_behavior` in `test_module.py`\n  Asserts pre-existing behavior unrelated to the fix.\n\nWrite tests that:\n1. Would FAIL if the fix is reverted\n2. Cover the specific code path changed in this PR\n3. Protect against the exact regression being fixed\n\nTests should answer: \"what breaks if someone undoes my\nchange?\" not \"what was wrong before my change?\"\n```\n\n## Integration Checklist\n\nWhen this module is loaded, the following checks are\nadded to the review workflow:\n\n### Phase 1 (Scope Establishment)\n- [ ] Check PR atomicity (Principle 2)\n- [ ] Flag mixed commit types\n- [ ] Note PR size for awareness\n\n### Phase 2.5 (Code Quality)\n- [ ] Scan for agent curation signals (Principle 3)\n- [ ] Check for redundant implementations\n- [ ] Flag premature abstractions\n- [ ] Identify incomplete refactors\n\n### Phase 2.5 (Test Quality)\n- [ ] Apply the revert test mentally (Principle 4)\n- [ ] Verify tests touch changed code\n- [ ] Flag demonstration-only assertions\n\n### Report Generation (Phase 6)\n- [ ] Include self-review checklist if signals found (Principle 1)\n- [ ] Include atomicity recommendation if warranted (Principle 2)\n- [ ] Include curation findings (Principle 3)\n- [ ] Include test quality findings (Principle 4)\n\nFile v1.9.19:modules/version-validation.md\n\n# Version Validation Module\n\n**Purpose:** Enforce version consistency checks in PR reviews to catch version mismatches before merge.\n\n## When to Run\n\n**MANDATORY** for every PR review UNLESS:\n- Maintainer explicitly passes `--skip-version-check` flag\n- PR is labeled with `skip-version-check` in GitHub\n- PR description contains `[skip-version-check]` marker\n\n## Validation Checklist\n\n### 1. Detect Project Type & Version Files\n\n```bash\n# Determine project structure\nPROJECT_TYPE=\"\"\nVERSION_FILES=()\n\nif [[ -f \"Cargo.toml\" ]]; then\n  PROJECT_TYPE=\"rust\"\n  VERSION_FILES+=(\"Cargo.toml\")\nelif [[ -f \"package.json\" ]]; then\n  PROJECT_TYPE=\"node\"\n  VERSION_FILES+=(\"package.json\")\nelif [[ -f \"pyproject.toml\" ]]; then\n  PROJECT_TYPE=\"python\"\n  VERSION_FILES+=(\"pyproject.toml\")\nelif [[ -f \".claude-plugin/marketplace.json\" ]]; then\n  PROJECT_TYPE=\"claude-marketplace\"\n  VERSION_FILES+=(\".claude-plugin/marketplace.json\")\nfi\n\n# Always check CHANGELOG if it exists\n[[ -f \"CHANGELOG.md\" ]] && VERSION_FILES+=(\"CHANGELOG.md\")\n[[ -f \"CHANGELOG\" ]] && VERSION_FILES+=(\"CHANGELOG\")\n```\n\n### 2. Check Branch Name for Version Indicator\n\n```bash\n# Extract version from branch name if present\nBRANCH_NAME=$(gh pr view $PR_NUMBER --json headRefName -q .headRefName)\nBRANCH_VERSION=\"\"\n\n# Match patterns: release/1.2.3, version-1.2.3, feature-name-1.2.3, v1.2.3-branch\nif echo \"$BRANCH_NAME\" | grep -qE '[0-9]+\\.[0-9]+\\.[0-9]+'; then\n  BRANCH_VERSION=$(echo \"$BRANCH_NAME\" | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+' | head -1)\n  echo \"Branch name indicates version: $BRANCH_VERSION\"\nfi\n```\n\n### 3. Check if Version Changed in PR\n\n```bash\n# Get PR diff for version files\nVERSION_CHANGED=false\nfor file in \"${VERSION_FILES[@]}\"; do\n  if gh pr diff $PR_NUMBER --name-only | grep -qF \"$file\"; then\n    if gh pr diff $PR_NUMBER -- \"$file\" | grep -qE '^\\+.*version|^\\+.*## \\['; then\n      VERSION_CHANGED=true\n      break\n    fi\n  fi\ndone\n```\n\n### 4. If Version Changed, Run Full Validation\n\nIf `VERSION_CHANGED=true`, perform detailed checks:\n\n#### A. Extract Version from Each Source\n\n```bash\n# Example for claude-marketplace\nMARKETPLACE_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n# For each plugin in marketplace\njq -r '.plugins[] | \"\\(.name):\\(.version)\"' .claude-plugin/marketplace.json > /tmp/marketplace_versions.txt\n\n# For each actual plugin\nfor plugin_dir in plugins/*/; do\n  PLUGIN_NAME=$(basename \"$plugin_dir\")\n  ACTUAL_VERSION=$(jq -r '.version' \"$plugin_dir/.claude-plugin/plugin.json\" 2>/dev/null || echo \"MISSING\")\n  echo \"$PLUGIN_NAME:$ACTUAL_VERSION\" >> /tmp/actual_versions.txt\ndone\n```\n\n#### B. Compare Marketplace vs Actual\n\n```bash\n# Cross-reference versions\nwhile IFS=: read -r name marketplace_version; do\n  actual_version=$(grep \"^$name:\" /tmp/actual_versions.txt | cut -d: -f2)\n\n  if [[ \"$marketplace_version\" != \"$actual_version\" ]]; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] Version mismatch for $name: marketplace=$marketplace_version, actual=$actual_version\"\n  fi\ndone < /tmp/marketplace_versions.txt\n```\n\n#### C. Verify CHANGELOG Updated\n\n```bash\n# Check if CHANGELOG has entry for new version\nif [[ -f \"CHANGELOG.md\" ]]; then\n  NEW_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n  if ! grep -q \"\\[$NEW_VERSION\\]\" CHANGELOG.md; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] CHANGELOG.md missing entry for version $NEW_VERSION\"\n  fi\n\n  # Check for release date\n  if grep -q \"\\[$NEW_VERSION\\] - Unreleased\" CHANGELOG.md; then\n    # SUGGESTION\n    echo \"[G-VERSION] CHANGELOG shows version $NEW_VERSION as Unreleased - update date before merge\"\n  fi\nfi\n```\n\n#### D. Validate Branch Name Version Matches Marketplace Version\n\n```bash\n# If branch name contains a version, it MUST match the marketplace/project version\nif [[ -n \"$BRANCH_VERSION\" ]]; then\n  # Get current project version based on project type\n  CURRENT_VERSION=\"\"\n\n  if [[ \"$PROJECT_TYPE\" == \"claude-marketplace\" ]]; then\n    CURRENT_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n  elif [[ \"$PROJECT_TYPE\" == \"python\" ]]; then\n    CURRENT_VERSION=$(grep \"^version\" pyproject.toml | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n  elif [[ \"$PROJECT_TYPE\" == \"node\" ]]; then\n    CURRENT_VERSION=$(jq -r '.version' package.json)\n  elif [[ \"$PROJECT_TYPE\" == \"rust\" ]]; then\n    CURRENT_VERSION=$(grep \"^version\" Cargo.toml | head -1 | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n  fi\n\n  if [[ -n \"$CURRENT_VERSION\" ]] && [[ \"$BRANCH_VERSION\" != \"$CURRENT_VERSION\" ]]; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] Branch name suggests version $BRANCH_VERSION, but marketplace/project version is $CURRENT_VERSION\"\n    echo \"  Branch: $BRANCH_NAME\"\n    echo \"  Expected: Version files should match branch name version\"\n    echo \"  Fix: Update version files to $BRANCH_VERSION OR rename branch to match $CURRENT_VERSION\"\n  fi\nfi\n```\n\n#### E. Check README Version References\n\n```bash\n# Check if README mentions version\nif [[ -f \"README.md\" ]]; then\n  if grep -q \"version\" README.md; then\n    # Extract version mentions\n    grep -i \"version\" README.md | while read -r line; do\n      # Check if it references old version\n      if echo \"$line\" | grep -qE \"[0-9]+\\.[0-9]+\\.[0-9]+\"; then\n        echo \"[INFO] README mentions version - verify accuracy\"\n      fi\n    done\n  fi\nfi\n```\n\n### 5. Project-Specific Validations\n\n#### Claude Plugin Marketplace\n\n```bash\n# Additional checks for claude-night-market structure\nif [[ \"$PROJECT_TYPE\" == \"claude-marketplace\" ]]; then\n\n  # Check metadata.version matches all plugin versions (unless independent cycle)\n  ECOSYSTEM_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n  # Get independent release plugins from CHANGELOG or docs\n  INDEPENDENT_PLUGINS=()\n  if grep -q \"independent release cycle\" CHANGELOG.md; then\n    # Extract plugin names marked as independent\n    INDEPENDENT_PLUGINS+=($(grep -A2 \"independent release cycle\" CHANGELOG.md | grep -oE '[a-z-]+' | head -5))\n  fi\n\n  # Verify non-independent plugins match ecosystem version\n  jq -r '.plugins[] | \"\\(.name):\\(.version)\"' .claude-plugin/marketplace.json | while IFS=: read -r name version; do\n    # Skip if independent\n    if [[ \" ${INDEPENDENT_PLUGINS[@]} \" =~ \" ${name} \" ]]; then\n      continue\n    fi\n\n    if [[ \"$version\" != \"$ECOSYSTEM_VERSION\" ]]; then\n      echo \"[B-VERSION] Plugin $name should be $ECOSYSTEM_VERSION (ecosystem version), but is $version\"\n    fi\n  done\nfi\n```\n\n#### Python Projects\n\n```bash\nif [[ \"$PROJECT_TYPE\" == \"python\" ]]; then\n  # Check __version__ in source\n  if [[ -d \"src\" ]]; then\n    VERSION_PY=$(find src -name \"__init__.py\" -exec grep -l \"__version__\" {} \\; | head -1)\n    if [[ -n \"$VERSION_PY\" ]]; then\n      CODE_VERSION=$(grep \"__version__\" \"$VERSION_PY\" | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n      TOML_VERSION=$(grep \"^version\" pyproject.toml | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n\n      if [[ \"$CODE_VERSION\" != \"$TOML_VERSION\" ]]; then\n        echo \"[B-VERSION] __version__ ($CODE_VERSION) doesn't match pyproject.toml ($TOML_VERSION)\"\n      fi\n    fi\n  fi\nfi\n```\n\n## Classification of Version Issues\n\nAll version mismatches are **BLOCKING** unless explicitly waived:\n\n| Issue Type | Severity | Rationale |\n|------------|----------|-----------|\n| Branch name version ≠ marketplace/project version | BLOCKING | Branch naming indicates intended version - mismatch suggests incomplete version bump |\n| Version mismatch between files | BLOCKING | Breaks installation/packaging |\n| Missing CHANGELOG entry | BLOCKING | Required for release audit trail |\n| Marketplace vs plugin version mismatch | BLOCKING | Plugin installation will fail |\n| README references old version | IN-SCOPE | Documentation accuracy |\n| __version__ doesn't match package version | BLOCKING | Runtime version reporting broken |\n\n## Bypass Mechanism\n\nMaintainer can bypass with one of:\n\n1. **CLI flag**: `/pr-review <pr> --skip-version-check`\n2. **GitHub label**: Add `skip-version-check` label to PR\n3. **PR description marker**: Include `[skip-version-check]` in PR body\n\n**When bypassed:**\n- Still run validation and report findings\n- Mark as `[WAIVED]` instead of `[BLOCKING]`\n- Add note: \"Version validation bypassed by maintainer\"\n\n## Output Format\n\n```markdown\n### Version Validation\n\n**Status:** ✅ PASSED | ⚠️ WAIVED | ❌ FAILED\n\n**Version Detected:** 1.2.3 → 1.2.4\n\n**Files Checked:**\n- [x] .claude-plugin/marketplace.json: 1.2.4 ✓\n- [x] plugins/*/plugin.json: 1.2.4 ✓ (11 plugins)\n- [x] plugins/memory-palace/plugin.json: 1.3.0 ✓ (independent cycle)\n- [x] CHANGELOG.md: Entry for 1.2.4 ✓\n- [x] README.md: References updated ✓\n\n**Blocking Issues (0):**\nNone - all version files consistent.\n\n---\n\nOR with issues:\n\n### Version Validation\n\n**Status:** ❌ FAILED\n\n**Branch Name:** skills-improvements-1.2.2\n**Version Detected:** 1.1.0 → 1.2.1\n\n**Files Checked:**\n- [ ] Branch name version: 1.2.2 ≠ Marketplace version: 1.2.1 ❌\n- [x] .claude-plugin/marketplace.json: 1.2.1 ✓\n- [x] plugins/abstract/plugin.json: 1.2.1 ✓\n- [ ] plugins/memory-palace/plugin.json: Marketplace lists 1.2.1 but actual is 1.2.0 ❌\n- [x] CHANGELOG.md: Entry for 1.2.1 ✓\n- [ ] README.md: Still references 1.1.0 ⚠️\n\n**Blocking Issues (2):**\n- [B-VERSION-1] Branch name suggests version 1.2.2, but marketplace/project version is 1.2.1\n  - Branch: skills-improvements-1.2.2\n  - Expected: Version files should match branch name version\n  - Fix: Update version files to 1.2.2 OR rename branch to match 1.2.1\n- [B-VERSION-2] Version mismatch: memory-palace\n  - Marketplace: 1.2.1\n  - Actual: 1.2.0\n  - Fix: Update marketplace.json line 52 to \"1.2.0\"\n\n**In-Scope Issues (1):**\n- [S-VERSION-1] README references old version 1.1.0\n  - Fix: Update README.md to reference 1.2.1\n```\n\n## Integration with PR Review Workflow\n\nThis module runs in **Phase 1.5** (after scope establishment, before code analysis):\n\n```\nPhase 1: Scope Establishment\nPhase 1.5: Version Validation ← NEW\nPhase 2: Code Analysis\nPhase 3: Synthesis & Validation\nPhase 4: GitHub Review Submission\nPhase 5: Test Plan Generation\n```\n\n**Why Phase 1.5?**\n- Version issues are blocking and should be caught early\n- Prevents wasting time on detailed code review if basic version hygiene fails\n- Provides fast feedback to PR author\n\n## Error Handling\n\n### Missing Version Files\n```markdown\n⚠️ Version validation skipped: No version files detected in repository.\nConsider adding CHANGELOG.md for release tracking.\n```\n\n### Multiple Version Schemes\n```markdown\nℹ️ Detected multiple version schemes:\n- Python package: 2.1.0 (pyproject.toml)\n- Frontend: 1.5.0 (package.json)\n\nValidated each independently.\n```\n\n### Parse Failures\n```bash\nif ! jq -e '.metadata.version' .claude-plugin/marketplace.json >/dev/null 2>&1; then\n  echo \"[B-VERSION] Failed to parse version from marketplace.json - invalid JSON?\"\nfi\n```\n\n## Testing the Module\n\n```bash\n# Test version validation manually\nSkill(sanctum:pr-review)\n\n# With bypass\n/pr-review 42 --skip-version-check\n\n# Dry run to see what would be checked\n/pr-review 42 --dry-run\n```\n\n## Maintenance Notes\n\n- Update detection patterns when new project types are added\n- Keep version file list synchronized with `sanctum:version-updates` skill\n- Consider adding support for monorepo version strategies\n- May need adjustment for projects using date-based or git-hash versions\n\nFile v1.9.19:skill-card.md\n\n## Description:\n\nReviews pull requests with scope validation, requirements compliance, and line comments.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[athola](https://clawhub.ai/user/athola)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill to review GitHub or GitLab pull requests against stated requirements, classify findings by scope and severity, and produce review reports, line comments, backlog items, and optional knowledge-capture entries.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Review findings and PR data may be persisted to local or project memory.\n\nMitigation: Use the skill only where project memory capture is acceptable, and disable knowledge capture unless explicitly needed.\n\nRisk: Review output may be posted to GitHub or GitLab surfaces.\n\nMitigation: Confirm publishing behavior and target repository before enabling posting steps; use local Markdown output for sensitive reviews.\n\nRisk: Server security evidence flags an unsafe bundled workflow involving Python command execution and temporary-file handling.\n\nMitigation: Review and fix those workflow paths before using the skill on private or security-sensitive pull requests.\n\nRisk: Broad triggers can activate the skill in more contexts than intended.\n\nMitigation: Invoke the skill explicitly or narrow deployment triggers for repositories where PR data is sensitive.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-sanctum-pr-review)\n- [Metadata homepage](https://github.com/athola/claude-night-market/tree/master/plugins/sanctum)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown review reports with structured finding classifications, inline comments, and shell command examples.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce local review files, platform review comments, issue drafts, and knowledge-capture entries depending on the selected workflow.]\n\n## Skill Version(s):\n\n1.9.19 (source: server release metadata; artifact frontmatter lists 1.9.8)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.9.17: 10 files, 30119 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2365b), SKILL.md (21009b), _meta.json (140b)\n\nFile v1.9.17:SKILL.md\n\n---\nname: pr-review\ndescription: |\n  Reviews pull requests with scope validation, requirements compliance, and line comments\nversion: 1.9.8\ntriggers:\n  - pr\n  - review\n  - scope\n  - github\n  - gitlab\n  - code-quality\n  - knowledge-capture\n  - cross-platform\n  - reviewing GitHub or GitLab PRs\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/sanctum\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.leyline:git-platform\", \"night-market.sanctum:shared\", \"night-market.sanctum:git-workspace-review\", \"night-market.sanctum:version-updates\", \"night-market.pensive:unified-review\", \"night-market.imbue:proof-of-work\", \"night-market.imbue:justify\", \"night-market.memory-palace:review-chamber\", \"night-market.scribe:slop-detector\", \"night-market.scribe:doc-generator\"]}}}\nsource: claude-night-market\nsource_plugin: sanctum\n---\n\n> **Night Market Skill** — ported from [claude-night-market/sanctum](https://github.com/athola/claude-night-market/tree/master/plugins/sanctum). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Core Principle](#core-principle)\n- [When to Use](#when-to-use)\n- [Scope Classification Framework](#scope-classification-framework)\n- [Classification Examples](#classification-examples)\n- [Workflow](#workflow)\n- [Phase 1: Establish Scope Baseline](#phase-1-establish-scope-baseline)\n- [Phase 2: Gather Changes](#phase-2-gather-changes)\n- [Phase 3: Requirements Validation](#phase-3-requirements-validation)\n- [Phase 1.5: Version Validation (MANDATORY)](#phase-15-version-validation-mandatory)\n- [Phase 4: Code Review with Scope Context](#phase-4-code-review-with-scope-context)\n- [Phase 4.5: Additive Bias Audit](#phase-45-additive-bias-audit)\n- [Phase 5: Backlog Triage](#phase-5-backlog-triage)\n- [Phase 6: Generate Report](#phase-6-generate-report)\n- [Phase 7: Knowledge Capture](#phase-7-knowledge-capture)\n- [Quality Gates](#quality-gates)\n- [Anti-Patterns to Avoid](#anti-patterns-to-avoid)\n- [Don't: Scope Creep Review](#dont-scope-creep-review)\n- [Don't: Perfect is Enemy of Good](#dont-perfect-is-enemy-of-good)\n- [Don't: Blocking on Style](#dont-blocking-on-style)\n- [Don't: Reviewing Unchanged Code](#dont-reviewing-unchanged-code)\n- [Integration with Other Tools](#integration-with-other-tools)\n- [Exit Criteria](#exit-criteria)\n\n\n# Scope-Focused PR Review\n\nReview pull/merge requests with discipline: validate against original requirements, prevent scope creep, and route out-of-scope findings to issues on the detected platform.\n\n**Platform detection is automatic** via `leyline:git-platform`. Use `gh` for GitHub, `glab` for GitLab. Check session context for `git_platform:`.\n\n## Core Principle\n\n**A PR review validates scope compliance, not code perfection.**\n\nThe goal is to validate the implementation meets its stated requirements without introducing regressions. Improvements beyond the scope belong in future PRs.\n\n## When To Use\n\n- Before merging any feature branch\n- When reviewing PRs from teammates\n- To validate your own work before requesting review\n- To generate a backlog of improvements discovered during review\n\n## When NOT To Use\n\n- Preparing PRs - use pr-prep instead\n- Deep code\n  review - use pensive:unified-review\n- Preparing PRs - use pr-prep instead\n- Deep code\n  review - use pensive:unified-review\n\n## Scope Classification Framework\n\nEvery finding must be classified:\n\n| Category | Definition | Action |\n|----------|------------|--------|\n| **BLOCKING** | Bug, security issue, or regression introduced by this change | Must fix before merge |\n| **IN-SCOPE** | Issue directly related to stated requirements | Should address in this PR |\n| **SUGGESTION** | Improvement within changed code, not required | Author decides |\n| **BACKLOG** | Good idea but outside PR scope | Create GitHub issue |\n| **IGNORE** | Nitpick, style preference, or not worth tracking | Skip entirely |\n\n### Classification Examples\n\n**BLOCKING:**\n- Null pointer exception in new code path\n- SQL injection in new endpoint\n- Breaking change to public API without migration\n- Test that was passing now fails\n\n**IN-SCOPE:**\n- Missing error handling specified in requirements\n- Feature doesn't match spec behavior\n- Incomplete implementation of planned functionality\n\n**SUGGESTION:**\n- Better variable name in changed function\n- Slightly more efficient algorithm\n- Additional edge case test\n\n**BACKLOG:**\n- Refactoring opportunity in adjacent code\n- \"While we're here\" improvements\n- Technical debt in files touched but not changed\n- Features sparked by seeing the code\n\n**IGNORE:**\n- Personal style preferences\n- Theoretical improvements with no practical impact\n- Premature optimization suggestions\n\n## Workflow\n\n### Phase 1: Establish Scope Baseline\n\nBefore looking at ANY code, understand what this PR is supposed to accomplish.\n\n**Note:** Version validation (Phase 1.5) runs AFTER scope establishment but BEFORE code review. See `modules/version-validation.md` for details.\n\n**Search for scope artifacts in order:**\n\n1. **Plan file**: Most authoritative (check spec-kit locations first, then root)\n   ```bash\n   # Spec-kit feature plans (preferred - structured implementation blueprints)\n   find specs -name \"plan.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   # Legacy/alternative locations\n   ls docs/plans/ 2>/dev/null\n   # Root plan.md (may be Claude Plan Mode artifact from v2.0.51+)\n   cat plan.md 2>/dev/null | head -100\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n2. **Spec file**: Requirements definition (check spec-kit locations first)\n   ```bash\n   find specs -name \"spec.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   cat spec.md 2>/dev/null | head -100\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n3. **Tasks file**: Implementation checklist (check spec-kit locations first)\n   ```bash\n   find specs -name \"tasks.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null\n   cat tasks.md 2>/dev/null\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n4. **PR/MR description**: Author's intent\n   ```bash\n   # GitHub\n   gh pr view <number> --json body --jq '.body'\n   # GitLab\n   glab mr view <number> --json description --jq '.description'\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n5. **Commit messages**: Incremental decisions\n   ```bash\n   # GitHub\n   gh pr view <number> --json commits --jq '.commits[].messageHeadline'\n   # GitLab\n   glab mr view <number> --json commits\n   ```\n   **Verification:** Run the command with `--help` flag to verify availability.\n\n**Output:** A clear statement of scope:\n> \"This PR implements [feature X] as specified in plan.md. The requirements are:\n> 1. [requirement]\n> 2. [requirement]\n> 3. [requirement]\"\n\nIf no scope artifacts exist, flag this as a process issue but continue with PR description as the baseline.\n\n### Phase 2: Gather Changes\n\n```bash\n# GitHub\ngh pr diff <number> --name-only\ngh pr diff <number>\ngh pr view <number> --json additions,deletions,changedFiles,commits\n\n# GitLab\nglab mr diff <number>\nglab mr view <number>\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n### Phase 3: Requirements Validation\n\nBefore detailed code review, check scope coverage:\n\n- [ ] Each requirement has corresponding implementation\n- [ ] No requirements are missing\n- [ ] Implementation doesn't exceed requirements (overengineering signal)\n\n### Phase 1.5: Version Validation (MANDATORY)\n\n**Run version validation checks BEFORE code review.**\n\nSee `modules/version-validation.md` for detailed validation procedures.\n\n**Quick reference:**\n1. Check if bypass requested (`--skip-version-check`, label, or PR marker)\n2. Detect if version files changed in PR diff\n3. If changed, run project-specific validations:\n   - Claude marketplace: Check marketplace.json vs plugin.json versions\n   - Python: Check pyproject.toml vs __version__\n   - Node: Check package.json vs package-lock.json\n   - Rust: Check Cargo.toml vs Cargo.lock\n4. Validate CHANGELOG has entry for new version\n5. Check README/docs for version references\n6. Classify findings as BLOCKING (or WAIVED if bypassed)\n\n**All version mismatches are BLOCKING unless explicitly waived by maintainer.**\n\n### Phase 3.5: PR Hygiene Checks\n\nBefore diving into code, run the PR hygiene checks from\n`modules/pr-hygiene.md`:\n\n1. **Atomicity check**: Does this PR contain one logical\n   change? Flag mixed commit types (feat, refactor, and fix),\n   formatting commits bundled with logic, or changes spanning\n   unrelated subsystems. Large PRs get 30% defect detection\n   vs 75% for focused ones.\n\n2. **Agent curation check**: Does the code show signs of\n   iterative AI generation without a cleanup pass? Look for\n   redundant implementations, premature abstractions, incomplete\n   refactors, and scope drift.\n\n3. **Self-review signals**: Are there unsquashed fixup commits,\n   debug statements, or commented-out code that suggest the\n   author did not read their own diff before sending?\n\nClassify findings per `modules/pr-hygiene.md` severity tables.\n\n### Phase 4: Code Review with Scope Context\n\nUse `pensive:unified-review` on the changed files. For comment quality assessment, see `modules/comment-guidelines.md`.\n\n**Critical:** Evaluate each finding against the scope baseline:\n\n```text\n**Verification:** Run the command with `--help` flag to verify availability.\nFinding: \"Function X lacks input validation\"\nScope check: Is input validation mentioned in requirements?\n  - YES → IN-SCOPE\n  - NO, but it's a security issue → BLOCKING\n  - NO, and it's a nice-to-have → BACKLOG\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n### Phase 4.5: Additive Bias Audit\n\nRun `Skill(imbue:justify)` on the PR changes to detect\nAI additive bias, test-logic tampering, and unnecessary\ncomplexity.\n\n**Key checks:**\n\n1. **Additive bias score** -- flag changes with high\n   add/delete ratio (>5:1) that lack justification\n2. **Iron Law compliance** -- verify test assertions were\n   not weakened to match broken implementations\n3. **Minimal intervention** -- confirm each changed file\n   was necessary and the change was the smallest fix\n\n**Classify justify findings using the scope framework:**\n\n| Justify Signal | Likely Classification |\n|---------------|----------------------|\n| Test logic tampered | BLOCKING |\n| High additive bias, no justification | IN-SCOPE |\n| Premature abstraction | SUGGESTION |\n| Compatibility shim | BACKLOG |\n\nInclude the additive bias score and Iron Law status in\nthe Phase 6 report.\n\n### Phase 4.6: Invariant Conflict Detection\n\nCheck whether the PR touches existing design invariants.\nThis is a judgment problem that models get wrong far too\noften — surface conflicts for human review rather than\nsilently accepting or rejecting them.\n\n**Quick detection heuristic:**\n\n1. Do changed files cross module boundaries that\n   previously didn't interact?\n2. Do changes introduce a new pattern alongside an\n   existing one (two ways to do the same thing)?\n3. Do interface/type/schema files change shape?\n4. Do data flow directions change?\n5. Are ADR-documented decisions being contradicted?\n\n```bash\n# Check for structural pattern changes\ngit diff --name-only HEAD...origin/master 2>/dev/null \\\n  | rg \"(interface|types|schema|model|base|core|contract)\" \\\n  || git diff --name-only HEAD...origin/master 2>/dev/null \\\n  | grep -E \"(interface|types|schema|model|base|core|contract)\"\n```\n\n**When a conflict is detected:**\n\nDo NOT resolve it. Add to the report as a special\ncategory:\n\n| Category | Definition | Action |\n|----------|------------|--------|\n| **INVARIANT** | Change conflicts with an existing design decision | Escalate to human with 3-option analysis |\n\n**For each invariant conflict, present:**\n\n1. **The invariant**: Name the design decision and why\n   it was made (reference ADRs if available)\n2. **The conflict**: What this PR does that clashes\n3. **Option A — Preserve**: Don't merge this change;\n   the invariant pays dividends elsewhere\n4. **Option B — Layer**: Merge as-is, accepting\n   inelegance; not every feature must be elegant\n5. **Option C — Revise**: The invariant is wrong;\n   here's what a redesign would look like\n\n**Classification:** INVARIANT findings are always\nBLOCKING — not because the code is wrong, but because\nthe judgment call requires human input. Only the human\nreviewer can decide which of the three options is right.\n\n**Why this matters:** Bad invariant decisions compound.\nA few wrong calls and the codebase becomes unsalvageable.\nThis is not a context problem solvable with better\ndocumentation — it is a judgment problem that requires\nhuman wisdom.\n\n### Phase 5: Backlog Triage\n\nFor each BACKLOG item, create an issue on the detected platform:\n\n```bash\n# GitHub\ngh issue create \\\n  --title \"[Tech Debt] Brief description\" \\\n  --body \"## Context\nIdentified during PR #<number> review.\n...\" \\\n  --label \"tech-debt\"\n\n# GitLab\nglab issue create \\\n  --title \"[Tech Debt] Brief description\" \\\n  --description \"## Context\nIdentified during MR !<number> review.\n...\" \\\n  --label \"tech-debt\"\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n**Ask user before creating:** \"I found N backlog items. Create issues? [y/n/select]\"\n\n### Phase 6: Generate Report\n\nStructure the report by classification. Every BLOCKING and\nIN-SCOPE finding MUST include educational insights per\n`modules/educational-insights.md`: **Why** (the principle),\n**Proof** (link to best practice), and a **Teachable Moment**\n(generalized lesson). SUGGESTION findings include Why and\noptionally Proof. BACKLOG items need only a brief rationale.\n\n```markdown\n## PR #X: Title\n\n### Scope Compliance\n**Requirements:** (from plan/spec)\n1. [x] Requirement A - Implemented\n2. [x] Requirement B - Implemented\n3. [ ] Requirement C - **Missing**\n\n### Blocking (1)\n1. [B1] SQL injection via string concatenation\n   - **Location**: `db/queries.py:89`\n   - **Issue**: User input interpolated directly into SQL\n   - **Why**: String-interpolated SQL allows attackers to\n     execute arbitrary queries (CWE-89). This is the #1\n     web application vulnerability per OWASP Top 10.\n   - **Proof**: [OWASP SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)\n   - **Teachable Moment**: Always use parameterized queries\n     or an ORM. This applies everywhere user input reaches\n     a database, cache, or search engine query.\n   - **Fix**: Use parameterized query:\n     `cursor.execute(\"SELECT * FROM t WHERE id = ?\", (uid,))`\n\n### In-Scope (1)\n1. [S1] Missing validation for edge case\n   - **Location**: `api.py:45`\n   - **Issue**: Empty input not handled per requirement\n   - **Why**: Defensive validation at API boundaries\n     prevents cascading failures in downstream logic.\n   - **Proof**: [Postel's Law](https://en.wikipedia.org/wiki/Robustness_principle)\n   - **Teachable Moment**: Validate inputs at system\n     boundaries (API handlers, CLI args, file parsers)\n     but trust internal function contracts.\n\n### Suggestions (1)\n1. [G1] Consider extracting helper function\n   - **Why**: The repeated pattern on lines 30-35 and\n     72-77 violates DRY. Extracting it reduces future\n     bug surface.\n   - Author's discretion\n\n### Backlog → GitHub Issues (3)\n1. #142 - Refactor authentication module\n2. #143 - Add caching layer\n3. #144 - Update deprecated dependency\n\n### Recommendation\n**APPROVE WITH CHANGES**\nAddress B1 and S1 before merge.\n```\n\n### Local Output (`--local`)\n\nWhen `--local [path]` is passed, write the Phase 6 report to a\nlocal `.md` file instead of posting via API. Default path:\n`.pr-review/pr-<number>-review.md`. The file includes the\nreview summary, test plan, and backlog items in a single\ndocument. Issue creation and PR description updates are skipped.\nKnowledge capture (Phase 7) still runs.\n\n### Phase 7: Knowledge Capture\n\nAfter generating the report, evaluate findings for knowledge capture into the project's review chamber.\n\n**Trigger:** Automatically for findings scoring ≥60 on evaluation criteria.\n\n```bash\n# Capture significant findings to review-chamber\n# Uses memory-palace:review-chamber evaluation framework\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n**Candidates for capture:**\n- BLOCKING findings with architectural context → `decisions/`\n- Recurring patterns seen in multiple PRs → `patterns/`\n- Quality standards and conventions → `standards/`\n- Post-mortem insights and learnings → `lessons/`\n\n**Output:** Add to report:\n```markdown\n### Knowledge Captured 📚\n\n| Entry ID | Title | Room |\n|----------|-------|------|\n| abc123 | JWT over sessions | decisions/ |\n| def456 | Token refresh pattern | patterns/ |\n\nView: `/review-room list --palace <project>`\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nSee `modules/knowledge-capture.md` for full workflow.\n\n## Quality Gates\n\nA PR should be approved when:\n- [ ] All stated requirements are implemented\n- [ ] No BLOCKING issues remain\n- [ ] IN-SCOPE issues are resolved or acknowledged\n- [ ] BACKLOG items are tracked as GitHub issues\n- [ ] Tests cover new code paths\n- [ ] Tests would fail if the fix were reverted (the revert test)\n- [ ] No obvious agent-generated code left uncurated\n- [ ] Author can explain how each changed section works and how\n      it could fail (understanding check, not just \"tests pass\")\n\n## Anti-Patterns to Avoid\n\n### Don't: Scope Creep Review\n> \"While you're here, you should also refactor X, add feature Y, and fix Z in adjacent files.\"\n\n**Do:** Create backlog issues, keep PR focused.\n\n### Don't: Perfect is Enemy of Good\n> \"This works but could be 5% more efficient with different approach.\"\n\n**Do:** If it meets requirements and has no bugs, it's ready.\n\n### Don't: Blocking on Style\n> \"I prefer tabs over spaces.\"\n\n**Do:** Use linters for style, reserve review for logic.\n\n### Don't: Reviewing Unchanged Code\n> \"The file you imported from has some issues...\"\n\n**Do:** That's a separate PR. Create an issue if important.\n\n### Don't: Tests That Prove Old Code Was Bad\n> \"Here's a test showing the old behavior was wrong.\"\n\n**Do:** Write tests that break if your fix is reverted.\nTests should protect against regressions in *your* code,\nnot document why the change was needed. See\n`modules/pr-hygiene.md` Principle 4.\n\n### Don't: Bundling Unrelated Changes\n> \"I also reformatted the file and fixed a typo in another module.\"\n\n**Do:** One PR = one logical change. Formatting, refactors,\nand unrelated fixes belong in separate PRs. See\n`modules/pr-hygiene.md` Principle 2.\n\n### Don't: Merge Code You Cannot Explain\n\n> \"It works and the tests pass.\"\n\nA PR where the author cannot explain how each changed section\nworks and how it might fail is not ready to merge. This is\nespecially true for AI-assisted code: generation speed creates\nthe illusion of understanding.\n\n**Do:** Before marking a PR ready, ask the reviewing agent to\nquestion you about the changed code — how each part works, what\nassumptions it makes, and what inputs would break it. Continue\nuntil you can answer without hesitation. Only merge code you\nown front-to-back.\n\nThis applies to self-reviews: run the same probe before\nrequesting external review. Do not submit a PR for review that\nyou yourself do not fully understand.\n\n## Integration with Other Tools\n\n- **`/fix-pr`**: After review identifies issues, use this to address them\n- **`/pr`**: To prepare a PR before review\n- **`pensive:unified-review`**: For the actual code analysis\n- **`pensive:bug-review`**: For deeper bug hunting if needed\n- **`scribe:slop-detector`**: For documentation AND commit message quality analysis\n- **`scribe:doc-generator`**: For PR description writing guidelines (slop-free)\n\n## Slop Detection Integration\n\n### Documentation Review\nFor all changed `.md` files, invoke `Skill(scribe:slop-detector)`:\n- Score ≥ 3.0: Flag as IN-SCOPE (should remediate)\n- Score ≥ 5.0: Flag as BLOCKING if `--strict` mode\n\n### Commit Message Review\nScan all PR commit messages for slop markers:\n```bash\ngh pr view <number> --json commits --jq '.commits[].messageBody' | \\\n  grep -iE 'leverage|seamless|comprehensive|delve|robust|utilize|facilitate'\n```\nIf slop found in commits: Add to SUGGESTION category with remediation guidance.\n\n### PR Description Review\nApply `scribe:slop-detector` to PR body:\n- Tier 1 words in description → SUGGESTION to rephrase\n- Marketing phrases (\"unlock potential\") → Flag for removal\n\n## Exit Criteria\n\n- Scope baseline established\n- All changes reviewed against scope\n- Findings classified correctly\n- Backlog items tracked as issues\n- Clear recommendation provided\n\n## Supporting Modules\n\n- [GitHub PR comment patterns](modules/github-comments.md) - `gh api` patterns for inline and summary PR comments\n\nFile v1.9.17:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-sanctum-pr-review\",\n  \"version\": \"1.9.17\",\n  \"publishedAt\": 1785390042486\n}\n\nFile v1.9.17:modules/comment-guidelines.md\n\n# Code Comment Quality Guidelines\n\nGuidance on when and how to write effective code comments that add value without bloat.\n\n## Core Philosophy: Why, Not What\n\nGood comments explain **why** code exists, not **what** it does. The code already shows what it does.\n\n| Comment Type | Value | Example |\n|--------------|-------|---------|\n| **Why** | High | \"Use exponential backoff to handle transient API failures\" |\n| **What** | Low | \"Loop through the array\" |\n| **Context** | High | \"AWS Lambda has 15-min timeout, so max 3 retries\" |\n| **Obvious** | Negative | \"Increment counter by 1\" |\n\n## When Comments Are Warranted\n\n### Require Comments For\n\n| Scenario | Reason | Example |\n|----------|--------|---------|\n| **Non-obvious behavior** | Future readers will wonder why | Edge case handling |\n| **Business logic decisions** | Domain knowledge not in code | \"Tax calculated per 2024 regulations\" |\n| **Performance optimizations** | Why this approach over simpler one | \"O(1) lookup vs O(n) iteration\" |\n| **Workarounds** | Temporary fixes need context | \"TODO: Remove after #123 fixed\" |\n| **Algorithm complexity** | Complex logic needs explanation | Mathematical formulas |\n| **External constraints** | Dependencies, APIs, limits | \"API rate limit: 100 req/min\" |\n\n### Don't Require Comments For\n\n| Scenario | Alternative |\n|----------|-------------|\n| Self-explanatory code | Good naming |\n| Simple CRUD operations | Patterns speak |\n| Well-named functions | Function name = documentation |\n| Standard patterns | Convention over comment |\n\n## Examples\n\n### Good Comments (Explain Why)\n\n```python\ndef retry_with_backoff(max_attempts=3):\n    \"\"\"Retry with exponential backoff for transient failures.\n\n    AWS Lambda has a 15-minute timeout, so max_attempts=3 prevents\n    exceeding this limit with our 1s/2s/4s backoff strategy.\n    \"\"\"\n    ...\n\n# Use set for O(1) membership testing instead of list O(n)\n# Critical for processing 100k+ items in batch jobs\nseen_ids = set()\n```\n\n### Bad Comments (Explain What - Avoid These)\n\n```python\n# Bad: Restates code\ni = 0  # Set i to 0\n\n# Bad: Obvious from code\nif user_input == \"\":  # Check if user_input is empty string\n    return DEFAULT_VALUE\n\n# Bad: Redundant docstring\ndef add(a, b):\n    \"\"\"Add two numbers and return the result.\"\"\"\n    return a + b\n```\n\n## Anti-Patterns\n\n### Over-Commenting (Bloat)\n\n**Problem**: Too many comments obscure code and become maintenance burden.\n\n**Symptoms**:\n- Comment-to-code ratio > 1:3\n- Comments on every line\n- Comments restating variable names\n\n**Solution**: Improve code clarity instead. Better names, smaller functions.\n\n### Stale Comments (Out of Sync)\n\n**Problem**: Comments that don't match current code behavior are worse than no comments.\n\n**Symptoms**:\n- Function behavior changed, comment didn't\n- TODO comments for completed work\n- References to deleted code\n\n**Solution**: Update comments with code changes. Delete outdated TODOs.\n\n### Commented-Out Code\n\n**Problem**: Dead code clutters codebase and confuses readers.\n\n**Solution**: Delete it. Git preserves history.\n\n## Docstring Conventions\n\n### When Required\n\n- Public functions/methods\n- Classes with non-obvious purpose\n- Modules with significant complexity\n\n### Format (Python)\n\n```python\ndef process_order(order: Order, apply_discount: bool = False) -> Receipt:\n    \"\"\"Process an order and generate a receipt.\n\n    Validates inventory, applies pricing rules, and records transaction.\n\n    Args:\n        order: The order to process.\n        apply_discount: Whether to apply member discount (default: False).\n\n    Returns:\n        Receipt with itemized charges and total.\n\n    Raises:\n        InsufficientStockError: If any item is out of stock.\n        PaymentFailedError: If payment processing fails.\n    \"\"\"\n```\n\n### Format (TypeScript)\n\n```typescript\n/**\n * Process an order and generate a receipt.\n *\n * Validates inventory, applies pricing rules, and records transaction.\n *\n * @param order - The order to process\n * @param applyDiscount - Whether to apply member discount\n * @returns Receipt with itemized charges and total\n * @throws InsufficientStockError if any item is out of stock\n */\nfunction processOrder(order: Order, applyDiscount = false): Receipt {\n```\n\n## Review Checklist\n\nWhen reviewing code comments:\n\n- [ ] Comments explain WHY, not WHAT\n- [ ] No redundant comments restating code\n- [ ] Complex logic is documented\n- [ ] Business rules have context\n- [ ] No stale/outdated comments\n- [ ] No commented-out code\n- [ ] Public APIs have docstrings\n- [ ] TODOs have issue references\n\n## Integration with KISS/YAGNI\n\nFrom `conserve:code-quality-principles`:\n\n- **KISS**: If code needs extensive comments to understand, simplify the code\n- **YAGNI**: Don't comment for hypothetical future readers - comment for current needs\n\n## Summary\n\n| Situation | Action |\n|-----------|--------|\n| Simple, clear code | No comment needed |\n| Non-obvious behavior | Comment the WHY |\n| Business logic | Document the rule source |\n| Complex algorithm | Explain approach/tradeoffs |\n| Workaround | Note why and when to remove |\n| Dead code | Delete, don't comment out |\n\nFile v1.9.17:modules/educational-insights.md\n\n---\nname: educational-insights\ndescription: >-\n  Enrich PR review findings with educational context:\n  why the fix matters, proof via best-practice links,\n  and teachable moments that grow the implementer.\nparent_skill: sanctum:pr-review\ncategory: review-infrastructure\ntags: [education, insights, best-practices, teaching]\nestimated_tokens: 300\n---\n\n# Educational Insights for PR Review Findings\n\nEvery finding in a PR review is a learning opportunity.\nEach reported issue, suggestion, or error MUST include\neducational context so the review improves both the code\nand the person who wrote it.\n\n## The Three Pillars\n\nEach finding includes three educational elements:\n\n| Pillar | Purpose | Content |\n|--------|---------|---------|\n| **Why It Matters** | Explain the principle | 1-2 sentences on the underlying concept |\n| **Proof** | Link to authoritative source | URL to docs, standard, or guide |\n| **Teachable Moment** | Generalize the lesson | How this pattern applies beyond this PR |\n\n## Enriched Finding Format\n\nEvery finding entry (BLOCKING, IN-SCOPE, SUGGESTION)\nMUST use this extended format:\n\n```markdown\n1. [S1] Missing input validation on user-supplied path\n   - **Location**: `api/handlers.py:45`\n   - **Issue**: Path traversal possible via `../` in filename\n   - **Why**: Unsanitized file paths allow directory traversal\n     attacks (CWE-22). An attacker can read or overwrite\n     files outside the intended directory.\n   - **Proof**: [OWASP Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal)\n   - **Teachable Moment**: Always normalize paths with\n     `os.path.realpath()` and verify they stay within the\n     expected root. This applies to any function accepting\n     file paths from external input.\n   - **Fix**:\n     ```python\n     real = os.path.realpath(user_path)\n     if not real.startswith(allowed_root):\n         raise ValueError(\"Path outside allowed directory\")\n     ```\n```\n\n## How to Source Proof Links\n\nUse authoritative references in this priority order:\n\n1. **Language/framework docs** (python.org, docs.rs,\n   developer.mozilla.org)\n2. **Security standards** (OWASP, CWE, NIST)\n3. **Style guides** (PEP 8, Google Style Guide, Effective Go)\n4. **Well-known articles** (Martin Fowler, Dan Abramov,\n   Kent Beck)\n5. **RFCs and specifications** (IETF RFCs, W3C specs)\n\nWhen no authoritative URL exists, cite the principle by\nname (e.g., \"Liskov Substitution Principle\") and briefly\nexplain it inline.\n\n## Insight Depth by Classification\n\n| Classification | Insight Depth | Proof Required |\n|---------------|--------------|----------------|\n| **BLOCKING** | Full (why, impact, and fix) | Yes, with link |\n| **IN-SCOPE** | Standard (why and fix) | Yes, with link |\n| **SUGGESTION** | Brief (why and alternative) | Optional |\n| **BACKLOG** | One-liner rationale | No |\n\nBLOCKING and IN-SCOPE findings always include proof links.\nSUGGESTION findings include them when a well-known source\nexists. BACKLOG items need only a brief rationale since\nthey become separate issues with their own context.\n\n## Anti-Patterns\n\n### Don't: Lecture Without Context\n> \"You should use `pathlib` instead of `os.path`.\"\n\n**Do:** Explain why:\n> \"`pathlib` provides object-oriented path handling that\n> prevents string concatenation bugs (PEP 428). It also\n> makes path operations cross-platform by default.\"\n\n### Don't: Link Without Explaining\n> \"See https://owasp.org/...\"\n\n**Do:** Summarize what the link teaches:\n> \"OWASP classifies this as CWE-22 (Path Traversal).\n> The linked guide shows three defense layers:\n> canonicalization, allowlisting, and sandboxing.\"\n\n### Don't: Over-Teach on Trivial Findings\n> [Three paragraphs explaining why a typo matters]\n\n**Do:** Match depth to severity. A typo fix needs one line,\nnot a lecture.\n\n## Integration with Phase 6 Report\n\nThe Phase 6 report template already groups findings by\nclassification. Educational insights are embedded inline\nwithin each finding, not in a separate section. This\nkeeps the insight next to the code it explains, making\nthe review scannable and the lessons immediately visible.\n\n## Exit Criteria\n\n- [ ] Every BLOCKING finding has Why + Proof + Teachable Moment\n- [ ] Every IN-SCOPE finding has Why + Proof\n- [ ] SUGGESTION findings have Why (Proof if available)\n- [ ] Proof links are to authoritative, stable URLs\n- [ ] Insights explain the principle, not just the symptom\n\nFile v1.9.17:modules/github-comments.md\n\n# GitHub PR Comment Patterns\n\nReusable patterns for posting comments to GitHub PRs via the `gh` CLI.\n\n## Key API Differences\n\n| Endpoint | Use Case | Notes |\n|----------|----------|-------|\n| `gh pr comment` | General PR comments | Simple, always works |\n| `gh api .../reviews` | Inline comments on diff lines | Use `-F` for integers |\n| `gh pr review` | Summary with approve/request changes | Final submission |\n\n## Common Mistakes\n\n### Wrong: Individual Comments Endpoint with `line` parameter\n```bash\n# This will FAIL with HTTP 422\ngh api repos/{owner}/{repo}/pulls/{pr}/comments \\\n  -X POST \\\n  -f path='file.rs' \\\n  -f line=63 \\  # ERROR: \"line\" is not a permitted key\n  -f body='Comment'\n```\n\n### Right: Reviews Endpoint with Comments Array\n```bash\n# This works correctly\ngh api repos/{owner}/{repo}/pulls/{pr}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"Review summary\" \\\n  -f 'comments[][path]=file.rs' \\\n  -F 'comments[][line]=63' \\  # Use -F for integers!\n  -f 'comments[][body]=Inline comment text'\n```\n\n## Pattern: Single Inline Comment\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"See inline comment.\" \\\n  -f 'comments[][path]=src/auth/jwt.rs' \\\n  -F 'comments[][line]=63' \\\n  -f 'comments[][side]=RIGHT' \\\n  -f 'comments[][body]=**[IN-SCOPE]** JWT secondary secret\n\nThis fallback secret poses a security risk.\n\n**Recommendation:** Fail-fast on missing JWT_SECRET.'\n```\n\n## Pattern: Multiple Inline Comments\n\nFor multiple comments, use JSON input via `--input -`:\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  --input - <<'EOF'\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Review with inline comments\",\n  \"comments\": [\n    {\n      \"path\": \"src/auth.rs\",\n      \"line\": 26,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[IN-SCOPE]** Basic email validation\"\n    },\n    {\n      \"path\": \"src/routes.rs\",\n      \"line\": 45,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[SUGGESTION]** Consider rate limiting\"\n    }\n  ]\n}\nEOF\n```\n\n**Note:** The indexed array syntax (`comments[0][path]`) does NOT work with `gh api` - it creates an object instead of an array. Always use JSON input for multiple comments.\n\n## Pattern: General PR Comment (Not Inline)\n\nFor findings not on diff lines or when inline fails:\n\n```bash\ngh pr comment $PR_NUMBER --body '## Detailed Findings\n\n### IN-SCOPE (Should fix before merge)\n\n#### 1. JWT Fallback Secret (`src/auth/jwt.rs:62-63`)\n**Risk**: If deployed without `JWT_SECRET`, tokens use known secret.\n**Fix**: Fail-fast on missing secret.\n\n#### 2. Basic Email Validation (`src/routes/auth.rs:26`)\n**Risk**: Accepts invalid emails like `@@` or `test@`.\n**Fix**: Use proper email validation.'\n```\n\n## Pattern: Submit Review with Summary\n\n```bash\n# Determine event based on findings\nEVENT=\"COMMENT\"  # or \"REQUEST_CHANGES\" or \"APPROVE\"\n\ngh pr review $PR_NUMBER \\\n  --event $EVENT \\\n  --body \"$(cat <<'EOF'\n## PR Review Summary\n\n### Blocking Issues (2)\n- [B1] Missing token validation (auth.py:45)\n- [B2] SQL injection risk (models.py:123)\n\n### Suggestions (3)\n- See inline comments for details\n\n**Action Required:** Address blocking issues before merge.\nEOF\n)\"\n```\n\n## Secondary Strategy\n\nWhen inline comments fail (line not in diff, API issues):\n\n1. **Try inline first** via reviews API\n2. **On failure, fall back to PR comment** with file:line reference in body\n3. **Always post a summary comment** with all findings aggregated\n\n```bash\n# Secondary: Post as regular comment with location reference\ngh pr comment $PR_NUMBER --body \"**[B1] Issue at src/auth.rs:45**\n\nThis line was not in the PR diff, but the issue was identified during review.\n\nIssue: Missing validation\nSeverity: BLOCKING\nFix: Add input sanitization\"\n```\n\n## Extracting Owner/Repo\n\n```bash\n# From remote URL\nREMOTE_URL=$(git remote get-url origin)\nOWNER_REPO=$(echo \"$REMOTE_URL\" | sed -E 's/.*github\\.com[:/]([^/]+\\/[^/.]+).*/\\1/')\nOWNER=$(echo \"$OWNER_REPO\" | cut -d'/' -f1)\nREPO=$(echo \"$OWNER_REPO\" | cut -d'/' -f2)\n\n# Or from gh CLI\ngh repo view --json owner,name --jq '\"\\(.owner.login)/\\(.name)\"'\n```\n\n## Getting Commit SHA for Comments\n\n```bash\n# Get HEAD commit of the PR\nCOMMIT_SHA=$(gh pr view $PR_NUMBER --json headRefOid --jq '.headRefOid')\n\n# Or get the latest commit\nCOMMIT_SHA=$(gh pr view $PR_NUMBER --json commits --jq '.commits[-1].oid')\n```\n\nFile v1.9.17:modules/insight-generation.md\n\n---\nname: insight-generation\ndescription: Post PR-scoped insights to GitHub Discussions\n---\n\n## PR Insight Generation\n\nAfter completing the PR review analysis, generate insights\nfrom the review findings and post them to Discussions.\n\n### When to Run\n\nRun this module AFTER the main review is complete and\nfindings have been documented. Only generate insights for\nfindings with severity \"high\" or \"medium\".\n\n### Process\n\n1. Collect review findings from the current PR analysis\n2. For each high/medium finding, create a Finding object:\n\n```bash\ncd /home/alext/claude-night-market\npython3 -c \"\nimport sys, json\nsys.path.insert(0, 'plugins/abstract/scripts')\nfrom insight_types import Finding\nfrom post_insights_to_discussions import post_findings\n\nfindings = [\n    Finding(\n        type='PR Finding',\n        severity='$SEVERITY',\n        skill='',\n        summary='PR #$PR_NUMBER: $FINDING_SUMMARY',\n        evidence='$EVIDENCE',\n        recommendation='$RECOMMENDATION',\n        source='pr-review',\n        related_files=$CHANGED_FILES,\n    )\n]\nurls = post_findings(findings)\nfor url in urls:\n    print(f'Posted: {url}')\n\"\n```\n\n3. The posting script handles all dedup automatically\n4. Report posted URLs in the review summary\n\n### Finding Types\n\nMap review categories to insight types:\n\n| Review Category | Insight Type |\n|----------------|-------------|\n| Security issue | `[Bug Alert]` |\n| Logic error | `[Bug Alert]` |\n| Performance concern | `[Optimization]` |\n| Code quality | `[Improvement]` |\n| Test gap | `[PR Finding]` |\n| Architecture issue | `[PR Finding]` |\n\nFile v1.9.17:modules/knowledge-capture.md\n\n# Knowledge Capture Module\n\nCapture significant PR review findings into the project's review chamber.\n\n## Integration Point\n\nThis module executes **after Phase 6 (Generate Report)** and **before posting to GitHub**.\n\n```\nPhase 6: Generate Report\n    ↓\n[KNOWLEDGE CAPTURE MODULE]\n    ↓\nPhase 7: Post to GitHub\n```\n\n## Trigger Conditions\n\nEvaluate knowledge capture when:\n\n1. Review contains BLOCKING findings with architectural context\n2. Review contains recurring patterns (seen in 2+ PRs)\n3. Review establishes new conventions or standards\n4. Review documents a significant decision with rationale\n\n## Capture Workflow\n\n### Step 1: Extract Capture Candidates\n\nFrom the review findings, identify candidates for knowledge capture:\n\n```python\ndef extract_candidates(findings, pr_info):\n    \"\"\"Identify findings worth capturing.\"\"\"\n    candidates = []\n\n    for finding in findings:\n        # Score using evaluation criteria\n        score = evaluate_finding(finding, pr_info)\n\n        if score >= 60:\n            candidates.append({\n                \"finding\": finding,\n                \"score\": score,\n                \"room_type\": classify_room_type(finding),\n            })\n\n    return candidates\n```\n\n### Step 2: Classify Room Type\n\nRoute each candidate to the appropriate review-chamber room:\n\n| Finding Characteristics | Target Room |\n|------------------------|-------------|\n| Architectural decision with rationale | `decisions/` |\n| Recurring pattern or solution | `patterns/` |\n| Quality standard or convention | `standards/` |\n| Post-mortem insight or learning | `lessons/` |\n\n### Step 3: Create Review Entries\n\nFor each approved candidate:\n\n```yaml\n---\nsource_pr: \"#42 - Add authentication\"\ndate: 2025-01-15\nparticipants: [author, reviewers...]\npalace_location: review-chamber/decisions\ntags: [authentication, jwt, security]\n---\n\n## Decision Title\n\n### Decision\n[What was decided]\n\n### Context\n[Discussion that led to decision]\n\n### Captured Knowledge\n- Pattern: [reusable pattern]\n- Tradeoff: [key tradeoffs]\n- Application: [where to apply]\n\n### Connected\n- [[related-room]] - connection type\n```\n\n### Step 4: User Confirmation\n\nBefore capturing, present candidates to user:\n\n```markdown\n## 📚 Knowledge Capture\n\nFound **3** findings worth capturing to review-chamber:\n\n| # | Title | Score | Room | Action |\n|---|-------|-------|------|--------|\n| 1 | JWT over sessions | 95 | decisions | Capture |\n| 2 | API error format | 77 | standards | Capture |\n| 3 | Missing null check | 25 | - | Skip |\n\n**Options:**\n- [Y] Capture all (2 findings)\n- [S] Select which to capture\n- [N] Skip knowledge capture\n- [E] Edit before capture\n```\n\n### Step 5: Store in Project Palace\n\n```python\nfrom memory_palace.project_palace import (\n    ProjectPalaceManager,\n    ReviewEntry,\n    capture_pr_review_knowledge,\n)\n\ndef store_findings(findings, pr_info):\n    \"\"\"Store findings in project palace.\"\"\"\n\n    # Get or create project palace\n    manager = ProjectPalaceManager()\n    palace = manager.get_or_create_project_palace(\n        repo_name=pr_info.repo,\n        repo_url=pr_info.repo_url,\n    )\n\n    # Create entries for each finding\n    created = []\n    for finding in findings:\n        entry = ReviewEntry(\n            source_pr=f\"#{pr_info.number} - {pr_info.title}\",\n            title=finding.title,\n            room_type=finding.room_type,\n            content={\n                \"decision\": finding.description,\n                \"context\": finding.context,\n                \"captured_knowledge\": {\n                    \"severity\": finding.severity,\n                    \"category\": finding.category,\n                    \"file\": finding.file,\n                    \"line\": finding.line,\n                },\n                \"connected_concepts\": finding.related,\n            },\n            participants=pr_info.participants,\n            tags=finding.tags,\n        )\n\n        if manager.add_review_entry(palace[\"id\"], entry):\n            created.append(entry.id)\n\n    return created\n```\n\n## Output Integration\n\nAdd knowledge capture summary to the review report:\n\n```markdown\n## PR #42: Add Authentication\n\n### Scope Compliance\n...\n\n### Blocking Issues\n...\n\n### In-Scope Issues\n...\n\n### Knowledge Captured 📚\n\nThe following findings were stored in the project's review chamber:\n\n| Entry ID | Title | Room |\n|----------|-------|------|\n| abc123 | JWT over sessions | decisions/ |\n| def456 | Token refresh pattern | patterns/ |\n\nView in palace: `python scripts/palace_manager.py list-reviews --palace project-id`\n```\n\n## CLI Integration\n\n### Automatic (Default)\n\nWhen running `/pr-review`, knowledge capture triggers automatically for high-scoring findings:\n\n```bash\n/pr-review 42\n# ... review output ...\n# → Knowledge Capture: Captured 2 findings to review-chamber\n```\n\n### Manual Override\n\n```bash\n# Skip knowledge capture\n/pr-review 42 --no-capture\n\n# Force capture all findings\n/pr-review 42 --capture-all\n\n# Review and select interactively\n/pr-review 42 --capture-interactive\n```\n\n### Retroactive Capture\n\nCapture knowledge from a past review:\n\n```bash\n/review-room capture 42\n# Fetches PR #42 review comments and extracts knowledge\n```\n\n## Configuration\n\nIn `memory-palace/config/settings.json`:\n\n```json\n{\n  \"review_chamber\": {\n    \"auto_capture\": true,\n    \"capture_threshold\": 60,\n    \"require_confirmation\": true,\n    \"default_rooms\": [\"decisions\", \"patterns\", \"standards\", \"lessons\"],\n    \"excluded_categories\": [\"typo\", \"formatting\", \"style\"]\n  }\n}\n```\n\n## Evaluation Criteria\n\nUses `memory-palace:review-chamber` evaluation framework:\n\n| Criterion | Weight | Description |\n|-----------|--------|-------------|\n| Novelty | 25% | Is this new knowledge? |\n| Applicability | 30% | Will this affect future PRs? |\n| Durability | 20% | Architectural vs tactical? |\n| Connectivity | 15% | Links to existing knowledge? |\n| Authority | 10% | Expert reviewer involved? |\n\n**Threshold:** Score ≥ 60 triggers capture consideration.\n\n## Dependencies\n\n- `memory-palace:project-palace` - Project palace management\n- `memory-palace:review-chamber` - Room structure and evaluation\n- `memory-palace:knowledge-intake` - Evaluation framework\n\nFile v1.9.17:modules/pr-hygiene.md\n\n# PR Hygiene: Four Principles\n\nResearch-backed practices for PR quality that apply to\nevery review. These checks run during scope establishment\n(Phase 1) and code quality analysis (Phase 2.5).\n\n> **See Also**: [Main Skill](../SKILL.md) |\n> [Review Framework](../../../commands/pr-review/modules/review-framework.md)\n\n## Principle 1: Self-Review Before Sending\n\nOpen your own PR in the diff view and read it as if you\nare a reviewer seeing it for the first time. This catches\nscope creep, formatting commits, and unclear changes\nbefore anyone else spends time on them.\n\n### Detection (during `/pr-review`)\n\nWhen reviewing a PR, check for signs the author skipped\nself-review:\n\n```bash\n# Check for formatting-only commits mixed with feature work\ngh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -iE '(fmt|format|lint|style|whitespace|cleanup)' \\\n  && echo \"WARNING: Formatting commits mixed with feature work\"\n\n# Check for fixup/amend commits that should have been squashed\ngh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -iE '(fixup|fix typo|oops|wip|forgot|actually)' \\\n  && echo \"WARNING: Unsquashed fixup commits suggest no self-review\"\n```\n\n### Classification\n\n| Signal | Severity | Action |\n|--------|----------|--------|\n| Formatting-only commits mixed with feature work | SUGGESTION | Recommend squash or split |\n| 3+ fixup/typo commits | SUGGESTION | Recommend self-review pass |\n| Debug code left in (`console.log`, `print()`, `TODO`) | IN-SCOPE | Should remove before review |\n| Commented-out code blocks | IN-SCOPE | Should clean up |\n\n### Guidance for `/pr-prep` (Self-Review Checklist)\n\nBefore sending the PR, the author should verify:\n\n- [ ] Read the diff as a reviewer would\n- [ ] No debug statements left in\n- [ ] No commented-out code\n- [ ] No formatting-only commits mixed with logic changes\n- [ ] No fixup commits that should be squashed\n- [ ] Changes are limited to what the PR description promises\n\n## Principle 2: One PR = One Logical Change\n\nThe Single Responsibility Principle for PRs. Small,\nfocused PRs get reviewed faster, get reviewed more\nthoroughly (75%+ defect detection vs 30% for large PRs),\nand are easier to revert if something goes wrong.\n\n### Detection (during Phase 1: Scope Establishment)\n\nAnalyze commit messages and changed files for mixed\nconcerns:\n\n```bash\n# Count distinct conventional commit types\nCOMMIT_TYPES=$(gh pr view $PR_NUMBER --json commits \\\n  --jq '.commits[].messageHeadline' | \\\n  grep -oE '^(feat|fix|refactor|docs|test|chore|style|perf)' | \\\n  sort -u | wc -l)\n\nif [[ \"$COMMIT_TYPES\" -gt 2 ]]; then\n  echo \"WARNING: $COMMIT_TYPES distinct commit types - possible mixed concerns\"\nfi\n\n# Check for unrelated directory changes\nCHANGED_DIRS=$(gh pr diff $PR_NUMBER --name-only | \\\n  awk -F/ '{print $1\"/\"$2}' | sort -u | wc -l)\n\n# Large PRs with many unrelated directories\nCHANGED_FILES=$(gh pr view $PR_NUMBER --json changedFiles \\\n  --jq '.changedFiles')\n\nif [[ \"$CHANGED_FILES\" -gt 30 ]]; then\n  echo \"WARNING: $CHANGED_FILES files changed - consider splitting\"\nfi\n```\n\n### Atomicity Signals\n\n| Signal | Severity | Threshold |\n|--------|----------|-----------|\n| Mixed commit types (feat, refactor, and fix) | SUGGESTION | >2 distinct types |\n| Large file count | SUGGESTION | >30 files |\n| Mixed concerns across unrelated subsystems | IN-SCOPE | Subjective, reviewer judgment |\n| Refactor bundled with feature | SUGGESTION | Any occurrence |\n| Formatting changes bundled with logic | SUGGESTION | Any occurrence |\n\n### Classification\n\n- **BLOCKING**: Never. Splitting a PR is the author's\n  judgment call, not a gate.\n- **IN-SCOPE**: When mixed concerns are obvious and the\n  split would be straightforward (e.g., a `cargo fmt`\n  commit bundled with a feature).\n- **SUGGESTION**: When the PR is large but logically\n  coherent, note the size for awareness.\n\n### Recommendation Template\n\nWhen atomicity concerns are found:\n\n```markdown\n**[G-ATOMICITY] Consider splitting this PR**\n\nThis PR contains N distinct concerns:\n1. [concern A] (files: ...)\n2. [concern B] (files: ...)\n\nSmaller PRs get reviewed more thoroughly (75%+ defect\ndetection rate vs 30% for large PRs) and are easier to\nrevert. Consider splitting into:\n- PR 1: [concern A]\n- PR 2: [concern B]\n\nAuthor's discretion - this is a suggestion, not a blocker.\n```\n\n## Principle 3: Agent-Generated Code Needs Human Curation\n\nAI coding tools produce code quickly, but the output\nneeds careful review for: redundant code, unnecessary\ncomplexity, incomplete refactors, and scope drift.\nFormatting commits and mixed-concern refactors are\ntelltale signs of iterative AI generation without a\nfinal cleanup pass.\n\n### Detection (during Phase 2.5: Code Quality)\n\nLook for patterns characteristic of AI-generated code\nthat was not curated by a human before submission.\n\n#### Tier 1: Structural checks (always run)\n\n```bash\n# 1. Wrapper functions (function body is a single call)\n# Agent pattern: create_user() just calls _do_create_user()\ngh pr diff $PR_NUMBER | \\\n  awk '/^\\+.*def |^\\+.*fn |^\\+.*function /{name=$0; getline; \\\n  if(/^\\+\\s*(return |self\\.)/ && !/^\\+\\s*$/) print name \" -> WRAPPER?\"}' \\\n  2>/dev/null || true\n\n# 2. Redundant implementations (same logic, different names)\ngh pr diff $PR_NUMBER | \\\n  grep -E '^\\+.*(def |fn |function |func )' | \\\n  awk '{print $NF}' | sort | uniq -d\n\n# 3. Over-abstraction signals\n# New interfaces/traits/protocols with single implementations\nNEW_ABSTRACTIONS=$(gh pr diff $PR_NUMBER | \\\n  grep -cE '^\\+.*(trait |interface |protocol |abstract class )' || true)\nif [[ \"$NEW_ABSTRACTIONS\" -gt 0 ]]; then\n  echo \"CHECK: $NEW_ABSTRACTIONS new abstractions - verify each has 2+ implementations\"\nfi\n\n# 4. Incomplete refactors\n# Old function still called after new replacement added\nNEW_FUNCS=$(gh pr diff $PR_NUMBER | \\\n  grep -E '^\\+.*(def |fn |function )' | \\\n  sed 's/.*\\(def\\|fn\\|function\\) \\+\\([a-zA-Z_]*\\).*/\\2/' | head -10)\nfor func in $NEW_FUNCS; do\n  OLD_VARIANT=$(echo \"$func\" | sed 's/new_//;s/_v2$//;s/_updated$//')\n  if [[ \"$OLD_VARIANT\" != \"$func\" ]]; then\n    STILL_CALLED=$(gh pr diff $PR_NUMBER | grep -c \"$OLD_VARIANT\" || true)\n    if [[ \"$STILL_CALLED\" -gt 0 ]]; then\n      echo \"INCOMPLETE REFACTOR? $func replaces $OLD_VARIANT but old version still referenced\"\n    fi\n  fi\ndone\n```\n\n#### Tier 2: Diff-ratio checks (run for PRs > 10 files)\n\n```bash\n# 5. Addition-heavy ratio (agents add more than they remove)\nSTATS=$(gh pr view $PR_NUMBER --json additions,deletions \\\n  --jq '\"\\(.additions) \\(.deletions)\"')\nADDITIONS=$(echo $STATS | cut -d' ' -f1)\nDELETIONS=$(echo $STATS | cut -d' ' -f2)\n\nif [[ \"$DELETIONS\" -gt 0 ]]; then\n  RATIO=$((ADDITIONS / DELETIONS))\n  if [[ \"$RATIO\" -gt 5 ]]; then\n    echo \"CHECK: Add/delete ratio $RATIO:1 - agents tend to add without removing\"\n  fi\nfi\n\n# 6. Import bloat (new imports that may be unused)\nADDED_IMPORTS=$(gh pr diff $PR_NUMBER | \\\n  grep -cE '^\\+.*(^import |^from .* import |^use |require\\()' || true)\nif [[ \"$ADDED_IMPORTS\" -gt 10 ]]; then\n  echo \"CHECK: $ADDED_IMPORTS new imports - verify none are unused\"\nfi\n\n# 7. Scope drift via directory spread\nCHANGED_DIRS=$(gh pr diff $PR_NUMBER --name-only | \\\n  awk -F/ 'NF>1{print $1\"/\"$2}' | sort -u)\nDIR_COUNT=$(echo \"$CHANGED_DIRS\" | wc -l)\nif [[ \"$DIR_COUNT\" -gt 5 ]]; then\n  echo \"CHECK: Changes span $DIR_COUNT directories:\"\n  echo \"$CHANGED_DIRS\"\nfi\n```\n\n#### Tier 3: Content-level checks (reviewer judgment)\n\nThese cannot be fully automated. The reviewer should\nmanually check for:\n\n- **Boilerplate inflation**: Does the PR add config\n  files, CI changes, or documentation that is not\n  required by the stated goal?\n- **Defensive over-engineering**: Are there error\n  handlers for conditions that cannot happen? Try/catch\n  blocks wrapping infallible operations?\n- **Naming inconsistency**: Do new functions follow\n  existing naming conventions, or do they introduce a\n  different style (camelCase vs snake_case, different\n  prefix patterns)?\n- **Comment density spike**: Agent-generated code\n  often has more comments per line than human code.\n  If the PR's comment density is notably higher than\n  the surrounding code, flag it.\n\n### Agent Code Curation Signals\n\n| Signal | What to look for | Severity |\n|--------|-----------------|----------|\n| Redundant implementations | Functions doing the same thing with different names | IN-SCOPE |\n| Premature abstraction | New trait/interface with exactly one implementation | SUGGESTION |\n| Incomplete refactor | Old code path still exists alongside the new one | IN-SCOPE |\n| Over-engineered error handling | Catch-all handlers, unnecessary Result wrapping | SUGGESTION |\n| Unnecessary wrapper functions | Function that just calls another function | SUGGESTION |\n| Scope drift | Changes to files unrelated to the stated goal | IN-SCOPE |\n| Formatting commit bundled with logic | `cargo fmt` or `ruff format` in same PR as feature | SUGGESTION |\n| Config/boilerplate bloat | New config files, CI changes unrelated to feature | SUGGESTION |\n\n### Recommendation Template\n\nWhen agent curation issues are found:\n\n```markdown\n**[G-CURATION] Agent-generated code needs cleanup pass**\n\nThis PR shows signs of iterative AI generation without\na final curation pass:\n\n- [specific finding 1]\n- [specific finding 2]\n\nRecommendation: Review the PR with fresh eyes, asking\n\"does every change here serve the stated goal?\" Remove\nredundant code, collapse unnecessary abstractions, and\nsplit unrelated changes into separate PRs.\n```\n\n### Integration with Anti-Slop (Phase 1.7)\n\nAgent curation overlaps with slop detection but targets\n*structural* issues rather than *prose* issues:\n\n- **Slop detection** (Phase 1.7): AI markers in prose,\n  documentation, and commit messages\n- **Agent curation** (Phase 2.5): AI patterns in code\n  structure, architecture, and implementation choices\n\nBoth should run. Slop detection catches the writing;\nagent curation catches the engineering.\n\n## Principle 4: Tests Should Test Your Code\n\nTests should break if someone reverts your fix, not\ndemonstrate why the fix was needed. Assertion blocks\nshowing unrelated functionality are documentation,\nnot regression protection.\n\n### Detection (during Phase 2.5 and Test Plan)\n\nAnalyze test files changed in the PR:\n\n```bash\n# Get test files in the PR\nTEST_FILES=$(gh pr diff $PR_NUMBER --name-only | \\\n  grep -E '(test_|_test\\.|\\.test\\.|\\.spec\\.)')\n\n# Check for tests that only assert existing behavior\n# without connecting to the changed code\nfor file in $TEST_FILES; do\n  # Look for assertions about code NOT changed in this PR\n  gh pr diff $PR_NUMBER -- \"$file\" | \\\n    grep -E '^\\+.*assert' | head -10\ndone\n```\n\n### Test Quality Signals\n\n| Signal | What it means | Severity |\n|--------|--------------|----------|\n| Tests only assert pre-existing behavior | Demonstrating the problem, not protecting the fix | IN-SCOPE |\n| No tests touch code changed in this PR | Tests don't protect against regression | IN-SCOPE |\n| Tests pass with the fix reverted | Tests don't actually verify the fix | BLOCKING |\n| Test names describe old behavior, not new | Naming suggests documentation, not verification | SUGGESTION |\n| Assertion count >> code change size | Over-testing existing behavior | SUGGESTION |\n\n### The Revert Test\n\nThe gold standard for test quality: if someone reverts\nthe fix, at least one test should fail. If no test\nfails on revert, the tests are documentation, not\nprotection.\n\n```bash\n# Mental model for each test:\n# 1. Does this test touch code changed in this PR?\n# 2. Would reverting the PR changes cause this test to fail?\n# 3. If not, what regression does this test actually prevent?\n```\n\n### Classification\n\n- **BLOCKING**: Tests that pass even when the fix is\n  reverted (they test nothing about the new code)\n- **IN-SCOPE**: Tests that only assert old behavior\n  without covering the new code path\n- **SUGGESTION**: Tests that work but could be more\n  targeted or better named\n\n### Recommendation Template\n\nWhen test quality issues are found:\n\n```markdown\n**[S-TESTS] Tests should protect against regressions**\n\nThe following tests don't break if someone reverts this\nPR's changes:\n\n- `test_existing_behavior` in `test_module.py`\n  Asserts pre-existing behavior unrelated to the fix.\n\nWrite tests that:\n1. Would FAIL if the fix is reverted\n2. Cover the specific code path changed in this PR\n3. Protect against the exact regression being fixed\n\nTests should answer: \"what breaks if someone undoes my\nchange?\" not \"what was wrong before my change?\"\n```\n\n## Integration Checklist\n\nWhen this module is loaded, the following checks are\nadded to the review workflow:\n\n### Phase 1 (Scope Establishment)\n- [ ] Check PR atomicity (Principle 2)\n- [ ] Flag mixed commit types\n- [ ] Note PR size for awareness\n\n### Phase 2.5 (Code Quality)\n- [ ] Scan for agent curation signals (Principle 3)\n- [ ] Check for redundant implementations\n- [ ] Flag premature abstractions\n- [ ] Identify incomplete refactors\n\n### Phase 2.5 (Test Quality)\n- [ ] Apply the revert test mentally (Principle 4)\n- [ ] Verify tests touch changed code\n- [ ] Flag demonstration-only assertions\n\n### Report Generation (Phase 6)\n- [ ] Include self-review checklist if signals found (Principle 1)\n- [ ] Include atomicity recommendation if warranted (Principle 2)\n- [ ] Include curation findings (Principle 3)\n- [ ] Include test quality findings (Principle 4)\n\nFile v1.9.17:modules/version-validation.md\n\n# Version Validation Module\n\n**Purpose:** Enforce version consistency checks in PR reviews to catch version mismatches before merge.\n\n## When to Run\n\n**MANDATORY** for every PR review UNLESS:\n- Maintainer explicitly passes `--skip-version-check` flag\n- PR is labeled with `skip-version-check` in GitHub\n- PR description contains `[skip-version-check]` marker\n\n## Validation Checklist\n\n### 1. Detect Project Type & Version Files\n\n```bash\n# Determine project structure\nPROJECT_TYPE=\"\"\nVERSION_FILES=()\n\nif [[ -f \"Cargo.toml\" ]]; then\n  PROJECT_TYPE=\"rust\"\n  VERSION_FILES+=(\"Cargo.toml\")\nelif [[ -f \"package.json\" ]]; then\n  PROJECT_TYPE=\"node\"\n  VERSION_FILES+=(\"package.json\")\nelif [[ -f \"pyproject.toml\" ]]; then\n  PROJECT_TYPE=\"python\"\n  VERSION_FILES+=(\"pyproject.toml\")\nelif [[ -f \".claude-plugin/marketplace.json\" ]]; then\n  PROJECT_TYPE=\"claude-marketplace\"\n  VERSION_FILES+=(\".claude-plugin/marketplace.json\")\nfi\n\n# Always check CHANGELOG if it exists\n[[ -f \"CHANGELOG.md\" ]] && VERSION_FILES+=(\"CHANGELOG.md\")\n[[ -f \"CHANGELOG\" ]] && VERSION_FILES+=(\"CHANGELOG\")\n```\n\n### 2. Check Branch Name for Version Indicator\n\n```bash\n# Extract version from branch name if present\nBRANCH_NAME=$(gh pr view $PR_NUMBER --json headRefName -q .headRefName)\nBRANCH_VERSION=\"\"\n\n# Match patterns: release/1.2.3, version-1.2.3, feature-name-1.2.3, v1.2.3-branch\nif echo \"$BRANCH_NAME\" | grep -qE '[0-9]+\\.[0-9]+\\.[0-9]+'; then\n  BRANCH_VERSION=$(echo \"$BRANCH_NAME\" | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+' | head -1)\n  echo \"Branch name indicates version: $BRANCH_VERSION\"\nfi\n```\n\n### 3. Check if Version Changed in PR\n\n```bash\n# Get PR diff for version files\nVERSION_CHANGED=false\nfor file in \"${VERSION_FILES[@]}\"; do\n  if gh pr diff $PR_NUMBER --name-only | grep -qF \"$file\"; then\n    if gh pr diff $PR_NUMBER -- \"$file\" | grep -qE '^\\+.*version|^\\+.*## \\['; then\n      VERSION_CHANGED=true\n      break\n    fi\n  fi\ndone\n```\n\n### 4. If Version Changed, Run Full Validation\n\nIf `VERSION_CHANGED=true`, perform detailed checks:\n\n#### A. Extract Version from Each Source\n\n```bash\n# Example for claude-marketplace\nMARKETPLACE_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n# For each plugin in marketplace\njq -r '.plugins[] | \"\\(.name):\\(.version)\"' .claude-plugin/marketplace.json > /tmp/marketplace_versions.txt\n\n# For each actual plugin\nfor plugin_dir in plugins/*/; do\n  PLUGIN_NAME=$(basename \"$plugin_dir\")\n  ACTUAL_VERSION=$(jq -r '.version' \"$plugin_dir/.claude-plugin/plugin.json\" 2>/dev/null || echo \"MISSING\")\n  echo \"$PLUGIN_NAME:$ACTUAL_VERSION\" >> /tmp/actual_versions.txt\ndone\n```\n\n#### B. Compare Marketplace vs Actual\n\n```bash\n# Cross-reference versions\nwhile IFS=: read -r name marketplace_version; do\n  actual_version=$(grep \"^$name:\" /tmp/actual_versions.txt | cut -d: -f2)\n\n  if [[ \"$marketplace_version\" != \"$actual_version\" ]]; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] Version mismatch for $name: marketplace=$marketplace_version, actual=$actual_version\"\n  fi\ndone < /tmp/marketplace_versions.txt\n```\n\n#### C. Verify CHANGELOG Updated\n\n```bash\n# Check if CHANGELOG has entry for new version\nif [[ -f \"CHANGELOG.md\" ]]; then\n  NEW_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n  if ! grep -q \"\\[$NEW_VERSION\\]\" CHANGELOG.md; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] CHANGELOG.md missing entry for version $NEW_VERSION\"\n  fi\n\n  # Check for release date\n  if grep -q \"\\[$NEW_VERSION\\] - Unreleased\" CHANGELOG.md; then\n    # SUGGESTION\n    echo \"[G-VERSION] CHANGELOG shows version $NEW_VERSION as Unreleased - update date before merge\"\n  fi\nfi\n```\n\n#### D. Validate Branch Name Version Matches Marketplace Version\n\n```bash\n# If branch name contains a version, it MUST match the marketplace/project version\nif [[ -n \"$BRANCH_VERSION\" ]]; then\n  # Get current project version based on project type\n  CURRENT_VERSION=\"\"\n\n  if [[ \"$PROJECT_TYPE\" == \"claude-marketplace\" ]]; then\n    CURRENT_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n  elif [[ \"$PROJECT_TYPE\" == \"python\" ]]; then\n    CURRENT_VERSION=$(grep \"^version\" pyproject.toml | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n  elif [[ \"$PROJECT_TYPE\" == \"node\" ]]; then\n    CURRENT_VERSION=$(jq -r '.version' package.json)\n  elif [[ \"$PROJECT_TYPE\" == \"rust\" ]]; then\n    CURRENT_VERSION=$(grep \"^version\" Cargo.toml | head -1 | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n  fi\n\n  if [[ -n \"$CURRENT_VERSION\" ]] && [[ \"$BRANCH_VERSION\" != \"$CURRENT_VERSION\" ]]; then\n    # BLOCKING ISSUE FOUND\n    echo \"[B-VERSION] Branch name suggests version $BRANCH_VERSION, but marketplace/project version is $CURRENT_VERSION\"\n    echo \"  Branch: $BRANCH_NAME\"\n    echo \"  Expected: Version files should match branch name version\"\n    echo \"  Fix: Update version files to $BRANCH_VERSION OR rename branch to match $CURRENT_VERSION\"\n  fi\nfi\n```\n\n#### E. Check README Version References\n\n```bash\n# Check if README mentions version\nif [[ -f \"README.md\" ]]; then\n  if grep -q \"version\" README.md; then\n    # Extract version mentions\n    grep -i \"version\" README.md | while read -r line; do\n      # Check if it references old version\n      if echo \"$line\" | grep -qE \"[0-9]+\\.[0-9]+\\.[0-9]+\"; then\n        echo \"[INFO] README mentions version - verify accuracy\"\n      fi\n    done\n  fi\nfi\n```\n\n### 5. Project-Specific Validations\n\n#### Claude Plugin Marketplace\n\n```bash\n# Additional checks for claude-night-market structure\nif [[ \"$PROJECT_TYPE\" == \"claude-marketplace\" ]]; then\n\n  # Check metadata.version matches all plugin versions (unless independent cycle)\n  ECOSYSTEM_VERSION=$(jq -r '.metadata.version' .claude-plugin/marketplace.json)\n\n  # Get independent release plugins from CHANGELOG or docs\n  INDEPENDENT_PLUGINS=()\n  if grep -q \"independent release cycle\" CHANGELOG.md; then\n    # Extract plugin names marked as independent\n    INDEPENDENT_PLUGINS+=($(grep -A2 \"independent release cycle\" CHANGELOG.md | grep -oE '[a-z-]+' | head -5))\n  fi\n\n  # Verify non-independent plugins match ecosystem version\n  jq -r '.plugins[] | \"\\(.name):\\(.version)\"' .claude-plugin/marketplace.json | while IFS=: read -r name version; do\n    # Skip if independent\n    if [[ \" ${INDEPENDENT_PLUGINS[@]} \" =~ \" ${name} \" ]]; then\n      continue\n    fi\n\n    if [[ \"$version\" != \"$ECOSYSTEM_VERSION\" ]]; then\n      echo \"[B-VERSION] Plugin $name should be $ECOSYSTEM_VERSION (ecosystem version), but is $version\"\n    fi\n  done\nfi\n```\n\n#### Python Projects\n\n```bash\nif [[ \"$PROJECT_TYPE\" == \"python\" ]]; then\n  # Check __version__ in source\n  if [[ -d \"src\" ]]; then\n    VERSION_PY=$(find src -name \"__init__.py\" -exec grep -l \"__version__\" {} \\; | head -1)\n    if [[ -n \"$VERSION_PY\" ]]; then\n      CODE_VERSION=$(grep \"__version__\" \"$VERSION_PY\" | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n      TOML_VERSION=$(grep \"^version\" pyproject.toml | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+')\n\n      if [[ \"$CODE_VERSION\" != \"$TOML_VERSION\" ]]; then\n        echo \"[B-VERSION] __version__ ($CODE_VERSION) doesn't match pyproject.toml ($TOML_VERSION)\"\n      fi\n    fi\n  fi\nfi\n```\n\n## Classification of Version Issues\n\nAll version mismatches are **BLOCKING** unless explicitly waived:\n\n| Issue Type | Severity | Rationale |\n|------------|----------|-----------|\n| Branch name version ≠ marketplace/project version | BLOCKING | Branch naming indicates intended version - mismatch suggests incomplete version bump |\n| Version mismatch between files | BLOCKING | Breaks installation/packaging |\n| Missing CHANGELOG entry | BLOCKING | Required for release audit trail |\n| Marketplace vs plugin version mismatch | BLOCKING | Plugin installation will fail |\n| README references old version | IN-SCOPE | Documentation accuracy |\n| __version__ doesn't match package version | BLOCKING | Runtime version reporting broken |\n\n## Bypass Mechanism\n\nMaintainer can bypass with one of:\n\n1. **CLI flag**: `/pr-review <pr> --skip-version-check`\n2. **GitHub label**: Add `skip-version-check` label to PR\n3. **PR description marker**: Include `[skip-version-check]` in PR body\n\n**When bypassed:**\n- Still run validation and report findings\n- Mark as `[WAIVED]` instead of `[BLOCKING]`\n- Add note: \"Version validation bypassed by maintainer\"\n\n## Output Format\n\n```markdown\n### Version Validation\n\n**Status:** ✅ PASSED | ⚠️ WAIVED | ❌ FAILED\n\n**Version Detected:** 1.2.3 → 1.2.4\n\n**Files Checked:**\n- [x] .claude-plugin/marketplace.json: 1.2.4 ✓\n- [x] plugins/*/plugin.json: 1.2.4 ✓ (11 plugins)\n- [x] plugins/memory-palace/plugin.json: 1.3.0 ✓ (independent cycle)\n- [x] CHANGELOG.md: Entry for 1.2.4 ✓\n- [x] README.md: References updated ✓\n\n**Blocking Issues (0):**\nNone - all version files consistent.\n\n---\n\nOR with issues:\n\n### Version Validation\n\n**Status:** ❌ FAILED\n\n**Branch Name:** skills-improvements-1.2.2\n**Version Detected:** 1.1.0 → 1.2.1\n\n**Files Checked:**\n- [ ] Branch name version: 1.2.2 ≠ Marketplace version: 1.2.1 ❌\n- [x] .claude-plugin/marketplace.json: 1.2.1 ✓\n- [x] plugins/abstract/plugin.json: 1.2.1 ✓\n- [ ] plugins/memory-palace/plugin.json: Marketplace lists 1.2.1 but actual is 1.2.0 ❌\n- [x] CHANGELOG.md: Entry for 1.2.1 ✓\n- [ ] README.md: Still references 1.1.0 ⚠️\n\n**Blocking Issues (2):**\n- [B-VERSION-1] Branch name suggests version 1.2.2, but marketplace/project version is 1.2.1\n  - Branch: skills-improvements-1.2.2\n  - Expected: Version files should match branch name version\n  - Fix: Update version files to 1.2.2 OR rename branch to match 1.2.1\n- [B-VERSION-2] Version mismatch: memory-palace\n  - Marketplace: 1.2.1\n  - Actual: 1.2.0\n  - Fix: Update marketplace.json line 52 to \"1.2.0\"\n\n**In-Scope Issues (1):**\n- [S-VERSION-1] README references old version 1.1.0\n  - Fix: Update README.md to reference 1.2.1\n```\n\n## Integration with PR Review Workflow\n\nThis module runs in **Phase 1.5** (after scope establishment, before code analysis):\n\n```\nPhase 1: Scope Establishment\nPhase 1.5: Version Validation ← NEW\nPhase 2: Code Analysis\nPhase 3: Synthesis & Validation\nPhase 4: GitHub Review Submission\nPhase 5: Test Plan Generation\n```\n\n**Why Phase 1.5?**\n- Version issues are blocking and should be caught early\n- Prevents wasting time on detailed code review if basic version hygiene fails\n- Provides fast feedback to PR author\n\n## Error Handling\n\n### Missing Version Files\n```markdown\n⚠️ Version validation skipped: No version files detected in repository.\nConsider adding CHANGELOG.md for release tracking.\n```\n\n### Multiple Version Schemes\n```markdown\nℹ️ Detected multiple version schemes:\n- Python package: 2.1.0 (pyproject.toml)\n- Frontend: 1.5.0 (package.json)\n\nValidated each independently.\n```\n\n### Parse Failures\n```bash\nif ! jq -e '.metadata.version' .claude-plugin/marketplace.json >/dev/null 2>&1; then\n  echo \"[B-VERSION] Failed to parse version from marketplace.json - invalid JSON?\"\nfi\n```\n\n## Testing the Module\n\n```bash\n# Test version validation manually\nSkill(sanctum:pr-review)\n\n# With bypass\n/pr-review 42 --skip-version-check\n\n# Dry run to see what would be checked\n/pr-review 42 --dry-run\n```\n\n## Maintenance Notes\n\n- Update detection patterns when new project types are added\n- Keep version file list synchronized with `sanctum:version-updates` skill\n- Consider adding support for monorepo version strategies\n- May need adjustment for projects using date-based or git-hash versions\n\nFile v1.9.17:skill-card.md\n\n## Description: <br>\nReviews pull requests with scope validation, requirements compliance, and line comments. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineers use this skill to review GitHub or GitLab pull and merge requests against the stated scope, validate version and hygiene requirements, classify findings, and generate review reports or comments. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill may interact with GitHub or GitLab to post PR comments, submit review summaries, or create backlog issues. <br>\nMitigation: Review platform commands before execution, use least-privilege tokens, and require confirmation before posting comments or creating issues. <br>\nRisk: The skill includes under-disclosed external posting of PR-scoped insights to GitHub Discussions. <br>\nMitigation: Disable or remove the Discussions insight module unless publishing review findings outside the PR is explicitly intended. <br>\nRisk: The skill can retain selected review findings through knowledge capture. <br>\nMitigation: Use no-capture or confirmation-required mode for sensitive repositories and review captured content before storage. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-sanctum-pr-review) <br>\n- [Publisher profile](https://clawhub.ai/user/athola) <br>\n- [OpenClaw homepage metadata](https://github.com/athola/claude-night-market/tree/master/plugins/sanctum) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, guidance] <br>\n**Output Format:** [Markdown review reports, inline review comments, issue text, and command guidance.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May propose platform API commands for PR comments, backlog issues, and review summaries.] <br>\n\n## Skill Version(s): <br>\n1.9.17 (source: server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.9.16: 10 files, 30248 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2649b), SKILL.md (21009b), _meta.json (140b)\n\nFile v1.9.16:SKILL.md\n\n---\nname: pr-review\ndescription: |\n  Reviews pull requests with scope validation, requirements compliance, and line comments\nversion: 1.9.8\ntriggers:\n  - pr\n  - review\n  - scope\n  - github\n  - gitlab\n  - code-quality\n  - knowledge-capture\n  - cross-platform\n  - reviewing GitHub or GitLab PRs\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/sanctum\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.leyline:git-platform\", \"night-market.sanctum:shared\n\nArchive v1.9.14: 10 files, 30216 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2522b), SKILL.md (21009b), _meta.json (140b)\n\nArchive v1.9.13: 10 files, 30127 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2461b), SKILL.md (21009b), _meta.json (140b)\n\nArchive v1.9.12: 10 files, 30161 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2390b), SKILL.md (21009b), _meta.json (140b)\n\nArchive v1.0.3: 10 files, 30120 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4375b), modules/github-comments.md (4368b), modules/insight-generation.md (1569b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13383b), modules/version-validation.md (11356b), skill-card.md (2300b), SKILL.md (21009b), _meta.json (139b)\n\nArchive v1.0.2: 9 files, 27575 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4369b), modules/github-comments.md (4368b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13381b), modules/version-validation.md (11356b), skill-card.md (2166b), SKILL.md (17275b), _meta.json (139b)\n\nArchive v1.0.1: 8 files, 26392 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4369b), modules/github-comments.md (4368b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13381b), modules/version-validation.md (11356b), SKILL.md (17275b), _meta.json (139b)\n\nArchive v1.0.0: 8 files, 26392 bytes\n\nFiles: modules/comment-guidelines.md (5122b), modules/educational-insights.md (4369b), modules/github-comments.md (4368b), modules/knowledge-capture.md (6126b), modules/pr-hygiene.md (13381b), modules/version-validation.md (11356b), SKILL.md (17275b), _meta.json (139b)","readmeExcerpt":"Skill: pr-review Owner: athola Summary: Reviews pull requests with scope validation, requirements compliance, and line comments Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:20:39.575Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:40:42.486Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:57:35.890Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:05:27.217Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# Spec-kit feature plans (preferred - structured implementation blueprints)\n   find specs -name \"plan.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   # Legacy/alternative locations\n   ls docs/plans/ 2>/dev/null\n   # Root plan.md (may be Claude Plan Mode artifact from v2.0.51+)\n   cat plan.md 2>/dev/null | head -100"},{"language":"bash","snippet":"find specs -name \"spec.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -100\n   cat spec.md 2>/dev/null | head -100"},{"language":"bash","snippet":"find specs -name \"tasks.md\" -type f 2>/dev/null | head -1 | xargs cat 2>/dev/null\n   cat tasks.md 2>/dev/null"},{"language":"bash","snippet":"# GitHub\n   gh pr view <number> --json body --jq '.body'\n   # GitLab\n   glab mr view <number> --json description --jq '.description'"},{"language":"bash","snippet":"# GitHub\n   gh pr view <number> --json commits --jq '.commits[].messageHeadline'\n   # GitLab\n   glab mr view <number> --json commits"},{"language":"bash","snippet":"# GitHub\ngh pr diff <number> --name-only\ngh pr diff <number>\ngh pr view <number> --json additions,deletions,changedFiles,commits\n\n# GitLab\nglab mr diff <number>\nglab mr view <number>"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: pr-review\ndescription: |\n  Reviews pull requests with scope validation, requirements compliance, and line comments\nversion: 1.9.8\ntriggers:\n  - pr\n  - review\n  - scope\n  - github\n  - gitlab\n  - code-quality\n  - knowledge-capture\n  - cross-platform\n  - reviewing GitHub or GitLab PRs\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/sanctum\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.leyline:git-platform\", \"night-market.sanctum:shared\", \"night-market.sanctum:git-workspace-review\", \"night-market.sanctum:version-updates\", \"night-market.pensive:unified-review\", \"night-market.imbue:proof-of-work\", \"night-market.imbue:justify\", \"night-market.memory-palace:review-chamber\", \"night-market.scribe:slop-detector\", \"night-market.scribe:doc-generator\"]}}}\nsource: claude-night-market\nsource_plugin: sanctum\n---\n\n> **Night Market Skill** — ported from [claude-night-market/sanctum](https://github.com/athola/claude-night-market/tree/master/plugins/sanctum). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Core Principle](#core-principle)\n- [When to Use](#when-to-use)\n- [Scope Classification Framework](#scope-classification-framework)\n- [Classification Examples](#classification-examples)\n- [Workflow](#workflow)\n- [Phase 1: Establish Scope Baseline](#phase-1-establish-scope-baseline)\n- [Phase 2: Gather Changes](#phase-2-gather-changes)\n- [Phase 3: Requirements Validation](#phase-3-requirements-validation)\n- [Phase 1.5: Version Validation (MANDATORY)](#phase-15-version-validation-mandatory)\n- [Phase 4: Code Review with Scope Context](#phase-4-code-review-with-scope-context)\n- [Phase 4.5: Additive Bias Audit](#phase-45-additive-bias-audit)\n- [Phase 5: Backlog Triage](#phase-5-backlog-triage)\n- [Phase 6: Generate Report](#phase-6-generate-report)\n- [Phase 7: Knowledge Capture](#phase-7-knowledge-capture)\n- [Quality Gates](#quality-gates)\n- [Anti-Patterns to Avoid](#anti-patterns-to-avoid)\n- [Don't: Scope Creep Review](#dont-scope-creep-review)\n- [Don't: Perfect is Enemy of Good](#dont-perfect-is-enemy-of-good)\n- [Don't: Blocking on Style](#dont-blocking-on-style)\n- [Don't: Reviewing Unchanged Code](#dont-reviewing-unchanged-code)\n- [Integration with Other Tools](#integration-with-other-tools)\n- [Exit Criteria](#exit-criteria)\n\n\n# Scope-Focused PR Review\n\nReview pull/merge requests with discipline: validate against original requirements, prevent scope creep, and route out-of-scope findings to issues on the detected platform.\n\n**Platform detection is automatic** via `leyline:git-platform`. Use `gh` for GitHub, `glab` for GitLab. Check session context for `git_platform:`.\n\n## Core Principle\n\n**A PR review validates scope compliance, not code perfection.**\n\nThe goal is to validate the implementation meets its stated requirements without introducing regressions. Improvements beyond the scope belong in future PRs.\n\n## When To U"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-sanctum-pr-review\",\n  \"version\": \"1.9.19\",\n  \"publishedAt\": 1787750439575\n}"},{"path":"modules/comment-guidelines.md","content":"# Code Comment Quality Guidelines\n\nGuidance on when and how to write effective code comments that add value without bloat.\n\n## Core Philosophy: Why, Not What\n\nGood comments explain **why** code exists, not **what** it does. The code already shows what it does.\n\n| Comment Type | Value | Example |\n|--------------|-------|---------|\n| **Why** | High | \"Use exponential backoff to handle transient API failures\" |\n| **What** | Low | \"Loop through the array\" |\n| **Context** | High | \"AWS Lambda has 15-min timeout, so max 3 retries\" |\n| **Obvious** | Negative | \"Increment counter by 1\" |\n\n## When Comments Are Warranted\n\n### Require Comments For\n\n| Scenario | Reason | Example |\n|----------|--------|---------|\n| **Non-obvious behavior** | Future readers will wonder why | Edge case handling |\n| **Business logic decisions** | Domain knowledge not in code | \"Tax calculated per 2024 regulations\" |\n| **Performance optimizations** | Why this approach over simpler one | \"O(1) lookup vs O(n) iteration\" |\n| **Workarounds** | Temporary fixes need context | \"TODO: Remove after #123 fixed\" |\n| **Algorithm complexity** | Complex logic needs explanation | Mathematical formulas |\n| **External constraints** | Dependencies, APIs, limits | \"API rate limit: 100 req/min\" |\n\n### Don't Require Comments For\n\n| Scenario | Alternative |\n|----------|-------------|\n| Self-explanatory code | Good naming |\n| Simple CRUD operations | Patterns speak |\n| Well-named functions | Function name = documentation |\n| Standard patterns | Convention over comment |\n\n## Examples\n\n### Good Comments (Explain Why)\n\n```python\ndef retry_with_backoff(max_attempts=3):\n    \"\"\"Retry with exponential backoff for transient failures.\n\n    AWS Lambda has a 15-minute timeout, so max_attempts=3 prevents\n    exceeding this limit with our 1s/2s/4s backoff strategy.\n    \"\"\"\n    ...\n\n# Use set for O(1) membership testing instead of list O(n)\n# Critical for processing 100k+ items in batch jobs\nseen_ids = set()\n```\n\n### Bad Comments (Explain What - Avoid These)\n\n```python\n# Bad: Restates code\ni = 0  # Set i to 0\n\n# Bad: Obvious from code\nif user_input == \"\":  # Check if user_input is empty string\n    return DEFAULT_VALUE\n\n# Bad: Redundant docstring\ndef add(a, b):\n    \"\"\"Add two numbers and return the result.\"\"\"\n    return a + b\n```\n\n## Anti-Patterns\n\n### Over-Commenting (Bloat)\n\n**Problem**: Too many comments obscure code and become maintenance burden.\n\n**Symptoms**:\n- Comment-to-code ratio > 1:3\n- Comments on every line\n- Comments restating variable names\n\n**Solution**: Improve code clarity instead. Better names, smaller functions.\n\n### Stale Comments (Out of Sync)\n\n**Problem**: Comments that don't match current code behavior are worse than no comments.\n\n**Symptoms**:\n- Function behavior changed, comment didn't\n- TODO comments for completed work\n- References to deleted code\n\n**Solution**: Update comments with code changes. Delete outdated TODOs.\n\n### Commented-Out Code\n\n**Problem**: Dead code clutters codebase and con"},{"path":"modules/educational-insights.md","content":"---\nname: educational-insights\ndescription: >-\n  Enrich PR review findings with educational context:\n  why the fix matters, proof via best-practice links,\n  and teachable moments that grow the implementer.\nparent_skill: sanctum:pr-review\ncategory: review-infrastructure\ntags: [education, insights, best-practices, teaching]\nestimated_tokens: 300\n---\n\n# Educational Insights for PR Review Findings\n\nEvery finding in a PR review is a learning opportunity.\nEach reported issue, suggestion, or error MUST include\neducational context so the review improves both the code\nand the person who wrote it.\n\n## The Three Pillars\n\nEach finding includes three educational elements:\n\n| Pillar | Purpose | Content |\n|--------|---------|---------|\n| **Why It Matters** | Explain the principle | 1-2 sentences on the underlying concept |\n| **Proof** | Link to authoritative source | URL to docs, standard, or guide |\n| **Teachable Moment** | Generalize the lesson | How this pattern applies beyond this PR |\n\n## Enriched Finding Format\n\nEvery finding entry (BLOCKING, IN-SCOPE, SUGGESTION)\nMUST use this extended format:\n\n```markdown\n1. [S1] Missing input validation on user-supplied path\n   - **Location**: `api/handlers.py:45`\n   - **Issue**: Path traversal possible via `../` in filename\n   - **Why**: Unsanitized file paths allow directory traversal\n     attacks (CWE-22). An attacker can read or overwrite\n     files outside the intended directory.\n   - **Proof**: [OWASP Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal)\n   - **Teachable Moment**: Always normalize paths with\n     `os.path.realpath()` and verify they stay within the\n     expected root. This applies to any function accepting\n     file paths from external input.\n   - **Fix**:\n     ```python\n     real = os.path.realpath(user_path)\n     if not real.startswith(allowed_root):\n         raise ValueError(\"Path outside allowed directory\")\n     ```\n```\n\n## How to Source Proof Links\n\nUse authoritative references in this priority order:\n\n1. **Language/framework docs** (python.org, docs.rs,\n   developer.mozilla.org)\n2. **Security standards** (OWASP, CWE, NIST)\n3. **Style guides** (PEP 8, Google Style Guide, Effective Go)\n4. **Well-known articles** (Martin Fowler, Dan Abramov,\n   Kent Beck)\n5. **RFCs and specifications** (IETF RFCs, W3C specs)\n\nWhen no authoritative URL exists, cite the principle by\nname (e.g., \"Liskov Substitution Principle\") and briefly\nexplain it inline.\n\n## Insight Depth by Classification\n\n| Classification | Insight Depth | Proof Required |\n|---------------|--------------|----------------|\n| **BLOCKING** | Full (why, impact, and fix) | Yes, with link |\n| **IN-SCOPE** | Standard (why and fix) | Yes, with link |\n| **SUGGESTION** | Brief (why and alternative) | Optional |\n| **BACKLOG** | One-liner rationale | No |\n\nBLOCKING and IN-SCOPE findings always include proof links.\nSUGGESTION findings include them when a well-known source\nexists. BACKLOG items need only a brief rationale since\nthey bec"},{"path":"modules/github-comments.md","content":"# GitHub PR Comment Patterns\n\nReusable patterns for posting comments to GitHub PRs via the `gh` CLI.\n\n## Key API Differences\n\n| Endpoint | Use Case | Notes |\n|----------|----------|-------|\n| `gh pr comment` | General PR comments | Simple, always works |\n| `gh api .../reviews` | Inline comments on diff lines | Use `-F` for integers |\n| `gh pr review` | Summary with approve/request changes | Final submission |\n\n## Common Mistakes\n\n### Wrong: Individual Comments Endpoint with `line` parameter\n```bash\n# This will FAIL with HTTP 422\ngh api repos/{owner}/{repo}/pulls/{pr}/comments \\\n  -X POST \\\n  -f path='file.rs' \\\n  -f line=63 \\  # ERROR: \"line\" is not a permitted key\n  -f body='Comment'\n```\n\n### Right: Reviews Endpoint with Comments Array\n```bash\n# This works correctly\ngh api repos/{owner}/{repo}/pulls/{pr}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"Review summary\" \\\n  -f 'comments[][path]=file.rs' \\\n  -F 'comments[][line]=63' \\  # Use -F for integers!\n  -f 'comments[][body]=Inline comment text'\n```\n\n## Pattern: Single Inline Comment\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  -f event=\"COMMENT\" \\\n  -f body=\"See inline comment.\" \\\n  -f 'comments[][path]=src/auth/jwt.rs' \\\n  -F 'comments[][line]=63' \\\n  -f 'comments[][side]=RIGHT' \\\n  -f 'comments[][body]=**[IN-SCOPE]** JWT secondary secret\n\nThis fallback secret poses a security risk.\n\n**Recommendation:** Fail-fast on missing JWT_SECRET.'\n```\n\n## Pattern: Multiple Inline Comments\n\nFor multiple comments, use JSON input via `--input -`:\n\n```bash\ngh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \\\n  --method POST \\\n  --input - <<'EOF'\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Review with inline comments\",\n  \"comments\": [\n    {\n      \"path\": \"src/auth.rs\",\n      \"line\": 26,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[IN-SCOPE]** Basic email validation\"\n    },\n    {\n      \"path\": \"src/routes.rs\",\n      \"line\": 45,\n      \"side\": \"RIGHT\",\n      \"body\": \"**[SUGGESTION]** Consider rate limiting\"\n    }\n  ]\n}\nEOF\n```\n\n**Note:** The indexed array syntax (`comments[0][path]`) does NOT work with `gh api` - it creates an object instead of an array. Always use JSON input for multiple comments.\n\n## Pattern: General PR Comment (Not Inline)\n\nFor findings not on diff lines or when inline fails:\n\n```bash\ngh pr comment $PR_NUMBER --body '## Detailed Findings\n\n### IN-SCOPE (Should fix before merge)\n\n#### 1. JWT Fallback Secret (`src/auth/jwt.rs:62-63`)\n**Risk**: If deployed without `JWT_SECRET`, tokens use known secret.\n**Fix**: Fail-fast on missing secret.\n\n#### 2. Basic Email Validation (`src/routes/auth.rs:26`)\n**Risk**: Accepts invalid emails like `@@` or `test@`.\n**Fix**: Use proper email validation.'\n```\n\n## Pattern: Submit Review with Summary\n\n```bash\n# Determine event based on findings\nEVENT=\"COMMENT\"  # or \"REQUEST_CHANGES\" or \"APPROVE\"\n\ngh pr review $PR_NUMBER \\\n  --event $EVENT \\\n  --body \"$(cat <<'EOF'\n## PR Review Summary\n\n### Blocking Issues (2)\n- [B1] Mi"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Reviews pull requests with scope validation, requirements compliance, and line comments Skill: pr-review Owner: athola Summary: Reviews pull requests with scope validation, requirements compliance, and line comments Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:20:39.575Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:40:42.486Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:57:35.890Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:05:27.217Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1468,"uniquenessScore":53,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:23:56.378Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:00:22.799Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}