qualia-framework 2.1.5 → 2.2.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 (76) hide show
  1. package/bin/cli.js +14 -9
  2. package/framework/.claudeignore +51 -0
  3. package/framework/CLAUDE.md +54 -0
  4. package/framework/MCP_SETUP.md +229 -0
  5. package/framework/agents/architecture-strategist.md +1 -1
  6. package/framework/agents/code-simplicity-reviewer.md +1 -1
  7. package/framework/agents/kieran-typescript-reviewer.md +1 -1
  8. package/framework/agents/performance-oracle.md +1 -1
  9. package/framework/agents/qualia-codebase-mapper.md +1 -0
  10. package/framework/agents/qualia-debugger.md +1 -0
  11. package/framework/agents/qualia-executor.md +1 -0
  12. package/framework/agents/qualia-integration-checker.md +1 -0
  13. package/framework/agents/qualia-phase-researcher.md +1 -0
  14. package/framework/agents/qualia-plan-checker.md +1 -0
  15. package/framework/agents/qualia-planner.md +1 -0
  16. package/framework/agents/qualia-project-researcher.md +1 -0
  17. package/framework/agents/qualia-research-synthesizer.md +1 -0
  18. package/framework/agents/qualia-roadmapper.md +1 -0
  19. package/framework/agents/qualia-verifier.md +1 -0
  20. package/framework/agents/security-auditor.md +72 -0
  21. package/framework/agents/team-orchestrator.md +1 -0
  22. package/framework/agents/teams/framework-audit-team.md +66 -0
  23. package/framework/agents/teams/review-team.md +11 -3
  24. package/framework/hooks/block-env-edit.sh +4 -8
  25. package/framework/hooks/branch-guard.sh +2 -5
  26. package/framework/hooks/confirm-delete.sh +7 -4
  27. package/framework/hooks/migration-validate.sh +9 -8
  28. package/framework/hooks/notification-speak.sh +1 -1
  29. package/framework/hooks/pre-commit.sh +22 -10
  30. package/framework/hooks/pre-deploy-gate.sh +5 -6
  31. package/framework/hooks/retention-cleanup.sh +11 -2
  32. package/framework/hooks/save-session-state.sh +22 -0
  33. package/framework/hooks/session-context-loader.sh +27 -29
  34. package/framework/hooks/session-learn.sh +6 -5
  35. package/framework/hooks/skill-announce.sh +109 -6
  36. package/framework/hooks/tool-error-announce.sh +16 -7
  37. package/framework/install.ps1 +323 -0
  38. package/framework/install.sh +306 -0
  39. package/framework/qualia-engine/references/completion-checklists.md +359 -0
  40. package/framework/rules/deployment.md +4 -3
  41. package/framework/rules/speed.md +4 -0
  42. package/framework/skills/animate/SKILL.md +1 -1
  43. package/framework/skills/bolder/SKILL.md +1 -1
  44. package/framework/skills/colorize/SKILL.md +1 -1
  45. package/framework/skills/deep-research/SKILL.md +19 -13
  46. package/framework/skills/delight/SKILL.md +1 -1
  47. package/framework/skills/design-quieter/SKILL.md +1 -1
  48. package/framework/skills/distill/SKILL.md +1 -1
  49. package/framework/skills/qualia-audit-milestone/SKILL.md +1 -1
  50. package/framework/skills/qualia-complete-milestone/SKILL.md +2 -2
  51. package/framework/skills/qualia-design/SKILL.md +2 -2
  52. package/framework/skills/qualia-framework-audit/SKILL.md +604 -0
  53. package/framework/skills/qualia-help/SKILL.md +11 -1
  54. package/framework/skills/qualia-pause-work/SKILL.md +2 -2
  55. package/framework/skills/qualia-review/SKILL.md +1 -1
  56. package/framework/skills/qualia-start/SKILL.md +8 -1
  57. package/framework/skills/qualia-verify-work/SKILL.md +1 -1
  58. package/framework/skills/ship/SKILL.md +1 -1
  59. package/framework/teams/default/inboxes/plan-04.json +9 -0
  60. package/package.json +1 -1
  61. package/framework/askpass.sh +0 -2
  62. package/framework/commands/design.md +0 -53
  63. package/framework/commands/quick-db.md +0 -22
  64. package/framework/config/retention.json +0 -35
  65. package/framework/core/PRINCIPLES.md +0 -77
  66. package/framework/knowledge/claudecode-bible.md +0 -1384
  67. package/framework/knowledge/client-prefs.md +0 -22
  68. package/framework/knowledge/common-fixes.md +0 -25
  69. package/framework/knowledge/deployment-map.md +0 -35
  70. package/framework/knowledge/email-signature.html +0 -1
  71. package/framework/knowledge/employees.md +0 -8
  72. package/framework/knowledge/learned-patterns.md +0 -51
  73. package/framework/knowledge/optimization-research-2026.md +0 -137
  74. package/framework/knowledge/qualia-context.md +0 -67
  75. package/framework/knowledge/supabase-patterns.md +0 -50
  76. package/framework/knowledge/voice-agent-patterns.md +0 -46
