autoworkflow 3.1.5 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.claude/commands/analyze.md +19 -0
  2. package/.claude/commands/audit.md +26 -0
  3. package/.claude/commands/build.md +39 -0
  4. package/.claude/commands/commit.md +25 -0
  5. package/.claude/commands/fix.md +23 -0
  6. package/.claude/commands/plan.md +18 -0
  7. package/.claude/commands/suggest.md +23 -0
  8. package/.claude/commands/verify.md +18 -0
  9. package/.claude/hooks/post-bash-router.sh +20 -0
  10. package/.claude/hooks/post-commit.sh +140 -0
  11. package/.claude/hooks/post-edit.sh +190 -17
  12. package/.claude/hooks/pre-edit.sh +221 -0
  13. package/.claude/hooks/session-check.sh +90 -0
  14. package/.claude/settings.json +56 -6
  15. package/.claude/settings.local.json +5 -1
  16. package/.claude/skills/actix.md +337 -0
  17. package/.claude/skills/alembic.md +504 -0
  18. package/.claude/skills/angular.md +237 -0
  19. package/.claude/skills/api-design.md +187 -0
  20. package/.claude/skills/aspnet-core.md +377 -0
  21. package/.claude/skills/astro.md +245 -0
  22. package/.claude/skills/auth-clerk.md +327 -0
  23. package/.claude/skills/auth-firebase.md +367 -0
  24. package/.claude/skills/auth-nextauth.md +359 -0
  25. package/.claude/skills/auth-supabase.md +368 -0
  26. package/.claude/skills/axum.md +386 -0
  27. package/.claude/skills/blazor.md +456 -0
  28. package/.claude/skills/chi.md +348 -0
  29. package/.claude/skills/code-review.md +133 -0
  30. package/.claude/skills/csharp.md +296 -0
  31. package/.claude/skills/css-modules.md +325 -0
  32. package/.claude/skills/cypress.md +343 -0
  33. package/.claude/skills/debugging.md +133 -0
  34. package/.claude/skills/diesel.md +392 -0
  35. package/.claude/skills/django.md +301 -0
  36. package/.claude/skills/docker.md +319 -0
  37. package/.claude/skills/doctrine.md +473 -0
  38. package/.claude/skills/documentation.md +182 -0
  39. package/.claude/skills/dotnet.md +409 -0
  40. package/.claude/skills/drizzle.md +293 -0
  41. package/.claude/skills/echo.md +321 -0
  42. package/.claude/skills/eloquent.md +256 -0
  43. package/.claude/skills/emotion.md +426 -0
  44. package/.claude/skills/entity-framework.md +370 -0
  45. package/.claude/skills/express.md +316 -0
  46. package/.claude/skills/fastapi.md +329 -0
  47. package/.claude/skills/fastify.md +299 -0
  48. package/.claude/skills/fiber.md +315 -0
  49. package/.claude/skills/flask.md +322 -0
  50. package/.claude/skills/gin.md +342 -0
  51. package/.claude/skills/git.md +116 -0
  52. package/.claude/skills/github-actions.md +353 -0
  53. package/.claude/skills/go.md +377 -0
  54. package/.claude/skills/gorm.md +409 -0
  55. package/.claude/skills/graphql.md +478 -0
  56. package/.claude/skills/hibernate.md +379 -0
  57. package/.claude/skills/hono.md +306 -0
  58. package/.claude/skills/java.md +400 -0
  59. package/.claude/skills/jest.md +313 -0
  60. package/.claude/skills/jpa.md +282 -0
  61. package/.claude/skills/kotlin.md +347 -0
  62. package/.claude/skills/kubernetes.md +363 -0
  63. package/.claude/skills/laravel.md +414 -0
  64. package/.claude/skills/mcp-browser.md +320 -0
  65. package/.claude/skills/mcp-database.md +219 -0
  66. package/.claude/skills/mcp-fetch.md +241 -0
  67. package/.claude/skills/mcp-filesystem.md +204 -0
  68. package/.claude/skills/mcp-github.md +217 -0
  69. package/.claude/skills/mcp-memory.md +240 -0
  70. package/.claude/skills/mcp-search.md +218 -0
  71. package/.claude/skills/mcp-slack.md +262 -0
  72. package/.claude/skills/micronaut.md +388 -0
  73. package/.claude/skills/mongodb.md +319 -0
  74. package/.claude/skills/mongoose.md +355 -0
  75. package/.claude/skills/mysql.md +281 -0
  76. package/.claude/skills/nestjs.md +335 -0
  77. package/.claude/skills/nextjs-app-router.md +260 -0
  78. package/.claude/skills/nextjs-pages.md +172 -0
  79. package/.claude/skills/nuxt.md +202 -0
  80. package/.claude/skills/openapi.md +489 -0
  81. package/.claude/skills/performance.md +199 -0
  82. package/.claude/skills/php.md +398 -0
  83. package/.claude/skills/playwright.md +371 -0
  84. package/.claude/skills/postgresql.md +257 -0
  85. package/.claude/skills/prisma.md +293 -0
  86. package/.claude/skills/pydantic.md +304 -0
  87. package/.claude/skills/pytest.md +313 -0
  88. package/.claude/skills/python.md +272 -0
  89. package/.claude/skills/quarkus.md +377 -0
  90. package/.claude/skills/react.md +230 -0
  91. package/.claude/skills/redis.md +391 -0
  92. package/.claude/skills/refactoring.md +143 -0
  93. package/.claude/skills/remix.md +246 -0
  94. package/.claude/skills/rest-api.md +490 -0
  95. package/.claude/skills/rocket.md +366 -0
  96. package/.claude/skills/rust.md +341 -0
  97. package/.claude/skills/sass.md +380 -0
  98. package/.claude/skills/sea-orm.md +382 -0
  99. package/.claude/skills/security.md +167 -0
  100. package/.claude/skills/sequelize.md +395 -0
  101. package/.claude/skills/spring-boot.md +416 -0
  102. package/.claude/skills/sqlalchemy.md +269 -0
  103. package/.claude/skills/sqlx-rust.md +408 -0
  104. package/.claude/skills/state-jotai.md +346 -0
  105. package/.claude/skills/state-mobx.md +353 -0
  106. package/.claude/skills/state-pinia.md +431 -0
  107. package/.claude/skills/state-redux.md +337 -0
  108. package/.claude/skills/state-tanstack-query.md +434 -0
  109. package/.claude/skills/state-zustand.md +340 -0
  110. package/.claude/skills/styled-components.md +403 -0
  111. package/.claude/skills/svelte.md +238 -0
  112. package/.claude/skills/sveltekit.md +207 -0
  113. package/.claude/skills/symfony.md +437 -0
  114. package/.claude/skills/tailwind.md +279 -0
  115. package/.claude/skills/terraform.md +394 -0
  116. package/.claude/skills/testing-library.md +371 -0
  117. package/.claude/skills/trpc.md +426 -0
  118. package/.claude/skills/typeorm.md +368 -0
  119. package/.claude/skills/vitest.md +330 -0
  120. package/.claude/skills/vue.md +202 -0
  121. package/.claude/skills/warp.md +365 -0
  122. package/README.md +163 -52
  123. package/package.json +1 -1
  124. package/system/triggers.md +256 -17
