@esoteric-logic/praxis-harness 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/base/CLAUDE.md +37 -3
  2. package/base/agents/evaluator.md +44 -0
  3. package/base/agents/planner.md +48 -0
  4. package/base/hooks/auto-format.sh +1 -1
  5. package/base/hooks/dep-audit.sh +1 -1
  6. package/base/hooks/file-guard.sh +3 -3
  7. package/base/hooks/recursion-guard.sh +7 -1
  8. package/base/hooks/session-data-collect.sh +1 -1
  9. package/base/hooks/vault-checkpoint.sh +5 -5
  10. package/base/rules/code-excellence.md +22 -0
  11. package/base/rules/coding.md +16 -0
  12. package/base/rules/context-budget.md +66 -0
  13. package/base/rules/context-management.md +4 -0
  14. package/base/rules/hooks-policy.md +53 -0
  15. package/base/rules/multi-agent-orchestration.md +99 -0
  16. package/base/rules/observable-code.md +87 -0
  17. package/base/rules/phase-detection.md +52 -0
  18. package/base/rules/refactor-triggers.md +59 -0
  19. package/base/rules/self-repair.md +53 -0
  20. package/base/rules/session-bridge.md +39 -0
  21. package/base/rules/session-metrics.md +61 -0
  22. package/base/rules/skill-authoring.md +85 -0
  23. package/base/rules/writing-quality.md +122 -0
  24. package/base/skills/px-compact/SKILL.md +100 -0
  25. package/base/skills/px-complexity-audit/SKILL.md +118 -0
  26. package/base/skills/px-context-probe/SKILL.md +1 -1
  27. package/base/skills/px-context-triage/SKILL.md +76 -0
  28. package/base/skills/px-discover/SKILL.md +4 -1
  29. package/base/skills/px-discuss/SKILL.md +4 -1
  30. package/base/skills/px-doc-lint/SKILL.md +107 -0
  31. package/base/skills/px-prose-review/SKILL.md +96 -0
  32. package/base/skills/px-quality-gate/SKILL.md +182 -0
  33. package/base/skills/px-risk/SKILL.md +4 -1
  34. package/base/skills/px-scaffold-new/SKILL.md +16 -14
  35. package/base/skills/px-session-retro/SKILL.md +1 -1
  36. package/base/skills/px-spec/SKILL.md +6 -2
  37. package/base/skills/px-verify/SKILL.md +2 -1
  38. package/bin/praxis.js +27 -6
  39. package/kits/api/KIT.md +2 -0
  40. package/kits/api/install.sh +1 -1
  41. package/kits/api/teardown.sh +1 -1
  42. package/kits/code-quality/KIT.md +2 -0
  43. package/kits/code-quality/hooks/generate-baseline.sh +1 -1
  44. package/kits/code-quality/hooks/post-commit.sh +3 -2
  45. package/kits/code-quality/hooks/pre-push.sh +15 -15
  46. package/kits/code-quality/install.sh +1 -1
  47. package/kits/code-quality/teardown.sh +3 -3
  48. package/kits/data/KIT.md +2 -0
  49. package/kits/data/install.sh +1 -1
  50. package/kits/data/teardown.sh +1 -1
  51. package/kits/infrastructure/KIT.md +2 -0
  52. package/kits/infrastructure/install.sh +1 -1
  53. package/kits/infrastructure/teardown.sh +1 -1
  54. package/kits/security/KIT.md +2 -0
  55. package/kits/security/install.sh +1 -1
  56. package/kits/security/teardown.sh +1 -1
  57. package/kits/web-designer/KIT.md +2 -0
  58. package/kits/web-designer/install.sh +1 -1
  59. package/kits/web-designer/teardown.sh +1 -1
  60. package/package.json +1 -1
  61. package/scripts/health-check.sh +21 -15
  62. package/scripts/install-tools.sh +5 -5
  63. package/scripts/lint-harness.sh +1 -1
  64. package/scripts/onboard-mcp.sh +1 -1
  65. package/scripts/test-harness.sh +1 -1
  66. package/scripts/update.sh +1 -1
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: px-complexity-audit
3
+ disable-model-invocation: true
4
+ description: "Codebase debt scanner. Ranks files by complexity score (size, nesting, debt markers, generic names). Use at sprint start, before major features, or quarterly. Outputs heat map and refactor targets."
5
+ ---
6
+
7
+ # px-complexity-audit — Codebase Debt Scanner
8
+
9
+ ## Purpose
10
+
11
+ Scans the existing codebase for accumulated technical debt.
12
+ Outputs a ranked heat map of files needing attention.
13
+ Use before starting major feature work or at sprint boundaries.
14
+
15
+ ## When To Use
16
+
17
+ 1. Sprint start: identify cleanup targets before new work begins
18
+ 2. Pre-feature: assess the health of files you are about to modify
19
+ 3. Quarterly: full codebase scan, results written to vault
20
+ 4. On-demand: `/px-complexity-audit {directory}` for targeted scan
21
+
22
+ ## What It Scans
23
+
24
+ ### File-level metrics
25
+
26
+ ```bash
27
+ FILE_LINES=$(wc -l < "$f")
28
+ TODO_COUNT=$(grep -cE 'TODO|FIXME|HACK|QUALITY:' "$f" || echo 0)
29
+ FUNC_COUNT=$(grep -cE '(func |def |function |const .* = )' "$f" || echo 0)
30
+ DEEP_NEST=$(grep -cE '^\s{16,}\S|^\t{4,}\S' "$f" || echo 0)
31
+ GENERIC_NAMES=$(grep -oE '\b(data|result|info|temp|tmp|obj|val|item|stuff|thing|ret|res)\b' "$f" | wc -l || echo 0)
32
+ ```
33
+
34
+ ### Debt score formula
35
+
36
+ Each file receives a composite score (higher = more urgent):
37
+
38
+ ```
39
+ debt_score = (
40
+ (file_lines / 300 * 30) + # Over size limit: 30 points at 300 lines
41
+ (todo_count * 10) + # 10 points per debt marker
42
+ (deep_nest_lines * 5) + # 5 points per deeply nested line
43
+ (generic_name_count * 2) + # 2 points per generic name
44
+ (longest_function / 30 * 20) # Over function limit: 20 points at 30 lines
45
+ )
46
+ ```
47
+
48
+ Thresholds:
49
+
50
+ - Score 0-20: CLEAN — no action needed
51
+ - Score 21-50: WATCH — consider cleanup if touching this file
52
+ - Score 51-80: REFACTOR — clean up before adding features
53
+ - Score 81+: CRITICAL — stop and refactor now
54
+
55
+ ### Potential dead code detection
56
+
57
+ ```bash
58
+ for func_name in $(grep -ohE '(func|def|function)\s+\w+' "$f" | awk '{print $2}'); do
59
+ refs=$(rg -l "$func_name" --type-add 'code:*.{go,ts,py,js,rs,java}' -t code . | grep -v "$f" | wc -l || echo 0)
60
+ if [[ "$refs" -eq 0 ]]; then
61
+ echo "POTENTIAL_DEAD: $func_name in $f (0 external references)"
62
+ fi
63
+ done
64
+ ```
65
+
66
+ ## Output Format
67
+
68
+ ### Heat Map (terminal output)
69
+
70
+ ```
71
+ ━━━ COMPLEXITY AUDIT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
72
+ Scanned: 47 files | CLEAN: 31 | WATCH: 9 | REFACTOR: 5 | CRIT: 2
73
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
74
+
75
+ TOP 5 REFACTOR TARGETS
76
+
77
+ Rank | File | Score | Primary Issue
78
+ ─────┼─────────────────────────────┼───────┼────────────────────
79
+ 1 | services/auth/handler.go | 94 | 342 lines, 4 TODOs
80
+ 2 | services/billing/calc.py | 87 | 60-line function
81
+ 3 | handlers/api/v2/users.ts | 73 | 5-level nesting
82
+ 4 | lib/cache/redis.go | 58 | 12 generic names
83
+ 5 | cmd/worker/process.go | 52 | 3 TODOs, 280 lines
84
+
85
+ Estimated effort: ~4 hours for top 5
86
+ ```
87
+
88
+ ### Effort estimation heuristic
89
+
90
+ | Action | Estimated time |
91
+ | ------ | -------------- |
92
+ | Split a 300+ line file | 30-45 min |
93
+ | Extract a 30+ line function | 15-20 min |
94
+ | Flatten deep nesting | 10-15 min per function |
95
+ | Rename generic variables | 5-10 min per file |
96
+ | Address a TODO with ticket | 5 min (triage) or 30+ min (fix) |
97
+
98
+ ### Vault output
99
+
100
+ When run with `--write-vault` or during quarterly scan:
101
+
102
+ ```
103
+ Output path: {vault_path}/specs/debt-audit-{YYYY-MM-DD}.md
104
+ ```
105
+
106
+ Contents:
107
+
108
+ - Full ranked file list with scores
109
+ - Top 5 refactor targets with specific actions
110
+ - Trend comparison if previous audit exists (score delta per file)
111
+ - Recommended sprint allocation (hours) for debt reduction
112
+
113
+ ## Limitations
114
+
115
+ - Dead code detection is heuristic — false positives on exported/public APIs
116
+ - Nesting depth uses indentation as proxy — may miscount in some styles
117
+ - Does not analyze cyclomatic complexity (would require AST parsing per language)
118
+ - Effort estimates are rough guides, not commitments
@@ -26,7 +26,7 @@ Assess these indicators (do NOT read external files just for this — use what y
26
26
  | Compaction occurred | Did you receive a compaction bootstrap? |
27
27
  | Active task complexity | Simple (1-2 files) vs complex (5+ files, multi-milestone) |
28
28
 
29
- **Step 2 — Estimate bracket**
29
+ **Step 2 — Estimate bracket** (quantitative thresholds: see `context-budget.md` § Budget signals)
30
30
 
31
31
  | Bracket | Signals | Action |
32
32
  |---------|---------|--------|
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: px-context-triage
3
+ disable-model-invocation: true
4
+ description: "Prioritize context contents: what to keep, what to offload to vault, what to drop. Use before compaction or when context bracket is DEPLETED."
5
+ ---
6
+
7
+ # context-triage Skill
8
+
9
+ You are triaging context contents to free budget for continued work.
10
+
11
+ ## Vault Path Resolution
12
+
13
+ Read vault_path from `~/.claude/praxis.config.json`.
14
+
15
+ ---
16
+
17
+ **Step 1 — Inventory current context**
18
+
19
+ From memory (do NOT read files just for inventory), list what is loaded:
20
+
21
+ | Category | Examples |
22
+ | -------- | -------- |
23
+ | Code files read/edited | Source files, configs, tests |
24
+ | Plan/spec files | Active plan, SPEC, ADRs |
25
+ | Conversation topics | Discussion threads, decisions, corrections |
26
+ | Reference material | Docs read, research, examples already applied |
27
+ | MCP connections | Which servers are active |
28
+
29
+ **Step 2 — Classify by priority tier**
30
+
31
+ | Tier | Rule | Examples |
32
+ | ---- | ---- | -------- |
33
+ | T1: Active working set | Always keep | File being edited, active plan milestone, failing test output |
34
+ | T2: Decision context | Keep if FRESH/MODERATE | SPEC, architectural constraints, last 3 decisions |
35
+ | T3: Session history | Offload to vault | Earlier discussion, exploration results, superseded approaches |
36
+ | T4: Reference material | Drop | Docs already consumed, examples already applied |
37
+
38
+ **Step 3 — Offload T3/T4 to vault**
39
+
40
+ For each T3/T4 item that contains decisions or state worth preserving:
41
+
42
+ 1. Append to `{vault_path}/plans/{YYYY-MM-DD}-triage-offload.md` (create if needed, append if exists)
43
+ 2. Format per item: date, item name, 1-2 line summary, file references if applicable
44
+ 3. Add YAML frontmatter if creating new file:
45
+ ```yaml
46
+ ---
47
+ tags: [triage, offload]
48
+ date: YYYY-MM-DD
49
+ source: agent
50
+ ---
51
+ ```
52
+
53
+ Items with no decision value (pure reference, already applied) — drop without saving.
54
+
55
+ **Step 4 — Report**
56
+
57
+ ```
58
+ CONTEXT TRIAGE
59
+ ━━━━━━━━━━━━━━━━━━━━━
60
+ Keeping: {count} items (T1/T2)
61
+ Offloaded: {count} items to vault
62
+ Dropped: {count} items (no state value)
63
+ ━━━━━━━━━━━━━━━━━━━━━
64
+ ```
65
+
66
+ **Step 5 — Recommend next action**
67
+
68
+ | Bracket | Recommendation |
69
+ | ------- | -------------- |
70
+ | FRESH/MODERATE | Triage complete. No compaction needed yet. |
71
+ | DEPLETED | Run `/px-compact` now for mid-session optimization. |
72
+ | CRITICAL | Run `/px-context-reset` + `/clear` for full reset. |
73
+
74
+ ## Removal Condition
75
+
76
+ Remove when Claude Code provides native context budget visibility and automatic triage.
@@ -10,7 +10,10 @@ You are running a structured technical discovery.
10
10
  - Read vault_path from `~/.claude/praxis.config.json`
11
11
  - What decision needs to be made? (one sentence)
12
12
  - What are the constraints? (compliance, performance, compatibility, cost)
13
- - What is already known? (run `obsidian search query="{topic}" limit=5`)
13
+ - What is already known? Search vault using configured backend:
14
+ - If `obsidian`: run `obsidian search query="{topic}" limit=5`
15
+ - If `ripgrep`: run `rg --files-with-matches "{topic}" {vault_path}/`
16
+ - If vault search fails: proceed without blocking
14
17
 
15
18
  **Step 2 — Research options**
16
19
  - Identify 2-4 viable options. For each:
@@ -23,7 +23,10 @@ Do NOT present a template or form. Let them talk.
23
23
 
24
24
  **Step 3 — Search for related work**
25
25
  After the user describes the task, search vault for prior art:
26
- Run: `obsidian search query="{topic}" limit=5`
26
+ Read `vault_backend` from `~/.claude/praxis.config.json`.
27
+ - If `obsidian`: run `obsidian search query="{topic}" limit=5`
28
+ - If `ripgrep`: run `rg --files-with-matches "{topic}" {vault_path}/`
29
+ - If vault search fails (e.g., Obsidian not running): warn and proceed without blocking.
27
30
  If related specs, plans, or research exist: mention them briefly.
28
31
  If nothing exists: proceed silently.
29
32
 
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: px-doc-lint
3
+ disable-model-invocation: true
4
+ description: "Fast structural markdown check. No subagent — pure pattern matching. Completes in under 5 seconds. Fires inside px-quality-gate for staged *.md files, or on-demand via /px-doc-lint."
5
+ ---
6
+
7
+ # px-doc-lint — Fast Structural Markdown Check
8
+
9
+ ## Purpose
10
+
11
+ Lightweight structural validation for markdown files. No subagent.
12
+ Pure pattern matching. Completes in under 5 seconds.
13
+ Use as a quick pre-save check or let px-quality-gate invoke it automatically.
14
+
15
+ ## When It Fires
16
+
17
+ 1. Automatically inside px-quality-gate for every staged `*.md` file
18
+ 2. On-demand: `/px-doc-lint {filepath}`
19
+ 3. On-demand batch: `/px-doc-lint {directory}` (all .md files in directory)
20
+
21
+ ## Checks by Document Type
22
+
23
+ ### All markdown files
24
+
25
+ ```bash
26
+ # 1. Frontmatter check — if present, must be valid
27
+ head -1 "$f" | grep -q '^---$' && {
28
+ awk '/^---$/{c++} c==2{found=1; exit} END{if(!found) print "BLOCK: unclosed frontmatter"}' "$f"
29
+ }
30
+
31
+ # 2. No trailing whitespace
32
+ grep -nE ' +$' "$f" && echo "WARN: trailing whitespace"
33
+
34
+ # 3. No consecutive blank lines (more than 2)
35
+ awk '/^$/{blank++; if(blank>2) print "WARN: line "NR": excessive blank lines"} /^.+$/{blank=0}' "$f"
36
+
37
+ # 4. Headers must increment by one level (no h1 -> h3 skip)
38
+ grep -E '^#{1,6} ' "$f" | awk '{
39
+ level = length($0) - length(gensub(/^#+/, "", 1, $0)) - 1
40
+ if (prev > 0 && level > prev + 1)
41
+ print "WARN: header level skip at: "$0
42
+ prev = level
43
+ }'
44
+
45
+ # 5. No empty headers
46
+ grep -nE '^#{1,6}\s*$' "$f" && echo "BLOCK: empty header"
47
+
48
+ # 6. Fluff kill list (same as px-quality-gate prose check)
49
+ grep -inE "$FLUFF_PATTERN" "$f" && echo "BLOCK: fluff phrases detected"
50
+ ```
51
+
52
+ ### Design docs (DESIGN-*.md, *-design.md)
53
+
54
+ ```bash
55
+ for section in "## Problem" "## Decision" "## Tradeoffs" "## Acceptance Criteria"; do
56
+ grep -q "$section" "$f" || echo "BLOCK: missing required section: $section"
57
+ done
58
+
59
+ tradeoff_count=$(awk '/## Tradeoffs/,/## /' "$f" | grep -c '^- ' || true)
60
+ if [[ "$tradeoff_count" -lt 2 ]]; then
61
+ echo "BLOCK: Tradeoffs section needs at least 2 items (found: $tradeoff_count)"
62
+ fi
63
+ ```
64
+
65
+ ### ADRs (ADR-*.md)
66
+
67
+ ```bash
68
+ for field in "Status:" "Date:" "## Context" "## Decision" "## Consequences"; do
69
+ grep -q "$field" "$f" || echo "BLOCK: missing required field: $field"
70
+ done
71
+
72
+ status=$(grep -oE 'Status: .*' "$f" | head -1)
73
+ echo "$status" | grep -qE '(Proposed|Accepted|Deprecated|Superseded)' || \
74
+ echo "BLOCK: invalid ADR status. Must be: Proposed | Accepted | Deprecated | Superseded by ADR-NNN"
75
+
76
+ grep -q '### Positive' "$f" || echo "BLOCK: missing Consequences > Positive"
77
+ grep -q '### Negative' "$f" || echo "BLOCK: missing Consequences > Negative"
78
+ ```
79
+
80
+ ### READMEs (README.md)
81
+
82
+ ```bash
83
+ for section in "## Install\|## Setup" "## Run" "## Test"; do
84
+ grep -qE "$section" "$f" || echo "BLOCK: missing required section matching: $section"
85
+ done
86
+
87
+ awk '/^```/,/^```/' "$f" | grep -E '\{placeholder\}|\{TODO\}|\{TBD\}' && \
88
+ echo "BLOCK: placeholder found inside code block"
89
+ ```
90
+
91
+ ## Output Format
92
+
93
+ ```
94
+ px-doc-lint: {filename}
95
+ Type: {Design Doc | ADR | README | General}
96
+ [PASS] frontmatter valid
97
+ [PASS] no trailing whitespace
98
+ [BLOCK] missing required section: ## Tradeoffs
99
+ [WARN] header level skip at: ### Details
100
+ Result: BLOCK (1 error, 1 warning)
101
+ ```
102
+
103
+ ## Performance Contract
104
+
105
+ - Single file: under 2 seconds
106
+ - Batch (10 files): under 5 seconds
107
+ - No network calls. No subagent. Pure grep/awk/sed.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: px-prose-review
3
+ disable-model-invocation: true
4
+ description: "Deep document review using an isolated subagent. Checks argument quality, clarity, completeness, and adherence to writing-quality.md. Use for design docs, ADRs, READMEs, specs. More thorough than px-doc-lint."
5
+ ---
6
+
7
+ # px-prose-review — Deep Document Review
8
+
9
+ ## Purpose
10
+
11
+ Performs deep quality review on prose documents using an isolated subagent.
12
+ More thorough than px-doc-lint — checks argument quality, clarity, completeness,
13
+ and adherence to writing-quality.md standards.
14
+
15
+ ## When It Fires
16
+
17
+ 1. On-demand: `/px-prose-review {filepath}`
18
+ 2. Automatic: during `/px-ship` against the PR description
19
+ 3. Recommended: before finalizing any design doc, ADR, or spec
20
+
21
+ ## Subagent Configuration
22
+
23
+ The review runs in an isolated context with zero conversation history.
24
+ The subagent receives ONLY the document content and the review instructions.
25
+
26
+ ### Subagent persona
27
+
28
+ ```
29
+ You are a ruthless technical editor. Your job is to make this document
30
+ shorter, clearer, and more precise. You have no loyalty to the author's
31
+ feelings. You have total loyalty to the reader's time.
32
+
33
+ Rules:
34
+ - Every sentence must earn its place. If it restates something already said, cut it.
35
+ - Every paragraph must have exactly one idea. If it has two, split it.
36
+ - Every claim must be specific. "Improves performance" is not a claim.
37
+ "Reduces p99 latency from 200ms to 50ms" is.
38
+ - Active voice on all decisions and actions.
39
+ - No fluff words (see kill list in writing-quality.md).
40
+ - No hedging on decided things. "will" not "should" or "might".
41
+ ```
42
+
43
+ The full fluff kill list from writing-quality.md is injected into the subagent prompt.
44
+
45
+ ## Document Type Detection
46
+
47
+ The subagent detects document type from filename and content:
48
+
49
+ | Pattern | Type | Structural checks applied |
50
+ | ------- | ---- | ------------------------- |
51
+ | `DESIGN-*.md`, `*-design.md` | Design Doc | Problem, Decision, Tradeoffs, Acceptance Criteria |
52
+ | `ADR-*.md` | ADR | Status, Date, Context, Decision, Consequences (Positive + Negative) |
53
+ | `README.md` | README | First paragraph, Install/Setup, Run, Test |
54
+ | `*.md` in PR context | PR Description | What, Why, How to verify, Breaking changes |
55
+ | All other `*.md` | General prose | Sentence limits, fluff, voice, hedging |
56
+
57
+ ## Review Output Format
58
+
59
+ ```
60
+ ## px-prose-review: {filename}
61
+ Type detected: {Design Doc | ADR | README | PR Description | General}
62
+
63
+ ### Structure
64
+ - [PASS|BLOCK] {section}: {detail}
65
+
66
+ ### Clarity
67
+ - Line {N}: {issue} → {suggested fix}
68
+
69
+ ### Fluff
70
+ - Line {N}: "{flagged phrase}" → {replacement or "delete"}
71
+
72
+ ### Voice
73
+ - Line {N}: passive on decision → {active rewrite}
74
+
75
+ ### Verdict
76
+ {CLEAN | {N} issues found — {M} auto-fixable}
77
+ ```
78
+
79
+ ## Auto-Fix Flow
80
+
81
+ For minor issues (fluff deletion, passive-to-active rewrites on clear cases):
82
+ 1. Subagent proposes the fix with before/after
83
+ 2. Operator is shown the diff
84
+ 3. Operator approves or rejects each fix individually
85
+ 4. Approved fixes are applied in-place
86
+
87
+ For structural issues (missing sections, incomplete analysis):
88
+ - Subagent flags the gap and describes what is needed
89
+ - Operator writes the content — subagent does NOT generate missing sections
90
+ - Rationale: the subagent lacks project context to write accurate content
91
+
92
+ ## Limitations
93
+
94
+ - Does not verify technical accuracy of claims — only prose quality
95
+ - Does not check code blocks inside markdown — only surrounding prose
96
+ - Does not run on files outside the repo (external links, references)
@@ -0,0 +1,182 @@
1
+ ---
2
+ name: px-quality-gate
3
+ disable-model-invocation: true
4
+ description: "Code style and prose quality gate. Checks what linters cannot: naming, doc completeness, prose clarity, structural patterns. Integrated into px-verify as Step 1 item 5b. Also available standalone via /px-quality-gate."
5
+ ---
6
+
7
+ # px-quality-gate — Style and Prose Quality Enforcement
8
+
9
+ ## Purpose
10
+
11
+ Runs automated style checks against changed files. Catches issues that linters and
12
+ test suites do not: generic variable names, missing docstrings, prose quality,
13
+ structural violations, and import verification.
14
+
15
+ Integrated into `/px-verify` as Step 1 item 5b (after security scan, before functional check).
16
+ Also available standalone via `/px-quality-gate`.
17
+
18
+ ## When It Fires
19
+
20
+ 1. Automatically inside `/px-verify` after security scan
21
+ 2. As the first step of `/px-ship`
22
+ 3. On-demand via `/px-quality-gate` for ad-hoc checks
23
+
24
+ ## Scope
25
+
26
+ Checks run against staged or changed files only (not the full codebase).
27
+ Use `/px-complexity-audit` for full codebase scans.
28
+
29
+ ## Verdicts
30
+
31
+ - **BLOCK**: violation found — must fix before proceeding. Commit blocked.
32
+ - **WARN**: advisory issue found — commit allowed, fix recommended.
33
+ - **PASS**: all checks clear.
34
+
35
+ ## Check Categories
36
+
37
+ ### 1. Code Structure Checks
38
+
39
+ Run against all changed code files (exclude vendor/, node_modules/, .git/).
40
+
41
+ #### File size
42
+
43
+ ```bash
44
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(go|ts|tsx|js|jsx|py|rs|java|sh|sql)$'); do
45
+ lines=$(wc -l < "$f")
46
+ if [[ "$lines" -gt 300 ]]; then
47
+ echo "BLOCK: $f is $lines lines (limit: 300). Split before committing."
48
+ fi
49
+ done
50
+ ```
51
+
52
+ #### TODO/FIXME/HACK detection
53
+
54
+ ```bash
55
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(go|ts|tsx|js|jsx|py|rs|java|sh|sql)$'); do
56
+ hits=$(grep -nE 'TODO|FIXME|HACK' "$f" || true)
57
+ if [[ -n "$hits" ]]; then
58
+ echo "BLOCK: $f contains banned markers. Use QUALITY: with a ticket number instead."
59
+ echo "$hits"
60
+ fi
61
+ done
62
+ ```
63
+
64
+ #### Nesting depth heuristic
65
+
66
+ ```bash
67
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(go|ts|tsx|js|jsx|py|rs|java)$'); do
68
+ deep=$(grep -nE '^\s{16,}\S|^\t{4,}\S' "$f" || true)
69
+ if [[ -n "$deep" ]]; then
70
+ echo "WARN: $f may have deep nesting. Review these lines:"
71
+ echo "$deep"
72
+ fi
73
+ done
74
+ ```
75
+
76
+ #### Generic variable names
77
+
78
+ ```bash
79
+ git diff --cached -U0 | grep '^+' | grep -v '^+++' | \
80
+ grep -oE '\b(data|result|info|temp|tmp|obj|val|item|stuff|thing|ret|res)\b' | \
81
+ sort | uniq -c | sort -rn | head -10
82
+ ```
83
+
84
+ If any appear 3+ times: WARN with suggestion to use domain-specific names.
85
+
86
+ #### Missing docstrings on new public functions
87
+
88
+ ```bash
89
+ git diff --cached -U3 | grep -E '^\+.*(func |def |export function |export const .* = )' | \
90
+ while read -r line; do
91
+ echo "CHECK: verify doc comment exists for: $line"
92
+ done
93
+ ```
94
+
95
+ ### 2. Prose Checks
96
+
97
+ Run against all changed markdown files.
98
+
99
+ #### AI fluff detection
100
+
101
+ ```bash
102
+ FLUFF_PATTERN='leverage|utilize|facilitate|moving forward|going forward|at this point in time|comprehensive solution|robust solution|seamlessly|cutting-edge|best-in-class|in order to|due to the fact that|at the end of the day|synergy|holistic|empower|streamline'
103
+
104
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$'); do
105
+ hits=$(grep -inE "$FLUFF_PATTERN" "$f" || true)
106
+ if [[ -n "$hits" ]]; then
107
+ echo "BLOCK: $f contains fluff phrases. Remove or replace per writing-quality.md."
108
+ echo "$hits"
109
+ fi
110
+ done
111
+ ```
112
+
113
+ #### Passive voice on decisions
114
+
115
+ ```bash
116
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$'); do
117
+ hits=$(grep -inE '(it was decided|was implemented|was chosen|was selected|has been determined)' "$f" || true)
118
+ if [[ -n "$hits" ]]; then
119
+ echo "WARN: $f uses passive voice on decisions. Rewrite in active voice."
120
+ echo "$hits"
121
+ fi
122
+ done
123
+ ```
124
+
125
+ #### Sentence length check
126
+
127
+ ```bash
128
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$'); do
129
+ awk 'BEGIN{RS="[.!?]"} NF>30 {print NR": "NF" words: "$0}' "$f" | head -5
130
+ done
131
+ ```
132
+
133
+ #### Unreplaced placeholders
134
+
135
+ ```bash
136
+ for f in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$'); do
137
+ hits=$(grep -nE '\{placeholder\}|\{TODO\}|\{TBD\}|\[INSERT\]|\[TBD\]|XXX' "$f" || true)
138
+ if [[ -n "$hits" ]]; then
139
+ echo "BLOCK: $f contains unreplaced placeholders."
140
+ echo "$hits"
141
+ fi
142
+ done
143
+ ```
144
+
145
+ ### 3. Context7 Import Check
146
+
147
+ ```bash
148
+ NEW_IMPORTS=$(git diff --cached -U0 | grep -E '^\+.*(import |require\(|using |use )' | grep -v '^+++' | grep -v '^//\|^#')
149
+
150
+ if [[ -n "$NEW_IMPORTS" ]]; then
151
+ echo "GATE: New external imports detected. Each requires a Context7 lookup:"
152
+ echo "$NEW_IMPORTS"
153
+ echo ""
154
+ echo "Confirm each import was verified via Context7 in this session."
155
+ echo "Internal packages (same repo/module) are excluded."
156
+ fi
157
+ ```
158
+
159
+ ## Output Format
160
+
161
+ ```
162
+ ━━━ QUALITY GATE ━━━━━━━━━━━━━━━━━━━
163
+ Code checks: PASS | WARN | BLOCK
164
+ Prose checks: PASS | WARN | BLOCK
165
+ Import check: PASS | WARN | BLOCK
166
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
167
+ Overall: PASS | WARN | BLOCK
168
+
169
+ Details:
170
+ [BLOCK] services/auth.go: 342 lines (limit: 300)
171
+ [BLOCK] docs/DESIGN-auth.md: contains "comprehensive solution" (fluff)
172
+ [WARN] handlers/login.go: possible deep nesting at line 47
173
+ [PASS] All other checks
174
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
175
+ ```
176
+
177
+ ## Rules
178
+
179
+ - Any single BLOCK = overall BLOCK. Commit prevented.
180
+ - WARN-only = overall WARN. Commit allowed. Fix recommended.
181
+ - Gate re-runs on re-stage. Fix the issue, `git add`, gate runs again.
182
+ - Do NOT bypass the gate. There is no `--force` flag.
@@ -9,7 +9,10 @@ You are adding a risk register entry for the current project.
9
9
  **Step 1 — Detect project and existing risks**
10
10
  - Read vault_path from `~/.claude/praxis.config.json`
11
11
  - Detect project from CWD
12
- - Run: `obsidian search query="risk register {project-slug}" limit=3`
12
+ - Search vault for existing risks using configured backend:
13
+ - If `obsidian`: run `obsidian search query="risk register {project-slug}" limit=3`
14
+ - If `ripgrep`: run `rg --files-with-matches "risk" {vault_path}/specs/`
15
+ - If vault search fails: proceed without blocking
13
16
  - Check if `{vault_path}/specs/risk-register.md` exists
14
17
  - If found: read it to determine next sequential risk ID (R-01, R-02, etc.)
15
18