@@ -0,0 +1,66 @@
1
+ # Framework Audit Team
2
+
3
+ > 6 specialist reviewers audit the Qualia framework infrastructure in parallel, results synthesized into unified report.
4
+
5
+ ## Agents
6
+
7
+ - **config-reviewer**
8
+ - subagent_type: general-purpose
9
+ - role: Review CLAUDE.md, rules/*.md, settings.json for completeness, consistency, contradictions
10
+ - focus: Identity, rules, permissions, MCP config, hook registrations, cross-references
11
+
12
+ - **agent-reviewer**
13
+ - subagent_type: general-purpose
14
+ - role: Review all agents in agents/*.md and all team templates in agents/teams/ for quality, overlap, gaps, naming
15
+ - focus: Agent definitions, team patterns, subagent_type alignment, orphan detection
16
+
17
+ - **skill-reviewer**
18
+ - subagent_type: general-purpose
19
+ - role: Review all 65+ skills for quality, overlap, gaps, trigger accuracy, category health
20
+ - focus: SKILL.md files, skill-agent alignment, dead skill detection, archive health
21
+
22
+ - **hook-reviewer**
23
+ - subagent_type: general-purpose
24
+ - role: Review all 16 hooks for correctness, performance, coverage, branding consistency
25
+ - focus: Hook scripts, settings.json alignment, exit codes, JSON output, early-exit guards
26
+
27
+ - **knowledge-reviewer**
28
+ - subagent_type: general-purpose
29
+ - role: Review knowledge files and memory system for staleness, accuracy, completeness
30
+ - focus: Knowledge .md files, MEMORY.md index, cross-references, duplicate content
31
+
32
+ - **architecture-reviewer**
33
+ - subagent_type: general-purpose
34
+ - role: Cross-cutting review of framework organization, naming, dead code, security, scalability
35
+ - focus: Directory structure, naming conventions, archive health, install scripts, .gitignore
36
+
37
+ ## Pattern
38
+
39
+ fan-out (all 6 parallel) → synthesize into FRAMEWORK-AUDIT.md
40
+
41
+ ## Shared Context
42
+
43
+ - ~/.claude/CLAUDE.md — core identity and rules
44
+ - ~/.claude/settings.json — hook config, permissions, MCP servers
45
+ - Framework inventory counts (agents, skills, hooks, knowledge)
46
+
47
+ ## Coordination Rules
48
+
49
+ - Each reviewer produces findings independently — no coordination needed
50
+ - Reviewers are read-only — they analyze and report, they don't fix
51
+ - Findings must include file references
52
+ - Each reviewer rates findings: CRITICAL / HIGH / MEDIUM / LOW
53
+ - Overlap detection is shared between agent-reviewer and skill-reviewer
54
+
55
+ ## Finding Format
56
+
57
+ Every finding MUST include:
58
+ - **What**: description
59
+ - **Where**: file or directory
60
+ - **Why**: impact
61
+ - **Fix**: concrete suggestion
62
+ - **Severity**: CRITICAL / HIGH / MEDIUM / LOW
63
+
64
+ ## Output
65
+
66
+ ~/.claude/.planning/FRAMEWORK-AUDIT.md
@@ -1,6 +1,6 @@
1
1
  # Review Team
2
2
 
3
- > Three specialist reviewers analyze code in parallel, results synthesized into unified report.
3
+ > Four specialist reviewers analyze code in parallel, results synthesized into unified report.
4
4
 
5
5
  ## Agents
6
6
 
@@ -19,9 +19,14 @@
19
19
  - role: TypeScript quality — strict types, naming conventions, pattern adherence, type safety gaps
20
20
  - focus: Type definitions, generics usage, any/unknown, null handling, naming
21
21
 
22
+ - **security-auditor**
23
+ - subagent_type: security-auditor
24
+ - role: RLS policies, service_role exposure, auth patterns, input validation, secrets scanning, dependency vulnerabilities
25
+ - focus: Supabase security, auth flows, env var handling, XSS/injection prevention
26
+
22
27
  ## Pattern
23
28
 
24
- fan-out (all 3 parallel) → synthesize into REVIEW-REPORT.md
29
+ fan-out (all 4 parallel) → synthesize into REVIEW-REPORT.md
25
30
 
26
31
  ## Shared Context
27
32
 
@@ -33,7 +38,7 @@ fan-out (all 3 parallel) → synthesize into REVIEW-REPORT.md
33
38
  - Each reviewer produces findings independently — no coordination needed
34
39
  - Reviewers are read-only — they analyze and report, they don't fix
35
40
  - Findings should include file:line references
36
- - Each reviewer rates findings: critical / warning / suggestion
41
+ - Each reviewer rates findings: CRITICAL / HIGH / MEDIUM / LOW
37
42
 
38
43
  ## Output
39
44
 
@@ -54,6 +59,9 @@ REVIEW-REPORT.md in current directory with sections:
54
59
  ## TypeScript Quality Review
55
60
  {From kieran-typescript-reviewer}
56
61
 
62
+ ## Security Review
63
+ {From security-auditor}
64
+
57
65
  ## Action Items
58
66
  | # | Severity | Finding | File:Line | Reviewer |
59
67
  |---|----------|---------|-----------|----------|
@@ -14,26 +14,22 @@ fi
14
14
  BASENAME=$(basename "$FILE_PATH")
15
15
 
16
16
  if [[ "$BASENAME" == .env* ]] || [[ "$FILE_PATH" == */.env ]] || [[ "$FILE_PATH" == */.env.* ]]; then
