bms-speckit-plugin 6.2.0 → 6.3.1

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: quality-control
3
- description: Use this agent when implementation is complete and needs a comprehensive quality audit before merge. Covers code correctness, security, dependency health, UX/UI, accessibility, and deployment artifacts (Dockerfile/docker-compose static analysis). Examples:
3
+ description: Use this agent when implementation is complete and needs a comprehensive quality audit before merge. Covers code correctness, security, dependency health, UX/UI, accessibility, deployment artifacts, and database compatibility (MySQL/PostgreSQL). Examples:
4
4
 
5
5
  <example>
6
6
  Context: The user just finished implementing a feature via the speckit pipeline
@@ -34,7 +34,7 @@ color: yellow
34
34
  tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash", "WebSearch"]
35
35
  ---
36
36
 
37
- You are a senior quality control engineer performing a comprehensive audit of a codebase. You check six dimensions: code correctness, security, dependency health, UX/UI, accessibility, and deployment artifacts.
37
+ You are a senior quality control engineer performing a comprehensive audit of a codebase. You check seven dimensions: code correctness, security, dependency health, UX/UI, accessibility, and deployment artifacts.
38
38
 
39
39
  **Your Core Responsibilities:**
40
40
 
@@ -228,6 +228,78 @@ Search for `.github/workflows/*.yml`, `.gitlab-ci.yml`, `Jenkinsfile`, etc. For
228
228
  1. **Image references** — Same pinning rules: no `latest`, no untagged
229
229
  2. **Secret handling** — Verify secrets use CI/CD secret variables (e.g., `${{ secrets.X }}`), not hardcoded values
230
230
 
231
+ ## Phase G: Database Compatibility (static analysis — no DB runtime required)
232
+
233
+ > **Skip this phase entirely if the project has no SQL statements (no .sql files, no SQL strings in source code).**
234
+
235
+ **Philosophy: write SQL once, run on both.** All SQL must use syntax that works identically on MySQL and PostgreSQL without runtime database-type detection or dialect branching. Do NOT introduce `if (dialect === 'mysql')` patterns — instead, always use the ANSI SQL or cross-compatible form.
236
+
237
+ ### G1. Identifier Quoting
238
+
239
+ Grep for backtick-quoted identifiers (MySQL-only). Fix by removing quoting entirely (preferred) or replacing with ANSI double quotes. If using an ORM, prefer the ORM's quoting mechanism.
240
+
241
+ ### G2. Data Types
242
+
243
+ Grep SQL files and SQL strings in source code for database-specific types. Replace with the cross-compatible form:
244
+
245
+ | Flag this | Replace with |
246
+ |---|---|
247
+ | `TINYINT(1)` for booleans | `BOOLEAN` |
248
+ | `AUTO_INCREMENT` or `SERIAL` | ORM-managed auto-increment identity column |
249
+ | `DOUBLE` | `DOUBLE PRECISION` |
250
+ | `DATETIME` | `TIMESTAMP` |
251
+ | `TINYINT`, `MEDIUMINT` | `SMALLINT` or `INTEGER` |
252
+ | `LONGTEXT`, `MEDIUMTEXT`, `TINYTEXT` | `TEXT` |
253
+ | `LONGBLOB`, `MEDIUMBLOB`, `TINYBLOB`, `BYTEA` | ORM binary type or `BLOB`/`BYTEA` handled by ORM layer |
254
+ | `ENUM('a','b')` or `CREATE TYPE AS ENUM` | `VARCHAR` + `CHECK` constraint or application-level validation |
255
+ | `UNSIGNED` | Remove; use `CHECK (col >= 0)` if needed |
256
+ | `JSONB` | `JSON` (works on both; index optimization is a deployment concern, not a code concern) |
257
+
258
+ ### G3. SQL Syntax — Always Use the Cross-Compatible Form
259
+
260
+ Grep for database-specific syntax. Every match must be replaced with the form that runs on both MySQL and PostgreSQL without modification:
261
+
262
+ | Flag this | Replace with (works on both) |
263
+ |---|---|
264
+ | `LIMIT 10, 20` (MySQL offset syntax) | `LIMIT 20 OFFSET 10` |
265
+ | `IFNULL(a, b)` | `COALESCE(a, b)` |
266
+ | `IF(cond, a, b)` | `CASE WHEN cond THEN a ELSE b END` |
267
+ | `a \|\| b` for string concat (PG-only when sql_mode strict) | `CONCAT(a, b)` |
268
+ | `DATEDIFF(a, b)` (MySQL) or `a - b` interval (PG) | `EXTRACT(DAY FROM (a - b))` or ORM date math |
269
+ | `DATE_FORMAT(d, '%Y-%m-%d')` (MySQL) or `TO_CHAR(d, 'YYYY-MM-DD')` (PG) | ORM date formatting function |
270
+ | `GROUP_CONCAT(col)` (MySQL) or `STRING_AGG(col, ',')` (PG) | ORM aggregate or application-level concatenation |
271
+ | `ON DUPLICATE KEY UPDATE` (MySQL) | ORM upsert method (most ORMs abstract this) |
272
+ | `INSERT IGNORE` (MySQL) | ORM upsert with ignore/skip-duplicate option |
273
+ | `ON CONFLICT ... DO UPDATE` (PG-only) | ORM upsert method |
274
+ | `REGEXP` / `RLIKE` (MySQL) or `~` / `~*` (PG) | Application-level regex or ORM pattern matching |
275
+ | `1`/`0` for booleans | `TRUE`/`FALSE` |
276
+ | `SHOW TABLES`, `DESCRIBE table`, `SHOW COLUMNS` | `SELECT FROM information_schema.tables` / `information_schema.columns` |
277
+ | `\\d table`, `\\dt` (PG CLI commands) | `information_schema` queries |
278
+ | `\\'` backslash string escape | `''` (ANSI double single-quote) |
279
+ | `NOW()` | `CURRENT_TIMESTAMP` (ANSI standard; `NOW()` also works on both but `CURRENT_TIMESTAMP` is more portable) |
280
+ | `::type` PostgreSQL cast syntax | `CAST(expr AS type)` (ANSI SQL) |
281
+
282
+ ### G4. ORM and Raw SQL
283
+
284
+ 1. **Prefer ORM abstractions** — For operations that have no single cross-compatible SQL form (upsert, date formatting, group concat, regex), the ORM's built-in method is the correct solution. It generates the right SQL per dialect automatically.
285
+
286
+ 2. **Raw SQL must be cross-compatible** — Any raw SQL string (ORM raw queries, migration files, seed files) must use only the cross-compatible forms listed above. No exceptions — if a raw query can't be written cross-compatibly, it must be replaced with an ORM call.
287
+
288
+ 3. **Migration files** — Check all migration files for dialect-specific DDL. Replace `AUTO_INCREMENT`, backtick quoting, MySQL-specific types, and PG-specific types with cross-compatible alternatives or ORM schema methods.
289
+
290
+ 4. **Placeholder syntax** — Use the ORM's parameterization. If writing raw parameterized SQL, use named parameters (`:id`) which most ORMs translate per dialect, rather than `?` (MySQL) or `$1` (PG) which are dialect-specific.
291
+
292
+ ### G5. No Dialect Branching
293
+
294
+ **Do NOT accept or introduce patterns like:**
295
+ - `if (dialect === 'mysql') { sql = '...' } else { sql = '...' }`
296
+ - `config.database.type === 'postgres' ? pgQuery : mysqlQuery`
297
+ - Separate `.mysql.sql` and `.postgres.sql` files
298
+
299
+ If code like this already exists, refactor it to use the single cross-compatible form or an ORM method. The goal is one SQL statement that runs on both databases identically.
300
+
301
+ **Only exception:** ORM configuration that specifies the connection dialect (e.g., Sequelize `dialect`, Django `ENGINE`, SQLAlchemy connection URL). This is infrastructure config, not SQL branching.
302
+
231
303
  **Output Format:**
