timsquad 3.4.0 → 3.6.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 (218) hide show
  1. package/README.ko.md +4 -0
  2. package/README.md +4 -0
  3. package/dist/commands/audit.d.ts +22 -0
  4. package/dist/commands/audit.d.ts.map +1 -0
  5. package/dist/commands/audit.js +233 -0
  6. package/dist/commands/audit.js.map +1 -0
  7. package/dist/commands/compile.d.ts.map +1 -1
  8. package/dist/commands/compile.js +84 -3
  9. package/dist/commands/compile.js.map +1 -1
  10. package/dist/commands/daemon.d.ts.map +1 -1
  11. package/dist/commands/daemon.js +50 -3
  12. package/dist/commands/daemon.js.map +1 -1
  13. package/dist/commands/full.js +1 -0
  14. package/dist/commands/full.js.map +1 -1
  15. package/dist/commands/git/pr.js +6 -5
  16. package/dist/commands/git/pr.js.map +1 -1
  17. package/dist/commands/git/release.js +2 -7
  18. package/dist/commands/git/release.js.map +1 -1
  19. package/dist/commands/improve.js +2 -2
  20. package/dist/commands/improve.js.map +1 -1
  21. package/dist/commands/init.js +42 -6
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/log.d.ts.map +1 -1
  24. package/dist/commands/log.js +34 -2
  25. package/dist/commands/log.js.map +1 -1
  26. package/dist/commands/meta-index.d.ts.map +1 -1
  27. package/dist/commands/meta-index.js +30 -0
  28. package/dist/commands/meta-index.js.map +1 -1
  29. package/dist/commands/metrics.d.ts.map +1 -1
  30. package/dist/commands/metrics.js +6 -2
  31. package/dist/commands/metrics.js.map +1 -1
  32. package/dist/commands/retro.d.ts.map +1 -1
  33. package/dist/commands/retro.js +71 -14
  34. package/dist/commands/retro.js.map +1 -1
  35. package/dist/commands/session.js +3 -3
  36. package/dist/commands/session.js.map +1 -1
  37. package/dist/commands/skills.js +4 -7
  38. package/dist/commands/skills.js.map +1 -1
  39. package/dist/commands/status.js +1 -1
  40. package/dist/commands/status.js.map +1 -1
  41. package/dist/commands/upgrade.d.ts.map +1 -1
  42. package/dist/commands/upgrade.js +18 -1
  43. package/dist/commands/upgrade.js.map +1 -1
  44. package/dist/commands/workflow.d.ts +2 -0
  45. package/dist/commands/workflow.d.ts.map +1 -1
  46. package/dist/commands/workflow.js +180 -6
  47. package/dist/commands/workflow.js.map +1 -1
  48. package/dist/daemon/context-writer.d.ts +14 -0
  49. package/dist/daemon/context-writer.d.ts.map +1 -1
  50. package/dist/daemon/context-writer.js +29 -0
  51. package/dist/daemon/context-writer.js.map +1 -1
  52. package/dist/daemon/event-queue.d.ts +4 -0
  53. package/dist/daemon/event-queue.d.ts.map +1 -1
  54. package/dist/daemon/event-queue.js +107 -6
  55. package/dist/daemon/event-queue.js.map +1 -1
  56. package/dist/daemon/file-watcher.d.ts +14 -8
  57. package/dist/daemon/file-watcher.d.ts.map +1 -1
  58. package/dist/daemon/file-watcher.js +78 -41
  59. package/dist/daemon/file-watcher.js.map +1 -1
  60. package/dist/daemon/index.d.ts +1 -0
  61. package/dist/daemon/index.d.ts.map +1 -1
  62. package/dist/daemon/index.js +129 -53
  63. package/dist/daemon/index.js.map +1 -1
  64. package/dist/daemon/jsonl-watcher.d.ts +1 -0
  65. package/dist/daemon/jsonl-watcher.d.ts.map +1 -1
  66. package/dist/daemon/jsonl-watcher.js.map +1 -1
  67. package/dist/daemon/session-notes.d.ts +33 -0
  68. package/dist/daemon/session-notes.d.ts.map +1 -0
  69. package/dist/daemon/session-notes.js +74 -0
  70. package/dist/daemon/session-notes.js.map +1 -0
  71. package/dist/daemon/session-state.d.ts +8 -0
  72. package/dist/daemon/session-state.d.ts.map +1 -1
  73. package/dist/daemon/session-state.js +33 -0
  74. package/dist/daemon/session-state.js.map +1 -1
  75. package/dist/daemon/shutdown.d.ts.map +1 -1
  76. package/dist/daemon/shutdown.js +3 -1
  77. package/dist/daemon/shutdown.js.map +1 -1
  78. package/dist/index.js +2 -0
  79. package/dist/index.js.map +1 -1
  80. package/dist/lib/agent-generator.d.ts +4 -0
  81. package/dist/lib/agent-generator.d.ts.map +1 -1
  82. package/dist/lib/agent-generator.js +63 -3
  83. package/dist/lib/agent-generator.js.map +1 -1
  84. package/dist/lib/compile-rules.d.ts +2 -0
  85. package/dist/lib/compile-rules.d.ts.map +1 -1
  86. package/dist/lib/compile-rules.js +2 -0
  87. package/dist/lib/compile-rules.js.map +1 -1
  88. package/dist/lib/compiler.d.ts +21 -1
  89. package/dist/lib/compiler.d.ts.map +1 -1
  90. package/dist/lib/compiler.js +113 -3
  91. package/dist/lib/compiler.js.map +1 -1
  92. package/dist/lib/config.d.ts +3 -0
  93. package/dist/lib/config.d.ts.map +1 -1
  94. package/dist/lib/config.js +17 -2
  95. package/dist/lib/config.js.map +1 -1
  96. package/dist/lib/project.d.ts.map +1 -1
  97. package/dist/lib/project.js +8 -3
  98. package/dist/lib/project.js.map +1 -1
  99. package/dist/lib/skill-generator.d.ts +1 -1
  100. package/dist/lib/skill-generator.d.ts.map +1 -1
  101. package/dist/lib/skill-generator.js +39 -3
  102. package/dist/lib/skill-generator.js.map +1 -1
  103. package/dist/lib/ssot-map.d.ts +31 -0
  104. package/dist/lib/ssot-map.d.ts.map +1 -0
  105. package/dist/lib/ssot-map.js +76 -0
  106. package/dist/lib/ssot-map.js.map +1 -0
  107. package/dist/lib/template.js +1 -0
  108. package/dist/lib/template.js.map +1 -1
  109. package/dist/lib/workflow-state.d.ts +1 -1
  110. package/dist/lib/workflow-state.d.ts.map +1 -1
  111. package/dist/lib/workflow-state.js +1 -1
  112. package/dist/lib/workflow-state.js.map +1 -1
  113. package/dist/types/config.d.ts +10 -1
  114. package/dist/types/config.d.ts.map +1 -1
  115. package/dist/types/config.js +22 -17
  116. package/dist/types/config.js.map +1 -1
  117. package/dist/types/index.d.ts +1 -0
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/types/index.js +1 -0
  120. package/dist/types/index.js.map +1 -1
  121. package/dist/types/meta-index.d.ts +8 -0
  122. package/dist/types/meta-index.d.ts.map +1 -1
  123. package/dist/types/project.d.ts +1 -1
  124. package/dist/types/project.d.ts.map +1 -1
  125. package/dist/types/project.js.map +1 -1
  126. package/dist/types/ssot-map.d.ts +28 -0
  127. package/dist/types/ssot-map.d.ts.map +1 -0
  128. package/dist/types/ssot-map.js +6 -0
  129. package/dist/types/ssot-map.js.map +1 -0
  130. package/package.json +4 -4
  131. package/templates/base/agents/base/tsq-architect.md +2 -2
  132. package/templates/base/agents/base/tsq-librarian.md +45 -0
  133. package/templates/base/knowledge/checklists/plan-quality.md +31 -0
  134. package/templates/base/knowledge/checklists/stability-verification.md +14 -0
  135. package/templates/base/skills/_shared/naming-conventions.md +49 -0
  136. package/templates/base/skills/_template/SKILL.md +33 -17
  137. package/templates/base/skills/audit/SKILL.md +66 -0
  138. package/templates/base/skills/coding/SKILL.md +49 -29
  139. package/templates/base/skills/coding/rules/async-patterns.md +81 -0
  140. package/templates/base/skills/coding/rules/code-organization.md +80 -0
  141. package/templates/base/skills/coding/rules/error-handling.md +76 -0
  142. package/templates/base/skills/coding/rules/type-safety.md +85 -0
  143. package/templates/base/skills/controller/SKILL.md +50 -84
  144. package/templates/base/skills/controller/delegation/developer.md +25 -0
  145. package/templates/base/skills/controller/delegation/librarian.md +33 -0
  146. package/templates/base/skills/controller/delegation/reviewer.md +19 -0
  147. package/templates/base/skills/controller/memory/.gitkeep +0 -0
  148. package/templates/base/skills/controller/triggers/phase-complete.md +25 -0
  149. package/templates/base/skills/controller/triggers/sequence-complete.md +15 -0
  150. package/templates/base/skills/controller/triggers/ssot-changed.md +14 -0
  151. package/templates/base/skills/controller/triggers/task-complete.md +14 -0
  152. package/templates/base/skills/database/SKILL.md +8 -25
  153. package/templates/base/skills/database/rules/query-optimization.md +32 -0
  154. package/templates/base/skills/database/rules/supabase-patterns.md +94 -0
  155. package/templates/base/skills/librarian/SKILL.md +53 -0
  156. package/templates/base/skills/main-session-constraints/SKILL.md +62 -0
  157. package/templates/base/skills/methodology/tdd/SKILL.md +6 -0
  158. package/templates/base/skills/product-audit/SKILL.md +115 -0
  159. package/templates/base/skills/product-audit/checklists/01-security.md +86 -0
  160. package/templates/base/skills/product-audit/checklists/02-performance.md +67 -0
  161. package/templates/base/skills/product-audit/checklists/03-seo.md +46 -0
  162. package/templates/base/skills/product-audit/checklists/04-accessibility.md +66 -0
  163. package/templates/base/skills/product-audit/checklists/05-ui-ux.md +50 -0
  164. package/templates/base/skills/product-audit/checklists/06-architecture.md +53 -0
  165. package/templates/base/skills/product-audit/checklists/07-functional-requirements.md +55 -0
  166. package/templates/base/skills/product-audit/rules/audit-protocol.md +136 -0
  167. package/templates/base/skills/product-audit/rules/false-positive-guard.md +81 -0
  168. package/templates/base/skills/product-audit/rules/scoring-criteria.md +113 -0
  169. package/templates/base/skills/product-audit/templates/improvement-plan-template.md +60 -0
  170. package/templates/base/skills/product-audit/templates/report-template.md +88 -0
  171. package/templates/base/skills/prompt-engineering/SKILL.md +54 -73
  172. package/templates/base/skills/retrospective/SKILL.md +70 -95
  173. package/templates/base/skills/retrospective/references/improvement-template.md +26 -0
  174. package/templates/base/skills/review/SKILL.md +72 -0
  175. package/templates/base/skills/security/SKILL.md +50 -37
  176. package/templates/base/skills/security/rules/auth-patterns.md +62 -0
  177. package/templates/base/skills/security/rules/dependency-security.md +69 -0
  178. package/templates/base/skills/security/rules/input-validation.md +68 -0
  179. package/templates/base/skills/security/rules/secrets-management.md +65 -0
  180. package/templates/base/skills/spec/SKILL.md +60 -0
  181. package/templates/base/skills/stability-verification/SKILL.md +64 -0
  182. package/templates/base/skills/stability-verification/references/release-checklist.md +34 -0
  183. package/templates/base/skills/stability-verification/references/security-fix-patterns.md +112 -0
  184. package/templates/base/skills/stability-verification/rules/verification-layers.md +67 -0
  185. package/templates/base/skills/stability-verification/rules/verification-workflow.md +69 -0
  186. package/templates/base/skills/stability-verification/scripts/verify.sh +294 -0
  187. package/templates/base/skills/testing/SKILL.md +33 -25
  188. package/templates/base/skills/testing/references/e2e-stability.md +33 -0
  189. package/templates/base/skills/tsq-cli/SKILL.md +73 -0
  190. package/templates/base/skills/tsq-cli/references/cli-reference.md +92 -0
  191. package/templates/base/skills/tsq-protocol/SKILL.md +41 -25
  192. package/templates/base/skills/typescript/SKILL.md +3 -9
  193. package/templates/base/timsquad/ssot/test-spec.template.md +11 -1
  194. package/templates/base/timsquad/ssot-map.template.yaml +41 -0
  195. package/templates/platforms/claude-code/rules/api-conventions.md +12 -0
  196. package/templates/platforms/claude-code/rules/build-gate.md +28 -0
  197. package/templates/platforms/claude-code/rules/completion-verification.md +30 -0
  198. package/templates/platforms/claude-code/rules/context-monitor.md +23 -0
  199. package/templates/platforms/claude-code/rules/librarian-constraints.md +11 -0
  200. package/templates/platforms/claude-code/rules/plan-review.md +45 -0
  201. package/templates/platforms/claude-code/rules/quality-guards.md +43 -0
  202. package/templates/platforms/claude-code/rules/session-notes.md +18 -0
  203. package/templates/platforms/claude-code/rules/skill-suggest.md +27 -0
  204. package/templates/platforms/claude-code/rules/test-conventions.md +13 -0
  205. package/templates/platforms/claude-code/scripts/build-gate.sh +73 -0
  206. package/templates/platforms/claude-code/scripts/change-scope-guard.sh +113 -0
  207. package/templates/platforms/claude-code/scripts/completion-guard.sh +122 -24
  208. package/templates/platforms/claude-code/scripts/context-restore.sh +68 -0
  209. package/templates/platforms/claude-code/scripts/e2e-commit-gate.sh +70 -0
  210. package/templates/platforms/claude-code/scripts/e2e-marker.sh +51 -0
  211. package/templates/platforms/claude-code/scripts/phase-guard.sh +5 -5
  212. package/templates/platforms/claude-code/scripts/pre-compact.sh +70 -0
  213. package/templates/platforms/claude-code/scripts/safe-guard.sh +83 -0
  214. package/templates/platforms/claude-code/scripts/skill-inject.sh +216 -0
  215. package/templates/platforms/claude-code/scripts/skill-rules.json +95 -0
  216. package/templates/platforms/claude-code/scripts/skill-suggest.sh +105 -0
  217. package/templates/platforms/claude-code/scripts/subagent-inject.sh +53 -0
  218. package/templates/platforms/claude-code/settings.json +71 -9
