@esoteric-logic/praxis-harness 2.10.0 → 2.12.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 (57) hide show
  1. package/base/CLAUDE.md +37 -9
  2. package/base/hooks/auto-format.sh +1 -1
  3. package/base/hooks/dep-audit.sh +1 -1
  4. package/base/hooks/file-guard.sh +3 -3
  5. package/base/hooks/recursion-guard.sh +7 -1
  6. package/base/hooks/session-data-collect.sh +1 -1
  7. package/base/hooks/vault-checkpoint.sh +5 -5
  8. package/base/rules/api-quality.md +25 -0
  9. package/base/{skills → rules}/code-excellence.md +31 -2
  10. package/base/rules/coding.md +16 -0
  11. package/base/rules/css-quality.md +25 -0
  12. package/base/rules/go-quality.md +25 -0
  13. package/base/rules/java-quality.md +25 -0
  14. package/base/rules/observable-code.md +87 -0
  15. package/base/rules/python-quality.md +25 -0
  16. package/base/rules/refactor-triggers.md +59 -0
  17. package/base/rules/rust-quality.md +25 -0
  18. package/base/rules/shell-quality.md +26 -0
  19. package/base/rules/sql-quality.md +25 -0
  20. package/base/rules/typescript-quality.md +26 -0
  21. package/base/rules/writing-quality.md +122 -0
  22. package/base/skills/px-complexity-audit/SKILL.md +118 -0
  23. package/base/skills/px-discover/SKILL.md +4 -1
  24. package/base/skills/px-discuss/SKILL.md +4 -1
  25. package/base/skills/px-doc-lint/SKILL.md +107 -0
  26. package/base/skills/px-prose-review/SKILL.md +96 -0
  27. package/base/skills/px-quality-gate/SKILL.md +182 -0
  28. package/base/skills/px-risk/SKILL.md +4 -1
  29. package/base/skills/px-scaffold-new/SKILL.md +16 -14
  30. package/base/skills/px-session-retro/SKILL.md +1 -1
  31. package/base/skills/px-spec/SKILL.md +6 -2
  32. package/base/skills/px-verify/SKILL.md +2 -1
  33. package/bin/praxis.js +27 -6
  34. package/kits/api/install.sh +1 -1
  35. package/kits/api/teardown.sh +1 -1
  36. package/kits/code-quality/hooks/generate-baseline.sh +1 -1
  37. package/kits/code-quality/hooks/post-commit.sh +3 -2
  38. package/kits/code-quality/hooks/pre-push.sh +15 -15
  39. package/kits/code-quality/install.sh +1 -1
  40. package/kits/code-quality/teardown.sh +3 -3
  41. package/kits/data/install.sh +1 -1
  42. package/kits/data/teardown.sh +1 -1
  43. package/kits/infrastructure/install.sh +1 -1
  44. package/kits/infrastructure/teardown.sh +1 -1
  45. package/kits/security/install.sh +1 -1
  46. package/kits/security/teardown.sh +1 -1
  47. package/kits/web-designer/install.sh +1 -1
  48. package/kits/web-designer/teardown.sh +1 -1
  49. package/package.json +1 -1
  50. package/scripts/health-check.sh +21 -15
  51. package/scripts/install-tools.sh +5 -5
  52. package/scripts/lint-harness.sh +1 -1
  53. package/scripts/onboard-mcp.sh +1 -1
  54. package/scripts/test-harness.sh +1 -1
  55. package/scripts/update.sh +1 -1
  56. /package/base/{skills → rules}/engineering-judgment.md +0 -0
  57. /package/base/{skills → rules}/self-verify.md +0 -0
