@esoteric-logic/praxis-harness 2.0.3 → 2.1.1

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
@@ -17,16 +17,18 @@ Praxis gives Claude Code a three-layer operating system:
17
17
  ## Quick start
18
18
 
19
19
  ```bash
20
- npx praxis-harness
20
+ npx @esoteric-logic/praxis-harness@latest
21
21
  ```
22
22
 
23
23
  One command. Copies rules, commands, skills, and kits directly into `~/.claude/`. Node.js 18+ must be installed first.
24
24
 
25
+ > **Always use `@latest`** — `npx` caches packages locally. Without `@latest`, you may get a stale version on machines that installed previously.
26
+
25
27
  **Subsequent commands:**
26
28
  ```bash
27
- npx praxis-harness update # re-copy from latest npm version
28
- npx praxis-harness health # verify install integrity
29
- npx praxis-harness uninstall # remove Praxis-owned files from ~/.claude/
29
+ npx @esoteric-logic/praxis-harness@latest update # re-copy from latest npm version
30
+ npx @esoteric-logic/praxis-harness@latest health # verify install integrity
31
+ npx @esoteric-logic/praxis-harness@latest uninstall # remove Praxis-owned files from ~/.claude/
30
32
  ```
31
33
 
32
34
  ## After install
@@ -66,7 +68,12 @@ For technical research: `/discover` (structured options evaluation before decisi
66
68
  | `risk` | Add a risk register entry to the vault |
67
69
  | `kit` | Activate/deactivate an AI-Kit |
68
70
  | `review` | Manual code review via subagent |
71
+ | `simplify` | Post-implementation code simplification via subagent |
69
72
  | `debug` | Structured test-first debugging |
73
+ | `ship` | Commit, push, and PR in one command with pre-flight checks |
74
+ | `verify-app` | End-to-end verification with regression analysis |
75
+ | `session-retro` | End-of-session retrospective with learnings extraction |
76
+ | `status-update` | Manual vault status.md update |
70
77
  | `context-reset` | Reload context from vault without clearing session |
71
78
 
72
79
  ## Rules
@@ -126,18 +133,64 @@ The vault path is configured per machine during install:
126
133
 
127
134
  Requires [Obsidian CLI](https://obsidian.md) (enable in Obsidian Settings > General > Command line interface). Obsidian must be running for vault search.
128
135
 
136
+ ### What gets documented automatically
137
+
138
+ Praxis auto-documents your work in the vault with zero manual effort. Two independent layers ensure nothing is lost:
139
+
140
+ 1. **Shell hooks** capture facts (git state, timestamps) even if Claude runs out of context
141
+ 2. **Stop prompt** captures meaning (summaries, decisions, learnings) from conversation context
142
+
143
+ **At session end** (zero action needed):
144
+ - `status.md` — updated with What/So What/Now What
145
+ - `claude-progress.json` — session entry with summary, accomplishments, milestones, features
146
+ - `notes/{date}_session-note.md` — session summary, decisions, learnings, next steps
147
+ - `notes/decision-log.md` — checkpoint decisions, scope changes (appended)
148
+ - `notes/learnings.md` — [LEARN:tag] pattern entries (appended)
149
+ - `specs/` — ADRs for architectural decisions made during the session
150
+
151
+ **During workflow skills** (automatic within each skill):
152
+
153
+ | Skill | Auto-writes to vault |
154
+ |-------|---------------------|
155
+ | `/execute` | `status.md` loop position, `decision-log.md` scope events |
156
+ | `/verify` | `claude-progress.json` milestones[] |
157
+ | `/review` | `specs/review-{date}-{slug}.md` (full findings breakdown) |
158
+ | `/simplify` | `notes/{date}_simplify-findings.md` |
159
+ | `/debug` | `notes/{date}_debug-trace.md` |
160
+ | `/verify-app` | `specs/verify-app-{date}-{slug}.md` |
161
+ | `/ship` | `claude-progress.json` features[] |
162
+
163
+ **On context compaction** (automatic fallback):
164
+ - `plans/{date}-compact-checkpoint.md` — git state, active plan, loop position
165
+ - `claude-progress.json` — session entry preserved
166
+
129
167
  ## Updating
130
168
 
169
+ ### Updating the harness
170
+
131
171
  ```bash
132
- npx praxis-harness update
172
+ npx @esoteric-logic/praxis-harness@latest update
173
+ ```
174
+
175
+ Re-copies all hooks, skills, rules, and kits from the latest npm package version. Config file is preserved.
176
+
177
+ > **Always use `@latest`** to avoid `npx` serving a cached older version.
178
+
179
+ ### Updating existing projects
180
+
181
+ 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.
182
+
183
+ ```
184
+ Step 1: npx @esoteric-logic/praxis-harness@latest update → deploys new hooks, skills, rules
185
+ Step 2: /scaffold-exist → audits vault, adds missing files
133
186
  ```
134
187
 
135
- Re-copies all files from the latest npm package version. Config file is preserved.
188
+ New projects get everything automatically via `/scaffold-new`.
136
189
 
137
190
  ## Uninstalling
138
191
 
139
192
  ```bash
140
- npx praxis-harness uninstall
193
+ npx @esoteric-logic/praxis-harness@latest uninstall
141
194
  ```
142
195
 
143
196
  Removes all Praxis-owned files from `~/.claude/`. Does not delete config, vault templates, or installed plugins.
@@ -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.1",
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 -->