Skip to content

Commit de50308

Browse files
committed
merge: resolve main conflicts in smart filtering hooks
2 parents 1777e47 + a7359cd commit de50308

File tree

18 files changed

+1603
-372
lines changed

18 files changed

+1603
-372
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
name: Validate
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
shellcheck:
11+
name: Shellcheck
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install shellcheck
17+
run: sudo apt-get update && sudo apt-get install -y shellcheck
18+
19+
- name: Run shellcheck on scripts
20+
run: |
21+
shellcheck -S error scripts/*.sh
22+
23+
- name: Run shellcheck on lib scripts (if any)
24+
run: |
25+
if compgen -G "scripts/lib/*.sh" > /dev/null; then
26+
shellcheck -S error scripts/lib/*.sh
27+
else
28+
echo "No scripts/lib/*.sh files found, skipping."
29+
fi
30+
31+
json-validation:
32+
name: JSON Validation
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
37+
- name: Validate data JSON files
38+
run: |
39+
for f in data/*.json; do
40+
echo "Validating $f"
41+
jq . "$f" > /dev/null
42+
done
43+
44+
- name: Validate plugin manifest files
45+
run: |
46+
for f in .claude-plugin/plugin.json .claude-plugin/marketplace.json hooks/hooks.json; do
47+
echo "Validating $f"
48+
jq . "$f" > /dev/null
49+
done
50+
51+
schema-validation:
52+
name: Schema Validation
53+
runs-on: ubuntu-latest
54+
steps:
55+
- uses: actions/checkout@v4
56+
57+
- name: Verify concept-tree.json has .categories object
58+
run: |
59+
result=$(jq '.categories | type' data/concept-tree.json)
60+
if [ "$result" != '"object"' ]; then
61+
echo "ERROR: concept-tree.json .categories is not an object (got $result)"
62+
exit 1
63+
fi
64+
echo "concept-tree.json .categories is a valid object"
65+
66+
- name: Verify quiz-bank.json is a non-empty object
67+
run: |
68+
type=$(jq 'type' data/quiz-bank.json)
69+
if [ "$type" != '"object"' ]; then
70+
echo "ERROR: quiz-bank.json is not an object (got $type)"
71+
exit 1
72+
fi
73+
keys=$(jq 'keys | length' data/quiz-bank.json)
74+
if [ "$keys" -eq 0 ]; then
75+
echo "ERROR: quiz-bank.json is an empty object"
76+
exit 1
77+
fi
78+
echo "quiz-bank.json is a valid non-empty object with $keys top-level keys"
79+
80+
- name: Verify plugin.json has required fields
81+
run: |
82+
name=$(jq -r '.name // empty' .claude-plugin/plugin.json)
83+
version=$(jq -r '.version // empty' .claude-plugin/plugin.json)
84+
if [ -z "$name" ]; then
85+
echo "ERROR: plugin.json is missing required field: name"
86+
exit 1
87+
fi
88+
if [ -z "$version" ]; then
89+
echo "ERROR: plugin.json is missing required field: version"
90+
exit 1
91+
fi
92+
echo "plugin.json has name='$name' and version='$version'"
93+
94+
concept-coverage:
95+
name: Concept Coverage Check
96+
runs-on: ubuntu-latest
97+
steps:
98+
- uses: actions/checkout@v4
99+
100+
- name: Compare quiz-bank keys vs concept-tree concept keys
101+
run: |
102+
echo "--- Quiz bank concept IDs ---"
103+
quiz_keys=$(jq -r '.quizzes | keys[]' data/quiz-bank.json | sort)
104+
echo "$quiz_keys"
105+
106+
echo ""
107+
echo "--- Concept tree concept IDs ---"
108+
concept_keys=$(jq -r '.categories | to_entries[] | .value.concepts | keys[]' data/concept-tree.json | sort)
109+
echo "$concept_keys"
110+
111+
echo ""
112+
echo "--- Concepts in quiz-bank but not in concept-tree ---"
113+
only_in_quiz=$(comm -23 <(echo "$quiz_keys") <(echo "$concept_keys"))
114+
if [ -n "$only_in_quiz" ]; then
115+
echo "WARNING: The following quiz-bank keys have no matching concept in concept-tree:"
116+
echo "$only_in_quiz"
117+
else
118+
echo "None"
119+
fi
120+
121+
echo ""
122+
echo "--- Concepts in concept-tree but not in quiz-bank ---"
123+
only_in_tree=$(comm -13 <(echo "$quiz_keys") <(echo "$concept_keys"))
124+
if [ -n "$only_in_tree" ]; then
125+
echo "WARNING: The following concept-tree concepts have no quiz-bank coverage:"
126+
echo "$only_in_tree"
127+
else
128+
echo "None"
129+
fi
130+
131+
echo ""
132+
echo "Concept coverage check complete (warnings do not fail CI)."

β€Ž.shellcheckrcβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# CodeSensei shell script conventions
2+
# Allow sourcing from dynamic paths
3+
external-sources=true
4+
# Common patterns we use
5+
disable=SC2034 # Unused variables (used by sourcing scripts)
6+
disable=SC2155 # Declare and assign separately (too noisy for our style)

β€ŽREADME.mdβ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,12 @@ code-sensei/
182182

183183
CodeSensei covers **42 concepts** across **9 categories**:
184184

185-
- **🧱 Fundamentals** β€” Variables, functions, loops, conditionals
185+
- **🧱 Fundamentals** β€” Variables, functions, loops, conditionals, Python
186186
- **🌐 Web Basics** β€” HTML, CSS, how browsers work
187-
- **⚑ JavaScript** β€” Core JS, async/await, imports, JSON
187+
- **⚑ JavaScript** β€” Core JS, async/await, imports, JSON, TypeScript
188188
- **πŸ’» Terminal & Tools** β€” Command line, npm, git, env variables
189189
- **🎨 Frontend** β€” React, components, props, state, routing
190-
- **βš™οΈ Backend** β€” Servers, routes, middleware, REST APIs, auth
190+
- **βš™οΈ Backend** β€” Servers, routes, middleware, REST APIs, auth, testing
191191
- **πŸ—„οΈ Databases** β€” SQL, schemas, ORMs, relationships
192192
- **πŸš€ Deployment** β€” Hosting, Docker, CI/CD
193193
- **πŸ—οΈ Architecture** β€” Design patterns, scalability, client-server

β€Žcommands/export.mdβ€Ž

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
description: Export your CodeSensei profile for backup or migration to another machine
3+
---
4+
5+
# Export
6+
7+
You are CodeSensei πŸ₯‹ by Dojo Coding. The user wants to export their learning profile.
8+
9+
## Instructions
10+
11+
1. Run the export script:
12+
13+
```bash
14+
bash ${CLAUDE_PLUGIN_ROOT}/scripts/export-profile.sh
15+
```
16+
17+
2. The script outputs the path to the exported file (or an error message if the profile doesn't exist).
18+
19+
3. Read the exported file to confirm it was created successfully and report back to the user:
20+
- Show the export file path
21+
- Show the profile summary: belt, XP, concepts mastered count, total quizzes
22+
- Show the schema version and export timestamp from the wrapper metadata
23+
24+
4. Display the result using this format:
25+
26+
```
27+
πŸ₯‹ CodeSensei β€” Profile Exported
28+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
29+
30+
βœ… Export saved to: [export file path]
31+
32+
Profile snapshot:
33+
[Belt Emoji] Belt: [belt name]
34+
⚑ XP: [XP total]
35+
🧠 Concepts mastered: [count]
36+
πŸ“Š Quizzes taken: [total]
37+
38+
Schema version: [schema_version]
39+
Exported at: [exported_at timestamp]
40+
41+
To restore this profile on another machine:
42+
β†’ Copy the export file to the target machine
43+
β†’ Run: /code-sensei:import [export file path]
44+
45+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
46+
πŸ₯‹ Powered by Dojo Coding | dojocoding.io
47+
```
48+
49+
5. If the script reports that no profile exists, show:
50+
51+
```
52+
πŸ₯‹ CodeSensei β€” No Profile Found
53+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
54+
55+
No profile found at ~/.code-sensei/profile.json
56+
57+
Start a session to create your profile, then export it.
58+
β†’ Use /code-sensei:progress to initialize your profile
59+
```
60+
61+
6. If the script reports that jq is missing, add a warning:
62+
63+
```
64+
⚠️ jq not found β€” export created without jq validation/pretty formatting.
65+
The file is still importable. Install jq for full export functionality: brew install jq
66+
```

β€Žcommands/import.mdβ€Ž

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
description: Import a CodeSensei profile from an export file to restore or migrate your progress
3+
---
4+
5+
# Import
6+
7+
You are CodeSensei πŸ₯‹ by Dojo Coding. The user wants to import a profile from an export file.
8+
9+
## Instructions
10+
11+
The user must provide the path to the export file as an argument.
12+
Example: `/code-sensei:import ~/code-sensei-export-2026-03-03.json`
13+
14+
If no argument is provided, show:
15+
16+
```
17+
πŸ₯‹ CodeSensei β€” Import Profile
18+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
19+
20+
Usage: /code-sensei:import [path to export file]
21+
22+
Example:
23+
/code-sensei:import ~/code-sensei-export-2026-03-03.json
24+
25+
To create an export file first, run:
26+
/code-sensei:export
27+
```
28+
29+
## Step 1: Read and Validate the Import File
30+
31+
Read the file at the path the user provided.
32+
33+
If the file does not exist or cannot be read, show:
34+
```
35+
❌ Import failed: File not found at [path]
36+
37+
Check the path and try again.
38+
```
39+
40+
Verify the file is valid JSON in one of these formats:
41+
- Preferred export format: must have a `schema_version` field and a `profile` field containing the profile data
42+
- Legacy/raw export format: may be the raw profile JSON itself, as long as it has at least a `belt` field
43+
44+
If validation fails, show:
45+
```
46+
❌ Import failed: Invalid export file
47+
48+
The file at [path] does not appear to be a valid CodeSensei export.
49+
Expected either a wrapped export (`schema_version` + `profile`) or a raw profile JSON with `belt`.
50+
51+
To create a valid export, run: /code-sensei:export
52+
```
53+
54+
## Step 2: Preview the Import
55+
56+
Show the user what will be imported and ask for confirmation:
57+
58+
```
59+
πŸ₯‹ CodeSensei β€” Import Preview
60+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
61+
62+
Import file: [path]
63+
Exported at: [exported_at from metadata, or "unknown" for legacy/raw exports]
64+
65+
Profile to import:
66+
[Belt Emoji] Belt: [belt]
67+
⚑ XP: [xp]
68+
🧠 Concepts mastered: [count of concepts_mastered]
69+
πŸ“Š Quizzes taken: [quizzes.total]
70+
πŸ”₯ Streak: [streak.current] days
71+
72+
⚠️ WARNING: This will overwrite your current profile.
73+
A backup will be saved to ~/.code-sensei/profile.json.backup
74+
75+
Type "yes" to confirm the import, or anything else to cancel.
76+
```
77+
78+
## Step 3: Read Current Profile for Comparison
79+
80+
Before proceeding, read the current profile at `~/.code-sensei/profile.json` (if it exists) and show a brief comparison in the preview if relevant.
81+
82+
## Step 4: Confirm and Apply
83+
84+
Wait for the user's response.
85+
86+
**If the user confirms (types "yes" or equivalent affirmation):**
87+
88+
1. Back up the current profile:
89+
- Use the Bash tool to run:
90+
```bash
91+
cp ~/.code-sensei/profile.json ~/.code-sensei/profile.json.backup 2>/dev/null && echo "backed_up" || echo "no_existing_profile"
92+
```
93+
94+
2. Create the target directory if needed:
95+
- Use the Bash tool to run:
96+
```bash
97+
mkdir -p ~/.code-sensei
98+
```
99+
100+
3. Extract and write the profile data:
101+
- If the import file has a `profile` field, write `import_data.profile` to `~/.code-sensei/profile.json`
102+
- If it is a legacy/raw export, write the full file contents as-is to `~/.code-sensei/profile.json`
103+
- Use `jq` if available for clean extraction:
104+
```bash
105+
if jq -e '.profile' [import file path] > /dev/null 2>&1; then
106+
jq '.profile' [import file path] > ~/.code-sensei/profile.json
107+
else
108+
cp [import file path] ~/.code-sensei/profile.json
109+
fi
110+
```
111+
- If jq is not available, instruct the user to manually copy the `profile` object from the import file, or the full file for legacy/raw exports
112+
113+
4. Show the success message:
114+
115+
```
116+
πŸ₯‹ CodeSensei β€” Import Complete
117+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
118+
119+
βœ… Profile imported successfully!
120+
121+
[Belt Emoji] Belt: [belt]
122+
⚑ XP: [xp]
123+
🧠 Concepts mastered: [count]
124+
πŸ“Š Quizzes taken: [quizzes.total]
125+
126+
Backup saved to: ~/.code-sensei/profile.json.backup
127+
128+
Your learning progress has been restored.
129+
Use /code-sensei:progress to view your full dashboard.
130+
131+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
132+
πŸ₯‹ Powered by Dojo Coding | dojocoding.io
133+
```
134+
135+
**If the user cancels:**
136+
137+
```
138+
↩️ Import cancelled. Your current profile was not changed.
139+
```
140+
141+
## Important Notes
142+
143+
- Always back up before overwriting β€” never skip the backup step
144+
- The preferred import path reads the `profile` field from wrapped exports; legacy/raw exports can be copied directly
145+
- If jq is unavailable, warn the user and provide manual instructions
146+
- After a successful import, do NOT reset session_concepts β€” preserve it as-is from the imported profile

0 commit comments

Comments
Β (0)