bms-speckit-plugin 6.3.0 → 6.4.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.
@@ -31,10 +31,10 @@ User explicitly asks for multi-dimensional quality review — matches quality-co
31
31
 
32
32
  model: inherit
33
33
  color: yellow
34
- tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash", "WebSearch"]
34
+ tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash", "WebSearch", "mcp__bms-session-mcp-server__query", "mcp__bms-session-mcp-server__list_tables", "mcp__bms-session-mcp-server__describe_table", "mcp__bms-knowledge-mcp__search_knowledge", "mcp__mysql__mysql_query", "mcp__postgres__query"]
35
35
  ---
36
36
 
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.
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, deployment artifacts, and database compatibility (including live SQL validation against the real schema).
38
38
 
39
39
  **Your Core Responsibilities:**
40
40
 
@@ -44,6 +44,7 @@ You are a senior quality control engineer performing a comprehensive audit of a
44
44
  4. **UX/UI Review** — Verify user feedback, error messages, loading states, and responsive design
45
45
  5. **Accessibility** — Check for basic a11y compliance (ARIA, contrast, keyboard nav)
46
46
  6. **Deployment Artifacts** — Static analysis of Dockerfile, docker-compose, and related deployment files
47
+ 7. **Database Compatibility & SQL Validation** — Cross-DB syntax compliance AND verifying every SQL statement references real tables/columns via live database MCP servers
47
48
 
48
49
  **Audit Process:**
49
50
 
@@ -232,80 +233,132 @@ Search for `.github/workflows/*.yml`, `.gitlab-ci.yml`, `Jenkinsfile`, etc. For
232
233
 
233
234
  > **Skip this phase entirely if the project has no SQL statements (no .sql files, no SQL strings in source code).**
234
235
 
235
- All SQL in the project must be compatible with both MySQL and PostgreSQL. Since no database runtime is available, this phase uses **static grep-based analysis** to find database-specific syntax and replace it with cross-compatible alternatives.
236
+ **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
 
237
238
  ### G1. Identifier Quoting
238
239
 
239
- - **MySQL backticks** — Grep for backtick-quoted identifiers: `` `table_name` ``, `` `column` ``
240
- - Fix: Replace with double quotes `"table_name"` (ANSI SQL, works on both) or remove quoting if identifiers don't need escaping
241
- - If using an ORM, prefer the ORM's quoting mechanism instead of raw quoting
240
+ 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.
242
241
 
243
242
  ### G2. Data Types
244
243
 
