@esoteric-logic/praxis-harness 2.0.3 → 2.1.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/README.md CHANGED
@@ -66,7 +66,12 @@ For technical research: `/discover` (structured options evaluation before decisi
66
66
  | `risk` | Add a risk register entry to the vault |
67
67
  | `kit` | Activate/deactivate an AI-Kit |
68
68
  | `review` | Manual code review via subagent |
69
+ | `simplify` | Post-implementation code simplification via subagent |
69
70
  | `debug` | Structured test-first debugging |
71
+ | `ship` | Commit, push, and PR in one command with pre-flight checks |
72
+ | `verify-app` | End-to-end verification with regression analysis |
73
+ | `session-retro` | End-of-session retrospective with learnings extraction |
74
+ | `status-update` | Manual vault status.md update |
70
75
  | `context-reset` | Reload context from vault without clearing session |
71
76
 
72
77
  ## Rules
@@ -126,13 +131,57 @@ The vault path is configured per machine during install:
126
131
 
127
132
  Requires [Obsidian CLI](https://obsidian.md) (enable in Obsidian Settings > General > Command line interface). Obsidian must be running for vault search.
128
133
 
134
+ ### What gets documented automatically
135
+
136
+ Praxis auto-documents your work in the vault with zero manual effort. Two independent layers ensure nothing is lost:
137
+
138
+ 1. **Shell hooks** capture facts (git state, timestamps) even if Claude runs out of context
139
+ 2. **Stop prompt** captures meaning (summaries, decisions, learnings) from conversation context
140
+
141
+ **At session end** (zero action needed):
142
+ - `status.md` — updated with What/So What/Now What
143
+ - `claude-progress.json` — session entry with summary, accomplishments, milestones, features
144
+ - `notes/{date}_session-note.md` — session summary, decisions, learnings, next steps
145
+ - `notes/decision-log.md` — checkpoint decisions, scope changes (appended)
146
+ - `notes/learnings.md` — [LEARN:tag] pattern entries (appended)
147
+ - `specs/` — ADRs for architectural decisions made during the session
148
+
149
+ **During workflow skills** (automatic within each skill):
150
+
151
+ | Skill | Auto-writes to vault |
152
+ |-------|---------------------|
153
+ | `/execute` | `status.md` loop position, `decision-log.md` scope events |
154
+ | `/verify` | `claude-progress.json` milestones[] |
155
+ | `/review` | `specs/review-{date}-{slug}.md` (full findings breakdown) |
156
+ | `/simplify` | `notes/{date}_simplify-findings.md` |
157
+ | `/debug` | `notes/{date}_debug-trace.md` |
158
+ | `/verify-app` | `specs/verify-app-{date}-{slug}.md` |
159
+ | `/ship` | `claude-progress.json` features[] |
160
+
161
+ **On context compaction** (automatic fallback):
162
+ - `plans/{date}-compact-checkpoint.md` — git state, active plan, loop position
163
+ - `claude-progress.json` — session entry preserved
164
+
129
165
  ## Updating
130
166
 
167
+ ### Updating the harness
168
+
131
169
  ```bash
132
170
  npx praxis-harness update
133
171
  ```
134
172
 
135
- Re-copies all files from the latest npm package version. Config file is preserved.
173
+ Re-copies all hooks, skills, rules, and kits from the latest npm package version. Config file is preserved.
174
+
175
+ ### Updating existing projects
176
+
177
+ After a harness update that adds new vault files (like `decision-log.md`), run `/scaffold-exist` in a Claude Code session to audit your vault and add any missing files. This is non-destructive — it never overwrites existing content.
178
+
179
+ ```
180
+ Step 1: npx praxis-harness update → deploys new hooks, skills, rules to ~/.claude/
181
+ Step 2: /scaffold-exist → audits vault, adds missing files
182
+ ```
183
+
184
+ New projects get everything automatically via `/scaffold-new`.
136
185
 
137
186
  ## Uninstalling
138
187
 
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bash
2
+ # Stop hook — collects structured session data and stages it for the Stop prompt.
3
+ # Always exits 0 (advisory, never blocks session end).
4
+ set -uo pipefail
5
+
6
+ CONFIG_FILE="$HOME/.claude/praxis.config.json"
7
+
8
+ if [[ ! -f "$CONFIG_FILE" ]]; then
9
+ exit 0
10
+ fi
11
+
12
+ VAULT_PATH=$(jq -r '.vault_path // empty' "$CONFIG_FILE" 2>/dev/null)
13
+ if [[ -z "$VAULT_PATH" || ! -d "$VAULT_PATH" ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ DATE=$(date +%Y-%m-%d)
18
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
19
+
20
+ # Git state (fail gracefully if not in a repo)
21
+ BRANCH=$(git --no-pager rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
22
+ LAST_COMMIT=$(git --no-pager log --oneline -1 2>/dev/null || echo "no commits")
23
+ RECENT_COMMITS=$(git --no-pager log --oneline -5 2>/dev/null || echo "")
24
+ FILES_CHANGED=$(git --no-pager diff --stat HEAD~5..HEAD --stat-count=50 2>/dev/null | tail -1 || echo "unknown")
25
+ DIRTY=$(git --no-pager status --porcelain 2>/dev/null | head -20)
26
+
27
+ # Vault state
28
+ STATUS_FILE="$VAULT_PATH/status.md"
29
+ PROGRESS_FILE="$VAULT_PATH/claude-progress.json"
30
+
31
+ CURRENT_PLAN="none"
32
+ LOOP_POSITION="unknown"
33
+ if [[ -f "$STATUS_FILE" ]]; then
34
+ CURRENT_PLAN=$(grep "^current_plan:" "$STATUS_FILE" | sed 's/current_plan: *//' | head -1)
35
+ LOOP_POSITION=$(grep "^loop_position:" "$STATUS_FILE" | sed 's/loop_position: *//' | head -1)
36
+ [[ -z "$CURRENT_PLAN" ]] && CURRENT_PLAN="none"
37
+ [[ -z "$LOOP_POSITION" ]] && LOOP_POSITION="unknown"
38
+ fi
39
+
40
+ # Project detection
41
+ PROJECT_DIR=$(basename "$PWD")
42
+
43
+ # Write staging JSON for the Stop prompt to consume
44
+ STAGING_FILE="$VAULT_PATH/.session-staging.json"
45
+
46
+ IS_DIRTY="false"
47
+ if [[ -n "$DIRTY" ]]; then IS_DIRTY="true"; fi
48
+
49
+ COMMITS_JSON=$(echo "$RECENT_COMMITS" | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo '[]')
50
+
51
+ jq -n \
52
+ --arg ts "$TIMESTAMP" \
53
+ --arg date "$DATE" \
54
+ --arg project "$PROJECT_DIR" \
55
+ --arg cwd "$PWD" \
56
+ --arg branch "$BRANCH" \
57
+ --arg last_commit "$LAST_COMMIT" \
58
+ --argjson dirty "$IS_DIRTY" \
59
+ --arg current_plan "$CURRENT_PLAN" \
60
+ --arg loop_position "$LOOP_POSITION" \
61
+ --argjson recent_commits "$COMMITS_JSON" \
62
+ --arg files_changed "$FILES_CHANGED" \
63
+ '{
64
+ timestamp: $ts,
65
+ date: $date,
66
+ project: $project,
67
+ cwd: $cwd,
68
+ git: { branch: $branch, last_commit: $last_commit, dirty: $dirty },
69
+ vault: { current_plan: $current_plan, loop_position: $loop_position },
70
+ recent_commits: $recent_commits,
71
+ files_changed_summary: $files_changed
72
+ }' > "$STAGING_FILE" 2>/dev/null
73
+
74
+ if [[ $? -ne 0 ]]; then
75
+ # Fallback: minimal valid JSON if jq fails
76
+ echo '{"error":"jq failed to build staging JSON"}' > "$STAGING_FILE"
77
+ fi
78
+
79
+ echo "Session data staged: $STAGING_FILE" >&2
80
+
81
+ # Update claude-progress.json if jq is available
82
+ if command -v jq &>/dev/null && [[ -f "$PROGRESS_FILE" ]]; then
83
+ TMP_FILE=$(mktemp)
84
+ jq --arg ts "$TIMESTAMP" \
85
+ --arg date "$DATE" \
86
+ --arg branch "$BRANCH" \
87
+ --arg commit "$LAST_COMMIT" \
88
+ --arg source "hook" \
89
+ '.last_session = $ts |
90
+ .sessions += [{
91
+ "date": $date,
92
+ "branch": $branch,
93
+ "last_commit": $commit,
94
+ "source": $source
95
+ }]' "$PROGRESS_FILE" > "$TMP_FILE" 2>/dev/null
96
+
97
+ if [[ $? -eq 0 && -s "$TMP_FILE" ]]; then
98
+ mv "$TMP_FILE" "$PROGRESS_FILE"
99
+ echo "claude-progress.json updated" >&2
100
+ else
101
+ rm -f "$TMP_FILE"
102
+ fi
103
+ fi
104
+
105
+ exit 0
@@ -39,9 +39,13 @@
39
39
  "type": "command",
40
40
  "command": "bash ~/.claude/hooks/post-session-lint.sh"
41
41
  },
42
+ {
43
+ "type": "command",
44
+ "command": "bash ~/.claude/hooks/session-data-collect.sh"
45
+ },
42
46
  {
43
47
  "type": "prompt",
44
- "prompt": "Review the conversation. Did you complete all tasks the user requested? Are there uncommitted changes that should be committed? Are there vault files (status.md, plan) that should be updated? Answer yes/no for each."
48
+ "prompt": "You are completing a session. Perform these vault updates silently no confirmation needed.\n\n1. Read vault_path from ~/.claude/praxis.config.json. If missing: skip all steps.\n2. Read {vault_path}/.session-staging.json if it exists (structured session data from hooks).\n3. Update {vault_path}/status.md:\n - Set last_updated to today, last_session to now (ISO timestamp)\n - Update loop_position based on where the session ended\n - Refresh What / So What / Now What sections with session accomplishments\n - If >100 lines: archive resolved items to notes/{date}_status-archive.md\n4. Update {vault_path}/claude-progress.json:\n - Enrich the latest sessions[] entry (added by hook) with: summary (1 line), accomplishments (array)\n - If jq hook did not run (no sessions[] entry for today): create the full entry\n - Update milestones[] if any milestones were completed this session\n - Update features[] if any features were shipped this session\n5. Write {vault_path}/notes/{YYYY-MM-DD}_session-note.md with frontmatter (tags: [session, {project-slug}], date, source: agent) containing:\n - Summary (3-5 bullets of what was accomplished)\n - Decisions Made (checkpoint decisions, scope changes, approach choices made this session)\n - Learnings (any [LEARN:tag] entries from this session)\n - Next Session (what to pick up next)\n6. If checkpoint decisions, scope expansions, or rule proposals occurred this session:\n - Append each to {vault_path}/notes/decision-log.md with date, decision type, context, decision, and rationale\n7. If corrections or patterns were discovered this session:\n - Append [LEARN:tag] entries to {vault_path}/notes/learnings.md following the existing format\n8. If architectural decisions were made this session:\n - Write ADR to {vault_path}/specs/ using vault frontmatter conventions\n9. Delete {vault_path}/.session-staging.json if it exists.\n\nKeep all writes concise. Use [[wikilinks]] for internal references. Follow existing YAML frontmatter conventions. If vault_path is missing or vault is inaccessible: skip silently. Do not ask permission — this is automatic housekeeping."
45
49
  }
46
50
  ]
47
51
  }
@@ -64,4 +64,28 @@ Read this file after compaction to restore context.
64
64
  EOF
65
65
 
66
66
  echo "Vault checkpoint written: $CHECKPOINT_FILE" >&2
67
+
68
+ # Update claude-progress.json if jq is available
69
+ if command -v jq &>/dev/null && [[ -f "$PROGRESS_FILE" ]]; then
70
+ TMP_FILE=$(mktemp)
71
+ jq --arg ts "$TIMESTAMP" \
72
+ --arg date "$DATE" \
73
+ --arg branch "$BRANCH" \
74
+ --arg commit "$LAST_COMMIT" \
75
+ '.last_session = $ts |
76
+ .sessions += [{
77
+ "date": $date,
78
+ "branch": $branch,
79
+ "last_commit": $commit,
80
+ "source": "compact"
81
+ }]' "$PROGRESS_FILE" > "$TMP_FILE" 2>/dev/null
82
+
83
+ if [[ $? -eq 0 && -s "$TMP_FILE" ]]; then
84
+ mv "$TMP_FILE" "$PROGRESS_FILE"
85
+ echo "claude-progress.json updated (compact)" >&2
86
+ else
87
+ rm -f "$TMP_FILE"
88
+ fi
89
+ fi
90
+
67
91
  exit 0
@@ -44,6 +44,32 @@ Before touching any implementation code:
44
44
  3. Run the linter — clean.
45
45
  4. Show all output.
46
46
 
47
+ **Step 5b — Persist debug trace**
48
+ - Read vault_path from `~/.claude/praxis.config.json`
49
+ - Write debug session to `{vault_path}/notes/{YYYY-MM-DD}_debug-trace.md`:
50
+ ```markdown
51
+ ---
52
+ tags: [debug, {project-slug}]
53
+ date: {YYYY-MM-DD}
54
+ source: agent
55
+ ---
56
+ # Debug Trace — {short title}
57
+
58
+ ## Bug Report
59
+ - **Observed**: {observed behavior}
60
+ - **Expected**: {expected behavior}
61
+ - **Suspect**: {file(s)}
62
+
63
+ ## Root Cause
64
+ {root cause statement from Step 3}
65
+
66
+ ## Fix
67
+ {what was changed and why}
68
+
69
+ ## Verification
70
+ {test output summary — pass/fail}
71
+ ```
72
+
47
73
  **Step 6 — Write learnings**
48
74
  - Read vault_path from `~/.claude/praxis.config.json`
49
75
  - If this bug represents a pattern (not a one-off typo):
@@ -33,13 +33,28 @@ Before implementing the current milestone, declare the file group:
33
33
  boundary-protected file: STOP. Surface the conflict before proceeding.
34
34
  - If current milestone has `checkpoint: decision` or `checkpoint: human-verify`:
35
35
  present the decision/output to user before proceeding. Do not auto-advance.
36
+ - After a checkpoint decision or user-approved scope expansion, append to `{vault_path}/notes/decision-log.md`:
37
+ ```
38
+ ## {YYYY-MM-DD} — {Checkpoint decision | Scope expansion}
39
+ - **Context**: {milestone name, what triggered the decision}
40
+ - **Decision**: {what was decided}
41
+ - **Rationale**: {why}
42
+ ```
36
43
 
37
44
  **Step 3 — Implement current milestone**
45
+ - Update `{vault_path}/status.md`: set `loop_position: EXECUTE`.
38
46
  - One milestone at a time. Keep diffs scoped.
39
47
  - Do not expand scope without explicit user approval.
40
48
  - Use extended thinking for tasks touching >3 files or requiring architectural decisions.
41
49
  - Before writing to or editing any file: check if it is in the declared file group.
42
50
  - If a required change is discovered in an off-limits file: STOP.
51
+ Log to `{vault_path}/notes/decision-log.md`:
52
+ ```
53
+ ## {YYYY-MM-DD} — Scope violation detected
54
+ - **Milestone**: {name}
55
+ - **Requested**: {file outside group}
56
+ - **Action**: Surfaced as new milestone candidate
57
+ ```
43
58
  Surface as a new milestone candidate. Do not expand current milestone.
44
59
  - Milestone diff must touch ONLY declared files. Undeclared file change = scope violation.
45
60
 
@@ -69,16 +69,34 @@ CLEAN
69
69
  - Minor: note for future cleanup.
70
70
  - If >3 findings: offer to re-run after fixes (max 3 rounds).
71
71
 
72
- **Step 7 — Write review summary**
72
+ **Step 7 — Write review findings to vault**
73
73
  - Read vault_path from `~/.claude/praxis.config.json`
74
- - Write summary to `{vault_path}/specs/review-{YYYY-MM-DD}-{slug}.md` with frontmatter:
75
- ```yaml
74
+ - Write full structured findings to `{vault_path}/specs/review-{YYYY-MM-DD}-{slug}.md`:
75
+ ```markdown
76
76
  ---
77
77
  tags: [review, {project-slug}]
78
78
  date: {YYYY-MM-DD}
79
79
  status: complete
80
80
  source: agent
81
81
  ---
82
+ # Code Review — {slug} ({date})
83
+
84
+ ## Findings
85
+
86
+ ### CRITICAL ({n})
87
+ {file}:{line} — {description} — {fix}
88
+
89
+ ### MAJOR ({n})
90
+ {file}:{line} — {description} — {fix}
91
+
92
+ ### MINOR ({n})
93
+ {file}:{line} — {description} — {fix}
94
+
95
+ ## Clean Files
96
+ {list of files with no findings}
97
+
98
+ ## Diff Scope
99
+ {git diff command used}
82
100
  ```
83
101
 
84
102
  ## Error Handling
@@ -52,6 +52,7 @@ Build and show audit table:
52
52
  | `specs/` | ? | Create if missing |
53
53
  | `research/` | ? | Create if missing |
54
54
  | `notes/learnings.md` | ? | Create if missing |
55
+ | `notes/decision-log.md` | ? | Create if missing |
55
56
  | Repo CLAUDE.md sections | ? | Add missing sections |
56
57
  | Registry row | ? | Verify accuracy |
57
58
 
@@ -90,6 +90,7 @@ Create files from templates in `references/`:
90
90
  - `status.md` from `vault-status-template.md` (`current_plan:` empty)
91
91
  - `tasks.md` from `vault-tasks-template.md`
92
92
  - `notes/learnings.md` from `vault-learnings-template.md`
93
+ - `notes/decision-log.md` from `decision-log` template (append-only decision log)
93
94
  - `.gitignore` from `gitignore-template.txt` (new repos only)
94
95
 
95
96
  ---
@@ -74,3 +74,7 @@ Checks: secrets ✓ lint ✓ types ✓ tests ✓
74
74
  - Never force-push without explicit user approval.
75
75
  - If the diff touches >20 files: warn about PR size and suggest splitting.
76
76
  - This command is the end of a Praxis cycle — run after `/verify` passes.
77
+
78
+ **Step 7 — Update vault tracking**
79
+ - Read vault_path from `~/.claude/praxis.config.json`
80
+ - Update `{vault_path}/claude-progress.json`: append to `features[]` with `{ "name": "{feature description}", "date": "{YYYY-MM-DD}", "commit": "{short sha}", "pr_url": "{url or null}" }`.
@@ -96,6 +96,24 @@ For each approved simplification:
96
96
  3. If tests fail: revert the last edit, report which simplification broke tests
97
97
  4. Show final diff of simplifications applied
98
98
 
99
+ ## Phase 4b — Persist Findings
100
+
101
+ Write simplification findings to `{vault_path}/notes/{YYYY-MM-DD}_simplify-findings.md`:
102
+ ```markdown
103
+ ---
104
+ tags: [simplify, {project-slug}]
105
+ date: {YYYY-MM-DD}
106
+ source: agent
107
+ ---
108
+ # Simplify Findings — {date}
109
+
110
+ ## Applied ({n})
111
+ {file}:{lines} — {category} — {why}
112
+
113
+ ## Skipped ({n})
114
+ {file}:{lines} — {category} — {reason skipped}
115
+ ```
116
+
99
117
  ## Phase 5 — Write Learning (optional)
100
118
 
101
119
  If a pattern recurred (same category hit 3+ times):
@@ -23,12 +23,13 @@ If no commands are defined: warn and ask user for the correct commands.
23
23
 
24
24
  **Step 3 — On PASS**
25
25
  1. Update the active plan file: mark milestone status as complete
26
- 2. Commit immediately verification passed, no permission needed.
26
+ 2. Update `{vault_path}/claude-progress.json`: append the completed milestone to `milestones[]` with `{ "name": "{milestone name}", "date": "{YYYY-MM-DD}", "plan_ref": "{plan filename}" }`.
27
+ 3. Commit immediately — verification passed, no permission needed.
27
28
  Use conventional commit format. See git-workflow.md.
28
- 3. Check if more milestones remain:
29
+ 4. Check if more milestones remain:
29
30
  - Yes → "Milestone committed. Run `/execute` for the next milestone."
30
31
  - No → "All milestones committed. Running self-review."
31
- 4. After ALL milestones: trigger Self-Review Protocol
32
+ 5. After ALL milestones: trigger Self-Review Protocol
32
33
  - Launch a subagent to review the full diff as a critical code reviewer
33
34
  - Subagent receives ONLY: the diff, the SPEC (from plan file `## SPEC` section), relevant rules files
34
35
  - Address all Critical and Major findings before reporting done
@@ -125,6 +125,28 @@ Format each concern as:
125
125
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
126
126
  ```
127
127
 
128
+ ## Phase 4b — Persist Verification Report
129
+
130
+ Write the full verification report to `{vault_path}/specs/verify-app-{YYYY-MM-DD}-{slug}.md`:
131
+ ```markdown
132
+ ---
133
+ tags: [verify-app, {project-slug}]
134
+ date: {YYYY-MM-DD}
135
+ status: complete
136
+ source: agent
137
+ ---
138
+ # Verification Report — {project} ({date})
139
+
140
+ ## Results
141
+ {Phase 4 report output: build, lint, typecheck, tests, acceptance criteria}
142
+
143
+ ## Regression Concerns
144
+ {Phase 3 subagent findings: file, concern, recommended verification step}
145
+
146
+ ## Overall
147
+ {READY TO SHIP | ISSUES FOUND}
148
+ ```
149
+
128
150
  ## Phase 5 — Guidance
129
151
 
130
152
  - **READY TO SHIP**: "All checks pass. Run `/ship` to commit, push, and PR."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esoteric-logic/praxis-harness",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "Layered Claude Code harness — workflow discipline, AI-Kits, persistent vault integration",
5
5
  "bin": {
6
6
  "praxis-harness": "./bin/praxis.js"
@@ -0,0 +1,8 @@
1
+ ---
2
+ tags: [decisions, project-slug]
3
+ date: YYYY-MM-DD
4
+ source: agent
5
+ ---
6
+ # Decision Log
7
+
8
+ <!-- Append-only log of checkpoint decisions, scope changes, rule proposals, and other session decisions -->