@kennethsolomon/shipkit 1.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.
Files changed (117) hide show
  1. package/README.md +321 -0
  2. package/bin/shipkit.js +146 -0
  3. package/commands/sk/brainstorm.md +63 -0
  4. package/commands/sk/branch.md +35 -0
  5. package/commands/sk/config.md +96 -0
  6. package/commands/sk/execute-plan.md +85 -0
  7. package/commands/sk/features.md +238 -0
  8. package/commands/sk/finish-feature.md +154 -0
  9. package/commands/sk/help.md +103 -0
  10. package/commands/sk/hotfix.md +61 -0
  11. package/commands/sk/plan.md +30 -0
  12. package/commands/sk/release.md +72 -0
  13. package/commands/sk/security-check.md +188 -0
  14. package/commands/sk/set-profile.md +71 -0
  15. package/commands/sk/status.md +25 -0
  16. package/commands/sk/update-task.md +35 -0
  17. package/commands/sk/write-plan.md +72 -0
  18. package/package.json +23 -0
  19. package/skills/sk:accessibility/LICENSE.txt +177 -0
  20. package/skills/sk:accessibility/SKILL.md +150 -0
  21. package/skills/sk:api-design/LICENSE.txt +177 -0
  22. package/skills/sk:api-design/SKILL.md +158 -0
  23. package/skills/sk:brainstorming/SKILL.md +124 -0
  24. package/skills/sk:debug/SKILL.md +252 -0
  25. package/skills/sk:debug/debug_conductor.py +177 -0
  26. package/skills/sk:debug/lib/__init__.py +1 -0
  27. package/skills/sk:debug/lib/bug_gatherer.py +55 -0
  28. package/skills/sk:debug/lib/context_reader.py +139 -0
  29. package/skills/sk:debug/lib/findings_writer.py +76 -0
  30. package/skills/sk:debug/lib/lessons_writer.py +165 -0
  31. package/skills/sk:debug/lib/step_runner.py +326 -0
  32. package/skills/sk:features/SKILL.md +238 -0
  33. package/skills/sk:frontend-design/LICENSE.txt +177 -0
  34. package/skills/sk:frontend-design/SKILL.md +191 -0
  35. package/skills/sk:laravel-init/SKILL.md +37 -0
  36. package/skills/sk:laravel-new/SKILL.md +68 -0
  37. package/skills/sk:lint/SKILL.md +113 -0
  38. package/skills/sk:perf/LICENSE.txt +177 -0
  39. package/skills/sk:perf/SKILL.md +188 -0
  40. package/skills/sk:release/SKILL.md +113 -0
  41. package/skills/sk:release/references/android-checklist.md +269 -0
  42. package/skills/sk:release/references/ios-checklist.md +339 -0
  43. package/skills/sk:release/release.sh +378 -0
  44. package/skills/sk:review/SKILL.md +346 -0
  45. package/skills/sk:review/references/security-checklist.md +223 -0
  46. package/skills/sk:schema-migrate/SKILL.md +125 -0
  47. package/skills/sk:schema-migrate/orms/drizzle.md +546 -0
  48. package/skills/sk:schema-migrate/orms/laravel.md +367 -0
  49. package/skills/sk:schema-migrate/orms/prisma.md +357 -0
  50. package/skills/sk:schema-migrate/orms/rails.md +351 -0
  51. package/skills/sk:schema-migrate/orms/sqlalchemy.md +385 -0
  52. package/skills/sk:schema-migrate/references/detection.md +110 -0
  53. package/skills/sk:setup-claude/SKILL.md +365 -0
  54. package/skills/sk:setup-claude/references/detection.md +6 -0
  55. package/skills/sk:setup-claude/references/templates.md +11 -0
  56. package/skills/sk:setup-claude/scripts/apply_setup_claude.py +443 -0
  57. package/skills/sk:setup-claude/scripts/detect_arch_changes.py +437 -0
  58. package/skills/sk:setup-claude/templates/.claude/docs/arch-changelog-guide.md.template +6 -0
  59. package/skills/sk:setup-claude/templates/.claude/docs/changelog-guide.md.template +12 -0
  60. package/skills/sk:setup-claude/templates/CHANGELOG.md.template +21 -0
  61. package/skills/sk:setup-claude/templates/CLAUDE.md.template +299 -0
  62. package/skills/sk:setup-claude/templates/arch-changelog-guide.md.template +3 -0
  63. package/skills/sk:setup-claude/templates/changelog-guide.md.template +3 -0
  64. package/skills/sk:setup-claude/templates/commands/brainstorm.md.template +74 -0
  65. package/skills/sk:setup-claude/templates/commands/execute-plan.md.template +57 -0
  66. package/skills/sk:setup-claude/templates/commands/features.md.template +238 -0
  67. package/skills/sk:setup-claude/templates/commands/finish-feature.md.template +155 -0
  68. package/skills/sk:setup-claude/templates/commands/plan.md.template +30 -0
  69. package/skills/sk:setup-claude/templates/commands/re-setup.md.template +38 -0
  70. package/skills/sk:setup-claude/templates/commands/release.md.template +74 -0
  71. package/skills/sk:setup-claude/templates/commands/security-check.md.template +172 -0
  72. package/skills/sk:setup-claude/templates/commands/status.md.template +17 -0
  73. package/skills/sk:setup-claude/templates/commands/write-plan.md.template +34 -0
  74. package/skills/sk:setup-claude/templates/finish-feature.md.template +3 -0
  75. package/skills/sk:setup-claude/templates/plan.md.template +3 -0
  76. package/skills/sk:setup-claude/templates/status.md.template +3 -0
  77. package/skills/sk:setup-claude/templates/tasks/findings.md.template +19 -0
  78. package/skills/sk:setup-claude/templates/tasks/lessons.md.template +26 -0
  79. package/skills/sk:setup-claude/templates/tasks/progress.md.template +20 -0
  80. package/skills/sk:setup-claude/templates/tasks/security-findings.md.template +5 -0
  81. package/skills/sk:setup-claude/templates/tasks/todo.md.template +26 -0
  82. package/skills/sk:setup-claude/templates/tasks/workflow-status.md.template +31 -0
  83. package/skills/sk:setup-claude/templates/tasks-findings.md.template +3 -0
  84. package/skills/sk:setup-claude/templates/tasks-lessons.md.template +3 -0
  85. package/skills/sk:setup-claude/templates/tasks-progress.md.template +3 -0
  86. package/skills/sk:setup-claude/templates/tasks-todo.md.template +3 -0
  87. package/skills/sk:setup-claude/tests/test_apply_setup_claude.py +193 -0
  88. package/skills/sk:setup-optimizer/SKILL.md +184 -0
  89. package/skills/sk:setup-optimizer/lib/__init__.py +24 -0
  90. package/skills/sk:setup-optimizer/lib/detect.py +205 -0
  91. package/skills/sk:setup-optimizer/lib/discover.py +221 -0
  92. package/skills/sk:setup-optimizer/lib/enrich.py +163 -0
  93. package/skills/sk:setup-optimizer/lib/merge.py +277 -0
  94. package/skills/sk:setup-optimizer/lib/sidecar.py +129 -0
  95. package/skills/sk:setup-optimizer/optimize_claude.py +174 -0
  96. package/skills/sk:setup-optimizer/templates/CLAUDE.md.template +105 -0
  97. package/skills/sk:skill-creator/LICENSE.txt +202 -0
  98. package/skills/sk:skill-creator/SKILL.md +479 -0
  99. package/skills/sk:skill-creator/agents/analyzer.md +274 -0
  100. package/skills/sk:skill-creator/agents/comparator.md +202 -0
  101. package/skills/sk:skill-creator/agents/grader.md +223 -0
  102. package/skills/sk:skill-creator/assets/eval_review.html +146 -0
  103. package/skills/sk:skill-creator/eval-viewer/generate_review.py +471 -0
  104. package/skills/sk:skill-creator/eval-viewer/viewer.html +1325 -0
  105. package/skills/sk:skill-creator/references/schemas.md +430 -0
  106. package/skills/sk:skill-creator/scripts/aggregate_benchmark.py +401 -0
  107. package/skills/sk:skill-creator/scripts/generate_report.py +326 -0
  108. package/skills/sk:skill-creator/scripts/improve_description.py +248 -0
  109. package/skills/sk:skill-creator/scripts/package_skill.py +136 -0
  110. package/skills/sk:skill-creator/scripts/quick_validate.py +103 -0
  111. package/skills/sk:skill-creator/scripts/run_eval.py +310 -0
  112. package/skills/sk:skill-creator/scripts/run_loop.py +332 -0
  113. package/skills/sk:skill-creator/scripts/utils.py +47 -0
  114. package/skills/sk:smart-commit/SKILL.md +175 -0
  115. package/skills/sk:test/SKILL.md +171 -0
  116. package/skills/sk:write-tests/SKILL.md +195 -0
  117. package/skills/sk:write-tests/references/patterns.md +209 -0