245
- Grep SQL files and SQL strings in source code for database-specific types:
246
-
247
- | MySQL-only | PostgreSQL-only | Cross-compatible replacement |
248
- |---|---|---|
249
- | `TINYINT(1)` for booleans | `BOOLEAN` | `BOOLEAN` (MySQL treats as TINYINT, PG native) |
250
- | `AUTO_INCREMENT` | `SERIAL`, `GENERATED ALWAYS AS IDENTITY` | Use ORM auto-increment, or `SERIAL` (PG) + `AUTO_INCREMENT` (MySQL) via migration |
251
- | `DOUBLE` | `DOUBLE PRECISION` | `DOUBLE PRECISION` (works on both) |
252
- | `DATETIME` | `TIMESTAMP` | `TIMESTAMP` (works on both) |
253
- | `TINYINT`, `MEDIUMINT` | not supported | `SMALLINT` or `INTEGER` |
254
- | `LONGTEXT`, `MEDIUMTEXT`, `TINYTEXT` | not supported | `TEXT` (works on both) |
255
- | `LONGBLOB`, `MEDIUMBLOB`, `TINYBLOB` | `BYTEA` | Handle via ORM or use `BLOB`/`BYTEA` per dialect |
256
- | `ENUM('a','b')` | `CREATE TYPE ... AS ENUM` | Use CHECK constraint or application-level validation |
257
- | `UNSIGNED` | not supported | Remove `UNSIGNED`, use CHECK constraint if needed |
258
- | `JSON` (MySQL 5.7+) | `JSON` / `JSONB` | `JSON` works on both; prefer `JSONB` on PG for indexing |
259
-
260
- ### G3. SQL Syntax Differences
261
-
262
- Grep for these MySQL-specific or PostgreSQL-specific patterns:
263
-
264
- | Pattern | MySQL | PostgreSQL | Cross-compatible |
265
- |---|---|---|---|
266
- | Pagination | `LIMIT 10, 20` | not supported | `LIMIT 20 OFFSET 10` (works on both) |
267
- | String concat | `CONCAT(a, b)` | `a \|\| b` | `CONCAT(a, b)` (works on both in modern versions) |
268
- | Null coalesce | `IFNULL(a, b)` | not supported | `COALESCE(a, b)` (ANSI SQL, works on both) |
269
- | If/else | `IF(cond, a, b)` | not supported | `CASE WHEN cond THEN a ELSE b END` |
270
- | Current time | `NOW()` | `NOW()` | `NOW()` works on both, or `CURRENT_TIMESTAMP` |
271
- | Date diff | `DATEDIFF(a, b)` | `a - b` (returns interval) | Use `EXTRACT(EPOCH FROM a - b)` or handle per dialect |
272
- | Date format | `DATE_FORMAT(d, '%Y-%m-%d')` | `TO_CHAR(d, 'YYYY-MM-DD')` | Handle per dialect or use ORM date formatting |
273
- | Group concat | `GROUP_CONCAT(col)` | `STRING_AGG(col, ',')` | Handle per dialect or use ORM |
274
- | Upsert | `ON DUPLICATE KEY UPDATE` | `ON CONFLICT ... DO UPDATE` | Use ORM upsert or handle per dialect |
275
- | Insert ignore | `INSERT IGNORE` | `ON CONFLICT DO NOTHING` | Use ORM or handle per dialect |
276
- | Regex | `REGEXP` / `RLIKE` | `~` / `~*` | Handle per dialect |
277
- | Boolean literals | `TRUE`/`FALSE` or `1`/`0` | `TRUE`/`FALSE` | `TRUE`/`FALSE` (works on both) |
278
- | Table exists | `SHOW TABLES` | `\dt` / information_schema | `SELECT FROM information_schema.tables` (works on both) |
279
- | Column info | `DESCRIBE table` / `SHOW COLUMNS` | `\d table` | `SELECT FROM information_schema.columns` (works on both) |
280
- | String escape | `\'` (backslash) | `''` (double single quote) | `''` (ANSI SQL, works on both) |
281
-
282
- ### G4. ORM/Query Builder Dialect Safety
283
-
284
- If the project uses an ORM or query builder:
285
-
286
- 1. **Check dialect configuration** — Verify the ORM is configured to produce dialect-agnostic SQL, or has explicit multi-dialect support:
287
- - Sequelize: check `dialect` option — should support switching between 'mysql' and 'postgres'
288
- - TypeORM: check `type` in data source config
289
- - Prisma: check `provider` in schema.prisma
290
- - SQLAlchemy: check engine URL should be configurable via env var, not hardcoded
291
- - Django: check `DATABASES.ENGINE` setting
292
-
293
- 2. **Raw SQL in ORM context** — Any raw SQL used alongside an ORM must follow the same cross-compatibility rules above. Flag raw SQL that uses dialect-specific syntax.
294
-
295
- 3. **Migration files** — Check migration files for dialect-specific DDL. Migrations that use `AUTO_INCREMENT`, backtick quoting, or MySQL-specific types will fail on PostgreSQL.
296
-
297
- ### G5. Handling Unavoidable Differences
298
-
299
- Some operations genuinely differ between databases. For these:
300
-
301
- 1. **Dialect abstraction** If the project must support both databases, verify there's a dialect layer that switches SQL per database type. Example:
302
- ```
303
- // Acceptable pattern
304
- const upsertSQL = dialect === 'mysql'
305
- ? 'INSERT INTO t (...) VALUES (?) ON DUPLICATE KEY UPDATE ...'
306
- : 'INSERT INTO t (...) VALUES ($1) ON CONFLICT (...) DO UPDATE ...';
307
- ```
308
- 2. **Document exceptions** — If a query intentionally uses dialect-specific syntax, it must have a comment explaining which database it targets and why cross-compatibility isn't possible.
244
+ Grep SQL files and SQL strings in source code for database-specific types. Replace with the cross-compatible form:
245
+
246
+ | Flag this | Replace with |
247
+ |---|---|
248
+ | `TINYINT(1)` for booleans | `BOOLEAN` |
249
+ | `AUTO_INCREMENT` or `SERIAL` | ORM-managed auto-increment identity column |
250
+ | `DOUBLE` | `DOUBLE PRECISION` |
251
+ | `DATETIME` | `TIMESTAMP` |
252
+ | `TINYINT`, `MEDIUMINT` | `SMALLINT` or `INTEGER` |
253
+ | `LONGTEXT`, `MEDIUMTEXT`, `TINYTEXT` | `TEXT` |
254
+ | `LONGBLOB`, `MEDIUMBLOB`, `TINYBLOB`, `BYTEA` | ORM binary type or `BLOB`/`BYTEA` handled by ORM layer |
255
+ | `ENUM('a','b')` or `CREATE TYPE AS ENUM` | `VARCHAR` + `CHECK` constraint or application-level validation |
256
+ | `UNSIGNED` | Remove; use `CHECK (col >= 0)` if needed |
257
+ | `JSONB` | `JSON` (works on both; index optimization is a deployment concern, not a code concern) |
258
+
259
+ ### G3. SQL Syntax — Always Use the Cross-Compatible Form
260
+
261
+ Grep for database-specific syntax. Every match must be replaced with the form that runs on both MySQL and PostgreSQL without modification:
262
+
263
+ | Flag this | Replace with (works on both) |
264
+ |---|---|
265
+ | `LIMIT 10, 20` (MySQL offset syntax) | `LIMIT 20 OFFSET 10` |
266
+ | `IFNULL(a, b)` | `COALESCE(a, b)` |
267
+ | `IF(cond, a, b)` | `CASE WHEN cond THEN a ELSE b END` |
268
+ | `a \|\| b` for string concat (PG-only when sql_mode strict) | `CONCAT(a, b)` |
269
+ | `DATEDIFF(a, b)` (MySQL) or `a - b` interval (PG) | `EXTRACT(DAY FROM (a - b))` or ORM date math |
270
+ | `DATE_FORMAT(d, '%Y-%m-%d')` (MySQL) or `TO_CHAR(d, 'YYYY-MM-DD')` (PG) | ORM date formatting function |
271
+ | `GROUP_CONCAT(col)` (MySQL) or `STRING_AGG(col, ',')` (PG) | ORM aggregate or application-level concatenation |
272
+ | `ON DUPLICATE KEY UPDATE` (MySQL) | ORM upsert method (most ORMs abstract this) |
273
+ | `INSERT IGNORE` (MySQL) | ORM upsert with ignore/skip-duplicate option |
274
+ | `ON CONFLICT ... DO UPDATE` (PG-only) | ORM upsert method |
275
+ | `REGEXP` / `RLIKE` (MySQL) or `~` / `~*` (PG) | Application-level regex or ORM pattern matching |
276
+ | `1`/`0` for booleans | `TRUE`/`FALSE` |
277
+ | `SHOW TABLES`, `DESCRIBE table`, `SHOW COLUMNS` | `SELECT FROM information_schema.tables` / `information_schema.columns` |
278
+ | `\\d table`, `\\dt` (PG CLI commands) | `information_schema` queries |
279
+ | `\\'` backslash string escape | `''` (ANSI double single-quote) |
280
+ | `NOW()` | `CURRENT_TIMESTAMP` (ANSI standard; `NOW()` also works on both but `CURRENT_TIMESTAMP` is more portable) |
281
+ | `::type` PostgreSQL cast syntax | `CAST(expr AS type)` (ANSI SQL) |
282
+
283
+ ### G4. ORM and Raw SQL
284
+
285
+ 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.
286
+
287
+ 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.
288
+
289
+ 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.
290
+
291
+ 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.
292
+
293
+ ### G5. No Dialect Branching
294
+
295
+ **Do NOT accept or introduce patterns like:**
296
+ - `if (dialect === 'mysql') { sql = '...' } else { sql = '...' }`
297
+ - `config.database.type === 'postgres' ? pgQuery : mysqlQuery`
298
+ - Separate `.mysql.sql` and `.postgres.sql` files
299
+
300
+ 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.
301
+
302
+ **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.
303
+
304
+ ### G6. SQL Statement Validation Against Real Schema (MOST IMPORTANT)
305
+
306
+ > **This is the most common QC failure — LLMs frequently hallucinate column names that do not exist in the real database schema. Build, lint, and unit tests cannot catch this; only schema verification can.**
307
+
308
+ For every SQL statement in the codebase, verify that:
309
+ 1. Every referenced table actually exists in the database
310
+ 2. Every referenced column actually exists in its table
311
+ 3. The SQL statement is syntactically valid and executes without error
312
+
313
+ **Use whatever verification tools are available in the coding environment**, in priority order:
314
+
315
+ #### Option 1 — Live database MCP server (preferred when available)
316
+
317
+ If the environment has a database MCP server connected to the target schema, use it to validate every SQL statement. Known MCP servers and their tools:
318
+
319
+ - **`bms-session-mcp-server`** (HOSxP hospital databases) — exposes:
320
+ - `list_tables(pattern)` — discover tables by wildcard pattern
321
+ - `describe_table(table_name)` — returns column names, types, nullability
322
+ - `query(sql)` — executes read-only SQL; use with `EXPLAIN <stmt>` to validate without returning rows, or `SELECT ... LIMIT 0` / `SELECT ... LIMIT 1` for zero-row shape check
323
+ - Read `bms://session-info` resource first to learn the database type (MariaDB vs PostgreSQL)
324
+ - **`mcp__mysql__mysql_query`** / **`mcp__postgres__query`** — direct MySQL/PostgreSQL access; use `EXPLAIN`, `PREPARE`, or `LIMIT 0` to validate without side effects
325
+ - **Any other database MCP server** — look for tools named `query`, `describe_table`, `list_columns`, `schema`, etc.
326
+
327
+ #### Option 2 — Schema knowledge base (fallback)
328
+
329
+ If no live database is available but a schema knowledge base exists, use it:
330
+ - **`mcp__bms-knowledge-mcp__search_knowledge`** with the `hosxp` collection — contains HOSxP data dictionaries, table schemas, and column details
331
+ - Search by table name to retrieve its official column list, then compare against the columns used in the SQL
332
+
333
+ #### Option 3 — Grep migration/schema files
334
+
335
+ If neither MCP is available, grep the project's migration files, `schema.sql`, `schema.prisma`, ORM model files, etc. to build a local map of tables and columns, then compare.
336
+
337
+ #### Validation Procedure
338
+
339
+ For each SQL statement found in the codebase (in `.sql` files, ORM raw queries, template literals, string constants):
340
+
341
+ 1. **Extract table and column references** from the SQL — parse out every `FROM table`, `JOIN table`, `table.column`, and bare column name
342
+ 2. **For each table** — verify it exists via `list_tables` or `describe_table`. If it does not exist, flag as "unknown table: <name>"
343
+ 3. **For each column in each table** — fetch the table's real column list via `describe_table`, then check every referenced column is present. If it is not, flag as "column <name> does not exist in table <table>" and suggest the closest matching real column name (via fuzzy match)
344
+ 4. **Syntactic + runtime validation** — run `EXPLAIN <statement>` (or `SELECT ... LIMIT 0`) via the MCP `query` tool to catch:
345
+ - Type mismatches (e.g., comparing int column to string literal without cast)
346
+ - Invalid JOIN conditions
347
+ - Ambiguous column references
348
+ - Missing required clauses
349
+ 5. **Fix each violation** — rewrite the SQL to use real table and column names. If the intent cannot be determined, flag for user review with a clear explanation of what column is missing and what similar columns exist
350
+
351
+ #### What NOT to flag
352
+
353
+ - SQL inside test fixtures that intentionally target mock tables
354
+ - Migration files that CREATE the tables being referenced (they define the schema, not consume it)
355
+ - Dynamic SQL where the column list comes from the schema itself (e.g., `SELECT * FROM information_schema.columns`)
356
+
357
+ #### Rules
358
+
359
+ - **Every SQL statement must be validated** — do not skip any. A single hallucinated column crashes the whole feature at runtime
360
+ - **Prefer live database validation over knowledge-base validation** — the knowledge base can be stale; the live database is the source of truth
361
+ - **If no validation source is available at all**, flag this as a FAIL condition and recommend the user provide a schema reference (MCP server, schema.sql, or migration files)
309
362
 
