codeninja 2.0.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/.gitattributes +11 -0
- package/README.md +293 -0
- package/agent/database-agent.md +504 -0
- package/agent/designs/README.md +10 -0
- package/agent/global-agent.md +236 -0
- package/agent/nodejs-agent.md +406 -0
- package/agent/reactjs-agent.md +260 -0
- package/cli.js +352 -0
- package/commands/audit.workflow.md +111 -0
- package/commands/create-api.workflow.md +99 -0
- package/commands/db-add-index.workflow.md +97 -0
- package/commands/db-create-table.workflow.md +132 -0
- package/commands/db-drop-table.workflow.md +103 -0
- package/commands/db-modify-table.workflow.md +159 -0
- package/commands/db-seed.workflow.md +99 -0
- package/commands/db-sync.workflow.md +100 -0
- package/commands/design.workflow.md +66 -0
- package/commands/initialize-project.workflow.md +500 -0
- package/commands/integrate-api.workflow.md +448 -0
- package/commands/modularize.workflow.md +329 -0
- package/commands/refactor.workflow.md +70 -0
- package/commands/sync.workflow.md +962 -0
- package/commands/test.workflow.md +40 -0
- package/commands/validate-page.workflow.md +543 -0
- package/mcp-server.js +842 -0
- package/package.json +24 -0
- package/tasks/README.md +283 -0
- package/tasks/add-health-route.task.md +103 -0
- package/tasks/ask-api-integration-scope.task.md +34 -0
- package/tasks/ask-api-key.task.md +23 -0
- package/tasks/ask-api-version.task.md +28 -0
- package/tasks/ask-client-type.task.md +24 -0
- package/tasks/ask-column-enum-values.task.md +51 -0
- package/tasks/ask-column-is-enum.task.md +39 -0
- package/tasks/ask-column-name.task.md +39 -0
- package/tasks/ask-column-position.task.md +39 -0
- package/tasks/ask-column-type.task.md +59 -0
- package/tasks/ask-database-config.task.md +66 -0
- package/tasks/ask-database-host.task.md +16 -0
- package/tasks/ask-database-name.task.md +18 -0
- package/tasks/ask-database-port.task.md +23 -0
- package/tasks/ask-database-type.task.md +30 -0
- package/tasks/ask-database-user.task.md +14 -0
- package/tasks/ask-design-description.task.md +16 -0
- package/tasks/ask-design-target.task.md +24 -0
- package/tasks/ask-encrypted-transport.task.md +25 -0
- package/tasks/ask-encryption-iv.task.md +23 -0
- package/tasks/ask-encryption-key.task.md +23 -0
- package/tasks/ask-feature-name.task.md +20 -0
- package/tasks/ask-http-method.task.md +21 -0
- package/tasks/ask-index-columns.task.md +46 -0
- package/tasks/ask-index-file-placement.task.md +33 -0
- package/tasks/ask-index-sort-order.task.md +37 -0
- package/tasks/ask-index-type.task.md +42 -0
- package/tasks/ask-init-mode.task.md +28 -0
- package/tasks/ask-linked-service.task.md +57 -0
- package/tasks/ask-modify-operation.task.md +36 -0
- package/tasks/ask-modularize-scope.task.md +31 -0
- package/tasks/ask-module-name.task.md +30 -0
- package/tasks/ask-new-column-name.task.md +21 -0
- package/tasks/ask-new-table-name.task.md +22 -0
- package/tasks/ask-old-column-name.task.md +22 -0
- package/tasks/ask-package-author.task.md +16 -0
- package/tasks/ask-package-name.task.md +23 -0
- package/tasks/ask-page-path.task.md +40 -0
- package/tasks/ask-primary-table.task.md +30 -0
- package/tasks/ask-project-figma.task.md +71 -0
- package/tasks/ask-project-info-doc.task.md +57 -0
- package/tasks/ask-project-scope-of-work.task.md +57 -0
- package/tasks/ask-project-type.task.md +24 -0
- package/tasks/ask-react-target-service.task.md +32 -0
- package/tasks/ask-redis-config.task.md +42 -0
- package/tasks/ask-redis-host.task.md +16 -0
- package/tasks/ask-redis-port.task.md +18 -0
- package/tasks/ask-refactor-type.task.md +26 -0
- package/tasks/ask-requires-auth.task.md +22 -0
- package/tasks/ask-response-mode.task.md +38 -0
- package/tasks/ask-route-description.task.md +20 -0
- package/tasks/ask-route-path.task.md +29 -0
- package/tasks/ask-seed-row-values.task.md +42 -0
- package/tasks/ask-seed-rows-count.task.md +22 -0
- package/tasks/ask-service-description.task.md +16 -0
- package/tasks/ask-service-name.task.md +27 -0
- package/tasks/ask-service-port.task.md +24 -0
- package/tasks/ask-supported-languages.task.md +40 -0
- package/tasks/ask-table-file-number.task.md +36 -0
- package/tasks/ask-table-indexes.task.md +47 -0
- package/tasks/ask-table-name.task.md +32 -0
- package/tasks/ask-table-needs-soft-delete.task.md +29 -0
- package/tasks/ask-table-needs-status.task.md +30 -0
- package/tasks/ask-table-purpose.task.md +28 -0
- package/tasks/ask-table-seed-data.task.md +44 -0
- package/tasks/ask-target-service.task.md +32 -0
- package/tasks/ask-test-type.task.md +20 -0
- package/tasks/ask-validation-library.task.md +38 -0
- package/tasks/detect-repository-state.task.md +92 -0
- package/tasks/generate-app.task.md +146 -0
- package/tasks/generate-common.task.md +330 -0
- package/tasks/generate-constants.task.md +123 -0
- package/tasks/generate-database.task.md +168 -0
- package/tasks/generate-docker-compose.task.md +298 -0
- package/tasks/generate-dockerfile.task.md +126 -0
- package/tasks/generate-dockerignore.task.md +123 -0
- package/tasks/generate-enc-dec-html.task.md +127 -0
- package/tasks/generate-enc-dec-php.task.md +145 -0
- package/tasks/generate-encryption.task.md +159 -0
- package/tasks/generate-fast-defaults.task.md +68 -0
- package/tasks/generate-gitignore.task.md +79 -0
- package/tasks/generate-headerValidator.task.md +377 -0
- package/tasks/generate-ide-configs.task.md +114 -0
- package/tasks/generate-ioRedis.task.md +120 -0
- package/tasks/generate-language-en.task.md +155 -0
- package/tasks/generate-logging.task.md +257 -0
- package/tasks/generate-model.task.md +180 -0
- package/tasks/generate-notification.task.md +251 -0
- package/tasks/generate-package-json.task.md +114 -0
- package/tasks/generate-rateLimiter.task.md +125 -0
- package/tasks/generate-react-api-client.task.md +169 -0
- package/tasks/generate-react-api-handler.task.md +102 -0
- package/tasks/generate-react-app-jsx.task.md +56 -0
- package/tasks/generate-react-dockerfile.task.md +175 -0
- package/tasks/generate-react-env.task.md +58 -0
- package/tasks/generate-react-gitignore.task.md +49 -0
- package/tasks/generate-react-htaccess.task.md +54 -0
- package/tasks/generate-react-index-html.task.md +53 -0
- package/tasks/generate-react-index-jsx.task.md +51 -0
- package/tasks/generate-react-package-json.task.md +77 -0
- package/tasks/generate-react-welcome-page.task.md +71 -0
- package/tasks/generate-readme.task.md +160 -0
- package/tasks/generate-response.task.md +202 -0
- package/tasks/generate-route-manager.task.md +173 -0
- package/tasks/generate-route.task.md +203 -0
- package/tasks/generate-swagger.task.md +290 -0
- package/tasks/generate-tbl-user-deviceinfo.task.md +75 -0
- package/tasks/generate-template.task.md +129 -0
- package/tasks/generate-validator.task.md +122 -0
- package/tasks/show-db-table-summary.task.md +66 -0
- package/tasks/show-final-summary.task.md +108 -0
- package/tasks/show-init-summary.task.md +257 -0
- package/tasks/write-context.task.md +314 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: audit
|
|
4
|
+
description: >
|
|
5
|
+
Review an existing service for code quality, security issues, naming
|
|
6
|
+
consistency, missing middleware, and context alignment.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Workflow: @audit
|
|
10
|
+
|
|
11
|
+
## Goal
|
|
12
|
+
Produce a structured audit report for a service. Identify issues by severity.
|
|
13
|
+
Optionally auto-fix low-risk issues.
|
|
14
|
+
|
|
15
|
+
## When to use @audit vs @sync drift detection
|
|
16
|
+
|
|
17
|
+
`@sync` drift detection: runs automatically with every @sync. Checks
|
|
18
|
+
structural markers only — middleware order, library consistency,
|
|
19
|
+
export patterns. Fast, read-only, always safe.
|
|
20
|
+
|
|
21
|
+
`@audit`: run manually when you want deep code quality analysis —
|
|
22
|
+
security checks, SQL injection patterns, response format consistency,
|
|
23
|
+
context alignment. Slower, comprehensive, covers logic not just structure.
|
|
24
|
+
|
|
25
|
+
Run @sync regularly. Run @audit before releasing a service or after
|
|
26
|
+
a major refactor.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Step-by-Step Execution
|
|
31
|
+
|
|
32
|
+
1. Run task: `ask-target-service`
|
|
33
|
+
|
|
34
|
+
2. Delegate to relevant agent(s) based on service type.
|
|
35
|
+
|
|
36
|
+
3. Agent checks:
|
|
37
|
+
|
|
38
|
+
### Security Checks
|
|
39
|
+
- [ ] API key validation middleware applied to all routes?
|
|
40
|
+
- [ ] Input validation on all POST/PUT/PATCH routes?
|
|
41
|
+
- [ ] SQL injection prevention (parameterized queries)?
|
|
42
|
+
- [ ] Sensitive values only from env vars (no hardcoded keys/passwords)?
|
|
43
|
+
- [ ] `.env` in `.gitignore`?
|
|
44
|
+
- [ ] Encryption using real AES-256-CBC (not base64)?
|
|
45
|
+
- [ ] utilities/encryption.js is the only file importing crypto-js or cryptlib?
|
|
46
|
+
- [ ] res.json() is never called directly in route.js or model files?
|
|
47
|
+
- [ ] Validator package never imported directly in route files?
|
|
48
|
+
- [ ] SMTP credentials only in .env — never hardcoded in
|
|
49
|
+
notification.js or template.js?
|
|
50
|
+
- [ ] Firebase service account file in pem/ and in .gitignore?
|
|
51
|
+
- [ ] GLOBALS object is frozen using Object.freeze?
|
|
52
|
+
|
|
53
|
+
### Code Quality Checks
|
|
54
|
+
- [ ] Controllers only call services (no DB queries in controllers)?
|
|
55
|
+
- [ ] Services contain business logic (no Express req/res objects)?
|
|
56
|
+
- [ ] Models contain only DB queries?
|
|
57
|
+
- [ ] Global error handler present and used?
|
|
58
|
+
- [ ] All routes call checkValidationRules from utilities/validator.js
|
|
59
|
+
before calling model functions?
|
|
60
|
+
- [ ] No separate _validator.js files exist per module?
|
|
61
|
+
- [ ] rateLimiter is the first middleware in route_manager.js?
|
|
62
|
+
- [ ] extractLanguage runs before validateApiKey in route_manager.js?
|
|
63
|
+
- [ ] decryptRequest is the last middleware in the chain?
|
|
64
|
+
- [ ] No route handlers defined directly in route_manager.js?
|
|
65
|
+
- [ ] asyncHandler wraps every middleware in route_manager.js?
|
|
66
|
+
- [ ] All model functions return exactly { responsecode, responsemsg,
|
|
67
|
+
responsedata } — no extra keys, no throws?
|
|
68
|
+
- [ ] No req/res objects in any model file?
|
|
69
|
+
- [ ] Passwords encrypted using utilities/encryption.js before storage?
|
|
70
|
+
- [ ] Session tokens generated only via common.generateSessionCode?
|
|
71
|
+
- [ ] No crypto-js or cryptlib imported directly in model files?
|
|
72
|
+
- [ ] No direct res.json() calls in route.js files?
|
|
73
|
+
|
|
74
|
+
### Consistency Checks
|
|
75
|
+
- [ ] All routes documented in `swagger_doc.json`?
|
|
76
|
+
- [ ] Response format consistent (success, message, data, timestamp)?
|
|
77
|
+
- [ ] Naming follows snake_case for DB, camelCase for JS?
|
|
78
|
+
- [ ] Port matches `context.services[<name>].port`?
|
|
79
|
+
- [ ] DB config matches `context.db`?
|
|
80
|
+
- [ ] All message keywords used in sendResponse calls exist in
|
|
81
|
+
languages/en.js?
|
|
82
|
+
- [ ] All language files contain the same set of keys as en.js?
|
|
83
|
+
- [ ] No two services share the same port in context.services?
|
|
84
|
+
- [ ] All encryption keys in context.services are exactly 32 characters?
|
|
85
|
+
- [ ] All encryption IVs in context.services are exactly 16 characters?
|
|
86
|
+
- [ ] No service name in context.services conflicts with a folder name
|
|
87
|
+
that already exists on disk for a different service?
|
|
88
|
+
|
|
89
|
+
### Context Alignment
|
|
90
|
+
- [ ] All routes present in `context.api_routes`?
|
|
91
|
+
- [ ] All DB tables referenced match `context.db.schema`?
|
|
92
|
+
- [ ] All router.use() lines in route_manager.js have a corresponding
|
|
93
|
+
entry in context.services[<name>].modules?
|
|
94
|
+
- [ ] All context.services[<name>].modules entries have a corresponding
|
|
95
|
+
router.use() line in route_manager.js?
|
|
96
|
+
- [ ] All paths in swagger_doc.json have a corresponding entry in
|
|
97
|
+
context.api_routes?
|
|
98
|
+
|
|
99
|
+
4. Present audit report:
|
|
100
|
+
```
|
|
101
|
+
AUDIT REPORT — <service_name>
|
|
102
|
+
══════════════════════════════════════
|
|
103
|
+
🔴 CRITICAL (must fix)
|
|
104
|
+
🟡 WARNING (should fix)
|
|
105
|
+
🟢 INFO (nice to have)
|
|
106
|
+
══════════════════════════════════════
|
|
107
|
+
[list findings with file + line context]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
5. Ask: "Auto-fix critical issues? (yes/no)"
|
|
111
|
+
6. If yes → delegate to relevant agent for fixes → run task: `write-context`
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: create-api
|
|
4
|
+
description: >
|
|
5
|
+
Add a new API module (route.js + model.js) to an existing NodeJS service.
|
|
6
|
+
Appends to route_manager.js and patches swagger_doc.json surgically —
|
|
7
|
+
never rewrites existing files. Fully context-aware.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Workflow: @create-api
|
|
11
|
+
|
|
12
|
+
## Goal
|
|
13
|
+
Scaffold a complete API module inside an existing NodeJS service.
|
|
14
|
+
Every generated file references actual DB columns from context.
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
- Ask ONE question at a time
|
|
18
|
+
- Never invent table or column names — read from `context.db.schema`
|
|
19
|
+
- Always add the new route to `context.api_routes`
|
|
20
|
+
- Always update `swagger_doc.json` with the new endpoint
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Step-by-Step Execution
|
|
25
|
+
|
|
26
|
+
### Phase 0 — Existing Pattern Review
|
|
27
|
+
Before asking any questions, read the existing modules in
|
|
28
|
+
context.services[<service_name>].modules and scan 1–2 existing
|
|
29
|
+
route.js and _model.js files from the service.
|
|
30
|
+
|
|
31
|
+
Identify:
|
|
32
|
+
- Naming conventions in use (camelCase vs PascalCase for functions)
|
|
33
|
+
- Common validation patterns (which fields always get required rules)
|
|
34
|
+
- Any project-specific response patterns beyond the standard contract
|
|
35
|
+
- Auth pattern used across existing routes (all full? mixed?)
|
|
36
|
+
|
|
37
|
+
Surface a one-line summary: "I've reviewed [n] existing modules.
|
|
38
|
+
I'll follow the same structure." Then proceed to Phase 1.
|
|
39
|
+
|
|
40
|
+
### Phase 1 — Target Service
|
|
41
|
+
1. Run task: `ask-target-service`
|
|
42
|
+
- List available services from `context.services`
|
|
43
|
+
- Stores: `context.current_api.service_name`
|
|
44
|
+
|
|
45
|
+
2. Run task: `ask-api-version`
|
|
46
|
+
- Default: v1
|
|
47
|
+
- Stores: `context.current_api.version`
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Phase 2 — Module Identity
|
|
52
|
+
3. Run task: `ask-module-name`
|
|
53
|
+
- Example: Products, Orders, Invoice
|
|
54
|
+
- Stores: `context.current_api.module_name`
|
|
55
|
+
|
|
56
|
+
4. Run task: `ask-http-method`
|
|
57
|
+
- Options: GET, POST, PUT, PATCH, DELETE
|
|
58
|
+
- Stores: `context.current_api.method`
|
|
59
|
+
|
|
60
|
+
5. Run task: `ask-route-path`
|
|
61
|
+
- Example: /products, /products/:id
|
|
62
|
+
- Stores: `context.current_api.route_path`
|
|
63
|
+
|
|
64
|
+
6. Run task: `ask-route-description`
|
|
65
|
+
- Stores: `context.current_api.description`
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Phase 3 — Database Binding
|
|
70
|
+
7. Run task: `ask-primary-table`
|
|
71
|
+
- Show available tables from `context.db.schema.tables`
|
|
72
|
+
- Stores: `context.current_api.primary_table`
|
|
73
|
+
|
|
74
|
+
8. Run task: `ask-requires-auth`
|
|
75
|
+
- Options: yes / no
|
|
76
|
+
- Stores: `context.current_api.requires_auth`
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Phase 4 — Generate
|
|
81
|
+
9. Confirm with user: "Generate [METHOD] [path] in [service]/modules/[version]/[Module]? (yes/no)"
|
|
82
|
+
|
|
83
|
+
10. Delegate to `nodejs-agent`:
|
|
84
|
+
- Generate: `route.js` — run task: generate-route
|
|
85
|
+
(new file — always a full write)
|
|
86
|
+
- Generate: `<module>_model.js` — run task: generate-model
|
|
87
|
+
(new file — always a full write)
|
|
88
|
+
- Append to: `modules/<version>/route_manager.js`
|
|
89
|
+
run task: generate-route-manager (Mode 2 — append only)
|
|
90
|
+
NEVER rewrite this file — surgical insert only
|
|
91
|
+
- Patch: `document/<version>/swagger_doc.json`
|
|
92
|
+
run task: generate-swagger (Mode 2 — patch paths object only)
|
|
93
|
+
NEVER rewrite this file — add new path key only
|
|
94
|
+
|
|
95
|
+
11. Run task: `write-context`
|
|
96
|
+
- Append to `context.api_routes`
|
|
97
|
+
- Update `context.services[<service>].modules`
|
|
98
|
+
|
|
99
|
+
12. Run task: `show-final-summary`
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: db-add-index
|
|
4
|
+
command: "@db:add-index"
|
|
5
|
+
description: >
|
|
6
|
+
Add a new index to an existing table. Determines whether the index belongs
|
|
7
|
+
in the table's own file (new tables) or in 111-setup-database-indexes.sql
|
|
8
|
+
(shared/cross-service indexes). Updates context and create-schema.sql.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Workflow: @db:add-index
|
|
12
|
+
|
|
13
|
+
## Goal
|
|
14
|
+
Generate a properly named CREATE INDEX statement and place it in the correct
|
|
15
|
+
file. Follow all index naming conventions from database-agent.md.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step-by-Step Execution
|
|
20
|
+
|
|
21
|
+
### Phase 1 — Target Table
|
|
22
|
+
1. Run task: `ask-table-name`
|
|
23
|
+
- List tables from `context.db.schema.tables`
|
|
24
|
+
- Stores: `context.current_db.table_name`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Phase 2 — Index Columns
|
|
29
|
+
2. Run task: `ask-index-columns`
|
|
30
|
+
- Ask: "Which column(s) should this index cover?"
|
|
31
|
+
- List available columns from `context.db.schema.tables[<table>].columns`
|
|
32
|
+
- Allow selecting one or multiple columns (compound index)
|
|
33
|
+
- Stores: `context.current_db.index_columns[]`
|
|
34
|
+
|
|
35
|
+
3. Run task: `ask-index-sort-order`
|
|
36
|
+
- Ask: "Should any column in this index be sorted descending?"
|
|
37
|
+
- Common case: `created_at DESC`, `time DESC`
|
|
38
|
+
- If yes → ask which column(s) should be DESC
|
|
39
|
+
- Stores: `context.current_db.index_desc_columns[]`
|
|
40
|
+
|
|
41
|
+
4. Run task: `ask-index-type`
|
|
42
|
+
- Ask: "Is this a standard index or a partial index?"
|
|
43
|
+
- Options:
|
|
44
|
+
1. Standard index (covers all rows)
|
|
45
|
+
2. Partial index (only indexes rows matching a condition)
|
|
46
|
+
- If partial → ask: "Enter the WHERE condition."
|
|
47
|
+
Example: `WHERE is_deleted = FALSE`
|
|
48
|
+
- Stores: `context.current_db.index_where_clause`
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### Phase 3 — File Placement
|
|
53
|
+
5. Run task: `ask-index-file-placement`
|
|
54
|
+
- Ask: "Where should this index be defined?"
|
|
55
|
+
- Options:
|
|
56
|
+
1. In the table's own setup file (for new/just-created tables)
|
|
57
|
+
2. In 111-setup-database-indexes.sql (for existing tables, shared use)
|
|
58
|
+
- Auto-suggest option 2 if table already has a setup file in migrations
|
|
59
|
+
- Stores: `context.current_db.index_file`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### Phase 4 — Generate
|
|
64
|
+
6. Agent auto-generates the index name following convention:
|
|
65
|
+
- In table file: `idx_<table_without_tbl_prefix>_<columns_joined>`
|
|
66
|
+
- In shared file: `idx_tbl_<table_without_tbl_prefix>_<columns_joined>`
|
|
67
|
+
- Show name to user: "Index will be named: <n> — OK? (yes / rename)"
|
|
68
|
+
|
|
69
|
+
7. Confirm: "Generate this index? (yes / no)"
|
|
70
|
+
|
|
71
|
+
8. Delegate to `database-agent`:
|
|
72
|
+
- If table file placement → append to `<repo_root>/database/<db_type>/migrations/<table_file>.sql`
|
|
73
|
+
- If shared file → append to `<repo_root>/database/<db_type>/migrations/111-setup-database-indexes.sql`
|
|
74
|
+
|
|
75
|
+
Generated SQL:
|
|
76
|
+
```sql
|
|
77
|
+
-- Standard
|
|
78
|
+
CREATE INDEX <index_name> ON public.<table_name> (<col> [DESC], ...);
|
|
79
|
+
|
|
80
|
+
-- Partial
|
|
81
|
+
CREATE INDEX <index_name> ON public.<table_name> (<col> [DESC], ...)
|
|
82
|
+
WHERE <where_clause>;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
With standard header comment:
|
|
86
|
+
```sql
|
|
87
|
+
--
|
|
88
|
+
-- Name: <index_name>; Type: INDEX; Schema: public
|
|
89
|
+
--
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
9. Run task: `write-context`
|
|
93
|
+
- Append index name to `context.db.schema.tables[<table>].indexes`
|
|
94
|
+
- Append to `context.db.schema.change_log`
|
|
95
|
+
- Clear `context.current_db`
|
|
96
|
+
|
|
97
|
+
10. Run task: `show-final-summary`
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: db-create-table
|
|
4
|
+
command: "@db:create-table"
|
|
5
|
+
description: >
|
|
6
|
+
Design and generate a new database table following all project conventions.
|
|
7
|
+
Collects table purpose, name, columns one at a time, then generates the
|
|
8
|
+
numbered SQL file, updates create-schema.sql, and records in context.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Workflow: @db:create-table
|
|
12
|
+
|
|
13
|
+
## Goal
|
|
14
|
+
Generate a complete, convention-compliant SQL table file. Every generated
|
|
15
|
+
file must pass ALL rules defined in database-agent.md.
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
- Ask ONE question at a time — never bundle column definitions
|
|
19
|
+
- Always enforce tbl_ prefix and snake_case naming
|
|
20
|
+
- Never create a table file without updating create-schema.sql
|
|
21
|
+
- Always record in context.db.schema after generation
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step-by-Step Execution
|
|
26
|
+
|
|
27
|
+
### Phase 1 — Table Identity
|
|
28
|
+
1. Run task: `ask-table-purpose`
|
|
29
|
+
- Stores: `context.current_db.table_purpose`
|
|
30
|
+
- Used by agent to suggest column names and structure
|
|
31
|
+
|
|
32
|
+
2. Run task: `ask-table-name`
|
|
33
|
+
- Enforce: lowercase, snake_case, must start with `tbl_`
|
|
34
|
+
- Stores: `context.current_db.table_name`
|
|
35
|
+
|
|
36
|
+
3. Run task: `ask-table-file-number`
|
|
37
|
+
- Agent reads existing files in `database/<db_type>/migrations/`
|
|
38
|
+
- Suggests next available number
|
|
39
|
+
- Stores: `context.current_db.file_number`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### Phase 2 — Standard Columns Decision
|
|
44
|
+
4. Run task: `ask-table-needs-status`
|
|
45
|
+
- Ask: "Does this table need status and is_deleted columns?"
|
|
46
|
+
- Agent guidance: suggest YES for user/entity tables, NO for event/log tables
|
|
47
|
+
- Stores: `context.current_db.needs_status`
|
|
48
|
+
|
|
49
|
+
5. Run task: `ask-table-needs-soft-delete`
|
|
50
|
+
- Ask: "Does this table support soft delete (is_deleted)?"
|
|
51
|
+
- Auto-suggest: YES if needs_status is YES
|
|
52
|
+
- Stores: `context.current_db.needs_soft_delete`
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### Phase 3 — Column Collection (repeat until done)
|
|
57
|
+
6. Run task: `ask-column-name`
|
|
58
|
+
- Show columns collected so far
|
|
59
|
+
- Ask: "Enter the next column name (or type 'done' to finish)"
|
|
60
|
+
- Enforce: snake_case, lowercase
|
|
61
|
+
- Stores: appends to `context.current_db.columns[]`
|
|
62
|
+
|
|
63
|
+
7. Run task: `ask-column-type`
|
|
64
|
+
- Show suggested type based on column name pattern:
|
|
65
|
+
- `*_id` → BIGINT NOT NULL DEFAULT 0
|
|
66
|
+
- When a column name ends in `_id`:
|
|
67
|
+
- Cross-reference context.db.schema.tables for a table whose name
|
|
68
|
+
matches the prefix (e.g. user_id → tbl_users)
|
|
69
|
+
- If found → suggest: "This looks like a foreign key to tbl_users.
|
|
70
|
+
Add FK constraint? (yes/no)"
|
|
71
|
+
- If yes → add REFERENCES clause to the column definition
|
|
72
|
+
- `is_*` → BOOLEAN NOT NULL DEFAULT FALSE
|
|
73
|
+
- `*_at` → TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
74
|
+
- `status` → INTEGER NOT NULL DEFAULT 0 CHECK (status IN (0,1))
|
|
75
|
+
- `*_count` → BIGINT NOT NULL DEFAULT 0
|
|
76
|
+
- `*_price`, `*_amount` → NUMERIC(18,8) NOT NULL DEFAULT 0.00000000
|
|
77
|
+
- `email` → VARCHAR(132) NOT NULL DEFAULT ''
|
|
78
|
+
- `phone` → VARCHAR(16) NOT NULL DEFAULT ''
|
|
79
|
+
- `password` → TEXT NOT NULL DEFAULT ''
|
|
80
|
+
- `*_image`, `*_url` → VARCHAR(255) NOT NULL DEFAULT ''
|
|
81
|
+
- `payload`, `metadata`, `*_result` → JSON NOT NULL DEFAULT '{}'
|
|
82
|
+
- default → VARCHAR(255) NOT NULL DEFAULT ''
|
|
83
|
+
- Stores: in current column entry
|
|
84
|
+
|
|
85
|
+
8. Run task: `ask-column-is-enum`
|
|
86
|
+
- Ask: "Does this column have a fixed set of allowed values? (enum-like)"
|
|
87
|
+
- If yes → run task: `ask-column-enum-values`
|
|
88
|
+
- Stores: check constraint and comment text
|
|
89
|
+
|
|
90
|
+
9. Return to step 6 until user types 'done'
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### Phase 4 — Index Decision
|
|
95
|
+
10. Run task: `ask-table-indexes`
|
|
96
|
+
- Agent auto-suggests indexes based on collected columns:
|
|
97
|
+
- Every `*_id` (foreign key) column → suggest index
|
|
98
|
+
- `status + is_deleted` compound → suggest if both exist
|
|
99
|
+
- `created_at DESC` → suggest for event/log tables
|
|
100
|
+
- Ask user to confirm suggested indexes or add custom ones
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### Phase 5 — Seed Data
|
|
105
|
+
11. Run task: `ask-table-seed-data`
|
|
106
|
+
- Ask: "Does this table need seed/initial data?"
|
|
107
|
+
- Guidance: suggest YES only for reference/master data tables
|
|
108
|
+
- If yes → run task: `ask-seed-data-input`
|
|
109
|
+
- Stores: `context.current_db.seed_rows[]`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Phase 6 — Summary and Generate
|
|
114
|
+
12. Run task: `show-db-table-summary`
|
|
115
|
+
- Display complete table definition as it will be generated
|
|
116
|
+
- Show: table name, file number, all columns with types, indexes, seed data
|
|
117
|
+
- Ask: "Generate this table? (yes / no / change a value)"
|
|
118
|
+
- If change → re-run specific task → return to this step
|
|
119
|
+
- If no → abort, nothing created
|
|
120
|
+
- If yes → proceed
|
|
121
|
+
|
|
122
|
+
13. Delegate to `database-agent`:
|
|
123
|
+
- Generate: `<repo_root>/database/<db_type>/migrations/<number>-setup-tbl-<name>.sql`
|
|
124
|
+
- Update: `<repo_root>/database/<db_type>/create-schema.sql`
|
|
125
|
+
- If any indexes belong in shared file → update: `111-setup-database-indexes.sql`
|
|
126
|
+
|
|
127
|
+
14. Run task: `write-context`
|
|
128
|
+
- Append table to `context.db.schema.tables`
|
|
129
|
+
- Append to `context.db.schema.change_log`
|
|
130
|
+
- Clear `context.current_db`
|
|
131
|
+
|
|
132
|
+
15. Run task: `show-final-summary`
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: db-drop-table
|
|
4
|
+
command: "@db:drop-table"
|
|
5
|
+
description: >
|
|
6
|
+
Generate a DROP TABLE migration file for an existing table. Removes the
|
|
7
|
+
table from context, updates create-schema.sql, and records the drop in
|
|
8
|
+
change_log. Never deletes the original setup file — history is preserved.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Workflow: @db:drop-table
|
|
12
|
+
|
|
13
|
+
## Goal
|
|
14
|
+
Safely generate a DROP TABLE migration. The original setup file is preserved
|
|
15
|
+
for history. The schema runner will execute the drop when run.
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
- NEVER delete the original <number>-setup-tbl-<n>.sql file
|
|
19
|
+
- ALWAYS generate a new numbered drop migration file
|
|
20
|
+
- ALWAYS warn the user about irreversibility
|
|
21
|
+
- Records in change_log with full before-state for rollback reference
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step-by-Step Execution
|
|
26
|
+
|
|
27
|
+
### Phase 1 — Target
|
|
28
|
+
1. Run task: `ask-table-name`
|
|
29
|
+
- List tables from `context.db.schema.tables`
|
|
30
|
+
- Stores: `context.current_db.table_name`
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
### Phase 2 — Impact Analysis
|
|
35
|
+
2. Agent scans `context`:
|
|
36
|
+
- Check `context.api_routes` for any routes that reference this table as `primary_table`
|
|
37
|
+
- Check `context.services` for any modules using this table
|
|
38
|
+
- Check `context.db.schema.tables` for any other tables with FK columns pointing here
|
|
39
|
+
|
|
40
|
+
3. If references found:
|
|
41
|
+
- Display warning:
|
|
42
|
+
```
|
|
43
|
+
⚠ WARNING: This table is referenced by:
|
|
44
|
+
- [service]/modules/[Module] (primary_table)
|
|
45
|
+
- tbl_<other_table>.user_id → tbl_users (FK dependency)
|
|
46
|
+
|
|
47
|
+
Dropping this table will break these references.
|
|
48
|
+
Make sure to update or remove dependent code first.
|
|
49
|
+
```
|
|
50
|
+
- Ask: "Do you still want to proceed? (yes / no)"
|
|
51
|
+
- If no → abort
|
|
52
|
+
|
|
53
|
+
4. Final confirmation:
|
|
54
|
+
- Ask exactly: "Type the table name to confirm the drop."
|
|
55
|
+
- Must match exactly — if wrong → abort
|
|
56
|
+
- Stores: confirmation
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Phase 3 — File Numbering
|
|
61
|
+
5. Run task: `ask-table-file-number`
|
|
62
|
+
- Suggest: next available number
|
|
63
|
+
- Stores: `context.current_db.file_number`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
### Phase 4 — Generate
|
|
68
|
+
6. Delegate to `database-agent`:
|
|
69
|
+
- Generate: `<repo_root>/database/<db_type>/migrations/<number>-drop-tbl-<n>.sql`
|
|
70
|
+
|
|
71
|
+
File contents:
|
|
72
|
+
```sql
|
|
73
|
+
-- Drop tbl_<table_name>
|
|
74
|
+
-- Migration: <number>-drop-tbl-<n>.sql
|
|
75
|
+
-- Generated: <ISO date>
|
|
76
|
+
-- WARNING: This migration is irreversible in production.
|
|
77
|
+
-- Original table definition: <original_setup_file>
|
|
78
|
+
|
|
79
|
+
BEGIN;
|
|
80
|
+
|
|
81
|
+
DROP TABLE IF EXISTS public.<table_name> CASCADE;
|
|
82
|
+
|
|
83
|
+
COMMIT;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- Update: `database/<db_type>/create-schema.sql`
|
|
87
|
+
- Keep the original `\i <setup_file>` entry
|
|
88
|
+
- Add the drop file entry AFTER it
|
|
89
|
+
|
|
90
|
+
7. Run task: `write-context`
|
|
91
|
+
- Move table from `context.db.schema.tables` → save columns snapshot
|
|
92
|
+
- Append to `context.db.schema.change_log`:
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"type": "table_dropped",
|
|
96
|
+
"table": "<table_name>",
|
|
97
|
+
"snapshot": { "<full column list saved here>" },
|
|
98
|
+
"file": "<drop_file_path>"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
- Clear `context.current_db`
|
|
102
|
+
|
|
103
|
+
8. Run task: `show-final-summary`
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: workflow
|
|
3
|
+
name: db-modify-table
|
|
4
|
+
command: "@db:modify-table"
|
|
5
|
+
description: >
|
|
6
|
+
Modify an existing table via a numbered ALTER migration file. Supports
|
|
7
|
+
adding columns, renaming columns, dropping columns, changing types,
|
|
8
|
+
and adding check constraints. Always generates a migration file and
|
|
9
|
+
updates context.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Workflow: @db:modify-table
|
|
13
|
+
|
|
14
|
+
## Goal
|
|
15
|
+
Generate a properly numbered ALTER TABLE migration file that modifies an
|
|
16
|
+
existing table. Record the change in context.db.schema.change_log so all
|
|
17
|
+
agents have the updated schema.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
- ALWAYS generate an ALTER file — never edit the original table setup file
|
|
21
|
+
- ALTER files are numbered sequentially after the last existing file
|
|
22
|
+
- Every change is recorded in context.db.schema.change_log
|
|
23
|
+
- create-schema.sql is updated after every ALTER file generated
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step-by-Step Execution
|
|
28
|
+
|
|
29
|
+
### Phase 1 — Target
|
|
30
|
+
1. Run task: `ask-table-name`
|
|
31
|
+
- List tables from `context.db.schema.tables`
|
|
32
|
+
- Stores: `context.current_db.table_name`
|
|
33
|
+
|
|
34
|
+
2. Run task: `ask-modify-operation`
|
|
35
|
+
- Ask: "What do you want to do?"
|
|
36
|
+
- Options:
|
|
37
|
+
1. Add a new column
|
|
38
|
+
2. Rename a column
|
|
39
|
+
3. Drop a column
|
|
40
|
+
4. Change a column type
|
|
41
|
+
5. Add a CHECK constraint to an existing column
|
|
42
|
+
6. Add a new index
|
|
43
|
+
- Stores: `context.current_db.modify_operation`
|
|
44
|
+
|
|
45
|
+
2b. If `context.current_db.modify_operation == "add_index"`:
|
|
46
|
+
→ Immediately route to `@db:add-index` workflow.
|
|
47
|
+
→ End this workflow (no further steps needed).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Phase 2 — Operation-Specific Collection
|
|
52
|
+
|
|
53
|
+
#### If "Add a new column":
|
|
54
|
+
3. Run task: `ask-column-name`
|
|
55
|
+
4. Run task: `ask-column-type`
|
|
56
|
+
5. Run task: `ask-column-is-enum`
|
|
57
|
+
6. Run task: `ask-column-position`
|
|
58
|
+
- Ask: "Add column after which existing column?"
|
|
59
|
+
- List current columns from context
|
|
60
|
+
- Stores: `context.current_db.after_column`
|
|
61
|
+
|
|
62
|
+
Generated SQL pattern:
|
|
63
|
+
```sql
|
|
64
|
+
ALTER TABLE public.<table_name>
|
|
65
|
+
ADD COLUMN <col_name> <type> NOT NULL DEFAULT <default>;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### If "Rename a column":
|
|
69
|
+
3. Run task: `ask-old-column-name`
|
|
70
|
+
- List current columns from context
|
|
71
|
+
4. Run task: `ask-new-column-name`
|
|
72
|
+
- Enforce: snake_case, lowercase
|
|
73
|
+
|
|
74
|
+
Generated SQL pattern:
|
|
75
|
+
```sql
|
|
76
|
+
ALTER TABLE public.<table_name>
|
|
77
|
+
RENAME COLUMN <old_name> TO <new_name>;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### If "Drop a column":
|
|
81
|
+
3. Run task: `ask-old-column-name`
|
|
82
|
+
- List current columns from context
|
|
83
|
+
- WARN: "This will generate a DROP COLUMN migration. This is irreversible
|
|
84
|
+
in production. Make sure you have removed all code references first."
|
|
85
|
+
- Ask: "Confirm dropping column '<col>'? (yes/no)"
|
|
86
|
+
|
|
87
|
+
Generated SQL pattern:
|
|
88
|
+
```sql
|
|
89
|
+
ALTER TABLE public.<table_name>
|
|
90
|
+
DROP COLUMN IF EXISTS <col_name>;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### If "Change a column type":
|
|
94
|
+
3. Run task: `ask-old-column-name`
|
|
95
|
+
4. Run task: `ask-column-type` (new type)
|
|
96
|
+
- WARN agent about potential data loss if changing to narrower type
|
|
97
|
+
|
|
98
|
+
Generated SQL pattern:
|
|
99
|
+
```sql
|
|
100
|
+
ALTER TABLE public.<table_name>
|
|
101
|
+
ALTER COLUMN <col_name> TYPE <new_type> USING <col_name>::<new_type>;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### If "Add a CHECK constraint":
|
|
105
|
+
3. Run task: `ask-old-column-name`
|
|
106
|
+
4. Run task: `ask-column-enum-values`
|
|
107
|
+
|
|
108
|
+
Generated SQL pattern:
|
|
109
|
+
```sql
|
|
110
|
+
ALTER TABLE public.<table_name>
|
|
111
|
+
ADD CONSTRAINT chk_<table>_<col> CHECK (<col_name> IN (<values>));
|
|
112
|
+
COMMENT ON COLUMN public.<table_name>.<col_name> IS '<enum explanation>';
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### If "Add a new index":
|
|
116
|
+
→ Route to `@db:add-index` workflow instead.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### Phase 3 — File Numbering
|
|
121
|
+
7. Run task: `ask-table-file-number`
|
|
122
|
+
- Suggest: next available number after all existing files
|
|
123
|
+
- Stores: `context.current_db.file_number`
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Phase 4 — Confirm and Generate
|
|
128
|
+
8. Show summary of the ALTER operation
|
|
129
|
+
- Display the exact SQL that will be generated
|
|
130
|
+
- Ask: "Generate this migration? (yes / no)"
|
|
131
|
+
|
|
132
|
+
9. Delegate to `database-agent`:
|
|
133
|
+
- Generate: `<repo_root>/database/<db_type>/migrations/<number>-alter-tbl-<n>-<description>.sql`
|
|
134
|
+
|
|
135
|
+
Full file structure:
|
|
136
|
+
```sql
|
|
137
|
+
-- Alter tbl_<table>: <description>
|
|
138
|
+
-- Migration: <number>-alter-tbl-<n>-<description>.sql
|
|
139
|
+
-- Generated: <ISO date>
|
|
140
|
+
|
|
141
|
+
BEGIN;
|
|
142
|
+
|
|
143
|
+
ALTER TABLE public.<table_name>
|
|
144
|
+
<operation>;
|
|
145
|
+
|
|
146
|
+
-- Optional: COMMENT ON COLUMN if enum/flag column
|
|
147
|
+
-- Optional: CREATE INDEX if new column needs one
|
|
148
|
+
|
|
149
|
+
COMMIT;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- Update: `database/<db_type>/create-schema.sql`
|
|
153
|
+
|
|
154
|
+
10. Run task: `write-context`
|
|
155
|
+
- Update `context.db.schema.tables[<table>].columns`
|
|
156
|
+
- Append to `context.db.schema.change_log`
|
|
157
|
+
- Clear `context.current_db`
|
|
158
|
+
|
|
159
|
+
11. Run task: `show-final-summary`
|