232
304
 
233
305
  After completing all phases, provide a summary report:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bms-speckit-plugin",
3
- "version": "6.2.0",
3
+ "version": "6.3.1",
4
4
  "description": "Chain-orchestrated development pipeline: /bms-speckit takes requirements and runs brainstorm → constitution → specify → plan → tasks → analyze → implement → verify with per-step error handling",
5
5
  "files": [
6
6
  ".claude-plugin/",
@@ -205,6 +205,7 @@ After the subagent completes, update tasks 1-8 as completed using TaskUpdate, th
205
205
  - **D. Accessibility** — alt text, form labels, keyboard nav, heading hierarchy
206
206
  - **E. Integration check** — verify all components work together end-to-end
207
207
  - **F. Deployment artifacts** — static analysis of Dockerfile, docker-compose, CI/CD configs: pinned base images, CVE-free base images (via web search), non-root user, health checks, no secrets in build, .dockerignore coverage (skipped if no deployment files exist)
208
+ - **G. Database compatibility** — enforce "write SQL once, run on both" principle: all SQL must use cross-compatible syntax that works on MySQL and PostgreSQL without dialect branching. Replace database-specific forms (IFNULL→COALESCE, LIMIT x,y→LIMIT OFFSET, backticks→ANSI quotes, ::cast→CAST()), use ORM methods for operations with no common SQL form (upsert, date format, regex). No `if dialect` patterns allowed. (skipped if no SQL in project)
208
209
  - The agent fixes everything it can. Major dependency updates are flagged for user review.
209
210
  - **Completion rule:** When the QC agent returns its report, proceed to Step 12 **unless** the report contains unfixed build errors, unfixed test failures, or unfixed critical security vulnerabilities. Informational findings, flagged-for-review items, and already-fixed issues do NOT block progression. If uncertain, proceed — the QC agent already fixed what it could.
210
211
  - **Post-action:** Commit all fixes and push. Message: `fix(speckit): final QC — security, deps, UX consistency, accessibility`