qualia-framework 2.2.1 → 2.4.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.
Files changed (51) hide show
  1. package/bin/collect-metrics.sh +62 -0
  2. package/framework/agents/qualia-phase-researcher.md +6 -3
  3. package/framework/agents/qualia-planner.md +10 -7
  4. package/framework/agents/qualia-research-synthesizer.md +110 -147
  5. package/framework/agents/red-team-qa.md +130 -0
  6. package/framework/hooks/auto-format.sh +9 -1
  7. package/framework/hooks/confirm-delete.sh +2 -2
  8. package/framework/hooks/migration-validate.sh +21 -16
  9. package/framework/hooks/pre-commit.sh +17 -9
  10. package/framework/hooks/pre-deploy-gate.sh +22 -15
  11. package/framework/hooks/retention-cleanup.sh +4 -4
  12. package/framework/hooks/save-session-state.sh +18 -10
  13. package/framework/hooks/session-context-loader.sh +21 -0
  14. package/framework/hooks/skill-announce.sh +2 -0
  15. package/framework/install.sh +9 -4
  16. package/framework/qualia-engine/VERSION +1 -1
  17. package/framework/qualia-engine/bin/collect-metrics.sh +71 -0
  18. package/framework/qualia-engine/bin/qualia-tools.js +104 -63
  19. package/framework/qualia-engine/references/continuation-prompt.md +97 -0
  20. package/framework/qualia-engine/references/employee-guide.md +167 -0
  21. package/framework/qualia-engine/templates/lab-notes.md +16 -0
  22. package/framework/qualia-engine/templates/projects/ai-agent.md +1 -1
  23. package/framework/qualia-engine/templates/projects/voice-agent.md +4 -4
  24. package/framework/qualia-engine/templates/roadmap.md +4 -0
  25. package/framework/qualia-engine/templates/state.md +3 -0
  26. package/framework/qualia-engine/workflows/execute-phase.md +17 -17
  27. package/framework/qualia-engine/workflows/new-project.md +54 -130
  28. package/framework/qualia-engine/workflows/progress.md +63 -28
  29. package/framework/skills/client-handoff/SKILL.md +135 -0
  30. package/framework/skills/collab-onboard/SKILL.md +111 -0
  31. package/framework/skills/deep-research/SKILL.md +34 -71
  32. package/framework/skills/docs-lookup/SKILL.md +4 -3
  33. package/framework/skills/learn/SKILL.md +30 -6
  34. package/framework/skills/mobile-expo/SKILL.md +117 -4
  35. package/framework/skills/openrouter-agent/SKILL.md +922 -0
  36. package/framework/skills/qualia/SKILL.md +65 -19
  37. package/framework/skills/qualia-audit-milestone/SKILL.md +5 -2
  38. package/framework/skills/qualia-complete-milestone/SKILL.md +34 -8
  39. package/framework/skills/qualia-evolve/SKILL.md +200 -0
  40. package/framework/skills/qualia-execute-phase/SKILL.md +5 -2
  41. package/framework/skills/qualia-guide/SKILL.md +32 -0
  42. package/framework/skills/qualia-help/SKILL.md +100 -64
  43. package/framework/skills/qualia-new-project/SKILL.md +186 -62
  44. package/framework/skills/qualia-plan-phase/SKILL.md +5 -2
  45. package/framework/skills/qualia-report/SKILL.md +217 -0
  46. package/framework/skills/qualia-start/SKILL.md +31 -59
  47. package/framework/skills/qualia-verify-work/SKILL.md +33 -6
  48. package/framework/skills/qualia-workflow/SKILL.md +5 -5
  49. package/framework/skills/ship/SKILL.md +32 -6
  50. package/framework/skills/voice-agent/SKILL.md +1174 -269
  51. package/package.json +1 -1
@@ -10,37 +10,39 @@ if [ ! -t 0 ]; then
10
10
  fi
11
11
  fi
12
12
 