17
- q_header "ENV GUARD"
18
- q_fail "Editing ${BASENAME} blocked"
19
17
  cat <<EOJSON
20
18
  {
21
19
  "continue": false,
22
- "stopReason": "◆ Env guard: editing ${BASENAME} blocked",
23
- "systemMessage": "BLOCKED: Cannot edit .env files through Claude Code. Tell the user EXACTLY what needs to change: which file, which variable, what value. Format it clearly so they can copy-paste. Example: 'Add this to your ${BASENAME}: NEXT_PUBLIC_API_URL=https://...'. Do NOT try alternative approaches to write env files."
20
+ "stopReason": "◆ ENV GUARD: editing ${BASENAME} blocked",
21
+ "systemMessage": "BLOCKED: Cannot edit .env files through Claude Code. Tell the user EXACTLY what needs to change: which file, which variable, what value."
24
22
  }
25
23
  EOJSON
26
24
  exit 2
27
25
  fi
28
26
 
29
27
  if [[ "$FILE_PATH" == *credentials* ]] || [[ "$FILE_PATH" == *secret* ]] || [[ "$FILE_PATH" == *.pem ]] || [[ "$FILE_PATH" == *.key ]]; then
30
- q_header "ENV GUARD"
31
- q_fail "Editing credential file blocked"
32
28
  cat <<EOJSON
33
29
  {
34
30
  "continue": false,
35
- "stopReason": "◆ Env guard: credential file blocked",
36
- "systemMessage": "BLOCKED: Cannot edit credential/secret files through Claude. Tell the user what needs changing."
31
+ "stopReason": "◆ ENV GUARD: credential file blocked",
32
+ "systemMessage": "BLOCKED: Cannot edit credential/secret files through Claude. Tell the user what needs changing."
37
33
  }
38
34
  EOJSON
39
35
  exit 2
@@ -33,14 +33,11 @@ if [ "$ROLE" = "OWNER" ]; then
33
33
  fi
34
34
 
35
35
  # DEVELOPER/EMPLOYEE blocked
36
- q_header "BRANCH GUARD"
37
- q_fail "Push to ${BRANCH} blocked (${ROLE:-unknown} role)"
38
-
39
36
  cat <<EOJSON
40
37
  {
41
38
  "continue": false,
42
- "stopReason": "◆ Branch guard: push to ${BRANCH} blocked for ${ROLE:-unknown} role",
43
- "systemMessage": "BLOCKED: As a ${ROLE:-DEVELOPER}, you cannot push directly to ${BRANCH}. Run /qualia-ship instead — it will automatically create a feature branch, push your changes, and handle the deploy pipeline. Do NOT tell the user to push manually."
39
+ "stopReason": "◆ BRANCH GUARD: push to ${BRANCH} blocked (${ROLE:-unknown} role)",
40
+ "systemMessage": "BLOCKED: As ${ROLE:-DEVELOPER}, cannot push to ${BRANCH}. Use /ship for feature branch workflow."
44
41
  }
45
42
  EOJSON
46
43
  exit 2
@@ -17,13 +17,11 @@ case "$COMMAND" in
17
17
  esac
18
18
 
