@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.
- package/base/CLAUDE.md +37 -3
- package/base/agents/evaluator.md +44 -0
- package/base/agents/planner.md +48 -0
- package/base/hooks/auto-format.sh +1 -1
- package/base/hooks/dep-audit.sh +1 -1
- package/base/hooks/file-guard.sh +3 -3
- package/base/hooks/recursion-guard.sh +7 -1
- package/base/hooks/session-data-collect.sh +1 -1
- package/base/hooks/vault-checkpoint.sh +5 -5
- package/base/rules/code-excellence.md +22 -0
- package/base/rules/coding.md +16 -0
- package/base/rules/context-budget.md +66 -0
- package/base/rules/context-management.md +4 -0
- package/base/rules/hooks-policy.md +53 -0
- package/base/rules/multi-agent-orchestration.md +99 -0
- package/base/rules/observable-code.md +87 -0
- package/base/rules/phase-detection.md +52 -0
- package/base/rules/refactor-triggers.md +59 -0
- package/base/rules/self-repair.md +53 -0
- package/base/rules/session-bridge.md +39 -0
- package/base/rules/session-metrics.md +61 -0
- package/base/rules/skill-authoring.md +85 -0
- package/base/rules/writing-quality.md +122 -0
- package/base/skills/px-compact/SKILL.md +100 -0
- package/base/skills/px-complexity-audit/SKILL.md +118 -0
- package/base/skills/px-context-probe/SKILL.md +1 -1
- package/base/skills/px-context-triage/SKILL.md +76 -0
- package/base/skills/px-discover/SKILL.md +4 -1
- package/base/skills/px-discuss/SKILL.md +4 -1
- package/base/skills/px-doc-lint/SKILL.md +107 -0
- package/base/skills/px-prose-review/SKILL.md +96 -0
- package/base/skills/px-quality-gate/SKILL.md +182 -0
- package/base/skills/px-risk/SKILL.md +4 -1
- package/base/skills/px-scaffold-new/SKILL.md +16 -14
- package/base/skills/px-session-retro/SKILL.md +1 -1
- package/base/skills/px-spec/SKILL.md +6 -2
- package/base/skills/px-verify/SKILL.md +2 -1
- package/bin/praxis.js +27 -6
- package/kits/api/KIT.md +2 -0
- package/kits/api/install.sh +1 -1
- package/kits/api/teardown.sh +1 -1
- package/kits/code-quality/KIT.md +2 -0
- package/kits/code-quality/hooks/generate-baseline.sh +1 -1
- package/kits/code-quality/hooks/post-commit.sh +3 -2
- package/kits/code-quality/hooks/pre-push.sh +15 -15
- package/kits/code-quality/install.sh +1 -1
- package/kits/code-quality/teardown.sh +3 -3
- package/kits/data/KIT.md +2 -0
- package/kits/data/install.sh +1 -1
- package/kits/data/teardown.sh +1 -1
- package/kits/infrastructure/KIT.md +2 -0
- package/kits/infrastructure/install.sh +1 -1
- package/kits/infrastructure/teardown.sh +1 -1
- package/kits/security/KIT.md +2 -0
- package/kits/security/install.sh +1 -1
- package/kits/security/teardown.sh +1 -1
- package/kits/web-designer/KIT.md +2 -0
- package/kits/web-designer/install.sh +1 -1
- package/kits/web-designer/teardown.sh +1 -1
- package/package.json +1 -1
- package/scripts/health-check.sh +21 -15
- package/scripts/install-tools.sh +5 -5
- package/scripts/lint-harness.sh +1 -1
- package/scripts/onboard-mcp.sh +1 -1
- package/scripts/test-harness.sh +1 -1
- 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?
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
|