@@ -0,0 +1,216 @@
1
+ #!/bin/bash
2
+ # Skill Inject — UserPromptSubmit Hook
3
+ # 사용자 프롬프트를 분석하여 매칭 스킬의 Contract/Protocol/Verification을
4
+ # systemMessage로 강제 주입한다 (advisory → mandatory 전환).
5
+ #
6
+ # 기존 skill-suggest.sh를 대체 (상위 호환).
7
+ # Input: JSON via stdin (Claude Code hook protocol, .prompt 필드 포함)
8
+ # Output: JSON with systemMessage (스킬 강제 주입)
9
+
10
+ set -e
11
+
12
+ # Read hook input
13
+ INPUT=$(cat 2>/dev/null || echo "")
14
+ if [ -z "$INPUT" ]; then
15
+ exit 0
16
+ fi
17
+
18
+ PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null || echo "")
19
+ if [ -z "$PROMPT" ] || [ "$PROMPT" = "null" ]; then
20
+ exit 0
21
+ fi
22
+
23
+ # Find project root
24
+ PROJECT_ROOT="$(pwd)"
25
+ while [ "$PROJECT_ROOT" != "/" ]; do
26
+ if [ -d "$PROJECT_ROOT/.timsquad" ]; then
27
+ break
28
+ fi
29
+ PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
30
+ done
31
+
32
+ if [ ! -d "$PROJECT_ROOT/.timsquad" ]; then
33
+ exit 0
34
+ fi
35
+
36
+ # Load skill rules
37
+ RULES_FILE="$PROJECT_ROOT/.claude/scripts/skill-rules.json"
38
+ if [ ! -f "$RULES_FILE" ]; then
39
+ exit 0
40
+ fi
41
+
42
+ THRESHOLD=$(jq -r '.threshold // 2' "$RULES_FILE" 2>/dev/null || echo "2")
43
+ PROMPT_LOWER=$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]')
44
+
45
+ # Match skills and collect top matches with scores
46
+ declare -a MATCH_SKILLS=()
47
+ declare -a MATCH_SCORES=()
48
+
49
+ RULE_COUNT=$(jq '.rules | length' "$RULES_FILE" 2>/dev/null || echo "0")
50
+
51
+ i=0
52
+ while [ "$i" -lt "$RULE_COUNT" ]; do
53
+ SKILL=$(jq -r ".rules[$i].skill" "$RULES_FILE" 2>/dev/null)
54
+ SCORE=0
55
+
56
+ # Check if skill is deployed
57
+ SKILL_DIR="$PROJECT_ROOT/.claude/skills/$SKILL"
58
+ if [ ! -d "$SKILL_DIR" ]; then
59
+ i=$((i + 1))
60
+ continue
61
+ fi
62
+
63
+ # Keyword matching (3 points each)
64
+ KW_COUNT=$(jq ".rules[$i].keywords | length" "$RULES_FILE" 2>/dev/null || echo "0")
65
+ j=0
66
+ while [ "$j" -lt "$KW_COUNT" ]; do
67
+ KW=$(jq -r ".rules[$i].keywords[$j]" "$RULES_FILE" 2>/dev/null)
68
+ if echo "$PROMPT_LOWER" | grep -qi -- "$KW" 2>/dev/null; then
69
+ SCORE=$((SCORE + 3))
70
+ fi
71
+ j=$((j + 1))
72
+ done
73
+
74
+ # Pattern matching (5 points each)
75
+ PAT_COUNT=$(jq ".rules[$i].patterns | length" "$RULES_FILE" 2>/dev/null || echo "0")
76
+ k=0
77
+ while [ "$k" -lt "$PAT_COUNT" ]; do
78
+ PAT=$(jq -r ".rules[$i].patterns[$k]" "$RULES_FILE" 2>/dev/null)
79
+ if [ -n "$PAT" ] && echo "$PROMPT_LOWER" | grep -qiE -- "$PAT" 2>/dev/null; then
80
+ SCORE=$((SCORE + 5))
81
+ fi
82
+ k=$((k + 1))
83
+ done
84
+
85
+ # Threshold check
86
+ if [ "$SCORE" -ge "$THRESHOLD" ]; then
87
+ MATCH_SKILLS+=("$SKILL")
88
+ MATCH_SCORES+=("$SCORE")
89
+ fi
90
+
91
+ i=$((i + 1))
92
+ done
93
+
94
+ # Sort by score descending and take top 3
95
+ SORTED_INDICES=""
96
+ if [ ${#MATCH_SKILLS[@]} -gt 0 ]; then
97
+ SORTED_INDICES=$(
98
+ for idx in "${!MATCH_SCORES[@]}"; do
99
+ echo "${MATCH_SCORES[$idx]} $idx"
100
+ done | sort -rn | head -3 | awk '{print $2}'
101
+ )
102
+ fi
103
+
104
+ # Extract Contract + Protocol + Verification sections from matched skills
105
+ INJECTION=""
106
+ CHAR_COUNT=0
107
+ MAX_CHARS=1500
108
+
109
+ for idx in $SORTED_INDICES; do
110
+ SKILL="${MATCH_SKILLS[$idx]}"
111
+ SKILL_FILE="$PROJECT_ROOT/.claude/skills/$SKILL/SKILL.md"
112
+
113
+ if [ ! -f "$SKILL_FILE" ]; then
114
+ continue
115
+ fi
116
+
117
+ # Extract key sections (Contract + Protocol + Verification)
118
+ SECTIONS=$(awk '
119
+ /^## Contract/ { capture=1; next }
120
+ /^## Protocol/ { capture=1; next }
121
+ /^## Verification/ { capture=1; next }
122
+ /^## / { capture=0 }
123
+ capture { print }
124
+ ' "$SKILL_FILE" 2>/dev/null | head -20)
125
+
126
+ if [ -z "$SECTIONS" ]; then
127
+ continue
128
+ fi
129
+
130
+ # Append memory/ contents if exists (project-specific decisions)
131
+ MEMORY_DIR="$PROJECT_ROOT/.claude/skills/$SKILL/memory"
132
+ MEMORY_CONTENT=""
133
+ if [ -d "$MEMORY_DIR" ]; then
134
+ for MEM_FILE in "$MEMORY_DIR"/*.md; do
135
+ [ ! -f "$MEM_FILE" ] && continue
136
+ MEM_TEXT=$(head -10 "$MEM_FILE" 2>/dev/null || echo "")
137
+ if [ -n "$MEM_TEXT" ]; then
138
+ MEMORY_CONTENT="$MEMORY_CONTENT
139
+ $MEM_TEXT"
140
+ fi
141
+ done
142
+ fi
143
+
144
+ ENTRY="[Skill: $SKILL] $SECTIONS"
145
+ if [ -n "$MEMORY_CONTENT" ]; then
146
+ ENTRY="$ENTRY
147
+ [Memory] $MEMORY_CONTENT"
148
+ fi
149
+ ENTRY_LEN=${#ENTRY}
150
+
151
+ if [ $((CHAR_COUNT + ENTRY_LEN)) -gt "$MAX_CHARS" ]; then
152
+ break
153
+ fi
154
+
155
+ if [ -n "$INJECTION" ]; then
156
+ INJECTION="$INJECTION
157
+ ---
158
+ $ENTRY"
159
+ else
160
+ INJECTION="$ENTRY"
161
+ fi
162
+ CHAR_COUNT=$((CHAR_COUNT + ENTRY_LEN))
163
+ done
164
+
165
+ # SSOT Map Tier 0 injection (always injected regardless of skill match)
166
+ SSOT_MAP="$PROJECT_ROOT/.timsquad/ssot-map.yaml"
167
+ if [ -f "$SSOT_MAP" ]; then
168
+ # Parse tier-0-always compiled paths from YAML
169
+ TIER0_PATHS=$(awk '
170
+ /^tier-0-always:/ { in_tier0=1; next }
171
+ /^tier-[0-9]/ { in_tier0=0 }
172
+ in_tier0 && /compiled:/ { gsub(/.*compiled: */, ""); gsub(/^ *| *$/, ""); print }
173
+ ' "$SSOT_MAP" 2>/dev/null)
174
+
175
+ TIER0_CONTENT=""
176
+ while IFS= read -r REL_PATH; do
177
+ [ -z "$REL_PATH" ] && continue
178
+ COMPILED_FILE="$PROJECT_ROOT/.claude/skills/controller/$REL_PATH"
179
+ if [ -f "$COMPILED_FILE" ]; then
180
+ FILE_CONTENT=$(cat "$COMPILED_FILE" 2>/dev/null || echo "")
181
+ if [ -n "$FILE_CONTENT" ]; then
182
+ if [ -n "$TIER0_CONTENT" ]; then
183
+ TIER0_CONTENT="$TIER0_CONTENT
184
+ ---
185
+ $FILE_CONTENT"
186
+ else
187
+ TIER0_CONTENT="$FILE_CONTENT"
188
+ fi
189
+ fi
190
+ fi
191
+ done <<< "$TIER0_PATHS"
192
+
193
+ if [ -n "$TIER0_CONTENT" ]; then
194
+ if [ -n "$INJECTION" ]; then
195
+ INJECTION="[SSOT Tier-0 Constraints]
196
+ $TIER0_CONTENT
197
+ ---
198
+ $INJECTION"
199
+ else
200
+ INJECTION="[SSOT Tier-0 Constraints]
201
+ $TIER0_CONTENT"
202
+ fi
203
+ fi
204
+ fi
205
+
206
+ # Output as systemMessage (mandatory injection)
207
+ if [ -n "$INJECTION" ]; then
208
+ jq -n --arg msg "$INJECTION" '{
209
+ hookSpecificOutput: {
210
+ hookEventName: "UserPromptSubmit",
211
+ systemMessage: $msg
212
+ }
213
+ }'
214
+ fi
215
+
216
+ exit 0
@@ -0,0 +1,95 @@
1
+ {
2
+ "threshold": 2,
3
+ "rules": [
4
+ {
5
+ "skill": "main-session-constraints",
6
+ "keywords": ["요구사항", "분석", "계획", "위임", "스프린트", "pm", "관리"],
7
+ "patterns": ["(plan|analyze|delegate|manage).*?(task|project|sprint)"]
8
+ },
9
+ {
10
+ "skill": "mobile/flutter",
11
+ "keywords": ["flutter", "widget", "riverpod", "stateless", "stateful", "플러터"],
12
+ "patterns": ["(build|create|implement|add).*?(app|screen|page|widget)"]
13
+ },
14
+ {
15
+ "skill": "mobile/dart",
16
+ "keywords": ["dart", "freezed", "isolate"],
17
+ "patterns": []
18
+ },
19
+ {
20
+ "skill": "frontend/react",
21
+ "keywords": ["react", "component", "hook", "useState", "useEffect", "리액트", "컴포넌트"],
22
+ "patterns": ["(create|build|refactor).*?(component|page|layout)"]
23
+ },
24
+ {
25
+ "skill": "frontend/nextjs",
26
+ "keywords": ["nextjs", "next.js", "app router", "server component", "middleware"],
27
+ "patterns": ["(ssr|server.*render|static.*generat)"]
28
+ },
29
+ {
30
+ "skill": "backend/node",
31
+ "keywords": ["express", "fastify", "middleware", "api endpoint", "route"],
32
+ "patterns": ["(create|add|implement).*?(api|endpoint|route|server)"]
33
+ },
34
+ {
35
+ "skill": "database",
36
+ "keywords": ["database", "sql", "migration", "schema", "table", "index", "데이터베이스", "스키마"],
37
+ "patterns": ["(create|modify|add|alter).*?(table|column|index|migration)"]
38
+ },
39
+ {
40
+ "skill": "database/prisma",
41
+ "keywords": ["prisma", "prisma schema", "prisma migrate"],
42
+ "patterns": []
43
+ },
44
+ {
45
+ "skill": "methodology/debugging",
46
+ "keywords": ["debug", "bug", "error", "crash", "fix", "디버그", "버그", "에러"],
47
+ "patterns": ["(why|how).*?(fail|break|crash|error|not work)"]
48
+ },
49
+ {
50
+ "skill": "methodology/tdd",
51
+ "keywords": ["tdd", "test-driven", "vitest", "jest", "테스트 주도"],
52
+ "patterns": ["(write|add|create).*?test"]
53
+ },
54
+ {
55
+ "skill": "methodology/ddd",
56
+ "keywords": ["ddd", "domain-driven", "aggregate", "bounded context", "도메인 주도"],
57
+ "patterns": []
58
+ },
59
+ {
60
+ "skill": "security",
61
+ "keywords": ["security", "owasp", "vulnerability", "xss", "csrf", "injection", "보안", "취약점"],
62
+ "patterns": ["(security|auth|permission).*?(review|audit|check)"]
63
+ },
64
+ {
65
+ "skill": "testing",
66
+ "keywords": ["test", "coverage", "assertion", "mock", "stub", "테스트"],
67
+ "patterns": ["(increase|improve).*?coverage"]
68
+ },
69
+ {
70
+ "skill": "architecture",
71
+ "keywords": ["architecture", "system design", "api design", "adr", "아키텍처", "설계"],
72
+ "patterns": ["(design|architect|structure).*?(system|api|service)"]
73
+ },
74
+ {
75
+ "skill": "typescript",
76
+ "keywords": ["typescript", "type", "interface", "generic", "타입"],
77
+ "patterns": ["(type|typing).*?(error|issue|strict)"]
78
+ },
79
+ {
80
+ "skill": "ui-design",
81
+ "keywords": ["ui", "ux", "design system", "responsive", "accessibility", "a11y"],
82
+ "patterns": ["(design|redesign|improve).*?(ui|layout|interface)"]
83
+ },
84
+ {
85
+ "skill": "planning",
86
+ "keywords": ["prd", "requirements", "specification", "기획", "요구사항"],
87
+ "patterns": ["(write|create|draft).*?(prd|spec|requirement)"]
88
+ },
89
+ {
90
+ "skill": "tsq-cli",
91
+ "keywords": ["tsq", "cli", "커맨드", "init", "status"],
92
+ "patterns": ["tsq\\s+(init|status|log|wf|mi|audit|knowledge)"]
93
+ }
94
+ ]
95
+ }
@@ -0,0 +1,105 @@
1
+ #!/bin/bash
2
+ # Skill Suggest — UserPromptSubmit Hook
3
+ # 사용자 프롬프트를 분석하여 관련 스킬을 제안한다.
4
+ # 키워드/패턴 매칭 기반, advisory only (블로킹 안 함).
5
+ #
6
+ # Input: JSON via stdin (Claude Code hook protocol, .prompt 필드 포함)
7
+ # Output: JSON with additionalContext (스킬 제안)
8
+
9
+ set -e
10
+
11
+ # Read hook input
12
+ INPUT=$(cat 2>/dev/null || echo "")
13
+ if [ -z "$INPUT" ]; then
14
+ exit 0
15
+ fi
16
+
17
+ PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null || echo "")
18
+ if [ -z "$PROMPT" ] || [ "$PROMPT" = "null" ]; then
19
+ exit 0
20
+ fi
21
+
22
+ # Find project root
23
+ PROJECT_ROOT="$(pwd)"
24
+ while [ "$PROJECT_ROOT" != "/" ]; do
25
+ if [ -d "$PROJECT_ROOT/.timsquad" ]; then
26
+ break
27
+ fi
28
+ PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
29
+ done
30
+
31
+ if [ ! -d "$PROJECT_ROOT/.timsquad" ]; then
32
+ exit 0
33
+ fi
34
+
35
+ # Load skill rules
36
+ RULES_FILE="$PROJECT_ROOT/.claude/scripts/skill-rules.json"
37
+ if [ ! -f "$RULES_FILE" ]; then
38
+ exit 0
39
+ fi
40
+
41
+ THRESHOLD=$(jq -r '.threshold // 4' "$RULES_FILE" 2>/dev/null || echo "4")
42
+ PROMPT_LOWER=$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]')
43
+
44
+ # Match skills
45
+ MATCHES=""
46
+ RULE_COUNT=$(jq '.rules | length' "$RULES_FILE" 2>/dev/null || echo "0")
47
+
48
+ i=0
49
+ while [ "$i" -lt "$RULE_COUNT" ]; do
50
+ SKILL=$(jq -r ".rules[$i].skill" "$RULES_FILE" 2>/dev/null)
51
+ SCORE=0
52
+
53
+ # Check if skill is deployed
54
+ SKILL_DIR="$PROJECT_ROOT/.claude/skills/$SKILL"
55
+ if [ ! -d "$SKILL_DIR" ]; then
56
+ i=$((i + 1))
57
+ continue
58
+ fi
59
+
60
+ # Keyword matching (2 points each)
61
+ KW_COUNT=$(jq ".rules[$i].keywords | length" "$RULES_FILE" 2>/dev/null)
62
+ j=0
63
+ while [ "$j" -lt "$KW_COUNT" ]; do
64
+ KW=$(jq -r ".rules[$i].keywords[$j]" "$RULES_FILE" 2>/dev/null)
65
+ if echo "$PROMPT_LOWER" | grep -qi -- "$KW" 2>/dev/null; then
66
+ SCORE=$((SCORE + 2))
67
+ fi
68
+ j=$((j + 1))
69
+ done
70
+
71
+ # Pattern matching (4 points each)
72
+ PAT_COUNT=$(jq ".rules[$i].patterns | length" "$RULES_FILE" 2>/dev/null)
73
+ k=0
74
+ while [ "$k" -lt "$PAT_COUNT" ]; do
75
+ PAT=$(jq -r ".rules[$i].patterns[$k]" "$RULES_FILE" 2>/dev/null)
76
+ if [ -n "$PAT" ] && echo "$PROMPT_LOWER" | grep -qiE -- "$PAT" 2>/dev/null; then
77
+ SCORE=$((SCORE + 4))
78
+ fi
79
+ k=$((k + 1))
80
+ done
81
+
82
+ # Threshold check
83
+ if [ "$SCORE" -ge "$THRESHOLD" ]; then
84
+ if [ -n "$MATCHES" ]; then
85
+ MATCHES="$MATCHES, $SKILL"
86
+ else
87
+ MATCHES="$SKILL"
88
+ fi
89
+ fi
90
+
91
+ i=$((i + 1))
92
+ done
93
+
94
+ # Output suggestion if matches found
95
+ if [ -n "$MATCHES" ]; then
96
+ SUGGESTION="[Skill Suggest] 관련 스킬이 감지되었습니다: $MATCHES. 해당 스킬의 rules/를 참조하면 더 높은 품질의 결과를 얻을 수 있습니다."
97
+ jq -n --arg ctx "$SUGGESTION" '{
98
+ hookSpecificOutput: {
99
+ hookEventName: "UserPromptSubmit",
100
+ additionalContext: $ctx
101
+ }
102
+ }'
103
+ fi
104
+
105
+ exit 0
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # Subagent Inject — SubagentStart Hook
3
+ # 서브에이전트 시작 시 tsq-protocol 핵심 내용을 자동 주입한다.
4
+ #
5
+ # Input: JSON via stdin (Claude Code hook protocol)
6
+ # Output: JSON with systemMessage (프로토콜 주입)
7
+
8
+ set -e
9
+
10
+ # Find project root
11
+ PROJECT_ROOT="$(pwd)"
12
+ while [ "$PROJECT_ROOT" != "/" ]; do
13
+ if [ -d "$PROJECT_ROOT/.timsquad" ]; then
14
+ break
15
+ fi
16
+ PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
17
+ done
18
+
19
+ if [ ! -d "$PROJECT_ROOT/.timsquad" ]; then
20
+ exit 0
21
+ fi
22
+
23
+ # Load tsq-protocol Contract + Protocol sections
24
+ PROTOCOL_FILE="$PROJECT_ROOT/.claude/skills/tsq-protocol/SKILL.md"
25
+ if [ ! -f "$PROTOCOL_FILE" ]; then
26
+ exit 0
27
+ fi
28
+
29
+ # Extract Contract + Quick Rules (compact, max 1000 chars)
30
+ SECTIONS=$(awk '
31
+ /^## Contract/ { capture=1; next }
32
+ /^## Quick Rules/ { capture=1; next }
33
+ /^## / { capture=0 }
34
+ capture { print }
35
+ ' "$PROTOCOL_FILE" 2>/dev/null | head -30)
36
+
37
+ if [ -z "$SECTIONS" ]; then
38
+ exit 0
39
+ fi
40
+
41
+ INJECTION="[TSQ Protocol - Subagent] $SECTIONS"
42
+
43
+ # Trim to 1000 chars max
44
+ INJECTION="${INJECTION:0:1000}"
45
+
46
+ jq -n --arg msg "$INJECTION" '{
47
+ hookSpecificOutput: {
48
+ hookEventName: "SubagentStart",
49
+ systemMessage: $msg
50
+ }
51
+ }'
52
+
53
+ exit 0
@@ -1,24 +1,44 @@
1
1
  {
2
2
  "hooks": {
3
+ "UserPromptSubmit": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "bash .claude/scripts/skill-inject.sh",
9
+ "timeout": 5
10
+ }
11
+ ]
12
+ }
13
+ ],
3
14
  "PreToolUse": [
4
15
  {
5
16
  "matcher": "Write|Edit",
6
17
  "hooks": [
7
18
  {
8
19
  "type": "command",
9
- "command": "bash .claude/scripts/phase-guard.sh 2>/dev/null || true",
20
+ "command": "bash .claude/scripts/phase-guard.sh",
10
21
  "timeout": 3
11
22
  }
12
23
  ]
13
- }
14
- ],
15
- "SessionStart": [
24
+ },
16
25
  {
26
+ "matcher": "Bash",
17
27
  "hooks": [
18
28
  {
19
29
  "type": "command",
20
- "command": "tsq daemon start 2>/dev/null || true",
21
- "timeout": 5
30
+ "command": "bash .claude/scripts/safe-guard.sh",
31
+ "timeout": 3
32
+ }
33
+ ]
34
+ },
35
+ {
36
+ "matcher": "Task",
37
+ "hooks": [
38
+ {
39
+ "type": "command",
40
+ "command": "tsq daemon notify subagent-start 2>/dev/null || true",
41
+ "timeout": 3
22
42
  }
23
43
  ]
24
44
  }