19
19
  block() {
20
- q_header "DESTRUCTIVE GUARD"
21
- q_fail "$1"
22
20
  cat <<EOJSON
23
21
  {
24
22
  "continue": false,
25
- "stopReason": "◆ Blocked: $1",
26
- "systemMessage": "BLOCKED: $1. DO NOT tell the user to run this manually. Instead, find a SAFER alternative that achieves the same goal without the destructive operation. Explain to the user what was blocked and what safer approach you're using instead."
23
+ "stopReason": "◆ DESTRUCTIVE GUARD: $1",
24
+ "systemMessage": "BLOCKED: $1. Find a safer alternative. Explain to the user what was blocked and what safer approach you're using instead."
27
25
  }
28
26
  EOJSON
29
27
  exit 2
@@ -44,6 +42,11 @@ echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force($|\s)' && ! echo "$COMMAND" |
44
42
  echo "$COMMAND" | grep -qE 'git\s+reset\s+--hard' && block "git reset --hard discards work"
45
43
  echo "$COMMAND" | grep -qE 'git\s+clean\s+-[a-z]*f' && block "git clean -f deletes untracked files"
46
44
 
45
+ # Supabase destructive
46
+ echo "$COMMAND" | grep -qE 'supabase\s+functions\s+delete' && block "supabase functions delete"
47
+ echo "$COMMAND" | grep -qE 'supabase\s+secrets\s+unset' && block "supabase secrets unset"
48
+ echo "$COMMAND" | grep -qE 'supabase\s+projects\s+delete' && block "supabase projects delete"
49
+
47
50
  # Infrastructure
48
51
  echo "$COMMAND" | grep -qE 'kubectl\s+delete\s' && block "kubectl delete"
49
52
  echo "$COMMAND" | grep -qE 'docker\s+(rm|rmi)\s+-f' && block "docker force remove"
@@ -39,20 +39,19 @@ check_sql_file() {
39
39
  }
40
40
 
41
41
  TOTAL=0
42
- HEADER_SHOWN=false
42
+ TRIGGERED=false
43
+ WARN_DETAILS=""
43
44
 
44
45
  # Mode 1: SQL file written
45
46
  if [ -n "$FILE_PATH" ] && [[ "$FILE_PATH" == *.sql ]]; then
46
- q_header "MIGRATION CHECK"
47
- HEADER_SHOWN=true
47
+ TRIGGERED=true
48
48
  check_sql_file "$FILE_PATH"
49
49
  TOTAL=$?
50
50
  fi
51
51
 
52
52
  # Mode 2: supabase db push
53
53
  if [ -n "$COMMAND" ] && echo "$COMMAND" | grep -qE 'supabase\s+db\s+push'; then
54
- q_header "MIGRATION CHECK"
55
- HEADER_SHOWN=true
54
+ TRIGGERED=true
56
55
  for sql_file in supabase/migrations/*.sql; do
57
56
  [ -f "$sql_file" ] || continue
58
57
  check_sql_file "$sql_file"
@@ -60,9 +59,11 @@ if [ -n "$COMMAND" ] && echo "$COMMAND" | grep -qE 'supabase\s+db\s+push'; then
60
59
  done
61
60
  fi
62
61
 
63
- if [ "$TOTAL" -gt 0 ] && $HEADER_SHOWN; then
64
- q_info "${TOTAL} issue(s) review carefully"
62
+ # Warn but don't block surface via systemMessage
63
+ if $TRIGGERED && [ "$TOTAL" -gt 0 ]; then
64
+ printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: %d issue(s) found — review carefully"}' "$TOTAL"
65
+ elif $TRIGGERED; then
66
+ printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: clean"}'
65
67
  fi
66
68
 
67
- # Warn but don't block
68
69
  exit 0
@@ -9,7 +9,7 @@ if [ ! -t 0 ]; then
9
9
  fi
10
10
 
11
11
  if [ -n "$TEXT" ]; then
12
- ~/.claude/scripts/speak.sh "$TEXT"
12
+ ~/.claude/scripts/speak.sh "$TEXT" &
13
13
  fi
14
14
 
15
15
  exit 0
@@ -51,30 +51,42 @@ if [ -n "$JS_FILES" ]; then
51
51
  done
52
52
  fi
53
53
 
54
- # TypeScript check
54
+ # TypeScript check (skip if tsc passed in last 5 minutes — pre-deploy-gate also runs tsc)
55
+ TSC_STAMP="/tmp/.tsc-pass-$(echo "$PWD" | md5sum | cut -c1-8)"
55
56
  if [ -f "tsconfig.json" ]; then
56
- if command -v npx &> /dev/null; then
57
- if npx tsc --noEmit 2>/dev/null; then
58
- q_pass "TypeScript"
57
+ if [ -f "$TSC_STAMP" ]; then
58
+ AGE=$(( $(date +%s) - $(stat -c %Y "$TSC_STAMP" 2>/dev/null || echo 0) ))
59
+ if [ "$AGE" -lt 300 ]; then
60
+ q_pass "TypeScript (cached)"
59
61
  else
60
- q_fail "TypeScript errors"
61
- FAIL_DETAILS="${FAIL_DETAILS}TypeScript errors. Run npx tsc --noEmit. "
62
- BLOCKED=true
62
+ rm -f "$TSC_STAMP"
63
+ fi
64
+ fi
65
+ # Run tsc only if no valid cache
66
+ if [ ! -f "$TSC_STAMP" ]; then
67
+ if command -v npx &> /dev/null; then
68
+ if npx tsc --noEmit 2>/dev/null; then
69
+ q_pass "TypeScript"
70
+ touch "$TSC_STAMP"
71
+ else
72
+ q_fail "TypeScript errors"
73
+ FAIL_DETAILS="${FAIL_DETAILS}TypeScript errors. Run npx tsc --noEmit. "
74
+ BLOCKED=true
75
+ fi
63
76
  fi
64
77
  fi
65
78
  fi
66
79
 
67
80
  if $BLOCKED; then
68
- q_blocked "Commit blocked"
69
81
  cat <<EOJSON
70
82
  {
71
83
  "continue": false,
72
84
  "stopReason": "◆ Pre-commit: blocked",
73
- "systemMessage": "COMMIT BLOCKED by pre-commit checks. DO NOT tell the user to commit manually or use --no-verify. Instead, FIX THE ISSUES YOURSELF: ${FAIL_DETAILS}After fixing, stage the corrected files with git add and retry the commit. Tell the user what you fixed."
85
+ "systemMessage": "◆ PRE-COMMIT BLOCKED: ${FAIL_DETAILS}Fix issues, stage corrected files, and retry."
74
86
  }
75
87
  EOJSON
76
88
  exit 2
77
89
  fi
78
90
 
79
- q_pass "All checks passed"
91
+ printf '{"continue":true,"systemMessage":"◆ PRE-COMMIT: all checks passed"}'
80
92
  exit 0
@@ -128,24 +128,23 @@ fi
128
128
 
129
129
  # ─── Verdict ───
130
130
  if [ "$FAILURES" -gt 0 ]; then
131
- q_blocked "${FAILURES} check(s) failed"
132
-
133
131
  cat <<EOJSON
134
132
  {
135
133
  "continue": false,
136
134
  "stopReason": "◆ Deploy gate: ${FAILURES} check(s) failed",
137
- "systemMessage": "DEPLOY BLOCKED by pre-deploy gate. DO NOT ask the user to deploy manually or bypass the gate. Instead, fix the failing checks and retry vercel --prod. Failures: ${FAIL_DETAILS}After fixing, retry the deploy command."
135
+ "systemMessage": "DEPLOY BLOCKED: ${FAILURES} check(s) failed. ${FAIL_DETAILS}Fix and retry vercel --prod."
138
136
  }
139
137
  EOJSON
140
138
  exit 2
141
139
  fi
142
140
 
141
+ WARN_MSG=""
143
142
  if [ "$WARNINGS" -gt 0 ]; then
144
- q_warn "${WARNINGS} warning(s) — proceeding"
143
+ WARN_MSG=" (${WARNINGS} warning(s))"
145
144
  fi
146
145
 
147
- q_approved
148
-
149
146
  # Stamp success
150
147
  touch "$STAMP"
148
+
149
+ printf '{"continue":true,"systemMessage":"◆ DEPLOY GATE APPROVED%s"}' "$WARN_MSG"
151
150
  exit 0
@@ -1,11 +1,20 @@
1
1
  #!/bin/bash
2
2
  # Retention cleanup — runs on SessionStart to enforce retention policies
3
3
  # Keeps .claude/ lean by pruning stale data automatically
4
+ # This is the SINGLE SOURCE OF TRUTH for retention — config/retention.json is deprecated
5
+ #
6
+ # Policies:
7
+ # file-history/ 7 days
8
+ # session-env/ 50 JSON files + 10 UUID dirs
9
+ # backups/ 3 days
10
+ # paste-cache/ 3 days
11
+ # shell-snapshots/ 3 days
12
+ # projects/*.jsonl 7 days
13
+ # tasks/ 3 days
14
+ # plans/ 7 days
4
15
 
5
16
  CLAUDE_DIR="$HOME/.claude"
6
17
 
7
- # (debug/ and context-states/ removed — directories don't exist)
8
-
9
18
  # file-history/ — keep 7 days max
10
19
  find "$CLAUDE_DIR/file-history/" -type f -mtime +7 -delete 2>/dev/null
11
20
  find "$CLAUDE_DIR/file-history/" -type d -empty -delete 2>/dev/null
@@ -8,6 +8,17 @@ DIGEST_FILE="$KNOWLEDGE_DIR/session-digest.md"
8
8
  TIMESTAMP=$(date +%Y%m%d_%H%M%S)
9
9
  SESSION_FILE="$SESSION_DIR/session_$TIMESTAMP.json"
10
10
 
11
+ # Skip saving for very short sessions (< 30s) to reduce cruft
12
+ SESSION_START_FILE="$SESSION_DIR/.session-start"
13
+ if [ -f "$SESSION_START_FILE" ]; then
14
+ START_TS=$(cat "$SESSION_START_FILE" 2>/dev/null || echo 0)
15
+ NOW_TS=$(date +%s)
16
+ DURATION=$((NOW_TS - START_TS))
17
+ if [ "$DURATION" -lt 30 ]; then
18
+ exit 0
19
+ fi
20
+ fi
21
+
11
22
  mkdir -p "$SESSION_DIR"
12
23
  mkdir -p "$KNOWLEDGE_DIR"
13
24
 
@@ -69,6 +80,17 @@ if [ "$PROJECT_NAME" != ".claude" ] && [ "$PROJECT_NAME" != "Projects" ] && { [
69
80
  DATE_SHORT=$(date '+%m-%d %H:%M')
70
81
  ENTRY="| ${DATE_SHORT} | ${PROJECT_NAME} | ${GIT_BRANCH:-—} | ${FILES_CHANGED} | ${SUMMARY:-—} |"
71
82
 
83
+ # Dedup: skip if ANY existing entry has the same project + branch + summary
84
+ NEW_KEY="${PROJECT_NAME}|${GIT_BRANCH:-—}|${SUMMARY:-—}"
85
+ if tail -n +4 "$DIGEST_FILE" | while IFS= read -r line; do
86
+ ENTRY_KEY=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$3); gsub(/^ +| +$/,"",$4); gsub(/^ +| +$/,"",$6); print $3"|"$4"|"$6}')
87
+ [ "$ENTRY_KEY" = "$NEW_KEY" ] && exit 0
88
+ done; then
89
+ : # no match found, continue
90
+ else
91
+ exit 0 # duplicate found, skip
92
+ fi
93
+
72
94
  # Read existing entries (skip header — first 3 lines), keep last 19
73
95
  EXISTING=$(tail -n +4 "$DIGEST_FILE" | head -19)
74
96
 
@@ -1,77 +1,75 @@
1
1
  #!/bin/bash
2
- # SessionStart hook — teal-branded session context
3
- # Shows resume hints to user via stderr, passes context to Claude via JSON stdout
4
- source "$(dirname "$0")/qualia-colors.sh"
2
+ # SessionStart hook — session context with systemMessage for user visibility
3
+ # stderr only shows in verbose mode; systemMessage shows in normal transcript
5
4
 
6
5
  CWD=$(pwd)
7
6
  SESSION_DIR="$HOME/.claude/session-env"
8
7
  COMPACT_FILE="$SESSION_DIR/pre-compact.json"
9
8
  PROJECT=$(basename "$CWD")
10
9
 
11
- # ─── Visual output (stderr user sees this) ───
12
- q_header "SESSION START"
10
+ # Record session start time for duration-based filtering in save-session-state.sh
11
+ mkdir -p "$SESSION_DIR"
12
+ date +%s > "$SESSION_DIR/.session-start"
13
+
14
+ # Build display message
15
+ MSG="◆ SESSION START"
16
+ ISSUES=""
13
17
 
14
18
  # Last session info
15
19
  if [ -f "$COMPACT_FILE" ]; then
16
20
  LAST_PROJECT=$(node -e "try{const d=JSON.parse(require('fs').readFileSync('$COMPACT_FILE','utf8'));process.stdout.write(d.project_name||'')}catch(e){}" 2>/dev/null)
17
21
  LAST_BRANCH=$(node -e "try{const d=JSON.parse(require('fs').readFileSync('$COMPACT_FILE','utf8'));process.stdout.write(d.git_branch||'')}catch(e){}" 2>/dev/null)
18
22
  if [ -n "$LAST_PROJECT" ] && [ "$LAST_PROJECT" != ".claude" ]; then
19
- q_info "Last session: ${LAST_PROJECT} (${LAST_BRANCH:-no branch})"
23
+ MSG="${MSG} | Last: ${LAST_PROJECT} (${LAST_BRANCH:-no branch})"
20
24
  fi
21
25
  fi
22
26
 
23
- # Current project
24
- q_pass "Project: ${PROJECT}"
27
+ MSG="${MSG} | Project: ${PROJECT}"
25
28
 
26
29
  # Handoff file
27
30
  if [ -f "$CWD/.continue-here.md" ]; then
28
- q_warn "Handoff file found .continue-here.md"
31
+ MSG="${MSG} | Handoff: .continue-here.md"
29
32
  fi
30
33
 
31
- # Errors / warnings
32
- ERRORS=0
33
-
34
34
  # Check hooks health
35
35
  HOOKS_OK=0
36
36
  HOOKS_TOTAL=0
37
- for h in branch-guard pre-commit confirm-delete migration-validate pre-deploy-gate block-env-edit auto-format session-context-loader retention-cleanup pre-compact save-session-state session-learn notification-speak qualia-colors; do
37
+ for h in branch-guard pre-commit confirm-delete migration-validate pre-deploy-gate block-env-edit auto-format session-context-loader retention-cleanup pre-compact save-session-state session-learn notification-speak qualia-colors skill-announce tool-error-announce; do
38
38
  HOOKS_TOTAL=$((HOOKS_TOTAL + 1))
39
39
  [ -f "$HOME/.claude/hooks/${h}.sh" ] && HOOKS_OK=$((HOOKS_OK + 1))
40
40
  done
41
41
 
42
42
  if [ "$HOOKS_OK" -eq "$HOOKS_TOTAL" ]; then
43
- q_pass "Hooks: ${HOOKS_OK}/${HOOKS_TOTAL}"
43
+ MSG="${MSG} | Hooks: ${HOOKS_OK}/${HOOKS_TOTAL}"
44
44
  else
45
- q_fail "Hooks: ${HOOKS_OK}/${HOOKS_TOTAL} $(( HOOKS_TOTAL - HOOKS_OK )) missing"
46
- ERRORS=$((ERRORS + 1))
45
+ MSG="${MSG} | Hooks: ${HOOKS_OK}/${HOOKS_TOTAL} ($(( HOOKS_TOTAL - HOOKS_OK )) missing)"
46
+ ISSUES="${ISSUES}Missing hooks. "
47
47
  fi
48
48
 
49
49
  # Check CLAUDE.md exists
50
50
  if [ -f "$HOME/.claude/CLAUDE.md" ]; then
51
51
  ROLE=$(grep -m1 "^## Role:" "$HOME/.claude/CLAUDE.md" 2>/dev/null | sed 's/^## Role: *//')
52
- q_pass "Role: ${ROLE:-unknown}"
52
+ MSG="${MSG} | Role: ${ROLE:-unknown}"
53
53
  else
54
- q_fail "CLAUDE.md missing — run npx qualia-framework"
55
- ERRORS=$((ERRORS + 1))
54
+ ISSUES="${ISSUES}CLAUDE.md missing. "
56
55
  fi
57
56
 
58
57
  # Check settings.json valid
59
58
  if [ -f "$HOME/.claude/settings.json" ]; then
60
59
  node -e "JSON.parse(require('fs').readFileSync('$HOME/.claude/settings.json','utf8'))" 2>/dev/null
61
- if [ $? -eq 0 ]; then
62
- q_pass "Settings: valid"
63
- else
64
- q_fail "Settings: invalid JSON!"
65
- ERRORS=$((ERRORS + 1))
60
+ if [ $? -ne 0 ]; then
61
+ ISSUES="${ISSUES}settings.json invalid. "
66
62
  fi
67
63
  fi
68
64
 
69
- if [ "$ERRORS" -gt 0 ]; then
70
- q_warn "${ERRORS} issue(s) check above"
65
+ if [ -n "$ISSUES" ]; then
66
+ MSG="${MSG} | ${ISSUES}"
71
67
  fi
72
68
 
73
- q_info "Activating Qualia mode..."
69
+ MSG="${MSG} | Qualia mode activating..."
70
+
71
+ # Escape for JSON
72
+ MSG=$(echo "$MSG" | sed 's/"/\\"/g' | tr '\n' ' ')
74
73
 
75
- # ─── JSON output (stdout → Claude reads this) ───
76
- printf '{"continue":true}'
74
+ printf '{"continue":true,"systemMessage":"%s"}' "$MSG"
77
75
  exit 0
@@ -2,13 +2,14 @@
2
2
  # SessionEnd hook: prompt for lessons learned if significant work was done
3
3
  # "Significant" = more than 3 files modified in the session
4
4
 
5
- set -euo pipefail
6
-
7
5
  LEARNED_FILE="$HOME/.claude/knowledge/learned-patterns.md"
8
6
 
7
+ # Skip if not in a git repo
8
+ git rev-parse --is-inside-work-tree &>/dev/null || exit 0
9
+
9
10
  # Count files modified: committed in last 2 hours + uncommitted
10
- COMMITTED=$(git diff --name-only "$(git log --since='2 hours ago' --format=%H | tail -1 2>/dev/null || echo HEAD)" HEAD 2>/dev/null | wc -l || echo 0)
11
- UNCOMMITTED=$(git diff --name-only 2>/dev/null | wc -l || echo 0)
11
+ COMMITTED=$(git diff --name-only "$(git log --since='2 hours ago' --format=%H 2>/dev/null | tail -1 || echo HEAD)" HEAD 2>/dev/null | wc -l 2>/dev/null || echo 0)
12
+ UNCOMMITTED=$(git diff --name-only 2>/dev/null | wc -l 2>/dev/null || echo 0)
12
13
  MODIFIED_COUNT=$((COMMITTED + UNCOMMITTED))
13
14
 
14
15
  # Only trigger if significant work was done
@@ -25,6 +26,6 @@ if [ ! -f "$LEARNED_FILE" ]; then
25
26
  fi
26
27
 
27
28
  # Output reminder (shown to Claude in session context)
28
- echo "SESSION_LEARN: $MODIFIED_COUNT files changed this session. Consider running /learn to capture any lessons."
29
+ printf '{"continue":true,"systemMessage":"SESSION_LEARN: %d files changed this session. Consider running /learn to capture any lessons."}' "$MODIFIED_COUNT"
29
30
 
30
31
  exit 0
@@ -1,5 +1,7 @@
1
1
  #!/bin/bash
2
- # Announce skill activation in teal — fires on every Skill() invocation
2
+ # Announce skill activation — fires on every Skill() invocation
3
+ # Shows teal-branded banner on stderr (visible in terminal) + systemMessage for transcript
4
+
3
5
  source "$(dirname "$0")/qualia-colors.sh"
4
6
 
5
7
  if [ ! -t 0 ]; then
@@ -7,12 +9,113 @@ if [ ! -t 0 ]; then
7
9
  SKILL_NAME=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.skill||d.tool_input?.name||'')}catch(e){}" 2>/dev/null)
