slash-do 1.5.1 → 1.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.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Unified DevSecOps audit, remediation, per-category PRs, CI verification, and Copilot review loop with worktree isolation
2
+ description: Unified DevSecOps audit, remediation, test enhancement, per-category PRs, CI verification, and Copilot review loop with worktree isolation
3
3
  argument-hint: "[--scan-only] [--no-merge] [path filter or focus areas]"
4
4
  ---
5
5
 
@@ -58,6 +58,9 @@ When compacting during this workflow, always preserve:
58
58
  - All PR numbers and URLs created so far
59
59
  - `BUILD_CMD`, `TEST_CMD`, `PROJECT_TYPE`, `WORKTREE_DIR` values
60
60
  - `VCS_HOST`, `CLI_TOOL`, `DEFAULT_BRANCH`, `CURRENT_BRANCH`
61
+ - `PHASE_4C_START_SHA` (needed for FILE_OWNER_MAP update in Phase 4c.3)
62
+ - `VACUOUS_TESTS_FIXED`, `WEAK_TESTS_STRENGTHENED`, `NEW_TEST_CASES`, `NEW_TEST_FILES`
63
+ - `CREATED_CATEGORY_SLUGS` (list of branch slugs created in Phase 5)
61
64
 
62
65
 
63
66
  ## Phase 0: Discovery & Setup
@@ -173,9 +176,31 @@ Skip step 4 if steps 1-3 reveal the code is correct.
173
176
  - **Database migrations**: exclusive-lock ALTER TABLE on large tables, CREATE INDEX without CONCURRENTLY, missing down migrations or untested rollback paths
174
177
  - General: framework-specific security issues, language-specific gotchas, domain-specific compliance, environment variable hygiene (missing `.env.example`, required env vars not validated at startup, secrets in config files that should be in env)
175
178
 