@@ -30,6 +50,11 @@
30
50
  "type": "command",
31
51
  "command": "tsq daemon notify subagent-start 2>/dev/null || true",
32
52
  "timeout": 3
53
+ },
54
+ {
55
+ "type": "command",
56
+ "command": "bash .claude/scripts/subagent-inject.sh",
57
+ "timeout": 5
33
58
  }
34
59
  ]
35
60
  }
@@ -40,6 +65,27 @@
40
65
  {
41
66
  "type": "command",
42
67
  "command": "tsq daemon notify subagent-stop 2>/dev/null || true",
68
+ "timeout": 3
69
+ }
70
+ ]
71
+ }
72
+ ],
73
+ "SessionStart": [
74
+ {
75
+ "hooks": [
76
+ {
77
+ "type": "command",
78
+ "command": "tsq daemon start 2>/dev/null || true",
79
+ "timeout": 5
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ "matcher": "compact",
85
+ "hooks": [
86
+ {
87
+ "type": "command",
88
+ "command": "bash .claude/scripts/context-restore.sh",
43
89
  "timeout": 5
44
90
  }
45
91
  ]
@@ -77,7 +123,23 @@
77
123
  },
78
124
  {
79
125
  "type": "command",
80
- "command": "bash .claude/scripts/completion-guard.sh 2>/dev/null || true",
126
+ "command": "bash .claude/scripts/completion-guard.sh",
127
+ "timeout": 5
128
+ },
129
+ {
130
+ "type": "command",
131
+ "command": "bash .claude/scripts/build-gate.sh",
132
+ "timeout": 30
133
+ }
134
+ ]
135
+ }
136
+ ],
137
+ "PreCompact": [
138
+ {
139
+ "hooks": [
140
+ {
141
+ "type": "command",
142
+ "command": "bash .claude/scripts/pre-compact.sh",
81
143
  "timeout": 5
82
144
  }
83
145
  ]
@@ -88,8 +150,8 @@
88
150
  "hooks": [
89
151
  {
90
152
  "type": "command",
91
- "command": "tsq daemon notify session-end 2>/dev/null || true && tsq daemon stop 2>/dev/null || true",
92
- "timeout": 15
153
+ "command": "tsq daemon notify session-end 2>/dev/null || true",
154
+ "timeout": 5
93
155
  }
94
156
  ]
95
157
  }