13
+ DESTRUCTIVE=0
14
+ WARNINGS_COUNT=0
15
+
13
16
  check_sql_file() {
14
17
  local file="$1"
15
- local issues=0
16
18
  [ ! -f "$file" ] && return 0
17
19
 
20
+ # Destructive ops → block
18
21
  if grep -iE '\bDROP\s+(TABLE|SCHEMA|DATABASE)\b' "$file" > /dev/null 2>&1; then
19
- q_warn "DROP TABLE/SCHEMA in ${file}"
20
- issues=$((issues + 1))
22
+ q_fail "DROP TABLE/SCHEMA in ${file}"
23
+ DESTRUCTIVE=$((DESTRUCTIVE + 1))
21
24
  fi
22
25
  if grep -iE '\bTRUNCATE\b' "$file" > /dev/null 2>&1; then
23
- q_warn "TRUNCATE in ${file}"
24
- issues=$((issues + 1))
26
+ q_fail "TRUNCATE in ${file}"
27
+ DESTRUCTIVE=$((DESTRUCTIVE + 1))
25
28
  fi
26
29
  if grep -iE '\bDELETE\s+FROM\b' "$file" > /dev/null 2>&1 && ! grep -iE '\bWHERE\b' "$file" > /dev/null 2>&1; then
27
- q_warn "DELETE without WHERE in ${file}"
28
- issues=$((issues + 1))
30
+ q_fail "DELETE without WHERE in ${file}"
31
+ DESTRUCTIVE=$((DESTRUCTIVE + 1))
29
32
  fi
30
33
  if grep -iE '\bALTER\s+TABLE\b.*\bDROP\s+COLUMN\b' "$file" > /dev/null 2>&1; then
31
- q_warn "DROP COLUMN in ${file}"
32
- issues=$((issues + 1))
34
+ q_fail "DROP COLUMN in ${file}"
35
+ DESTRUCTIVE=$((DESTRUCTIVE + 1))
33
36
  fi
37
+ # Missing RLS → warn only (reminder, not destructive)
34
38
  if grep -iE '\bCREATE\s+TABLE\b' "$file" > /dev/null 2>&1 && ! grep -iE '\bENABLE\s+ROW\s+LEVEL\s+SECURITY\b' "$file" > /dev/null 2>&1; then
35
- q_warn "New table without RLS in ${file}"
36
- issues=$((issues + 1))
39
+ q_warn "New table needs RLS in ${file} — tell Claude: 'add RLS policies to the new table'"
40
+ WARNINGS_COUNT=$((WARNINGS_COUNT + 1))
37
41
  fi
38
- return $issues
39
42
  }
40
43
 
41
44
  TOTAL=0
42
45
  TRIGGERED=false
43
- WARN_DETAILS=""
44
46
 
45
47
  # Mode 1: SQL file written
46
48
  if [ -n "$FILE_PATH" ] && [[ "$FILE_PATH" == *.sql ]]; then
@@ -59,9 +61,12 @@ if [ -n "$COMMAND" ] && echo "$COMMAND" | grep -qE 'supabase\s+db\s+push'; then
59
61
  done
60
62
  fi
61
63
 
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"
64
+ # Block on destructive ops, warn on missing RLS
65
+ if $TRIGGERED && [ "$DESTRUCTIVE" -gt 0 ]; then
66
+ printf '{"continue":false,"stopReason":"◆ MIGRATION: %d destructive operation(s) blocked","systemMessage":"◆ MIGRATION BLOCKED: %d destructive operation(s) found. Tell Claude to review the SQL and confirm these operations are intentional."}' "$DESTRUCTIVE" "$DESTRUCTIVE"
67
+ exit 2
68
+ elif $TRIGGERED && [ "$WARNINGS_COUNT" -gt 0 ]; then
69
+ printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: %d warning(s) — tell Claude to review missing RLS policies."}' "$WARNINGS_COUNT"
65
70
  elif $TRIGGERED; then
66
71
  printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: clean"}'
67
72
  fi
