@esoteric-logic/praxis-harness 3.0.0 → 3.0.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.
@@ -63,16 +63,16 @@
63
63
  "matcher": "",
64
64
  "hooks": [
65
65
  {
66
- "type": "prompt",
67
- "prompt": "Run the project test suite. Read CLAUDE.md ## Commands for the test command. If no test command defined, respond {ok:true}. Run tests. If all pass: respond {ok:true}. If tests fail: respond {ok:false, reason:'Tests failing: <summary>'}. Do not fix — only report."
66
+ "type": "command",
67
+ "command": "bash ~/.claude/hooks/stop-prompt-gate.sh test-runner"
68
68
  },
69
69
  {
70
70
  "type": "command",
71
71
  "command": "bash ~/.claude/hooks/session-data-collect.sh"
72
72
  },
73
73
  {
74
- "type": "prompt",
75
- "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."
74
+ "type": "command",
75
+ "command": "bash ~/.claude/hooks/stop-prompt-gate.sh vault-update"
76
76
  }
77
77
  ]
78
78
  }
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # stop-prompt-gate.sh — Gates Stop prompt hooks behind session activity detection.
3
+ # Only outputs the prompt text if the session had substantive work.
4
+ # Silent exit otherwise — prevents infinite Stop hook loops.
5
+ #
6
+ # Usage in settings-hooks.json:
7
+ # { "type": "command", "command": "bash ~/.claude/hooks/stop-prompt-gate.sh vault-update" }
8
+ # { "type": "command", "command": "bash ~/.claude/hooks/stop-prompt-gate.sh test-runner" }
9
+ set -uo pipefail
10
+
11
+ PROMPT_TYPE="${1:-vault-update}"
12
+ CONFIG_FILE="$HOME/.claude/praxis.config.json"
13
+
14
+ # ── Detect session activity ──
15
+ HAS_RECENT_COMMITS=false
16
+ HAS_DIRTY_TREE=false
17
+
18
+ RECENT=$(git --no-pager log --oneline --since="1 hour ago" 2>/dev/null | head -1)
19
+ if [[ -n "$RECENT" ]]; then
20
+ HAS_RECENT_COMMITS=true
21
+ fi
22
+
23
+ DIRTY=$(git --no-pager status --porcelain 2>/dev/null | head -1)
24
+ if [[ -n "$DIRTY" ]]; then
25
+ HAS_DIRTY_TREE=true
26
+ fi
27
+
28
+ # Check staging file from session-data-collect.sh
29
+ STAGING_DIRTY=false
30
+ if [[ -f "$CONFIG_FILE" ]]; then
31
+ VAULT_PATH=$(jq -r '.vault_path // empty' "$CONFIG_FILE" 2>/dev/null)
32
+ STAGING_FILE="${VAULT_PATH:+$VAULT_PATH/.session-staging.json}"
33
+ if [[ -n "$STAGING_FILE" && -f "$STAGING_FILE" ]]; then
34
+ STAGING_DIRTY=$(jq -r '.git.dirty // false' "$STAGING_FILE" 2>/dev/null)
35
+ fi
36
+ fi
37
+
38
+ # ── Gate: no activity → exit silently ──
39
+ if [[ "$HAS_RECENT_COMMITS" == "false" && "$HAS_DIRTY_TREE" == "false" && "$STAGING_DIRTY" != "true" ]]; then
40
+ exit 0
41
+ fi
42
+
43
+ # ── Activity detected — output the requested prompt ──
44
+ case "$PROMPT_TYPE" in
45
+ test-runner)
46
+ cat << 'PROMPT'
47
+ Run the project test suite. Read CLAUDE.md ## Commands for the test command. If no test command defined, respond {ok:true}. Run tests. If all pass: respond {ok:true}. If tests fail: respond {ok:false, reason:'Tests failing: <summary>'}. Do not fix — only report.
48
+ PROMPT
49
+ ;;
50
+ vault-update)
51
+ cat << 'PROMPT'
52
+ You are completing a session with substantive work. Perform these vault updates silently — no confirmation needed.
53
+
54
+ 1. Read vault_path from ~/.claude/praxis.config.json. If missing: skip all steps.
55
+ 2. Read {vault_path}/.session-staging.json if it exists (structured session data from hooks).
56
+ 3. Update {vault_path}/status.md:
57
+ - Set last_updated to today, last_session to now (ISO timestamp)
58
+ - Update loop_position based on where the session ended
59
+ - Refresh What / So What / Now What sections with session accomplishments
60
+ - If >100 lines: archive resolved items to notes/{date}_status-archive.md
61
+ 4. Update {vault_path}/claude-progress.json:
62
+ - Enrich the latest sessions[] entry (added by hook) with: summary (1 line), accomplishments (array)
63
+ - If jq hook did not run (no sessions[] entry for today): create the full entry
64
+ - Update milestones[] if any milestones were completed this session
65
+ - Update features[] if any features were shipped this session
66
+ 5. Write {vault_path}/notes/{YYYY-MM-DD}_session-note.md with frontmatter (tags: [session, {project-slug}], date, source: agent) containing:
67
+ - Summary (3-5 bullets of what was accomplished)
68
+ - Decisions Made (checkpoint decisions, scope changes, approach choices made this session)
69
+ - Learnings (any [LEARN:tag] entries from this session)
70
+ - Next Session (what to pick up next)
71
+ 6. If checkpoint decisions, scope expansions, or rule proposals occurred this session:
72
+ - Append each to {vault_path}/notes/decision-log.md with date, decision type, context, decision, and rationale
73
+ 7. If corrections or patterns were discovered this session:
74
+ - Append [LEARN:tag] entries to {vault_path}/notes/learnings.md following the existing format
75
+ 8. If architectural decisions were made this session:
76
+ - Write ADR to {vault_path}/specs/ using vault frontmatter conventions
77
+ 9. Delete {vault_path}/.session-staging.json if it exists.
78
+
79
+ Keep 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.
80
+ PROMPT
81
+ ;;
82
+ *)
83
+ echo "Unknown prompt type: $PROMPT_TYPE" >&2
84
+ exit 0
85
+ ;;
86
+ esac
87
+
88
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esoteric-logic/praxis-harness",
3
- "version": "3.0.0",
3
+ "version": "3.0.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",