@@ -0,0 +1,26 @@
1
+ # TypeScript Quality — Generation Constraints
2
+ # Scope: **/*.ts, **/*.tsx
3
+ # Active during code generation, not post-hoc review
4
+
5
+ ## Invariants — BLOCK on violation
6
+
7
+ - No `any` type — ever. Use `unknown` and narrow, or define the actual type.
8
+ - Explicit return types on all exported functions.
9
+ - No non-null assertion (`!`) without an inline comment explaining why it's safe.
10
+ - No `@ts-ignore` or `@ts-expect-error` without an inline comment explaining why.
11
+ - No `as` type assertions unless narrowing from `unknown` — prefer type guards.
12
+ - Strict null checks: handle `null` and `undefined` explicitly, never assume presence.
13
+
14
+ ## Conventions — WARN on violation
15
+
16
+ - `const` by default — `let` only when reassignment is necessary. Never `var`.
17
+ - Discriminated unions over optional fields for modeling distinct states.
18
+ - `readonly` on properties that should not be mutated after construction.
19
+ - `interface` for object shapes, `type` for unions, intersections, and computed types.
20
+ - Named exports over default exports — better refactoring support and tree-shaking.
21
+ - `Promise.all` for independent async operations — never sequential awaits for parallel work.
22
+ - Error boundaries in React components that render user-generated or external data.
23
+ - `satisfies` operator over `as` for type validation without widening.
24
+
25
+ ## Removal Condition
26
+ Remove when a TypeScript-specific linter rule engine replaces generation-time constraints.
@@ -0,0 +1,122 @@
1
+ # Writing Quality — Prose Generation Constraints
2
+ # Scope: All prose output — design docs, ADRs, READMEs, specs, PR descriptions,
3
+ # commit messages, code comments, status reports
4
+ # Always active during prose generation
5
+
6
+ ## The Prime Directive for Prose
7
+ Write for the engineer reading this at 11pm during an incident.
8
+ They have 90 seconds. Every word must earn its place.
9
+
10
+ ## Invariants — BLOCK on violation
11
+
12
+ ### Sentence limits
13
+ - Maximum 30 words per sentence. Count before writing long sentences.
14
+ - Maximum 5 sentences per paragraph.
15
+ - One idea per paragraph.
16
+
17
+ ### Fluff kill list — never write these words or phrases
18
+ leverage (use: use), utilize (use: use), facilitate (use: enable, allow, help),
19
+ moving forward, going forward, at this point in time, comprehensive solution,
20
+ robust solution, seamlessly, cutting-edge, best-in-class,
21
+ in order to (use: to), due to the fact that (use: because),
22
+ at the end of the day, synergy, holistic, empower, streamline
23
+
24
+ For additional banned AI-filler phrases, see `px-communication-standards` skill.
25
+ That skill covers: "Certainly!", "Absolutely!", "Great question!", "I'd be happy to",
26
+ "It's worth noting that", "In conclusion", "To summarize the above".
27
+ Both lists are enforced. Neither is optional.
28
+
29
+ ### Voice on decisions
30
+ - Active voice on decisions: "we decided" not "it was decided"
31
+ - Active voice on architecture: "this service handles X" not "X is handled by"
32
+ - Reserve passive voice for describing states: "the cache is invalidated when..."
33
+
34
+ ### Hedging on decided things
35
+ - Decided things use "will", not "should" or "might"
36
+ - Uncertain things are labeled explicitly: "open question:", "to be decided:"
37
+ - Never hedge silently. If you are uncertain, say so.
38
+
39
+ ## Document Structure — Mandatory Templates
40
+
41
+ ### Design Doc (filename: DESIGN-*.md or *-design.md)
42
+ Required sections — none optional, none empty:
43
+
44
+ #### Problem
45
+ - What is broken, missing, or painful? Past tense. Specific.
46
+ - "The auth service does not rate-limit failed login attempts" — GOOD
47
+ - "We need better authentication" — BAD (not specific, not a problem statement)
48
+
49
+ #### Decision
50
+ - What are we building? Active voice. One paragraph.
51
+ - State what this is AND what it is NOT (explicit scope boundary).
52
+
53
+ #### Tradeoffs
54
+ - Minimum 2 items. For each: what we gain AND what we give up.
55
+ - Not "pros and cons of the overall approach" — tradeoffs of THIS decision vs alternatives.
56
+
57
+ #### Acceptance Criteria
58
+ - Verifiable statements. Observable outcomes. Present tense.
59
+ - GOOD: "The login endpoint returns 429 after 5 failed attempts within 60 seconds"
60
+ - BAD: "The system handles failed logins correctly"
61
+ - BAD: "Improved security posture"
62
+
63
+ ### ADR (filename: ADR-NNN-*.md)
64
+ Required fields in this order:
65
+ ```
66
+ # ADR-NNN: {title}
67
+ Status: Proposed | Accepted | Deprecated | Superseded by ADR-NNN
68
+ Date: YYYY-MM-DD
69
+
70
+ ## Context
71
+ {past tense — what situation forced this decision}
72
+
73
+ ## Decision
74
+ {active voice — what we decided}
75
+
76
+ ## Consequences
77
+ ### Positive
78
+ - {at least one}
79
+ ### Negative
80
+ - {at least one — if no negatives, the decision is not analyzed}
81
+ ```
82
+
83
+ ### README (filename: README.md)
84
+ Required sections:
85
+ - First paragraph: what does this do (3 sentences max, no jargon)
86
+ - `## Install` or `## Setup` with exact commands
87
+ - `## Run` with exact commands — no `{placeholder}` in code blocks
88
+ - `## Test` with exact commands
89
+
90
+ ### PR Description
91
+ Required sections:
92
+ - **What**: one sentence — what changed
93
+ - **Why**: one sentence — why this was needed
94
+ - **How to verify**: exact steps a reviewer takes to confirm it works
95
+ - **Breaking changes**: explicit "None" if none — do not omit
96
+
97
+ ## Commit Messages
98
+ Format: `{type}({scope}): {what changed in imperative mood}`
99
+
100
+ Types: feat, fix, refactor, test, docs, chore, perf, ci
101
+ Scope: the module, package, or subsystem changed
102
+ Subject: present tense imperative — "add retry logic" not "added retry logic"
103
+
104
+ 50-char subject limit. 72-char body line limit if body is present.
105
+ Body explains WHY the change was needed, not what the diff shows.
106
+
107
+ ## Code Comments
108
+ - WHY not WHAT. The code shows what.
109
+ - GOOD: `// retry 3x — upstream returns 503 on cold start, recovers within 2s`
110
+ - BAD: `// increment counter`
111
+ - Zero tolerance for TODO/FIXME/HACK in committed code.
112
+ Use `// QUALITY: {issue} — tracked in #{issue-number}` if deferring.
113
+ See `refactor-triggers.md` for the QUALITY comment convention.
114
+
115
+ ## Cross-References
116
+ - Document-level formatting (proposals, status reports, executive summaries): see `px-communication-standards` skill
117
+ - Commit standards and git workflow: see `git-workflow.md`
118
+ - Code comment rules: see `code-quality.md` § On comments
119
+
120
+ ## Removal Condition
121
+ Remove when a prose linter (Vale or equivalent) runs as a generation-time hook
122
+ on all markdown and prose output.
@@ -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
@@ -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.