@@ -0,0 +1,504 @@
1
+ # Alembic Skill
2
+
3
+ ## Initial Setup
4
+ \`\`\`bash
5
+ # Initialize Alembic in project
6
+ alembic init alembic
7
+
8
+ # Or for async SQLAlchemy
9
+ alembic init -t async alembic
10
+ \`\`\`
11
+
12
+ ## Project Structure
13
+ \`\`\`
14
+ project/
15
+ ├── alembic/
16
+ │ ├── versions/ # Migration files
17
+ │ ├── env.py # Migration environment
18
+ │ ├── script.py.mako # Migration template
19
+ │ └── README
20
+ ├── alembic.ini # Alembic config
21
+ └── app/
22
+ └── models.py # SQLAlchemy models
23
+ \`\`\`
24
+
25
+ ## alembic.ini Configuration
26
+ \`\`\`ini
27
+ [alembic]
28
+ script_location = alembic
29
+ prepend_sys_path = .
30
+ version_path_separator = os
31
+
32
+ # Use environment variable for database URL (don't commit credentials!)
33
+ sqlalchemy.url = driver://user:pass@localhost/dbname
34
+
35
+ [post_write_hooks]
36
+ hooks = black
37
+ black.type = console_scripts
38
+ black.entrypoint = black
39
+ black.options = -q
40
+
41
+ [loggers]
42
+ keys = root,sqlalchemy,alembic
43
+
44
+ [logger_alembic]
45
+ level = INFO
46
+ handlers =
47
+ qualname = alembic
48
+ \`\`\`
49
+
50
+ ## env.py - Standard Configuration
51
+ \`\`\`python
52
+ # alembic/env.py
53
+ import os
54
+ from logging.config import fileConfig
55
+ from sqlalchemy import engine_from_config, pool
56
+ from alembic import context
57
+
58
+ # Import your models' Base
59
+ from app.models import Base
60
+
61
+ config = context.config
62
+
63
+ # Override sqlalchemy.url from environment variable
64
+ config.set_main_option(
65
+ "sqlalchemy.url",
66
+ os.environ.get("DATABASE_URL", "postgresql://localhost/mydb")
67
+ )
68
+
69
+ if config.config_file_name is not None:
70
+ fileConfig(config.config_file_name)
71
+
72
+ target_metadata = Base.metadata
73
+
74
+
75
+ def run_migrations_offline() -> None:
76
+ """Run migrations in 'offline' mode (SQL script generation)."""
77
+ url = config.get_main_option("sqlalchemy.url")
78
+ context.configure(
79
+ url=url,
80
+ target_metadata=target_metadata,
81
+ literal_binds=True,
82
+ dialect_opts={"paramstyle": "named"},
83
+ )
84
+
85
+ with context.begin_transaction():
86
+ context.run_migrations()
87
+
88
+
89
+ def run_migrations_online() -> None:
90
+ """Run migrations in 'online' mode (direct database connection)."""
91
+ connectable = engine_from_config(
92
+ config.get_section(config.config_ini_section, {}),
93
+ prefix="sqlalchemy.",
94
+ poolclass=pool.NullPool,
95
+ )
96
+
97
+ with connectable.connect() as connection:
98
+ context.configure(
99
+ connection=connection,
100
+ target_metadata=target_metadata,
101
+ )
102
+
103
+ with context.begin_transaction():
104
+ context.run_migrations()
105
+
106
+
107
+ if context.is_offline_mode():
108
+ run_migrations_offline()
109
+ else:
110
+ run_migrations_online()
111
+ \`\`\`
112
+
113
+ ## env.py - Async Configuration
114
+ \`\`\`python
115
+ # alembic/env.py (async version)
116
+ import asyncio
117
+ import os
118
+ from logging.config import fileConfig
119
+ from sqlalchemy import pool
120
+ from sqlalchemy.ext.asyncio import async_engine_from_config
121
+ from alembic import context
122
+
123
+ from app.models import Base
124
+
125
+ config = context.config
126
+ config.set_main_option(
127
+ "sqlalchemy.url",
128
+ os.environ.get("DATABASE_URL", "postgresql+asyncpg://localhost/mydb")
129
+ )
130
+
131
+ if config.config_file_name is not None:
132
+ fileConfig(config.config_file_name)
133
+
134
+ target_metadata = Base.metadata
135
+
136
+
137
+ def run_migrations_offline() -> None:
138
+ url = config.get_main_option("sqlalchemy.url")
139
+ context.configure(
140
+ url=url,
141
+ target_metadata=target_metadata,
142
+ literal_binds=True,
143
+ dialect_opts={"paramstyle": "named"},
144
+ )
145
+
146
+ with context.begin_transaction():
147
+ context.run_migrations()
148
+
149
+
150
+ def do_run_migrations(connection):
151
+ context.configure(connection=connection, target_metadata=target_metadata)
152
+ with context.begin_transaction():
153
+ context.run_migrations()
154
+
155
+
156
+ async def run_async_migrations() -> None:
157
+ connectable = async_engine_from_config(
158
+ config.get_section(config.config_ini_section, {}),
159
+ prefix="sqlalchemy.",
160
+ poolclass=pool.NullPool,
161
+ )
162
+
163
+ async with connectable.connect() as connection:
164
+ await connection.run_sync(do_run_migrations)
165
+
166
+ await connectable.dispose()
167
+
168
+
169
+ def run_migrations_online() -> None:
170
+ asyncio.run(run_async_migrations())
171
+
172
+
173
+ if context.is_offline_mode():
174
+ run_migrations_offline()
175
+ else:
176
+ run_migrations_online()
177
+ \`\`\`
178
+
179
+ ## Common Migration Commands
180
+ \`\`\`bash
181
+ # Create auto-generated migration
182
+ alembic revision --autogenerate -m "Add users table"
183
+
184
+ # Create empty migration (for data migrations)
185
+ alembic revision -m "Populate default categories"
186
+
187
+ # Apply all pending migrations
188
+ alembic upgrade head
189
+
190
+ # Apply specific number of migrations
191
+ alembic upgrade +2
192
+
193
+ # Rollback one migration
194
+ alembic downgrade -1
195
+
196
+ # Rollback to specific revision
197
+ alembic downgrade abc123
198
+
199
+ # Rollback all migrations
200
+ alembic downgrade base
201
+
202
+ # Show current revision
203
+ alembic current
204
+
205
+ # Show migration history
206
+ alembic history --verbose
207
+
208
+ # Show pending migrations
209
+ alembic history -r current:head
210
+
211
+ # Generate SQL instead of applying
212
+ alembic upgrade head --sql > migration.sql
213
+ \`\`\`
214
+
215
+ ## Schema Migration Example
216
+ \`\`\`python
217
+ """Add users table
218
+
219
+ Revision ID: abc123
220
+ Revises:
221
+ Create Date: 2024-01-15 10:00:00.000000
222
+ """
223
+ from typing import Sequence, Union
224
+ from alembic import op
225
+ import sqlalchemy as sa
226
+
227
+ revision: str = 'abc123'
228
+ down_revision: Union[str, None] = None
229
+ branch_labels: Union[str, Sequence[str], None] = None
230
+ depends_on: Union[str, Sequence[str], None] = None
231
+
232
+
233
+ def upgrade() -> None:
234
+ op.create_table(
235
+ 'users',
236
+ sa.Column('id', sa.Integer(), primary_key=True),
237
+ sa.Column('email', sa.String(255), nullable=False, unique=True),
238
+ sa.Column('password_hash', sa.String(255), nullable=False),
239
+ sa.Column('is_active', sa.Boolean(), server_default='true'),
240
+ sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
241
+ )
242
+ op.create_index('ix_users_email', 'users', ['email'])
243
+
244
+
245
+ def downgrade() -> None:
246
+ op.drop_index('ix_users_email', table_name='users')
247
+ op.drop_table('users')
248
+ \`\`\`
249
+
250
+ ## Data Migration Example
251
+ \`\`\`python
252
+ """Populate default categories
253
+
254
+ Revision ID: def456
255
+ Revises: abc123
256
+ Create Date: 2024-01-16 10:00:00.000000
257
+ """
258
+ from alembic import op
259
+ import sqlalchemy as sa
260
+
261
+ revision: str = 'def456'
262
+ down_revision: str = 'abc123'
263
+
264
+ # Define table for data operations
265
+ categories = sa.table(
266
+ 'categories',
267
+ sa.column('id', sa.Integer),
268
+ sa.column('name', sa.String),
269
+ sa.column('slug', sa.String),
270
+ )
271
+
272
+
273
+ def upgrade() -> None:
274
+ # Bulk insert default data
275
+ op.bulk_insert(
276
+ categories,
277
+ [
278
+ {'id': 1, 'name': 'Technology', 'slug': 'technology'},
279
+ {'id': 2, 'name': 'Business', 'slug': 'business'},
280
+ {'id': 3, 'name': 'Science', 'slug': 'science'},
281
+ ]
282
+ )
283
+
284
+
285
+ def downgrade() -> None:
286
+ op.execute(categories.delete().where(categories.c.id.in_([1, 2, 3])))
287
+ \`\`\`
288
+
289
+ ## Complex Data Migration with Queries
290
+ \`\`\`python
291
+ """Migrate user roles to new format
292
+
293
+ Revision ID: ghi789
294
+ Revises: def456
295
+ """
296
+ from alembic import op
297
+ import sqlalchemy as sa
298
+ from sqlalchemy.orm import Session
299
+
300
+ revision: str = 'ghi789'
301
+ down_revision: str = 'def456'
302
+
303
+ # Old and new tables
304
+ old_user_roles = sa.table(
305
+ 'user_roles',
306
+ sa.column('user_id', sa.Integer),
307
+ sa.column('role', sa.String),
308
+ )
309
+
310
+ new_roles = sa.table(
311
+ 'roles',
312
+ sa.column('id', sa.Integer),
313
+ sa.column('name', sa.String),
314
+ )
315
+
316
+ user_role_assignments = sa.table(
317
+ 'user_role_assignments',
318
+ sa.column('user_id', sa.Integer),
319
+ sa.column('role_id', sa.Integer),
320
+ )
321
+
322
+
323
+ def upgrade() -> None:
324
+ bind = op.get_bind()
325
+ session = Session(bind=bind)
326
+
327
+ # Create new roles table
328
+ op.create_table(
329
+ 'roles',
330
+ sa.Column('id', sa.Integer(), primary_key=True),
331
+ sa.Column('name', sa.String(50), unique=True),
332
+ )
333
+
334
+ # Create junction table
335
+ op.create_table(
336
+ 'user_role_assignments',
337
+ sa.Column('user_id', sa.Integer(), sa.ForeignKey('users.id')),
338
+ sa.Column('role_id', sa.Integer(), sa.ForeignKey('roles.id')),
339
+ )
340
+
341
+ # Migrate data
342
+ unique_roles = session.execute(
343
+ sa.select(old_user_roles.c.role).distinct()
344
+ ).fetchall()
345
+
346
+ role_mapping = {}
347
+ for i, (role_name,) in enumerate(unique_roles, 1):
348
+ session.execute(new_roles.insert().values(id=i, name=role_name))
349
+ role_mapping[role_name] = i
350
+
351
+ # Migrate assignments
352
+ old_assignments = session.execute(sa.select(old_user_roles)).fetchall()
353
+ for user_id, role_name in old_assignments:
354
+ session.execute(
355
+ user_role_assignments.insert().values(
356
+ user_id=user_id,
357
+ role_id=role_mapping[role_name]
358
+ )
359
+ )
360
+
361
+ # Drop old column
362
+ op.drop_table('user_roles')
363
+
364
+
365
+ def downgrade() -> None:
366
+ # Reverse migration logic
367
+ pass
368
+ \`\`\`
369
+
370
+ ## Batch Operations (SQLite Compatible)
371
+ \`\`\`python
372
+ """Add new columns with batch mode for SQLite
373
+
374
+ Revision ID: jkl012
375
+ Revises: ghi789
376
+ """
377
+ from alembic import op
378
+ import sqlalchemy as sa
379
+
380
+ revision: str = 'jkl012'
381
+ down_revision: str = 'ghi789'
382
+
383
+
384
+ def upgrade() -> None:
385
+ # SQLite doesn't support ALTER TABLE well, use batch mode
386
+ with op.batch_alter_table('users') as batch_op:
387
+ batch_op.add_column(sa.Column('phone', sa.String(20)))
388
+ batch_op.add_column(sa.Column('verified', sa.Boolean(), server_default='false'))
389
+ batch_op.alter_column('email', nullable=False)
390
+ batch_op.create_index('ix_users_phone', ['phone'])
391
+
392
+
393
+ def downgrade() -> None:
394
+ with op.batch_alter_table('users') as batch_op:
395
+ batch_op.drop_index('ix_users_phone')
396
+ batch_op.drop_column('verified')
397
+ batch_op.drop_column('phone')
398
+ \`\`\`
399
+
400
+ ## Testing Migrations
401
+ \`\`\`python
402
+ # tests/test_migrations.py
403
+ import pytest
404
+ from alembic import command
405
+ from alembic.config import Config
406
+ from sqlalchemy import create_engine, inspect
407
+
408
+ @pytest.fixture
409
+ def alembic_config():
410
+ config = Config("alembic.ini")
411
+ config.set_main_option("sqlalchemy.url", "sqlite:///:memory:")
412
+ return config
413
+
414
+ @pytest.fixture
415
+ def engine():
416
+ return create_engine("sqlite:///:memory:")
417
+
418
+
419
+ def test_migrations_upgrade_downgrade(alembic_config, engine):
420
+ """Test that all migrations can be applied and rolled back."""
421
+ # Run all upgrades
422
+ with engine.begin() as connection:
423
+ alembic_config.attributes['connection'] = connection
424
+ command.upgrade(alembic_config, "head")
425
+
426
+ # Verify final state
427
+ inspector = inspect(engine)
428
+ tables = inspector.get_table_names()
429
+ assert 'users' in tables
430
+ assert 'alembic_version' in tables
431
+
432
+ # Run all downgrades
433
+ command.downgrade(alembic_config, "base")
434
+
435
+ # Verify clean state
436
+ inspector = inspect(engine)
437
+ tables = inspector.get_table_names()
438
+ assert 'users' not in tables
439
+
440
+
441
+ def test_migration_data_integrity(alembic_config, engine):
442
+ """Test data migrations preserve integrity."""
443
+ with engine.begin() as connection:
444
+ alembic_config.attributes['connection'] = connection
445
+
446
+ # Apply migrations up to data migration
447
+ command.upgrade(alembic_config, "def456")
448
+
449
+ # Verify data was inserted
450
+ result = connection.execute(sa.text("SELECT COUNT(*) FROM categories"))
451
+ assert result.scalar() == 3
452
+ \`\`\`
453
+
454
+ ## Multi-Database Support
455
+ \`\`\`python
456
+ # alembic/env.py with multiple databases
457
+ from alembic import context
458
+ import os
459
+
460
+ def get_url_for_db(db_name: str) -> str:
461
+ urls = {
462
+ 'primary': os.environ.get('PRIMARY_DB_URL'),
463
+ 'analytics': os.environ.get('ANALYTICS_DB_URL'),
464
+ }
465
+ return urls.get(db_name)
466
+
467
+
468
+ def run_migrations_online() -> None:
469
+ db_name = context.get_x_argument(as_dictionary=True).get('db', 'primary')
470
+ url = get_url_for_db(db_name)
471
+
472
+ # Use appropriate metadata based on database
473
+ if db_name == 'analytics':
474
+ from app.models.analytics import Base as AnalyticsBase
475
+ target_metadata = AnalyticsBase.metadata
476
+ else:
477
+ from app.models import Base
478
+ target_metadata = Base.metadata
479
+
480
+ # ... rest of configuration
481
+ \`\`\`
482
+
483
+ \`\`\`bash
484
+ # Run migrations for specific database
485
+ alembic -x db=primary upgrade head
486
+ alembic -x db=analytics upgrade head
487
+ \`\`\`
488
+
489
+ ## ✅ DO
490
+ - Always review auto-generated migrations before applying
491
+ - Use environment variables for database URLs (never commit credentials)
492
+ - Write both \`upgrade()\` and \`downgrade()\` functions
493
+ - Use \`batch_alter_table\` for SQLite compatibility
494
+ - Test migrations in CI before deploying
495
+ - Use descriptive migration messages
496
+ - Create separate migrations for schema and data changes
497
+ - Back up database before running migrations in production
498
+
499
+ ## ❌ DON'T
500
+ - Don't edit migrations that have already been applied in production
501
+ - Don't use \`autogenerate\` for data migrations
502
+ - Don't commit database credentials in alembic.ini
503
+ - Don't skip downgrade implementations (needed for rollbacks)
504
+ - Don't run untested migrations directly in production