@@ -0,0 +1,367 @@
1
+ # /schema-migrate — Laravel + Eloquent Analysis (Phases 2–5)
2
+
3
+ > This file is loaded by `SKILL.md` when Laravel ORM is detected.
4
+ > Execute Phase 2 through Phase 5 below, then return the final report.
5
+
6
+ ---
7
+
8
+ ## Phase 2: Classify Changes
9
+
10
+ ### Files to Scan (read in parallel)
11
+
12
+ 1. **`composer.json`** — framework and package versions
13
+ - Confirm `laravel/framework` version
14
+ - Check for `doctrine/dbal` (required for column renames on MySQL < 8.0)
15
+
16
+ 2. **`.env`** — environment config
17
+ - Extract `DB_CONNECTION`: `mysql` | `pgsql` | `sqlite`
18
+ - Extract `DB_HOST`, `DB_DATABASE` for context
19
+
20
+ 3. **`config/database.php`** — database configuration
21
+ - Fallback if `.env` unreadable
22
+ - Read `default` connection key
23
+
24
+ 4. **`database/migrations/*.php`** — migration files
25
+ - List all files sorted by timestamp
26
+ - Read the most recent migration(s) for pending changes
27
+
28
+ 5. **`app/Models/`** — Eloquent model files
29
+ - Check `$table`, `$casts`, `$fillable`, `$guarded` properties
30
+ - Identify models affected by pending migration changes
31
+
32
+ 6. **`git diff HEAD -- database/migrations/`** — uncommitted migration changes
33
+
34
+ 7. **`git log --oneline -5 -- database/migrations/`** — recent migration commit history
35
+
36
+ ### Dialect Detection
37
+
38
+ From `.env` `DB_CONNECTION` or `config/database.php`:
39
+
40
+ | Value | Dialect |
41
+ |-------|---------|
42
+ | `mysql` | MySQL |
43
+ | `pgsql` | PostgreSQL |
44
+ | `sqlite` | SQLite |
45
+ | `sqlsrv` | SQL Server |
46
+
47
+ Default if undetectable: MySQL
48
+
49
+ ### Risk Matrix
50
+
51
+ | Change | Risk | Notes |
52
+ |--------|------|-------|
53
+ | Add new table (`Schema::create`) | 🟢 Safe | Additive — no existing data affected |
54
+ | Add nullable column (`->nullable()`) | 🟢 Safe | Standard additive change |
55
+ | Add index (`->index()`) | 🟢 Safe | Non-blocking for most engines |
56
+ | Add column with default (`->default(value)`) | 🟡 Careful | Existing rows get default value — verify acceptability |
57
+ | Add unique index (`->unique()`) | 🟡 Careful | Fails if duplicate values exist |
58
+ | Add FK constraint | 🟡 Careful | Orphan row check required; MySQL online DDL |
59
+ | Add NOT NULL column without default | 🔴 Breaking | Existing rows have no value → migration fails |
60
+ | Change column type (`->change()`) | 🔴 Breaking | MySQL online DDL; SQLite: table recreation required |
61
+ | Drop column (`->dropColumn()`) | 🔴 Breaking | Check model `$casts`, `$fillable`, queries |
62
+ | Drop table (`Schema::drop`) | 🔴 Breaking | Check all model references and FK constraints |
63
+ | Rename column (`->renameColumn()`) | 🔴 Breaking | Requires `doctrine/dbal` on MySQL < 8.0 |
64
+ | Rename table (`Schema::rename`) | 🟡 Careful | Update model `$table` property and any hardcoded references |
65
+
66
+ ### Also Detect
67
+
68
+ - ⚠️ **Missing `down()` method**: Migration has empty `down()` — rollback silently does nothing
69
+ - ⚠️ **Missing `Schema::disableForeignKeyConstraints()`**: MySQL drops with FK constraints will fail without this wrapper
70
+ - ⚠️ **SQLite ALTER TABLE limitations**: SQLite does not support most column modifications — requires table recreation
71
+ - ⚠️ **Missing `doctrine/dbal`**: `renameColumn()` / `change()` on MySQL < 8.0 requires this package
72
+
73
+ ---
74
+
75
+ ## Phase 3: Present Risk Report
76
+
77
+ ### Report Format
78
+
79
+ ```
80
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
81
+ /schema-migrate — Schema Change Analysis
82
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
83
+
84
+ ORM: Laravel + Eloquent
85
+ Dialect: MySQL 8.0+
86
+ Workflow: php artisan migrate (versioned migrations)
87
+ Migrations dir: database/migrations/
88
+ Last migration: 2025_02_28_120000_add_applied_notes_to_jobs_table
89
+
90
+ Status:
91
+ 📁 Migration files: COMMITTED
92
+ 📝 Pending: 1 uncommitted migration
93
+ 🔧 doctrine/dbal: INSTALLED ✅
94
+
95
+ Detected Changes (since last commit):
96
+ ──────────────────────────────────────────
97
+
98
+ 🟢 SAFE (1 change)
99
+ • jobs: Added nullable column `applied_notes` (text, nullable)
100
+
101
+ 🟡 CAREFUL (1 change — review before migrating)
102
+ • profile: Added column `email` (string, NOT NULL, default: '')
103
+ ↳ All existing rows will get empty string value
104
+ ↳ Is '' an acceptable default? Consider nullable first.
105
+
106
+ 🔴 BREAKING (1 change — stop and read migration plan)
107
+ • jobs: Column `job_type` changed from string → integer
108
+ ↳ MySQL online DDL will attempt MODIFY COLUMN
109
+ ↳ Review for silent truncation or cast failures
110
+ ↳ Test with --pretend first
111
+
112
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
113
+ ```
114
+
115
+ ### Dialect-Specific Notes
116
+
117
+ #### MySQL
118
+ - ✅ Online DDL available in MySQL 8.0+ (ALGORITHM=INPLACE for many operations)
119
+ - ⚠️ `renameColumn()` and `change()` require `doctrine/dbal` on MySQL < 8.0
120
+ - ⚠️ FK drops require `Schema::disableForeignKeyConstraints()` wrapper
121
+ - ⚠️ Strict mode warnings: large table defaults may trigger metadata lock
122
+
123
+ #### PostgreSQL
124
+ - ✅ Full ALTER TABLE support — most changes are online
125
+ - ✅ Column type changes generally safe with implicit casts
126
+ - ⚠️ Long-running ALTER may briefly lock large tables
127
+
128
+ #### SQLite
129
+ - 🚨 Cannot rename columns or change column types directly
130
+ - 🚨 Must recreate table via raw SQL in migration (see Scenario below)
131
+ - ✅ All other additive changes work normally
132
+
133
+ ---
134
+
135
+ ## Phase 4: Per-Change Migration Plans
136
+
137
+ ### Scenario: Add NOT NULL Column Without Default
138
+
139
+ ```
140
+ Problem: Existing rows have no value for the new column → migration fails.
141
+
142
+ Safe path (nullable-first deploy):
143
+ Step 1: Create migration with nullable column
144
+ $table->string('email')->nullable();
145
+ php artisan migrate
146
+
147
+ Step 2: Backfill existing rows
148
+ DB::table('users')->whereNull('email')->update(['email' => '']);
149
+ # Or use a separate data migration
150
+
151
+ Step 3: Create second migration to add NOT NULL constraint
152
+ $table->string('email')->nullable(false)->change();
153
+ php artisan migrate
154
+
155
+ Alternative (with default — single migration):
156
+ $table->string('email')->default('');
157
+ php artisan migrate
158
+ ⚠️ All existing rows get '' — verify this is acceptable
159
+ ```
160
+
161
+ ---
162
+
163
+ ### Scenario: Rename Column
164
+
165
+ ```
166
+ Check doctrine/dbal requirement:
167
+ MySQL < 8.0: composer require doctrine/dbal --dev
168
+ MySQL 8.0+: Native rename support (no doctrine/dbal needed)
169
+ PostgreSQL: Native rename support
170
+ SQLite: Not supported — requires table recreation (see below)
171
+
172
+ Migration:
173
+ $table->renameColumn('old_name', 'new_name');
174
+
175
+ After migrating:
176
+ ✅ Update model $casts, $fillable, $guarded arrays
177
+ ✅ Search codebase for 'old_name' string references
178
+ ✅ Update any API resources / form requests referencing the old name
179
+
180
+ Zero-downtime rename (for production with live traffic):
181
+ Step 1: Add new column (nullable): $table->string('new_name')->nullable();
182
+ Step 2: Deploy code that writes to both old_name AND new_name
183
+ Step 3: Backfill: UPDATE table SET new_name = old_name WHERE new_name IS NULL;
184
+ Step 4: Deploy code that reads from new_name only
185
+ Step 5: Remove old_name column in final migration
186
+ ```
187
+
188
+ ---
189
+
190
+ ### Scenario: SQLite Destructive Change (Column Type / Rename)
191
+
192
+ ```
193
+ SQLite does not support ALTER COLUMN — must recreate the table.
194
+
195
+ Migration template using raw SQL:
196
+ public function up(): void
197
+ {
198
+ // 1. Create new table with desired schema
199
+ DB::statement('CREATE TABLE users_new (
200
+ id INTEGER PRIMARY KEY,
201
+ name TEXT NOT NULL,
202
+ new_column INTEGER NOT NULL DEFAULT 0, -- changed type
203
+ created_at DATETIME,
204
+ updated_at DATETIME
205
+ )');
206
+
207
+ // 2. Copy data from old table
208
+ DB::statement('INSERT INTO users_new (id, name, new_column, created_at, updated_at)
209
+ SELECT id, name, CAST(old_column AS INTEGER), created_at, updated_at
210
+ FROM users');
211
+
212
+ // 3. Drop old table
213
+ Schema::drop('users');
214
+
215
+ // 4. Rename new table
216
+ DB::statement('ALTER TABLE users_new RENAME TO users');
217
+ }
218
+
219
+ public function down(): void
220
+ {
221
+ // Reverse the process with original schema
222
+ }
223
+ ```
224
+
225
+ ---
226
+
227
+ ### Scenario: Missing `down()` Method
228
+
229
+ ```
230
+ Problem: Laravel's rollback calls down() — if it's empty, rollback silently does nothing.
231
+
232
+ Detection: Check if down() is empty (just {}) or missing.
233
+
234
+ Template for correct down() methods:
235
+
236
+ // For: $table->string('new_column')
237
+ // Down should be:
238
+ public function down(): void
239
+ {
240
+ Schema::table('users', function (Blueprint $table) {
241
+ $table->dropColumn('new_column');
242
+ });
243
+ }
244
+
245
+ // For: Schema::create('new_table', ...)
246
+ // Down should be:
247
+ public function down(): void
248
+ {
249
+ Schema::dropIfExists('new_table');
250
+ }
251
+
252
+ // For: $table->renameColumn('old', 'new')
253
+ // Down should be:
254
+ public function down(): void
255
+ {
256
+ Schema::table('users', function (Blueprint $table) {
257
+ $table->renameColumn('new', 'old');
258
+ });
259
+ }
260
+ ```
261
+
262
+ ---
263
+
264
+ ### Scenario: FK Constraint Ordering Issue
265
+
266
+ ```
267
+ Detection: A migration creates a FK reference to a table that is created
268
+ in a LATER migration file (by timestamp).
269
+
270
+ Example:
271
+ 2025_01_01_000000_create_posts_table.php → references users.id
272
+ 2025_01_01_000001_create_users_table.php → creates users table
273
+
274
+ This will fail because posts FK references users before users exists.
275
+
276
+ Fix options:
277
+ Option A: Rename migration files to fix timestamp ordering
278
+ - Change 2025_01_01_000000_create_posts_table.php to a later timestamp
279
+
280
+ Option B: Split FK creation into separate migration
281
+ - Create posts table without FK first
282
+ - Add FK in a third migration after users table migration
283
+
284
+ Option C: Add FK in the users migration
285
+ - After creating users table, add FK to posts in same migration file
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Phase 5: Command Recommendations
291
+
292
+ ### Core Commands
293
+
294
+ ```bash
295
+ # Check migration status
296
+ php artisan migrate:status
297
+
298
+ # Run pending migrations
299
+ php artisan migrate
300
+
301
+ # Preview SQL without executing (dry run)
302
+ php artisan migrate --pretend
303
+
304
+ # Rollback last batch of migrations
305
+ php artisan migrate:rollback --step=1
306
+
307
+ # Roll back a specific migration
308
+ php artisan migrate:rollback --step=1
309
+
310
+ # Roll back to specific migration version
311
+ php artisan migrate:down --path=database/migrations/[filename].php
312
+
313
+ # Check current migration version
314
+ php artisan migrate:status
315
+
316
+ # Create a new migration file
317
+ php artisan make:migration [describe_change] --table=[table_name]
318
+ php artisan make:migration create_[table_name]_table
319
+
320
+ # Reset all migrations and re-run (dev only — DESTRUCTIVE)
321
+ php artisan migrate:fresh
322
+ php artisan migrate:fresh --seed # with seeders
323
+ ```
324
+
325
+ ### Workflow: Development
326
+
327
+ ```bash
328
+ # 1. Review pending migrations
329
+ /schema-migrate
330
+
331
+ # 2. Preview SQL (dry run)
332
+ php artisan migrate --pretend
333
+
334
+ # 3. If SQL looks correct, apply
335
+ php artisan migrate
336
+
337
+ # 4. Verify status
338
+ php artisan migrate:status
339
+
340
+ # 5. Commit
341
+ git add database/migrations/
342
+ git commit -m "feat(schema): [describe change]"
343
+ ```
344
+
345
+ ### Workflow: MySQL — Column Changes
346
+
347
+ ```bash
348
+ # Check doctrine/dbal for rename/change operations
349
+ composer show doctrine/dbal # must be installed for MySQL < 8.0
350
+
351
+ # Preview change
352
+ php artisan migrate --pretend
353
+
354
+ # Apply
355
+ php artisan migrate
356
+ ```
357
+
358
+ ### Workflow: SQLite — Destructive Changes
359
+
360
+ ```bash
361
+ # SQLite: always use raw SQL for column type changes or renames
362
+ # See Scenario: SQLite Destructive Change above
363
+
364
+ # After writing raw SQL migration:
365
+ php artisan migrate --pretend # verify SQL output
366
+ php artisan migrate # apply
367
+ ```