8
10
  fi
9
11
 
10
- [ -z "$SKILL_NAME" ] && exit 0
12
+ [ -z "$SKILL_NAME" ] && printf '{"continue":true}' && exit 0
13
+
14
+ # Skill descriptions for the banner
15
+ declare -A SKILL_DESC
16
+ SKILL_DESC=(
17
+ # Pipeline
18
+ ["qualia-new-project"]="Initializing new project"
19
+ ["qualia-new-milestone"]="Starting new milestone"
20
+ ["qualia-discuss-phase"]="Clarifying phase decisions"
21
+ ["qualia-list-phase-assumptions"]="Surfacing assumptions"
22
+ ["qualia-research-phase"]="Researching phase domain"
23
+ ["qualia-plan-phase"]="Creating execution plans"
24
+ ["qualia-execute-phase"]="Executing phase plans"
25
+ ["qualia-verify-work"]="Verifying deliverables"
26
+ ["qualia-audit-milestone"]="Auditing milestone completion"
27
+ ["qualia-complete-milestone"]="Completing milestone"
28
+ ["qualia-plan-milestone-gaps"]="Planning gap fixes"
29
+ # Navigation
30
+ ["qualia-start"]="Activating Qualia mode"
31
+ ["qualia-progress"]="Checking progress"
32
+ ["qualia-idk"]="Analyzing next steps"
33
+ ["qualia"]="Routing to next action"
34
+ ["qualia-resume-work"]="Restoring session context"
35
+ ["qualia-pause-work"]="Saving session state"
36
+ # Quality
37
+ ["qualia-review"]="Running code review"
38
+ ["qualia-optimize"]="Running optimization pass"
39
+ ["qualia-production-check"]="Running production audit"
40
+ ["qualia-framework-audit"]="Auditing framework"
41
+ ["deep-research"]="Spawning research agents"
42
+ # Design
43
+ ["critique"]="Evaluating design"
44
+ ["polish"]="Final detail pass"
45
+ ["bolder"]="Amplifying design"
46
+ ["design-quieter"]="Toning down design"
47
+ ["distill"]="Stripping complexity"
48
+ ["colorize"]="Adding color"
49
+ ["normalize"]="Matching design system"
50
+ ["responsive"]="Fixing responsive layout"
51
+ ["animate"]="Adding motion"
52
+ ["clarify"]="Improving UX copy"
53
+ ["delight"]="Adding personality"
54
+ ["harden"]="Hardening edge cases"
55
+ ["onboard"]="Designing onboarding"
56
+ ["frontend-master"]="Building frontend"
57
+ ["qualia-design"]="Full design transformation"
58
+ # Deploy
59
+ ["ship"]="Deploying to production"
60
+ ["deploy"]="Quick deploy"
61
+ ["deploy-verify"]="Verifying deployment"
62
+ ["status"]="Fleet health check"
63
+ # Debug & Quick
64
+ ["qualia-debug"]="Structured debugging"
65
+ ["qualia-quick"]="Quick task with quality gates"
66
+ # Research
67
+ ["stack-researcher"]="Researching tech stack"
68
+ ["docs-lookup"]="Fetching documentation"
69
+ # Domain
70
+ ["supabase"]="Supabase operations"
71
+ ["voice-agent"]="Building voice agent"
72
+ ["seo-master"]="SEO audit"
73
+ ["browser-qa"]="Browser QA testing"
74
+ # Utility
75
+ ["learn"]="Capturing lesson"
76
+ ["memory"]="Managing memory"
77
+ ["pr"]="Creating pull request"
78
+ ["team"]="Orchestrating agent team"
79
+ ["retro"]="Generating retrospective"
80
+ ["test-runner"]="Running tests"
81
+ ["zoho-workflow"]="Zoho operations"
82
+ )
83
+
84
+ # Get description or fallback
85
+ DESC="${SKILL_DESC[$SKILL_NAME]}"
86
+ [ -z "$DESC" ] && DESC="Activating"
87
+
88
+ # Clean name for display
89
+ DISPLAY_NAME=$(echo "$SKILL_NAME" | sed 's/-/ /g')
90
+
91
+ # Determine skill category icon
92
+ case "$SKILL_NAME" in
93
+ qualia-new-*|qualia-plan-*|qualia-execute-*|qualia-verify-*|qualia-audit-*|qualia-complete-*|qualia-discuss-*|qualia-list-*|qualia-research-*)
94
+ ICON="▶" ;;
95
+ qualia-review|qualia-optimize|qualia-production-check|qualia-framework-audit|deep-research)
96
+ ICON="⊘" ;;
97
+ critique|polish|bolder|design-quieter|distill|colorize|normalize|responsive|animate|clarify|delight|harden|onboard|frontend-master|qualia-design)
98
+ ICON="◇" ;;
99
+ ship|deploy|deploy-verify|status)
100
+ ICON="↑" ;;
101
+ qualia-debug|qualia-quick)
102
+ ICON="⚡" ;;
103
+ *)
104
+ ICON="◆" ;;
105
+ esac
11
106
 