310
363
  **Output Format:**
311
364
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bms-speckit-plugin",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
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/",
@@ -183,13 +183,14 @@ After the subagent completes, update tasks 1-8 as completed using TaskUpdate, th
183
183
  - Never spread or iterate a function's return value without verifying it returns the expected collection type (e.g., array not object, list not dict)
184
184
  - Use strict equality, add null/undefined/None guards for external data (API responses, DB results, config, user input)
185
185
  - Add unit tests that actually execute data transformation functions and verify the output type and shape
186
+ - **SQL validation:** before writing any SQL statement, verify the exact table and column names exist. Use `bms-session-mcp-server` tools (`list_tables`, `describe_table`) or `mcp__bms-knowledge-mcp__search_knowledge` (hosxp collection) to confirm every field reference. Never guess column names. After writing a query, test it with `query` tool using `EXPLAIN` or `LIMIT 0` to confirm it parses and executes.
186
187
  2. **INLINE QC** — immediately run: build, lint, ALL tests, security quick scan, UX check
187
188
  3. **FIX** — fix every issue found, re-run checks
188
189
  4. **COMMIT** — only commit when build + lint + tests pass with zero errors
189
190
  5. **NEXT** — move to next task
190
191
  - **Action:** Run:
191
192
 
192
- `/ralph-loop:ralph-loop "systematically execute speckit.implement via the Skill tool to complete every task defined in {TASKS_PATH} with strict adherence to specification requirements. IMPORTANT: apply rolling QC after EACH task — after implementing a task run build and fix build errors, run linter and fix lint errors, run ALL tests (not just new ones) and fix failures, check for hardcoded secrets and injection vulnerabilities in code you just wrote, verify UI code has actionable error messages and loading states. RUNTIME SAFETY: always add explicit return type annotations on data transformation functions, never spread or iterate a function return value without verifying it returns the expected collection type, use strict equality and null guards for external data, write tests that execute data transformers and verify output type and shape. Only commit when build plus lint plus tests all pass with zero errors then proceed to next task. Report progress to the user after each task: output [Task N/total] DONE — task_name. Do NOT batch QC at the end. Maintain atomic commits after each successful task with clear traceability, avoid requesting confirmation and proceed autonomously, once all tasks are implemented invoke speckit.analyze via the Skill tool to perform a full validation pass, automatically apply all recommended improvements or corrections, re-run all tests to confirm stability and zero regression, and only output <promise>FINISHED</promise> after every task is fully completed, validated, and aligned with production-grade quality standards" --completion-promise "FINISHED" --max-iterations 10`
193
+ `/ralph-loop:ralph-loop "systematically execute speckit.implement via the Skill tool to complete every task defined in {TASKS_PATH} with strict adherence to specification requirements. IMPORTANT: apply rolling QC after EACH task — after implementing a task run build and fix build errors, run linter and fix lint errors, run ALL tests (not just new ones) and fix failures, check for hardcoded secrets and injection vulnerabilities in code you just wrote, verify UI code has actionable error messages and loading states. RUNTIME SAFETY: always add explicit return type annotations on data transformation functions, never spread or iterate a function return value without verifying it returns the expected collection type, use strict equality and null guards for external data, write tests that execute data transformers and verify output type and shape. SQL VALIDATION: before writing any SQL statement verify exact table and column names exist via bms-session-mcp-server list_tables/describe_table or bms-knowledge-mcp search_knowledge with hosxp collection, never guess column names, after writing test each query with EXPLAIN or LIMIT 0 via the query tool to confirm it executes without error. Only commit when build plus lint plus tests all pass with zero errors then proceed to next task. Report progress to the user after each task: output [Task N/total] DONE — task_name. Do NOT batch QC at the end. Maintain atomic commits after each successful task with clear traceability, avoid requesting confirmation and proceed autonomously, once all tasks are implemented invoke speckit.analyze via the Skill tool to perform a full validation pass, automatically apply all recommended improvements or corrections, re-run all tests to confirm stability and zero regression, and only output <promise>FINISHED</promise> after every task is fully completed, validated, and aligned with production-grade quality standards" --completion-promise "FINISHED" --max-iterations 10`
193
194
 
