codeninja 2.0.0 → 3.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.
- package/README.md +122 -251
- package/agent/global-agent.md +8 -0
- package/cli.js +248 -223
- package/commands/debug.workflow.md +94 -0
- package/commands/explain.workflow.md +59 -0
- package/commands/optimize.workflow.md +124 -0
- package/commands/review.workflow.md +85 -0
- package/ide/antigravity/.agents/personas/database-architect.md +249 -0
- package/ide/antigravity/.agents/personas/global-orchestrator.md +144 -0
- package/ide/antigravity/.agents/personas/nodejs-backend.md +250 -0
- package/ide/antigravity/.agents/personas/reactjs-frontend.md +179 -0
- package/ide/antigravity/.agents/skills/api-builder/SKILL.md +179 -0
- package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +184 -0
- package/ide/antigravity/.agents/skills/database/SKILL.md +165 -0
- package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +111 -0
- package/ide/antigravity/.agents/skills/reactjs/SKILL.md +211 -0
- package/ide/antigravity/.agents/workflows/codeninja-api.md +111 -0
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +81 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +124 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +87 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +106 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +76 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +82 -0
- package/ide/antigravity/.agents/workflows/codeninja-design.md +54 -0
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +40 -0
- package/ide/antigravity/.agents/workflows/codeninja-init.md +336 -0
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +336 -0
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +216 -0
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +84 -0
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +68 -0
- package/ide/antigravity/.agents/workflows/codeninja-review.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +183 -0
- package/ide/antigravity/.agents/workflows/codeninja-test.md +61 -0
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +250 -0
- package/ide/cursor/.cursor/mcp.json +8 -0
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +63 -0
- package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +38 -0
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +124 -0
- package/ide/cursor/.cursor/rules/04-database.mdc +90 -0
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +147 -0
- package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +112 -0
- package/ide/vscode/.github/copilot-instructions.md +399 -0
- package/ide/vscode/.vscode/mcp.json +9 -0
- package/package.json +24 -23
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:modularize
|
|
3
|
+
personas: [global-orchestrator, reactjs-frontend]
|
|
4
|
+
skills: [mcp-and-context, reactjs, code-intelligence]
|
|
5
|
+
description: >
|
|
6
|
+
Scan ReactJS pages, extract repeated layout blocks into reusable components
|
|
7
|
+
under src/components/, and update each page to import and use them.
|
|
8
|
+
Layout structure only — never touches business logic, state, or API calls.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# /codeninja:modularize
|
|
12
|
+
|
|
13
|
+
## Before Running
|
|
14
|
+
1. Call `context_check_stale`
|
|
15
|
+
2. Call `context_read` — load `context.services` to find ReactJS services
|
|
16
|
+
3. Call `service_scan` — verify ReactJS service exists on disk
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
- Read ALL target pages fully before creating any component
|
|
20
|
+
- NEVER create a component that already exists in `src/components/` — reuse it
|
|
21
|
+
- NEVER modify business logic, state, API calls, or event handlers in any page
|
|
22
|
+
- NEVER break existing imports or prop flows
|
|
23
|
+
- ONE confirmation before any file is written
|
|
24
|
+
- After writing files → call `context_write`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Execution — Full Step-by-Step
|
|
29
|
+
|
|
30
|
+
### Phase 1 — Target Selection
|
|
31
|
+
|
|
32
|
+
**Step 1.** Ask: "Which ReactJS service?" (list ReactJS services from `context.services`)
|
|
33
|
+
- Store: `context.current_action.service_name`
|
|
34
|
+
|
|
35
|
+
**Step 2.** Ask: "What scope?"
|
|
36
|
+
1. All pages — scan every page in `src/pages/` and `src/views/`
|
|
37
|
+
2. Specific page — I'll provide the path
|
|
38
|
+
- Store: `context.current_action.modularize_scope`
|
|
39
|
+
- If specific → also ask: "Page path?" → Store: `context.current_action.page_path`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### Phase 2 — Inventory Existing Components
|
|
44
|
+
|
|
45
|
+
Before scanning any pages, inventory what already exists:
|
|
46
|
+
|
|
47
|
+
**Step 1.** Scan `src/components/` in the target service.
|
|
48
|
+
For each subdirectory → record component name and file path.
|
|
49
|
+
|
|
50
|
+
**Step 2.** For each existing component:
|
|
51
|
+
- Read the file
|
|
52
|
+
- Identify structural role: header, footer, sidebar, navbar, modal wrapper, card shell, breadcrumbs, etc.
|
|
53
|
+
- Record: `{ name, path, role, props_accepted }`
|
|
54
|
+
|
|
55
|
+
Store this as the "existing components registry" — the source of truth for reuse decisions.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Phase 3 — Scan Target Pages
|
|
60
|
+
|
|
61
|
+
#### If scope == "all":
|
|
62
|
+
Scan `src/pages/` — each subdirectory with `index.jsx` or `index.js` = one page.
|
|
63
|
+
Also scan `src/views/` if it exists.
|
|
64
|
+
|
|
65
|
+
#### If scope == "specific":
|
|
66
|
+
Pages list = [ context.current_action.page_path ]
|
|
67
|
+
|
|
68
|
+
For each page:
|
|
69
|
+
|
|
70
|
+
**Step 1.** Read the full file content.
|
|
71
|
+
|
|
72
|
+
**Step 2.** Identify all structural blocks (layout HTML — NOT business logic):
|
|
73
|
+
- Look for repeated layout patterns: `<header>`, `<nav>`, `<footer>`, `<aside>`, sidebar wrappers
|
|
74
|
+
- Look for structural patterns repeated across pages: top nav bars, breadcrumb areas, page wrappers
|
|
75
|
+
- Record each structural block as: `{ block_type, jsx_content, props_needed }`
|
|
76
|
+
|
|
77
|
+
**Step 3.** Cross-check against existing components registry:
|
|
78
|
+
- Does a component already exist that covers this block?
|
|
79
|
+
- If YES → mark as "reuse existing: <ComponentName>"
|
|
80
|
+
- If NO → mark as "new component needed: <ComponentName>"
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### Phase 4 — Deduplicate Across Pages
|
|
85
|
+
|
|
86
|
+
After scanning all pages:
|
|
87
|
+
|
|
88
|
+
**Step 1.** Group blocks by structural similarity across pages.
|
|
89
|
+
- If the same header JSX appears in 3+ pages → one shared Header component
|
|
90
|
+
- If a sidebar appears in 2+ pages → one shared Sidebar component
|
|
91
|
+
- If a block appears in only 1 page → do NOT extract it (no duplication benefit)
|
|
92
|
+
|
|
93
|
+
**Step 2.** For each component to create, decide:
|
|
94
|
+
- Component name (PascalCase, descriptive: `PageHeader`, `AppSidebar`, `MainFooter`)
|
|
95
|
+
- Props needed (what varies between pages: title, navLinks, userName, etc.)
|
|
96
|
+
- File location: `src/components/<ComponentName>/index.jsx` and `<ComponentName>.module.css`
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### Phase 5 — Show Extraction Plan
|
|
101
|
+
|
|
102
|
+
Display the plan before writing anything:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
┌─────────────────────────────────────────────────────┐
|
|
106
|
+
│ MODULARIZE PLAN │
|
|
107
|
+
├─────────────────────────────────────────────────────┤
|
|
108
|
+
│ Service : [service_name] │
|
|
109
|
+
│ Scope : [all pages | specific page] │
|
|
110
|
+
│ Pages : [n] scanned │
|
|
111
|
+
├─────────────────────────────────────────────────────┤
|
|
112
|
+
│ COMPONENTS TO CREATE │
|
|
113
|
+
│ ✦ AppHeader — appears in [n] pages │
|
|
114
|
+
│ Props: title (string) │
|
|
115
|
+
│ File: src/components/AppHeader/index.jsx │
|
|
116
|
+
│ │
|
|
117
|
+
│ ✦ MainSidebar — appears in [n] pages │
|
|
118
|
+
│ Props: activeRoute (string) │
|
|
119
|
+
│ File: src/components/MainSidebar/index.jsx │
|
|
120
|
+
├─────────────────────────────────────────────────────┤
|
|
121
|
+
│ COMPONENTS REUSED (already exist) │
|
|
122
|
+
│ ✓ Footer — src/components/Footer/index.jsx │
|
|
123
|
+
├─────────────────────────────────────────────────────┤
|
|
124
|
+
│ PAGES TO UPDATE │
|
|
125
|
+
│ → src/pages/Dashboard/index.jsx │
|
|
126
|
+
│ → src/pages/Profile/index.jsx │
|
|
127
|
+
│ → src/pages/Settings/index.jsx │
|
|
128
|
+
└─────────────────────────────────────────────────────┘
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Ask: "Apply this plan? (yes / no / adjust)"
|
|
132
|
+
- If yes → proceed to Phase 6
|
|
133
|
+
- If no → abort, nothing written
|
|
134
|
+
- If adjust → ask what to change → re-display plan
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### Phase 6 — Generate Components
|
|
139
|
+
|
|
140
|
+
For each new component:
|
|
141
|
+
|
|
142
|
+
**Step 1.** Generate `src/components/<ComponentName>/index.jsx`:
|
|
143
|
+
```jsx
|
|
144
|
+
/**
|
|
145
|
+
* <ComponentName> — <one-line description of structural role>.
|
|
146
|
+
*
|
|
147
|
+
* @param {Object} props
|
|
148
|
+
* @param {string} props.<propName> - <description>
|
|
149
|
+
* @returns {JSX.Element}
|
|
150
|
+
*/
|
|
151
|
+
function <ComponentName>({ <props> }) {
|
|
152
|
+
return (
|
|
153
|
+
<extracted JSX block, using props where values varied>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default <ComponentName>;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Step 2.** Generate `src/components/<ComponentName>/<ComponentName>.module.css`:
|
|
161
|
+
- Extract any inline styles or className references that were in the original block
|
|
162
|
+
- Create CSS classes for them
|
|
163
|
+
- If no styles → empty file with a comment: `/* <ComponentName> styles */`
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
### Phase 7 — Update Pages
|
|
168
|
+
|
|
169
|
+
For each page that used the extracted block:
|
|
170
|
+
|
|
171
|
+
**Step 1.** Read the current page file.
|
|
172
|
+
|
|
173
|
+
**Step 2.** Apply changes surgically:
|
|
174
|
+
1. Add import at top of file:
|
|
175
|
+
```jsx
|
|
176
|
+
import <ComponentName> from '../../components/<ComponentName>';
|
|
177
|
+
```
|
|
178
|
+
(adjust relative path based on page depth)
|
|
179
|
+
|
|
180
|
+
2. Replace the extracted JSX block with the component:
|
|
181
|
+
```jsx
|
|
182
|
+
<ComponentName <prop>={<value>} />
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
3. Remove any now-unused imports that were only used by the extracted block.
|
|
186
|
+
|
|
187
|
+
4. Remove any CSS classes in the page's `.module.css` that are now handled by the component's own CSS file.
|
|
188
|
+
|
|
189
|
+
**Step 3.** Write the updated file.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### Phase 8 — Finalize
|
|
194
|
+
|
|
195
|
+
**Step 1.** Call `context_write`:
|
|
196
|
+
- Append to `context.services[<service_name>].components`:
|
|
197
|
+
`{ name, path, role, props_accepted, used_in: [list of page paths] }`
|
|
198
|
+
- Set `last_command` = "modularize"
|
|
199
|
+
- Append to `change_log`: `{ timestamp, command: "modularize", action: "Created [n] component(s) from [n] pages" }`
|
|
200
|
+
|
|
201
|
+
**Step 2.** Call `context_clear_scratchpad` with keys: ["current_action"]
|
|
202
|
+
|
|
203
|
+
**Step 3.** Show completion report:
|
|
204
|
+
```
|
|
205
|
+
/codeninja:modularize Complete
|
|
206
|
+
─────────────────────────────────────────
|
|
207
|
+
Components created : [n]
|
|
208
|
+
Components reused : [n]
|
|
209
|
+
Pages updated : [n]
|
|
210
|
+
─────────────────────────────────────────
|
|
211
|
+
[list created files]
|
|
212
|
+
[list modified files]
|
|
213
|
+
─────────────────────────────────────────
|
|
214
|
+
Next: /codeninja:validate-page to add validation
|
|
215
|
+
/codeninja:integrate-api to wire forms to backend
|
|
216
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:optimize
|
|
3
|
+
personas: [global-orchestrator, nodejs-backend, database-architect]
|
|
4
|
+
skills: [mcp-and-context, api-builder, database, code-intelligence]
|
|
5
|
+
description: Analyse and improve performance using real project context.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /codeninja:optimize
|
|
9
|
+
|
|
10
|
+
## Before Running
|
|
11
|
+
1. Call `context_read` — load `context.db.schema`, `context.services`
|
|
12
|
+
2. Call `context_check_stale`
|
|
13
|
+
|
|
14
|
+
## Execution — Full Step-by-Step
|
|
15
|
+
|
|
16
|
+
### Step 1 — Identify Target
|
|
17
|
+
If not specified, ask:
|
|
18
|
+
"What would you like to optimise?
|
|
19
|
+
(a) A slow API endpoint — paste the route path
|
|
20
|
+
(b) A heavy SQL query — paste the query or file path
|
|
21
|
+
(c) Overall service startup / memory usage
|
|
22
|
+
(d) Something else — describe it"
|
|
23
|
+
|
|
24
|
+
### Step 2 — Load Context
|
|
25
|
+
1. Call `fs_read` on the relevant files (route.js, _model.js)
|
|
26
|
+
2. For DB queries: list existing indexes from `context.db.schema.<table>.indexes`
|
|
27
|
+
|
|
28
|
+
### Step 3A — Database Query Analysis
|
|
29
|
+
|
|
30
|
+
For each query in the target:
|
|
31
|
+
|
|
32
|
+
**Check 1 — Missing Indexes**
|
|
33
|
+
Compare WHERE / JOIN / ORDER BY columns against existing indexes.
|
|
34
|
+
Generate `CREATE INDEX CONCURRENTLY` for missing ones.
|
|
35
|
+
|
|
36
|
+
**Check 2 — SELECT * Anti-Pattern**
|
|
37
|
+
Replace with explicit column list. Show before/after.
|
|
38
|
+
|
|
39
|
+
**Check 3 — N+1 Query Pattern**
|
|
40
|
+
Flag any loop calling a DB function per iteration. Suggest single query with IN or JOIN.
|
|
41
|
+
|
|
42
|
+
**Check 4 — Window Function Choice**
|
|
43
|
+
- `RANK()` → gaps after ties (wrong for leaderboards)
|
|
44
|
+
- `DENSE_RANK()` → no gaps (correct for leaderboards)
|
|
45
|
+
- `ROW_NUMBER()` → unique position (correct for pagination)
|
|
46
|
+
|
|
47
|
+
**Check 5 — Duplicate Row Prevention**
|
|
48
|
+
Flag duplicate rows from missing dedup. Suggest `MIN(id) GROUP BY user_id`.
|
|
49
|
+
|
|
50
|
+
**Check 6 — Functional Index Trap**
|
|
51
|
+
Flag `DATE(created_at) = '...'` → suggest range form for index usage.
|
|
52
|
+
|
|
53
|
+
**Check 7 — work_mem for Sort Operations**
|
|
54
|
+
If EXPLAIN shows external merge disk sort → suggest `SET work_mem = '64MB'`.
|
|
55
|
+
|
|
56
|
+
### Step 3B — API Route Analysis
|
|
57
|
+
|
|
58
|
+
- Is heavy middleware on lightweight routes?
|
|
59
|
+
- Synchronous blocking in request path?
|
|
60
|
+
- Repeated DB lookups that could be cached in Redis?
|
|
61
|
+
- Pagination missing on list endpoints?
|
|
62
|
+
|
|
63
|
+
### Step 4 — Output Recommendations
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
[HIGH | MED | LOW] — Impact label
|
|
67
|
+
|
|
68
|
+
Target: what's being optimised
|
|
69
|
+
Root cause: why it's slow right now
|
|
70
|
+
Fix:
|
|
71
|
+
[exact SQL or code change]
|
|
72
|
+
Estimated gain: concrete estimate
|
|
73
|
+
Side effects: anything developer should know
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
List all, highest impact first.
|
|
77
|
+
|
|
78
|
+
### Step 5 — Offer to Apply
|
|
79
|
+
"I've found [N] optimisations. Want me to apply them?
|
|
80
|
+
I'll implement each one and show you the change before writing."
|
|
81
|
+
|
|
82
|
+
For index changes → generate `NNN_add_index_<n>.sql` migration file.
|
|
83
|
+
For code changes → edit the relevant model or route file surgically.
|
|
84
|
+
Always call `context_write` after applying index additions.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:refactor
|
|
3
|
+
personas: [global-orchestrator, nodejs-backend, database-architect]
|
|
4
|
+
skills: [mcp-and-context, api-builder, database, code-intelligence]
|
|
5
|
+
description: Rename or restructure code with full context tracking.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /codeninja:refactor
|
|
9
|
+
|
|
10
|
+
## Before Running
|
|
11
|
+
1. Call `context_read`
|
|
12
|
+
2. Call `context_check_stale`
|
|
13
|
+
|
|
14
|
+
## Execution — Full Step-by-Step
|
|
15
|
+
|
|
16
|
+
**Step 1.** Ask: "What type of refactor?"
|
|
17
|
+
1. Rename a DB column
|
|
18
|
+
2. Rename a service
|
|
19
|
+
3. Rename a table
|
|
20
|
+
4. Rename a module
|
|
21
|
+
5. Restructure files
|
|
22
|
+
- Store: `context.current_refactor.type`
|
|
23
|
+
|
|
24
|
+
**Step 2.** Ask: "Which service?" (if applicable — skip for DB-only refactors)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### If "Rename DB column":
|
|
29
|
+
- Ask: "Which table?" (list from context)
|
|
30
|
+
- Ask: "Which column to rename?" (list current columns)
|
|
31
|
+
- Ask: "New column name?" (snake_case)
|
|
32
|
+
- Delegate to database-agent:
|
|
33
|
+
- Generate ALTER TABLE migration file
|
|
34
|
+
- Update `context.db.schema.tables[<table>].columns`
|
|
35
|
+
- Append to `context.db.schema.change_log`
|
|
36
|
+
- Delegate to nodejs-agent:
|
|
37
|
+
- Find all references to old column name in service files
|
|
38
|
+
- Update model queries
|
|
39
|
+
- Update swagger_doc.json
|
|
40
|
+
|
|
41
|
+
### If "Rename service":
|
|
42
|
+
- Ask: "Current service name?" (list from context)
|
|
43
|
+
- Ask: "New service name?"
|
|
44
|
+
- Update `context.services` key
|
|
45
|
+
- Append to `context.change_log`
|
|
46
|
+
|
|
47
|
+
### If "Rename table":
|
|
48
|
+
- Ask: "Which table?" (list from context)
|
|
49
|
+
- Ask: "New table name?" (must start with tbl_, snake_case)
|
|
50
|
+
- Delegate to database-agent:
|
|
51
|
+
- Generate ALTER migration: `RENAME TABLE <old> TO <new>`
|
|
52
|
+
- Update `context.db.schema.tables` key
|
|
53
|
+
- Append to `context.db.schema.change_log`: `{ type: "table_renamed", from: "<old>", to: "<new>" }`
|
|
54
|
+
- Delegate to nodejs-agent:
|
|
55
|
+
- Find all references to old table name in model files
|
|
56
|
+
- Update queries in all affected services
|
|
57
|
+
- Append to top-level `context.change_log`
|
|
58
|
+
|
|
59
|
+
### If "Rename module":
|
|
60
|
+
- Ask: "Current module name?"
|
|
61
|
+
- Ask: "New module name?"
|
|
62
|
+
- Delegate to nodejs-agent → rename files and update route_manager
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
**Confirm:** "Apply refactor? (yes/no)"
|
|
67
|
+
If yes → make all changes → call `context_write` → call `context_clear_scratchpad` ["current_refactor"]
|
|
68
|
+
Show final summary.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:review
|
|
3
|
+
personas: [global-orchestrator, nodejs-backend]
|
|
4
|
+
skills: [mcp-and-context, api-builder, code-intelligence]
|
|
5
|
+
description: Deep code review with severity-ranked findings and concrete fixes.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /codeninja:review
|
|
9
|
+
|
|
10
|
+
## Before Running
|
|
11
|
+
1. Call `context_read`
|
|
12
|
+
2. Call `context_check_stale`
|
|
13
|
+
|
|
14
|
+
## Execution — Full Step-by-Step
|
|
15
|
+
|
|
16
|
+
### Step 1 — Identify Target
|
|
17
|
+
If not specified, ask: "Which file or module would you like reviewed?"
|
|
18
|
+
|
|
19
|
+
### Step 2 — Load Context
|
|
20
|
+
1. Call `fs_read` on the target file
|
|
21
|
+
2. Read 1–2 similar modules from `context.services[<service>].modules` for pattern comparison
|
|
22
|
+
3. Cross-reference `context.db.schema` for table/column accuracy
|
|
23
|
+
|
|
24
|
+
### Step 3 — Run Review Checklist
|
|
25
|
+
|
|
26
|
+
#### Security (CRITICAL if failing)
|
|
27
|
+
- [ ] All POST/PUT/PATCH routes have validatorjs input validation
|
|
28
|
+
- [ ] API key middleware applied before any route logic
|
|
29
|
+
- [ ] JWT auth middleware present on protected routes
|
|
30
|
+
- [ ] No hardcoded secrets, keys, or passwords
|
|
31
|
+
- [ ] Parameterized queries only — no string concatenation in SQL
|
|
32
|
+
- [ ] Error responses don't leak stack traces or internal details
|
|
33
|
+
|
|
34
|
+
#### Architecture (WARNING if failing)
|
|
35
|
+
- [ ] 2-layer rule: no SQL in route.js, no res.json() in model.js
|
|
36
|
+
- [ ] route_manager.js registration matches route file
|
|
37
|
+
- [ ] swagger_doc.json has entry for this endpoint
|
|
38
|
+
- [ ] All user-facing strings in languages/en.js — none hardcoded in route.js
|
|
39
|
+
|
|
40
|
+
#### Code Quality (SUGGESTION if failing)
|
|
41
|
+
- [ ] JSDoc on every exported function
|
|
42
|
+
- [ ] No unused variables or dead imports
|
|
43
|
+
- [ ] No console.log — project logger used instead
|
|
44
|
+
- [ ] Async functions have try/catch blocks
|
|
45
|
+
- [ ] SELECT * not used — explicit column list
|
|
46
|
+
|
|
47
|
+
#### Database (WARNING if failing)
|
|
48
|
+
- [ ] Column names match context.db.schema exactly (snake_case)
|
|
49
|
+
- [ ] Foreign key columns indexed
|
|
50
|
+
- [ ] Transactions used where multiple writes occur together
|
|
51
|
+
- [ ] LIMIT clause on any query that could return unbounded rows
|
|
52
|
+
|
|
53
|
+
### Step 4 — Output Findings
|
|
54
|
+
|
|
55
|
+
For each issue:
|
|
56
|
+
```
|
|
57
|
+
[CRITICAL|WARNING|SUGGESTION]
|
|
58
|
+
File: path/to/file.js (~line N)
|
|
59
|
+
Issue: clear one-line description
|
|
60
|
+
Before: the current code
|
|
61
|
+
After: the corrected code
|
|
62
|
+
Why: one sentence explanation
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
End with: `Review complete: X critical · Y warnings · Z suggestions`
|
|
66
|
+
|
|
67
|
+
### Step 5 — Offer Auto-Fix
|
|
68
|
+
"Would you like me to apply any of these fixes?
|
|
69
|
+
- SUGGESTION-level: apply all at once
|
|
70
|
+
- WARNING/CRITICAL: one at a time, confirm each"
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:sync
|
|
3
|
+
personas: [global-orchestrator, nodejs-backend]
|
|
4
|
+
skills: [mcp-and-context, code-intelligence]
|
|
5
|
+
description: Scan the entire repository and rebuild context.json from what actually exists on disk.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /codeninja:sync
|
|
9
|
+
|
|
10
|
+
## Before Running
|
|
11
|
+
1. Call `context_read` — load current state (or detect empty)
|
|
12
|
+
2. Call `service_scan` — discover all services on disk
|
|
13
|
+
3. Call `context_check_stale`
|
|
14
|
+
|
|
15
|
+
## Two Operating Modes (auto-detected — do NOT ask user)
|
|
16
|
+
|
|
17
|
+
### Mode A — Agent-Initialized Project
|
|
18
|
+
Indicators: context.json exists AND `context_version > 0` AND `context.services` has entries.
|
|
19
|
+
→ Trust context.json as baseline, scan for drift and gaps, merge new findings without overwriting.
|
|
20
|
+
|
|
21
|
+
### Mode B — Legacy / No-Context Project
|
|
22
|
+
Indicators: context.json missing OR `context_version == 0` OR `context.services` is empty.
|
|
23
|
+
→ Treat every discovery as new. Build context.json entirely from disk. No assumptions about structure.
|
|
24
|
+
|
|
25
|
+
## Core Rules (both modes)
|
|
26
|
+
- ALWAYS write context.json at the end — no exceptions
|
|
27
|
+
- NEVER delete existing context entries — only add or update
|
|
28
|
+
- NEVER assume a file will be in a specific location — scan first
|
|
29
|
+
- Report all findings in the sync report at the end
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Execution — Full Step-by-Step
|
|
34
|
+
|
|
35
|
+
### Phase 0 — Prepare
|
|
36
|
+
|
|
37
|
+
**Step 0a.** Check if `.codeninja/context/` exists. If not → create it.
|
|
38
|
+
**Step 0b.** Call `context_read`. If returns empty schema (version == 0) → set mode B, fresh schema.
|
|
39
|
+
**Step 0c.** Call `service_scan` — detect all service directories at repo root.
|
|
40
|
+
**Step 0d.** Init sync report counters: `services_synced`, `routes_discovered`, `routes_new`,
|
|
41
|
+
`db_tables_synced`, `db_tables_new`, `gaps_filled`, `unchanged`, `legacy_inferences`
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### Phase 1 — Repository Structure Discovery
|
|
46
|
+
|
|
47
|
+
#### 1a — Find all service-like directories
|
|
48
|
+
Scan every directory at repository root. A directory is a candidate service if it contains ANY of:
|
|
49
|
+
- `package.json`
|
|
50
|
+
- `app.js` or `index.js`
|
|
51
|
+
- `src/` directory
|
|
52
|
+
- `composer.json` (PHP — record but do not deep-scan)
|
|
53
|
+
|
|
54
|
+
For each candidate service directory:
|
|
55
|
+
- Read `package.json` if present → extract name, version, dependencies
|
|
56
|
+
- Detect type: NodeJS vs ReactJS:
|
|
57
|
+
- ReactJS: has `react` in dependencies, has `src/App.jsx` or `src/App.js`
|
|
58
|
+
- NodeJS: has `express` in dependencies, has `app.js` with `require('express')`
|
|
59
|
+
- Unknown: record type as "unknown"
|
|
60
|
+
- Read `.env` if present (gitignored, may not exist) → extract PORT, DB_*, REDIS_*, KEY, IV, API_KEY
|
|
61
|
+
- Read `.env.example` if present → extract all keys defined
|
|
62
|
+
|
|
63
|
+
#### 1b — Detect service port
|
|
64
|
+
Priority order:
|
|
65
|
+
1. PORT value from `.env`
|
|
66
|
+
2. PORT value from `.env.example`
|
|
67
|
+
3. `app.listen(PORT, ...)` call in `app.js` — extract default
|
|
68
|
+
4. `context.services[<n>].port` if already recorded
|
|
69
|
+
|
|
70
|
+
#### 1c — Detect modules (NodeJS services)
|
|
71
|
+
For each NodeJS service:
|
|
72
|
+
- Scan `modules/` directory (may be `v1/`, `v2/`, etc.)
|
|
73
|
+
- Each subdirectory containing `route.js` = one module
|
|
74
|
+
- Read `route.js` — extract: HTTP method, route path, whether auth middleware is applied
|
|
75
|
+
- Record: `{ module_name, version, method, route_path, has_auth }`
|
|
76
|
+
|
|
77
|
+
#### 1d — Detect React pages (ReactJS services)
|
|
78
|
+
For each ReactJS service:
|
|
79
|
+
- Scan `src/pages/` — each subdirectory with `index.jsx` or `index.js` = one page
|
|
80
|
+
- Scan `src/views/` if it exists — same logic
|
|
81
|
+
- Detect linked backend:
|
|
82
|
+
- Read `src/api/apiClient.js` → extract `baseURL` → parse port → match against `context.services`
|
|
83
|
+
- Or read `.env` → `REACT_APP_BASE_URL` → parse port
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### Phase 2 — Database Discovery
|
|
88
|
+
|
|
89
|
+
**Step 2a.** Scan for `database/` directory at repo root.
|
|
90
|
+
If found → read sub-directories to determine db type (postgresql, mysql, mongodb).
|
|
91
|
+
|
|
92
|
+
**Step 2b.** For each db type directory found:
|
|
93
|
+
- List all `.sql` files in `migrations/` sorted by numeric prefix
|
|
94
|
+
- Parse each setup file:
|
|
95
|
+
- Extract table name from `CREATE TABLE`
|
|
96
|
+
- Extract column names and types
|
|
97
|
+
- Extract CHECK constraints and COMMENT ON COLUMN
|
|
98
|
+
- Extract per-file CREATE INDEX statements
|
|
99
|
+
- Parse ALTER files: ADD COLUMN, RENAME COLUMN, DROP COLUMN, ADD CONSTRAINT
|
|
100
|
+
- Parse DROP files: mark table as dropped
|
|
101
|
+
- Parse `111-setup-database-indexes.sql`: extract CREATE INDEX, associate with tables
|
|
102
|
+
- Build the full schema state from all files in order
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### Phase 3 — Context Assembly
|
|
107
|
+
|
|
108
|
+
#### Mode A — Merge with existing context
|
|
109
|
+
|
|
110
|
+
For each discovered service:
|
|
111
|
+
- If service already in `context.services` → check for drift:
|
|
112
|
+
- Port changed? → flag and ask user which to keep
|
|
113
|
+
- New modules found not in context → add them
|
|
114
|
+
- Modules in context not found on disk → flag as "missing on disk"
|
|
115
|
+
- If service NOT in context → add it as new entry
|
|
116
|
+
|
|
117
|
+
For DB schema:
|
|
118
|
+
- Add any tables not in context
|
|
119
|
+
- Add any columns not tracked
|
|
120
|
+
- Add any indexes not tracked
|
|
121
|
+
- For renames found in ALTER files → append to change_log if not already there
|
|
122
|
+
|
|
123
|
+
#### Mode B — Build from scratch
|
|
124
|
+
|
|
125
|
+
For each discovered service, build full entry:
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"service_name": "<n>",
|
|
129
|
+
"type": "nodejs|reactjs",
|
|
130
|
+
"port": <n>,
|
|
131
|
+
"description": "<inferred from package.json description or service name>",
|
|
132
|
+
"modules": [...],
|
|
133
|
+
"linked_service": "<inferred from apiClient.js>",
|
|
134
|
+
"detected_by": "sync"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For legacy projects that don't follow agent conventions:
|
|
139
|
+
- Record what IS found without imposing expected structure
|
|
140
|
+
- Set `legacy: true` flag on the service entry
|
|
141
|
+
- Note what is missing and suggest /codeninja:init to scaffold missing pieces
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### Phase 4 — Drift Report and Confirmation
|
|
146
|
+
|
|
147
|
+
Before writing anything, present a drift report:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
SYNC REPORT
|
|
151
|
+
════════════════════════════════════════════
|
|
152
|
+
Mode: A (agent-initialized) | B (legacy/fresh)
|
|
153
|
+
────────────────────────────────────────────
|
|
154
|
+
Services discovered on disk: [n]
|
|
155
|
+
Services already in context: [n]
|
|
156
|
+
New services to add: [n]
|
|
157
|
+
Services with drift: [n]
|
|
158
|
+
────────────────────────────────────────────
|
|
159
|
+
DB tables on disk: [n]
|
|
160
|
+
DB tables already in context: [n]
|
|
161
|
+
New tables to add: [n]
|
|
162
|
+
────────────────────────────────────────────
|
|
163
|
+
DRIFT ITEMS (require confirmation):
|
|
164
|
+
⚠ service [n]: port in context = 1001, found on disk = 1002
|
|
165
|
+
⚠ module [n] in context but route.js not found on disk
|
|
166
|
+
────────────────────────────────────────────
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For each DRIFT ITEM: ask user to confirm which value to keep — one at a time.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### Phase 5 — Write Context
|
|
174
|
+
|
|
175
|
+
**Step 5.** Call `context_write` with the fully assembled context object.
|
|
176
|
+
Set `last_command` = "sync"
|
|
177
|
+
|
|
178
|
+
**Step 6.** Show final sync summary with counts of what was added/updated.
|
|
179
|
+
|
|
180
|
+
**Step 7.** Suggest next steps based on findings:
|
|
181
|
+
- If new services found → "Run /codeninja:api to add API routes"
|
|
182
|
+
- If schema gaps found → "Run /codeninja:db:sync to rebuild DB schema"
|
|
183
|
+
- If legacy project → "Run /codeninja:init to scaffold missing baseline files"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:test
|
|
3
|
+
personas: [global-orchestrator, nodejs-backend]
|
|
4
|
+
skills: [mcp-and-context, api-builder, code-intelligence]
|
|
5
|
+
description: Generate or run Jest + Supertest tests for a NodeJS module.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /codeninja:test
|
|
9
|
+
|
|
10
|
+
## Before Running
|
|
11
|
+
1. Call `context_read`
|
|
12
|
+
2. Call `context_check_stale`
|
|
13
|
+
|
|
14
|
+
## Execution — Full Step-by-Step
|
|
15
|
+
|
|
16
|
+
**Step 1.** Ask: "Which service?" (list from `context.services`)
|
|
17
|
+
- Store: `context.current_test.service_name`
|
|
18
|
+
|
|
19
|
+
**Step 2.** Ask: "Which module?" (list from `context.services[<n>].modules`)
|
|
20
|
+
- Store: `context.current_test.module_name`
|
|
21
|
+
|
|
22
|
+
**Step 3.** Ask: "Generate new tests or run existing tests?"
|
|
23
|
+
- Option 1: Generate new tests
|
|
24
|
+
- Option 2: Run existing tests
|
|
25
|
+
- Store: `context.current_test.type`
|
|
26
|
+
|
|
27
|
+
**Step 4.** If `generate`:
|
|
28
|
+
- Read `modules/<version>/<Module>/route.js` from disk
|
|
29
|
+
- Read `modules/<version>/<Module>/<module>_model.js` from disk
|
|
30
|
+
- Read `context.api_routes` for this module
|
|
31
|
+
- Delegate to nodejs-agent → generate `tests/<version>/<Module>.test.js`
|
|
32
|
+
|
|
33
|
+
Generated test file covers:
|
|
34
|
+
- 200 happy path for each endpoint
|
|
35
|
+
- 400 validation failures (missing required fields, wrong types)
|
|
36
|
+
- 401 missing or invalid API key header
|
|
37
|
+
- 401 missing or invalid auth token (for protected routes)
|
|
38
|
+
- 404 not found (where applicable)
|
|
39
|
+
- 500 simulated service error (mock DB failure)
|
|
40
|
+
|
|
41
|
+
Test structure:
|
|
42
|
+
```javascript
|
|
43
|
+
const request = require('supertest');
|
|
44
|
+
const app = require('../../app');
|
|
45
|
+
|
|
46
|
+
describe('<Module> — POST /<path>', () => {
|
|
47
|
+
it('200 — happy path', async () => { ... });
|
|
48
|
+
it('400 — missing required field', async () => { ... });
|
|
49
|
+
it('401 — invalid api-key', async () => { ... });
|
|
50
|
+
it('401 — invalid auth token', async () => { ... });
|
|
51
|
+
it('404 — record not found', async () => { ... });
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Step 5.** If `run`:
|
|
56
|
+
- Execute: `npm test` inside service directory
|
|
57
|
+
- Parse results and display pass/fail summary
|
|
58
|
+
|
|
59
|
+
**Step 6.** Call `context_write` → update `context.services[<n>].tests`
|
|
60
|
+
|
|
61
|
+
**Step 7.** Show final summary.
|