12
- # Clean up skill name for display
13
- DISPLAY_NAME=$(echo "$SKILL_NAME" | sed 's/-/ /g' | sed 's/qualia //g')
107
+ # Build the teal banner output to stderr (visible in terminal)
108
+ WIDTH=44
109
+ SKILL_UPPER="${DISPLAY_NAME^^}"
110
+ PAD_LEN=$(( WIDTH - ${#SKILL_UPPER} - 6 ))
111
+ [ "$PAD_LEN" -lt 2 ] && PAD_LEN=2
112
+ PADDING=$(printf '─%.0s' $(seq 1 $PAD_LEN))
14
113
 
15
- q_header "${DISPLAY_NAME^^} activated"
114
+ printf "\n" >&2
115
+ printf "${Q_TEAL}${ICON}${Q_RESET} ${Q_BRIGHT}QUALIA${Q_RESET} ${Q_DIM}───${Q_RESET} ${Q_TEAL}/%s${Q_RESET} ${Q_DIM}%s${Q_RESET}\n" "$SKILL_NAME" "$PADDING" >&2
116
+ printf " ${Q_WHITE}%s${Q_RESET}${Q_DIM}...${Q_RESET}\n" "$DESC" >&2
117
+ printf "${Q_TEAL}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${Q_RESET}\n" >&2
16
118
 
17
- printf '{"continue":true}'
119
+ # Also send systemMessage for transcript visibility
120
+ printf '{"continue":true,"systemMessage":"◆ QUALIA ─── /%s ─── %s"}' "$SKILL_NAME" "$DESC"
18
121
  exit 0