@@ -2,6 +2,12 @@
2
2
  # Pre-commit validation — secrets, debug statements, TypeScript, lint
3
3
  source "$(dirname "$0")/qualia-colors.sh"
4
4
 
5
+ if ! command -v node &>/dev/null; then
6
+ [ ! -t 0 ] && cat > /dev/null
7
+ printf '{"continue":false,"stopReason":"PRE-COMMIT: node is not installed — cannot verify safety. Install node to proceed."}'
8
+ exit 2
9
+ fi
10
+
5
11
  if [ ! -t 0 ]; then
6
12
  INPUT=$(cat)
7
13
  COMMAND=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.command||d.tool_input||'')}catch(e){}" 2>/dev/null)
@@ -28,7 +34,7 @@ SECRETS_PATTERN="(api[_-]?key|apikey|secret[_-]?key|password|passwd|pwd|token|au
28
34
  for file in $STAGED_FILES; do
29
35
  if [ -f "$file" ] && grep -iE "$SECRETS_PATTERN" "$file" > /dev/null 2>&1; then
30
36
  q_fail "Secret in ${file}"
31
- FAIL_DETAILS="${FAIL_DETAILS}Potential secret in ${file}. "
37
+ FAIL_DETAILS="${FAIL_DETAILS}A password or API key was found in ${file} — tell Claude: 'remove the secret and use an environment variable instead.' "
32
38
  BLOCKED=true
33
39
  fi
34
40
  done
@@ -37,16 +43,18 @@ done
37
43
  ENV_FILES=$(echo "$STAGED_FILES" | grep -E '\.env($|\.)' | grep -v '.example' | grep -v '.sample' || true)
38
44
  if [ -n "$ENV_FILES" ]; then
39
45
  q_fail ".env file staged: ${ENV_FILES}"
40
- FAIL_DETAILS="${FAIL_DETAILS}.env file staged for commit. "
46
+ FAIL_DETAILS="${FAIL_DETAILS}.env file contains secrets and shouldn't be committed — tell Claude: 'unstage the .env file.' "
41
47
  BLOCKED=true
42
48
  fi
43
49
 
44
- # Debug statements in JS/TS
45
- JS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|jsx|ts|tsx)$' || true)
46
- if [ -n "$JS_FILES" ]; then
47
- for file in $JS_FILES; do
50
+ # Debug statements in JS/TS (block in production code, allow in tests/stories)
51
+ JS_PROD_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|jsx|ts|tsx)$' | grep -vE '\.test\.|\.spec\.|__tests__/|\.stories\.' || true)
52
+ if [ -n "$JS_PROD_FILES" ]; then
53
+ for file in $JS_PROD_FILES; do
48
54
  if [ -f "$file" ] && grep -E "console\.(log|debug|info)|debugger" "$file" > /dev/null 2>&1; then
49
- q_warn "Debug statement in ${file}"
55
+ q_fail "Debug statement in ${file}"
56
+ FAIL_DETAILS="${FAIL_DETAILS}Debug statement in ${file} — tell Claude: 'remove console.log/debugger from production code.' "
57
+ BLOCKED=true
50
58
  fi
51
59
  done
52
60
  fi
@@ -70,7 +78,7 @@ if [ -f "tsconfig.json" ]; then
70
78
  touch "$TSC_STAMP"
71
79
  else
72
80
  q_fail "TypeScript errors"
73
- FAIL_DETAILS="${FAIL_DETAILS}TypeScript errors. Run npx tsc --noEmit. "
81
+ FAIL_DETAILS="${FAIL_DETAILS}Code errors found — tell Claude: 'fix the TypeScript errors and try committing again.' "
74
82
  BLOCKED=true
75
83
  fi
76
84
  fi