194
195
  - **Done:** Update task 10 as completed. Output `[Step 10/12] DONE — all tasks implemented and verified`
195
196
 
@@ -205,7 +206,9 @@ After the subagent completes, update tasks 1-8 as completed using TaskUpdate, th
205
206
  - **D. Accessibility** — alt text, form labels, keyboard nav, heading hierarchy
206
207
  - **E. Integration check** — verify all components work together end-to-end
207
208
  - **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** static analysis of all SQL statements for MySQL/PostgreSQL cross-compatibility: identifier quoting, data types, syntax differences (IFNULL→COALESCE, LIMIT offset, upsert), ORM dialect config, migration files (skipped if no SQL in project)
209
+ - **G. Database compatibility & SQL validation** two-part check:
210
+ - **G1-G5 (cross-compatibility):** enforce "write SQL once, run on both" — 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.
211
+ - **G6 (SQL schema validation — MOST IMPORTANT):** validate every SQL statement in the codebase against the real database schema. Hallucinated column names are the #1 QC failure — LLMs frequently reference columns that don't exist. For each SQL statement: use `bms-session-mcp-server` (`list_tables`, `describe_table`, `query` with EXPLAIN/LIMIT 0) or `mcp__mysql__mysql_query` / `mcp__postgres__query` to verify every table and column reference exists. Fall back to `mcp__bms-knowledge-mcp__search_knowledge` (hosxp collection) or grep migration files if live DB is unavailable. Fix every hallucinated reference. (skipped if no SQL in project)
209
212
  - The agent fixes everything it can. Major dependency updates are flagged for user review.
210
213
  - **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.
211
214
  - **Post-action:** Commit all fixes and push. Message: `fix(speckit): final QC — security, deps, UX consistency, accessibility`