176
- 7. **Test Coverage**
177
- Uses Batch 1 findings as context to prioritize:
178
- Focus: missing test files for critical modules, untested edge cases, tests that only cover happy paths, mocked dependencies that hide real bugs, areas with high complexity (identified by agents 1-5) but no tests, test files that don't actually assert anything meaningful
179
+ 7. **Test Quality & Coverage**
180
+ Uses Batch 1 findings as context to prioritize.
181
+ Focus areas:
182
+
183
+ **Coverage gaps:**
184
+ - Missing test files for critical modules, untested edge cases, tests that only cover happy paths
185
+ - Areas with high complexity (identified by agents 1-5) but no tests
186
+ - Remediation changes from agents 1-6 that lack corresponding test coverage
187
+
188
+ **Vacuous tests (tests that don't actually test anything):**
189
+ - Tests that assert on mocked return values instead of real behavior (testing the mock, not the code)
190
+ - Tests that only check truthiness (`assert.ok(result)`) when they should verify specific values or shapes
191
+ - Tests with assertions that can never fail (e.g., asserting a hardcoded value equals itself, asserting `typeof x === 'object'` on a literal `{}`)
192
+ - Tests that re-implement the logic under test instead of importing the real function — these pass even when real code regresses
193
+ - `it('should work', ...)` tests with no meaningful assertion or with assertions commented out
194
+ - Tests that mock the module they're testing (testing mock behavior, not real behavior)
195
+
196
+ **Weak test patterns:**
197
+ - Tests that verify implementation details (internal state, private methods, call counts) instead of observable behavior
198
+ - Tests where all assertions pass even if the function under test returns `null`/`undefined`/empty — verify by mentally substituting a no-op and checking if the test would still pass
199
+ - Integration tests that mock so aggressively they become unit tests of glue code
200
+ - Tests missing negative cases (invalid input, error paths, boundary conditions)
201
+ - Tests with shared mutable state between cases (`beforeEach` that doesn't reset, module-level variables)
202
+
203
+ Report each finding with a severity prefix `**[CRITICAL]**`, `**[HIGH]**`, `**[MEDIUM]**`, or `**[LOW]**` followed immediately by a quality prefix `[VACUOUS]`, `[WEAK]`, or `[MISSING]` (for example, `**[HIGH][VACUOUS]**`) to distinguish quality issues from coverage gaps while keeping the format consistent with other agents. Include the specific test name and file:line for existing test issues.
179
204
 
180
205
  Wait for ALL agents to complete before proceeding.
181
206
 
@@ -220,10 +245,18 @@ For each file touched by multiple categories, document why it was assigned to on
220
245
  ### Architecture & SOLID
221
246
  ### Bugs, Performance & Error Handling
222
247
  ### Stack-Specific
223
- ### Test Coverage (tracked, not auto-remediated)
248
+ ### Test Quality & Coverage
224
249
  ```
225
250
 
226
- 6. Print a summary table:
251
+ 6. Print a summary table (short labels → full category → branch slug):
252
+ - Security → Security & Secrets → `security`
253
+ - Code Quality → Code Quality & Style → `code-quality`
254
+ - DRY & YAGNI → DRY & YAGNI → `dry`
255
+ - Architecture → Architecture & SOLID → `architecture`
256
+ - Bugs & Perf → Bugs, Performance & Error Handling → `bugs-perf`
257
+ - Stack-Specific → Stack-Specific → `stack-specific`
258
+ - Tests → Test Quality & Coverage → `tests`
259
+
227
260
  ```
228
261
  | Category | CRITICAL | HIGH | MEDIUM | LOW | Total |
229
262
  |-------------------|----------|------|--------|-----|-------|
@@ -233,7 +266,7 @@ For each file touched by multiple categories, document why it was assigned to on
233
266
  | Architecture | ... | ... | ... | ... | ... |
234
267
  | Bugs & Perf | ... | ... | ... | ... | ... |
235
268
  | Stack-Specific | ... | ... | ... | ... | ... |
236
- | Test Coverage | ... | ... | ... | ... | ... |
269
+ | Tests | ... | ... | ... | ... | ... |
237
270
  | TOTAL | ... | ... | ... | ... | ... |
238
271
  ```
239
272
 
@@ -241,7 +274,7 @@ For each file touched by multiple categories, document why it was assigned to on
241
274
 
242
275
  ## Phase 3: Worktree Remediation
243
276
 
244
- Only proceed with CRITICAL, HIGH, and MEDIUM findings. LOW and Test Coverage findings remain tracked in PLAN.md but are not auto-remediated.
277
+ Only proceed with CRITICAL, HIGH, and MEDIUM findings for code remediation. LOW findings remain tracked in PLAN.md but are not auto-remediated. Test Quality & Coverage findings are handled separately in Phase 4c.
245
278
 
246
279
  ### 3a: Setup
247
280
 
@@ -349,18 +382,119 @@ Before creating PRs, run a deep code review on all remediation changes to catch
349
382
  ```
350
383
  5. If "Show diff" selected, print the diff and re-ask. If "Abort", stop and print the worktree path.
351
384
 
385
+ ## Phase 4c: Test Enhancement
386
+
387
+ After internal code review passes, evaluate and enhance the project's test suite. This phase acts on Agent 7's findings AND ensures all remediation work from Phase 3 has proper test coverage.
388
+
389
+ ### 4c.0: Record Start SHA
390
+
391
+ Before any test enhancement commits, capture the current HEAD so Phase 4c changes can be diffed later:
392
+ ```bash
393
+ cd {WORKTREE_DIR}
394
+ PHASE_4C_START_SHA="$(git rev-parse HEAD)"
395
+ ```
396
+
397
+ ### 4c.1: Test Audit Triage
398
+
399
+ Review Agent 7 findings from Phase 1 and categorize them:
400
+
401
+ 1. **`[VACUOUS]` findings** — tests that exist but don't test real behavior. These are the highest priority because they create a false sense of safety.
402
+ 2. **`[WEAK]` findings** — tests that partially cover behavior but miss important cases. Strengthen with additional assertions and edge cases.
403
+ 3. **`[MISSING]` findings** — no tests exist for critical paths. Write new test files or add test cases to existing files.
404
+
405
+ Additionally, scan all remediation changes from Phase 3:
406
+ - For each file modified by remediation agents, check if corresponding tests exist
407
+ - If tests exist, verify they cover the specific behavior that was fixed/changed
408
+ - If no tests exist for a remediated module, flag for new test creation
409
+
410
+ ### 4c.2: Test Enhancement Execution
411
+
412
+ Spawn a general-purpose agent (using `REMEDIATION_MODEL`) in the worktree to fix and write tests. Populate the template placeholders below from Phase 4c.1 triage output: `{VACUOUS_AND_WEAK_FINDINGS}` from `[VACUOUS]`/`[WEAK]` findings, `{MISSING_FINDINGS}` from `[MISSING]` findings, and `{REMEDIATED_FILES_WITHOUT_TESTS}` from the remediation-change scan. The agent instructions:
413
+
414
+ ```
415
+ You are a test enhancement agent working in {WORKTREE_DIR}.
416
+ Project type: {PROJECT_TYPE}. Test command: {TEST_CMD}.
417
+
418
+ Your job is to fix weak/vacuous tests and write missing tests that verify REAL BEHAVIOR.
419
+
420
+ ## Rules for writing good tests
421
+
422
+ 1. **Test observable behavior, not implementation.** Assert on return values, side effects (files written, state changed), and error messages — never on internal variable names, call counts, or private method invocations.
423
+
424
+ 2. **Every assertion must be falsifiable.** For each assertion you write, mentally substitute a broken implementation (returns null, returns wrong value, throws instead of succeeding, succeeds instead of throwing). If your assertion would still pass, it's vacuous — rewrite it.
425
+
426
+ 3. **Prefer real modules over mocks.** Only mock at system boundaries (filesystem, network, time). If you must mock, assert on the arguments passed TO the mock, not on its return value.
427
+
428
+ 4. **Test the edges.** Each test function needs at minimum:
429
+ - Happy path with specific expected output
430
+ - Empty/null/undefined input
431
+ - Invalid input that should error
432
+ - Boundary values (0, -1, MAX, empty string vs null)
433
+
434
+ 5. **Use concrete expected values.** `assert.equal(result, 'expected string')` not `assert.ok(result)`. `assert.deepEqual(output, { key: 'value' })` not `assert.ok(typeof output === 'object')`.
435
+
436
+ 6. **One behavior per test.** Each `it()` block tests exactly one scenario. The test name describes the scenario and expected outcome.
437
+
438
+ 7. **No shared mutable state.** Each test must be independently runnable. Use `beforeEach` to create fresh fixtures. Never rely on test execution order.
439
+
440
+ ## Task list
441
+
442
+ Fix these vacuous/weak tests:
443
+ {VACUOUS_AND_WEAK_FINDINGS}
444
+
445
+ Write tests for these gaps:
446
+ {MISSING_FINDINGS}
447
+
448
+ Write tests for these remediated files:
449
+ {REMEDIATED_FILES_WITHOUT_TESTS}
450
+
451
+ ## Verification
452
+
453
+ After writing/fixing each test file:
454
+ 1. Run `{TEST_CMD}` to verify all tests pass
455
+ 2. For each NEW test, verify that it fails when the behavior under test is wrong:
456
+ - Ensure you have no unstaged changes (`git diff` is clean)
457
+ - Apply a small, obvious, and **uncommitted** change to the code under test (e.g., return a constant, flip a conditional)
458
+ - Run `{TEST_CMD}` and confirm the new test FAILS
459
+ - Immediately restore the code: `git checkout -- {file_path}`
460
+ - Confirm the worktree is clean again (`git diff` shows no changes)
461
+ This is the key quality gate — a test that does not fail when the code is broken is worthless.
462
+ 3. After confirming the code is restored and the worktree is clean, commit passing tests: `test: {description of what's tested}`
463
+ ```
464
+
465
+ ### 4c.3: Verification
466
+
467
+ After the test agent completes:
468
+
469
+ 1. Run the full test suite:
470
+ ```bash
471
+ cd {WORKTREE_DIR} && {TEST_CMD}
472
+ ```
473
+ 2. If tests fail, fix in a new commit
474
+ 3. Count new/fixed tests and record four variables:
475
+ - `VACUOUS_TESTS_FIXED` — number of vacuous tests fixed
476
+ - `WEAK_TESTS_STRENGTHENED` — number of weak tests strengthened
477
+ - `NEW_TEST_CASES` — number of new test cases added
478
+ - `NEW_TEST_FILES` — number of new test files created
479
+ 4. **Update `FILE_OWNER_MAP`** — Phase 4c may have created or modified test files that were not in the Phase 2 map. Before Phase 5 assembles branches:
480
+ - List all files changed by Phase 4c commits: `git diff --name-only "$PHASE_4C_START_SHA"..HEAD`
481
+ - For each file not already in `FILE_OWNER_MAP`, assign it to the `tests` category
482
+ - For each file already owned by another category, leave it in that category (co-located test changes ship with the code they test — the `tests` branch only contains standalone test files not owned by other categories)
483
+
352
484
  ## Phase 5: Per-Category PR Creation
353
485
 
354
486
  Instead of one mega PR, create **separate branches and PRs for each category**. This enables independent review, targeted CI, and granular merge decisions.
355
487
 
356
488
  ### 5a: Build the Category Branches
357
489
 
358
- Using the `FILE_OWNER_MAP` from Phase 2, create one branch per category:
490
+ Using the `FILE_OWNER_MAP` from Phase 2 (updated in Phase 4c.3), create one branch per category.
491
+
492
+ Initialize `CREATED_CATEGORY_SLUGS=""` (empty space-delimited string). After each category branch is successfully created and pushed below, append its slug: `CREATED_CATEGORY_SLUGS="$CREATED_CATEGORY_SLUGS {CATEGORY_SLUG}"`. Phase 7 uses this for cleanup.
359
493
 
360
494
  For each category that has findings:
361
495
  1. Switch to `{DEFAULT_BRANCH}`: `git checkout {DEFAULT_BRANCH}`
362
496
  2. Create a category branch: `git checkout -b better/{CATEGORY_SLUG}`
363
- - Use slugs: `security`, `code-quality`, `dry`, `arch-bugs`, `stack-specific`
497
+ - Use slugs: `security`, `code-quality`, `dry`, `architecture`, `bugs-perf`, `stack-specific`, `tests`
364
498
  3. For each file assigned to this category in `FILE_OWNER_MAP`:
365
499
  - **Modified files**: `git checkout origin/better/{DATE} -- {file_path}`
366
500
  - **New files (Added)**: `git checkout origin/better/{DATE} -- {file_path}`
@@ -546,16 +680,16 @@ If merge fails (e.g., branch protection, merge conflicts from a prior PR):
546
680
  ```bash
547
681
  git worktree remove {WORKTREE_DIR}
548
682
  ```
549
- 2. Delete local AND remote branches (only if merged):
683
+ 2. Delete local AND remote branches (only categories that were created and merged). Use the tracked list of branches from Phase 5 rather than a fixed list:
550
684
  ```bash
551
685
  git branch -d better/{DATE}
552
- git branch -d better/security better/code-quality better/dry better/arch-bugs better/stack-specific
686
+ # CREATED_CATEGORY_SLUGS is a space-delimited string, e.g. "security code-quality tests"
687
+ for slug in $CREATED_CATEGORY_SLUGS; do
688
+ git branch -d "better/$slug" || echo "warning: local branch better/$slug not found or not fully merged"
689
+ git push origin --delete "better/$slug" 2>/dev/null || echo "warning: remote branch better/$slug not found"
690
+ done
553
691
  ```
554
- ```bash
555
- git push origin --delete better/{DATE}
556
- git push origin --delete better/security better/code-quality better/dry better/arch-bugs better/stack-specific
557
- ```
558
- Ignore errors from `--delete` if a branch doesn't exist remotely.
692
+ The guards prevent errors from interrupting cleanup. Warnings are printed so leftover branches are visible.
559
693
  3. Restore stashed changes (if stashed in Phase 3a):
560
694
  ```bash
561
695
  git stash pop
@@ -575,8 +709,14 @@ If merge fails (e.g., branch protection, merge conflicts from a prior PR):
575
709
  | Architecture | ... | ... | ... | #number | pass | approved |
576
710
  | Bugs & Perf | ... | ... | ... | #number | pass | approved |
577
711
  | Stack-Specific | ... | ... | ... | #number | pass | approved |
578
- | Test Coverage | ... | (tracked only) | ... | | |
712
+ | Tests | ... | ... | ... | #number | pass | approved |
579
713
  | TOTAL | ... | ... | ... | N PRs | | |
714
+
715
+ Test Enhancement Stats:
716
+ - Vacuous tests fixed: {VACUOUS_TESTS_FIXED}
717
+ - Weak tests strengthened: {WEAK_TESTS_STRENGTHENED}
718
+ - New test cases added: {NEW_TEST_CASES}
719
+ - New test files created: {NEW_TEST_FILES}
580
720
  ```
581
721
 
582
722
  ## Error Recovery
@@ -602,6 +742,7 @@ If merge fails (e.g., branch protection, merge conflicts from a prior PR):
602
742
  - Each file appears in exactly ONE PR (file ownership map) to prevent merge conflicts between PRs
603
743
  - When extracting modules, always add backward-compatible re-exports in the original module to prevent cross-PR breakage
604
744
  - Version bump happens exactly once on the first category branch based on aggregate commit analysis
605
- - Only CRITICAL, HIGH, and MEDIUM findings are auto-remediated; LOW and Test Coverage remain tracked in PLAN.md
745
+ - Only CRITICAL, HIGH, and MEDIUM findings are auto-remediated for code categories; LOW findings remain tracked in PLAN.md
746
+ - Test Quality & Coverage findings are remediated in Phase 4c with a dedicated test enhancement agent that verifies tests fail when code is broken
606
747
  - GitLab projects skip the Copilot review loop entirely (Phase 6) and stop after MR creation
607
748
  - CI must pass on each PR before requesting Copilot review or merging
@@ -60,6 +60,7 @@
60
60
  **Validation & consistency** _[applies when: code handles user input, schemas, or API contracts]_
61
61
  - API versioning: breaking changes to public endpoints without version bump or deprecation path
62
62
  - Backward-incompatible response shape changes without client migration plan
63
+ - Backward compatibility breaking changes — renamed/removed config keys, changed file formats, altered DB schemas, modified event payloads, or restructured persisted data (localStorage, files, database rows) without a migration path or fallback that reads the old format. Trace all consumers of the changed contract (other services, CLI versions, stored data) and verify they still work or have an upgrade path. For schema changes, require a migration script; for config/format changes, support both old and new formats during a transition period or provide a one-time converter
63
64
  - New endpoints/schemas should match validation patterns of existing similar endpoints — field limits, required fields, types, error handling. If validation exists on one endpoint for a param, the same param on other endpoints needs the same validation
64
65
  - When a validation/sanitization function is introduced for a field, trace ALL write paths (create, update, sync, import) — partial application means invalid values re-enter through the unguarded path
65
66
  - Schema fields accepting values downstream code can't handle; Zod/schema stripping fields the service reads (silent `undefined`); config values persisted but silently ignored by the implementation — trace each field through schema → service → consumer. Update schemas derived from create schemas (e.g., `.partial()`) must also make nested object fields optional — shallow partial on a deeply-required schema rejects valid partial updates. Additionally, `.deepPartial()` or `.partial()` on schemas with `.default()` values will apply those defaults on update, silently overwriting existing persisted values with defaults — create explicit update schemas without defaults instead
@@ -133,6 +134,7 @@
133
134
  - Labels, comments, status messages, or documentation that describe behavior the code doesn't implement — e.g., a map named "renamed" that only deletes, or an action labeled "migrated" that never creates the target
134
135
  - Inline code examples, command templates, and query snippets that aren't syntactically valid as written — template placeholders must use a consistent format, queries must use correct syntax for their language (e.g., single `{}` in GraphQL, not `{{}}`)
135
136
  - Cross-references between files (identifiers, parameter names, format conventions, operational thresholds) that disagree — when one reference changes, trace all other files that reference the same entity and update them
137
+ - Template/workflow variables referenced (`{VAR_NAME}`) but never assigned — trace each placeholder to a definition step; undefined variables cause silent failures or confusing instructions. Also check for colliding identifiers (two distinct concepts mapped to the same slug, key, or name)
136
138
  - Responsibility relocated from one module to another (e.g., writes moved from handler to middleware) without updating all consumers that depended on the old location's timing, return value, or side effects — trace callers that relied on the synchronous or co-located behavior and verify they still work with the new execution point. Remove dead code left behind at the old location
137
139
  - Sequential instructions or steps whose ordering doesn't match the required execution order — readers following in order will perform actions at the wrong time (e.g., "record X" in step 2 when X must be captured before step 1's action)
138
140
  - Sequential numbering (section numbers, step numbers) with gaps or jumps after edits — verify continuity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slash-do",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Curated slash commands for AI coding assistants — Claude Code, OpenCode, Gemini CLI, and Codex",
5
5
  "author": "Adam Eivy <adam@eivy.com>",
6
6
  "license": "MIT",