@@ -82,7 +90,7 @@ if $BLOCKED; then
82
90
  {
83
91
  "continue": false,
84
92
  "stopReason": "◆ Pre-commit: blocked",
85
- "systemMessage": "◆ PRE-COMMIT BLOCKED: ${FAIL_DETAILS}Fix issues, stage corrected files, and retry."
93
+ "systemMessage": "◆ PRE-COMMIT BLOCKED: ${FAIL_DETAILS}Tell Claude to fix these issues and try committing again."
86
94
  }
87
95
  EOJSON
88
96
  exit 2
@@ -5,6 +5,12 @@
5
5
 
6
6
  source "$(dirname "$0")/qualia-colors.sh"
7
7
 
8
+ if ! command -v node &>/dev/null; then
9
+ [ ! -t 0 ] && cat > /dev/null
10
+ printf '{"continue":false,"stopReason":"DEPLOY GATE: node is not installed — cannot verify safety. Install node to proceed."}'
11
+ exit 2
12
+ fi
13
+
8
14
  # Parse command from stdin JSON
9
15
  if [ ! -t 0 ]; then
10
16
  INPUT=$(cat)
@@ -14,10 +20,11 @@ else
14
20
  fi
15
21
 
16
22
  # Only gate production deploys
17
- if ! echo "$COMMAND" | grep -qE 'vercel\s+.*--prod|vercel\s+--prod'; then
23
+ if ! echo "$COMMAND" | grep -qE '(npx\s+|bunx\s+)?vercel\s+.*--prod|(npx\s+|bunx\s+)?vercel\s+--prod'; then
18
24
  exit 0
19
25
  fi
20
26
 
27
+
21
28
  # Skip if gate was passed recently (within 5 minutes)
22
29
  STAMP="/tmp/.deploy-gate-$(echo "$PWD" | md5sum | cut -c1-8)"
23
30
  if [ -f "$STAMP" ]; then
@@ -39,7 +46,7 @@ if [ -f "tsconfig.json" ]; then
39
46
  q_pass "TypeScript"
40
47
  else
41
48
  q_fail "TypeScript errors"
42
- FAIL_DETAILS="${FAIL_DETAILS}TypeScript errors found. Run npx tsc --noEmit to see details. "
49
+ FAIL_DETAILS="${FAIL_DETAILS}Code errors found tell Claude: 'fix the TypeScript errors' before deploying. "
43
50
  FAILURES=$((FAILURES + 1))
44
51
  fi
45
52
  else
@@ -52,7 +59,7 @@ if [ -f ".eslintrc.json" ] || [ -f ".eslintrc.js" ] || [ -f "eslint.config.js" ]
52
59
  q_pass "Lint"
53
60
  else
54
61
  q_fail "Lint errors"
55
- FAIL_DETAILS="${FAIL_DETAILS}ESLint errors found. Run npx eslint . to see details. "
62
+ FAIL_DETAILS="${FAIL_DETAILS}Code quality issues found tell Claude: 'fix the lint errors' before deploying. "
56
63
  FAILURES=$((FAILURES + 1))
57
64
  fi
58
65
  else
@@ -67,7 +74,7 @@ if [ -f "package.json" ]; then
67
74
  q_pass "Tests"
68
75
  else
69
76
  q_fail "Tests failed"
70
- FAIL_DETAILS="${FAIL_DETAILS}Tests failed. Run npm test to see details. "
77
+ FAIL_DETAILS="${FAIL_DETAILS}Tests are failing tell Claude: 'fix the failing tests' before deploying. "
71
78
  FAILURES=$((FAILURES + 1))
72
79
  fi
73
80
  else
@@ -75,7 +82,15 @@ if [ -f "package.json" ]; then
75
82
  fi
76
83
  fi
77
84
 
78
- # ─── Check 4: Build ───
85
+ # ─── Check 4: Environment ───
86
+ if [ -f ".env.example" ] && [ ! -f ".env.local" ] && [ ! -f ".env" ]; then
87
+ q_warn "Missing .env.local"
88
+ WARNINGS=$((WARNINGS + 1))
89
+ else
90
+ q_pass "Environment"
91
+ fi
92
+
93
+ # ─── Check 5: Build ───
79
94
  if [ -f "package.json" ]; then
80
95
  BUILD_SCRIPT=$(node -e "try{console.log(require('./package.json').scripts?.build||'')}catch(e){console.log('')}" 2>/dev/null)
81
96
  if [ -n "$BUILD_SCRIPT" ]; then
@@ -83,7 +98,7 @@ if [ -f "package.json" ]; then
83
98
  q_pass "Build"
84
99
  else
85
100
  q_fail "Build failed"
86
- FAIL_DETAILS="${FAIL_DETAILS}Build failed. Run npm run build to see errors. "
101
+ FAIL_DETAILS="${FAIL_DETAILS}Build is failing tell Claude: 'fix the build errors' before deploying. "
87
102
  FAILURES=$((FAILURES + 1))
88
103
  fi
89
104
  else
@@ -91,14 +106,6 @@ if [ -f "package.json" ]; then
91
106
  fi
92
107
  fi
93
108
 
94
- # ─── Check 5: Environment ───
95
- if [ -f ".env.example" ] && [ ! -f ".env.local" ] && [ ! -f ".env" ]; then
96
- q_warn "Missing .env.local"
97
- WARNINGS=$((WARNINGS + 1))
98
- else
99
- q_pass "Environment"
100
- fi
101
-
102
109
  # ─── Check 6: REVIEW.md ───
103
110
  REVIEW_FILE=""
104
111
  [ -f ".planning/REVIEW.md" ] && REVIEW_FILE=".planning/REVIEW.md"
@@ -132,7 +139,7 @@ if [ "$FAILURES" -gt 0 ]; then
132
139
  {
133
140
  "continue": false,
134
141
  "stopReason": "◆ Deploy gate: ${FAILURES} check(s) failed",
135
- "systemMessage": "◆ DEPLOY BLOCKED: ${FAILURES} check(s) failed. ${FAIL_DETAILS}Fix and retry vercel --prod."
142
+ "systemMessage": "◆ DEPLOY BLOCKED: ${FAILURES} check(s) failed. ${FAIL_DETAILS}Fix issues and retry with /ship."
136
143
  }
137
144
  EOJSON
138
145
  exit 2
@@ -10,7 +10,7 @@
10
10
  # paste-cache/ 3 days
11
11
  # shell-snapshots/ 3 days
12
12
  # projects/*.jsonl 7 days
13
- # tasks/ 3 days
13
+ # tasks/ 14 days
14
14
  # plans/ 7 days
15
15
 
16
16
  CLAUDE_DIR="$HOME/.claude"
@@ -37,9 +37,9 @@ find "$CLAUDE_DIR/shell-snapshots/" -type f -mtime +3 -delete 2>/dev/null
37
37
  find "$CLAUDE_DIR/projects/" -name "*.jsonl" -mtime +7 -delete 2>/dev/null
38
38
  find "$CLAUDE_DIR/projects/" -type d -empty -delete 2>/dev/null
39
39
 
40
- # tasks/ — keep 3 days (stale task files from old sessions)
41
- find "$CLAUDE_DIR/tasks/" -type f -mtime +3 -delete 2>/dev/null
42
- find "$CLAUDE_DIR/tasks/" -type d -empty -delete 2>/dev/null
40
+ # tasks/ — keep 14 days (team sessions may span multiple days)
41
+ find "$CLAUDE_DIR/tasks/" -type f -mtime +14 -delete 2>/dev/null
42
+ find "$CLAUDE_DIR/tasks/" -mindepth 1 -type d -empty -delete 2>/dev/null
43
43
 
44
44
  # plans/ — keep 7 days (old Claude Code plan mode files)
45
45
  find "$CLAUDE_DIR/plans/" -type f -mtime +7 -delete 2>/dev/null
@@ -82,14 +82,17 @@ if [ "$PROJECT_NAME" != ".claude" ] && [ "$PROJECT_NAME" != "Projects" ] && { [
82
82
 
83
83
  # Dedup: skip if ANY existing entry has the same project + branch + summary
84
84
  NEW_KEY="${PROJECT_NAME}|${GIT_BRANCH:-—}|${SUMMARY:-—}"
85
- if tail -n +4 "$DIGEST_FILE" | while IFS= read -r line; do
85
+ DUPLICATE=false
86
+ while IFS= read -r line; do
86
87
  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
88
+ if [ "$ENTRY_KEY" = "$NEW_KEY" ]; then
89
+ DUPLICATE=true
90
+ break
91
+ fi
92
+ done < <(tail -n +4 "$DIGEST_FILE")
93
+ if [ "$DUPLICATE" = "true" ]; then
94
+ : # duplicate found, skip adding to digest
90
95
  else
91
- exit 0 # duplicate found, skip
92
- fi
93
96
 
94
97
  # Read existing entries (skip header — first 3 lines), keep last 19
95
98
  EXISTING=$(tail -n +4 "$DIGEST_FILE" | head -19)
@@ -101,6 +104,7 @@ if [ "$PROJECT_NAME" != ".claude" ] && [ "$PROJECT_NAME" != "Projects" ] && { [
101
104
  ${ENTRY}
102
105
  ${EXISTING}
103
106
  HEADER
107
+ fi
104
108
  fi
105
109
 
106
110
  # --- Auto-handoff for significant sessions (>5 files changed) ---
@@ -156,15 +160,19 @@ HANDOFF
156
160
  fi
157
161
  fi
158
162
 
159
- # --- Push to portal (non-blocking, fire-and-forget) ---
163
+ # --- Push to portal (with error tracking) ---
160
164
  PORTAL_API_KEY="${CLAUDE_PORTAL_API_KEY:-}"
161
165
  if [ -n "$PORTAL_API_KEY" ] && [ "$PROJECT_NAME" != ".claude" ]; then
162
- curl -s -X POST "https://portal.qualiasolutions.net/api/claude/session-log" \
166
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "https://portal.qualiasolutions.net/api/claude/session-log" \
163
167
  -H "X-API-Key: $PORTAL_API_KEY" \
164
168
  -H "Content-Type: application/json" \
165
169
  -d @"$SESSION_FILE" \
166
- --max-time 5 \
167
- > /dev/null 2>&1 &
170
+ --max-time 5 2>/dev/null || echo "000")
171
+ if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then
172
+ rm -f "$SESSION_DIR/.portal-last-error"
173
+ else
174
+ echo "$HTTP_CODE" > "$SESSION_DIR/.portal-last-error"
175
+ fi
168
176
  fi
169
177
 
170
178
  # --- Cleanup old session files (keep last 50 for retrospective analytics — RETR-04) ---
@@ -62,6 +62,27 @@ if [ -f "$HOME/.claude/settings.json" ]; then
62
62
  fi
63
63
  fi
64
64
 
65
+ # Check for stale knowledge files (>30 days old)
66
+ STALE_COUNT=0
67
+ STALE_NAMES=""
68
+ for kf in "$HOME/.claude/knowledge"/*.md; do
69
+ [ -f "$kf" ] || continue
70
+ KF_AGE=$(( ($(date +%s) - $(stat -c %Y "$kf" 2>/dev/null || echo 0)) / 86400 ))
71
+ if [ "$KF_AGE" -gt 30 ]; then
72
+ STALE_COUNT=$((STALE_COUNT + 1))
73
+ STALE_NAMES="${STALE_NAMES} $(basename "$kf")(${KF_AGE}d)"
74
+ fi
75
+ done
76
+ if [ "$STALE_COUNT" -gt 0 ]; then
77
+ ISSUES="${ISSUES}${STALE_COUNT} stale knowledge file(s):${STALE_NAMES}. "
78
+ fi
79
+
80
+ # Check portal sync health
81
+ if [ -f "$SESSION_DIR/.portal-last-error" ]; then
82
+ PORTAL_ERR=$(cat "$SESSION_DIR/.portal-last-error" 2>/dev/null)
83
+ ISSUES="${ISSUES}Portal sync failed (HTTP ${PORTAL_ERR}). "
84
+ fi
85
+
65
86
  if [ -n "$ISSUES" ]; then
66
87
  MSG="${MSG} | ▲ ${ISSUES}"
67
88
  fi
@@ -29,6 +29,7 @@ SKILL_DESC=(
29
29
  # Navigation
30
30
  ["qualia-start"]="Activating Qualia mode"
31
31
  ["qualia-progress"]="Checking progress"
32
+ ["qualia-guide"]="Showing developer guide"
32
33
  ["qualia-idk"]="Analyzing next steps"
33
34
  ["qualia"]="Routing to next action"
34
35
  ["qualia-resume-work"]="Restoring session context"
@@ -36,6 +37,7 @@ SKILL_DESC=(
36
37
  # Quality
37
38
  ["qualia-review"]="Running code review"
38
39
  ["qualia-optimize"]="Running optimization pass"
40
+ ["qualia-evolve"]="Evolving framework"
39
41
  ["qualia-production-check"]="Running production audit"
40
42
  ["qualia-framework-audit"]="Auditing framework"
41
43
  ["deep-research"]="Spawning research agents"
@@ -150,14 +150,13 @@ elif [ ! -f "$CLAUDE_DIR/CLAUDE.md" ]; then
150
150
  ## Identity
151
151
  **$ROLE_NAME** — Developer at Qualia Solutions.
152
152
 
153
- - Stack: Next.js 16+, React 19, TypeScript, Supabase, Vercel, VAPI, ElevenLabs, Telnyx, Retell AI, OpenRouter
153
+ - Stack: Next.js 16+, React 19, TypeScript, Supabase, Vercel, Retell AI, ElevenLabs, Telnyx, OpenRouter
154
154
 
155
155
  ## Role: DEVELOPER
156
156
 
157
157
  You are a developer at Qualia Solutions, working under Fawzi Goussous (founder).
158
158
  - Work on feature branches only — never push to main/master
159
- - Submit PRs for review before merging
160
- - Do NOT deploy to production — Fawzi handles deploys
159
+ - Use \`/ship\` to deploy it runs quality gates, auto-creates feature branches, and deploys
161
160
  - Cannot modify the Qualia framework (CLAUDE.md, skills, hooks)
162
161
  - Ask Fawzi when unsure about architecture decisions
163
162
 
@@ -169,10 +168,16 @@ You are a developer at Qualia Solutions, working under Fawzi Goussous (founder).
169
168
  - See \`rules/security.md\` for auth, RLS, Zod, secrets rules
170
169
  - See \`rules/frontend.md\` for design standards
171
170
 
171
+ ## Getting Started
172
+ - Run \`/collab-onboard\` when joining a new project — it explains what's built and how to contribute
173
+ - Onboarding guide: ~/Projects/qualia-erp/docs/trainee-onboarding.md
174
+
172
175
  ## Workflow
173
176
  - **MANDATORY FIRST ACTION**: On every session start, invoke the \`qualia-start\` skill before doing anything else.
174
- - Run \`/qualia-review\` before deploying anything
177
+ - Run \`/qualia-review\` before deploying
175
178
  - Run \`/browser-qa\` after frontend changes
179
+ - Run \`/pr\` to submit work for review — never push to main directly
180
+ - Run \`/qualia-idk\` if stuck — it suggests next steps and can escalate to Fawzi
176
181
  - Ask for help if stuck — don't guess
177
182
 
178
183
  ## Qualia Mode (always active)
@@ -1 +1 @@
1
- 1.14.0
1
+ 2.4.1
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+ # Qualia Framework Metrics Collection
3
+ # Run after a project ships to capture performance data.
4
+ # Usage: collect-metrics.sh [project-dir]
5
+ # Output: appends to ~/.claude/knowledge/framework-metrics.md
6
+
7
+ PROJECT_DIR="${1:-.}"
8
+ METRICS_FILE="$HOME/.claude/knowledge/framework-metrics.md"
9
+ DATE=$(date +%Y-%m-%d)
10
+
11
+ # Ensure metrics file exists
12
+ if [ ! -f "$METRICS_FILE" ]; then
13
+ cat > "$METRICS_FILE" << 'HEADER'
14
+ # Framework Performance Metrics
15
+
16
+ > Auto-collected after each project ships. Read by `/qualia-evolve` to optimize the framework.
17
+
18
+ | Date | Project | Phases | Sessions | Deviations | IDK Calls | Verify Pass Rate | Lab Notes | FQS |
19
+ |------|---------|--------|----------|------------|-----------|-----------------|-----------|-----|
20
+ HEADER
21
+ fi
22
+
23
+ cd "$PROJECT_DIR" || exit 1
24
+
25
+ # Project name
26
+ PROJECT=$(basename "$(pwd)")
27
+
28
+ # Phase count
29
+ PHASES=$(ls -d .planning/phases/*/ 2>/dev/null | wc -l)
30
+
31
+ # Session count (from session-digest entries for this project)
32
+ SESSIONS=$(grep -c "$PROJECT" ~/.claude/knowledge/session-digest.md 2>/dev/null || echo "?")
33
+
34
+ # Deviation count (gap-fix plans)
35
+ DEVIATIONS=$(find .planning/phases/ -name "*-PLAN.md" -exec grep -l "gaps" {} \; 2>/dev/null | wc -l)
36
+
37
+ # IDK calls (search session digest for qualia-idk mentions with this project)
38
+ IDK_CALLS=$(grep "$PROJECT" ~/.claude/knowledge/session-digest.md 2>/dev/null | grep -c "idk\|stuck\|lost" || echo "0")
39
+
40
+ # Verify pass rate (UAT files with PASSED vs total UAT files)
41
+ TOTAL_UAT=$(find .planning/phases/ -name "*-UAT.md" 2>/dev/null | wc -l)
42
+ PASSED_UAT=$(grep -rl "PASSED\|✅.*Overall" .planning/phases/*/*.md 2>/dev/null | wc -l)
43
+ if [ "$TOTAL_UAT" -gt 0 ]; then
44
+ PASS_RATE=$(( PASSED_UAT * 100 / TOTAL_UAT ))%
45
+ else
46
+ PASS_RATE="n/a"
47
+ fi
48
+
49
+ # Lab Notes count
50
+ LAB_NOTES=$(grep -c "^###" .planning/lab-notes.md 2>/dev/null || echo "0")
51
+
52
+ # Completion rate from ROADMAP.md (actual, not assumed)
53
+ TOTAL_PLANS=$(grep -c "^- \[" .planning/ROADMAP.md 2>/dev/null || echo "0")
54
+ COMPLETED_PLANS=$(grep -c "^- \[x\]" .planning/ROADMAP.md 2>/dev/null || echo "0")
55
+ if [ "$TOTAL_PLANS" -gt 0 ]; then
56
+ COMPLETION_RATE=$(( COMPLETED_PLANS * 100 / TOTAL_PLANS ))
57
+ else
58
+ COMPLETION_RATE=100
59
+ fi
60
+
61
+ # FQS = completion_rate / avg_sessions_to_ship * 100 (per OBJECTIVE.md)
62
+ if [ "$SESSIONS" != "?" ] && [ "$SESSIONS" -gt 0 ]; then
63
+ FQS=$(( COMPLETION_RATE * 100 / SESSIONS ))
64
+ else
65
+ FQS="?"
66
+ fi
67
+
68
+ # Append to metrics file
69
+ echo "| $DATE | $PROJECT | $PHASES | $SESSIONS | $DEVIATIONS | $IDK_CALLS | $PASS_RATE | $LAB_NOTES | $FQS |" >> "$METRICS_FILE"
70
+
71
+ echo "Metrics collected for $PROJECT → $METRICS_FILE"