| name | steroid-verify |
| description | The verification skill for Steroid-Workflow. This skill runs after the engine completes all tasks, proving the code works before allowing archival. It performs core verification by default and can run optional deep scans. Produces review.md/review.json and verify.md/verify.json as durable evidence. |
Steroid Verify (Proof of Work)
This skill runs after the engine completes all tasks in plan.md. It proves the AI's code actually works before the feature can be archived. Without verification, the pipeline is just a promise — this skill makes it proof.
The governed live outputs for this skill are:
.memory/changes/<feature>/review.md
.memory/changes/<feature>/review.json
.memory/changes/<feature>/verify.md
.memory/changes/<feature>/verify.json
.memory/changes/<feature>/completion.json
The live governed authority chain for this phase is:
Steroid runtime contract
Steroid runtime contract
Steroid runtime contract
Steroid runtime contract
Adapted from:
- Steroid Verifier (see
Steroid internal reference) — Goal-backward verification, 3-level artifact checks, anti-pattern scanning
- Steroid Spec Compliance Review (see
Steroid internal reference) — Independent requirement verification
- Steroid Code Quality Review (see
Steroid internal reference) — Structural quality checks
- Steroid Verification Before Completion (see
Steroid internal reference) — Evidence-before-claims gate
The Iron Law
NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
Source: Steroid internal reference — "Claiming work is complete without verification is dishonesty, not efficiency."
If you haven't run the verification command and seen its output, you cannot claim the feature passes.
The Circuit Breaker Mandate
All terminal commands executed by this skill MUST be wrapped in the physical Node.js circuit breaker:
node steroid-run.cjs '<command>'
For file inspection and code searches, prefer shell-free helpers like node steroid-run.cjs fs-cat ..., node steroid-run.cjs fs-find ..., and node steroid-run.cjs fs-grep .... Avoid cat, type, find, grep, pipes, and redirection for routine inspection because they are brittle across hardened and Windows environments.
Phase Gate (Physical Enforcement)
Before doing anything, run the gate check:
node steroid-run.cjs gate verify <feature>
If this command fails, STOP. The engine phase is not complete.
Then run the feature verification pre-check:
node steroid-run.cjs verify-feature <feature>
This is the core verification gate. It confirms review status, task completion, runtime checks, runs the Steroid-owned AccessLint audit when local HTML targets exist, and refreshes ui-review.md / ui-review.json whenever the latest verification evidence changes the frontend review picture. The receipt records freshness metadata so later handoff surfaces can show who refreshed the frontend verdict and which evidence triggered it.
If you want optional deep scans for runtime UI behavior, code smells, and license auditing, run:
node steroid-run.cjs verify-feature <feature> --deep
If you already have a deployed preview, pass it explicitly:
node steroid-run.cjs verify-feature <feature> --deep --url https://preview.example.com
Two-Stage Review Gate (v5.0)
Before running the verification process, ensure the two-stage review is complete:
node steroid-run.cjs review status <feature>
If frontend evidence changed and you want to refresh the consolidated UI verdict without rerunning the full verification command, use:
node steroid-run.cjs review ui <feature>
archive <feature> and report generate <feature> will also auto-refresh stale UI review receipts before they archive or hand off a UI-intensive feature.
If the refreshed ui-review.json is CONDITIONAL, Steroid now distinguishes cautionary frontend issues from blocking frontend issues. Blocking CONDITIONAL cases require an explicit node steroid-run.cjs archive <feature> --force-ui override.
If both stages show PASS, proceed to verification. If not:
- Run
node steroid-run.cjs review spec <feature> — then complete Stage 1
- Run
node steroid-run.cjs review quality <feature> — then complete Stage 2
The review MUST pass both stages before core verification can pass and before verify.json can record a passing result.
The two-stage review produces the governed review artifacts:
.memory/changes/<feature>/review.md — human-readable review report
.memory/changes/<feature>/review.json — machine-readable review receipt
Source: Steroid internal reference — "Spec compliance first, then code quality. Never skip reviews."
The Verification Process
Step 1: Load Context
Read these files to understand what was built:
.memory/changes/<feature>/spec.md — The acceptance criteria (what SHOULD be true)
.memory/changes/<feature>/plan.md — The task list (what was DONE)
.memory/changes/<feature>/tasks.md — The durable live task artifact from execution
.memory/changes/<feature>/execution.json — The durable execution receipt from engine
.memory/changes/<feature>/context.md — The project context (tech stack, test infra)
.memory/changes/<feature>/prompt.json — The normalized user intent, if present
.memory/changes/<feature>/design-routing.json — The internal frontend routing receipt, if present
.memory/changes/<feature>/accessibility.json — The latest AccessLint receipt, if present
.memory/changes/<feature>/ui-audit.json — The latest Playwright-backed browser audit receipt, if present
.memory/changes/<feature>/preview-url.txt — An explicit preview target if the browser audit was pointed at one
.memory/changes/<feature>/ui-review.md — The consolidated frontend review summary, if present
.memory/changes/<feature>/ui-review.json — The machine-readable frontend review receipt, if present
Extract:
- All acceptance scenarios (Given/When/Then) from spec.md
- All completed tasks from plan.md and the live task mirror in tasks.md
- Fresh execution evidence from execution.json when present
- Test framework and run command from context.md
- All success criteria (SC-001, SC-002, etc.) from spec.md
- Recommended route, assumptions, and non-goals from prompt.json when available
- Imported frontend systems selected for the feature from design-routing.json when available
- AccessLint findings from accessibility.json when available
- Browser-runtime findings from ui-audit.json when available
- Preview target hints from preview-url.txt, environment variables, or
.env* files when deep browser audit is requested
- The final frontend review verdict from ui-review.md when present
- The machine-readable frontend review verdict from ui-review.json when present
If the feature followed the fix pipeline and uses diagnosis.md instead of plan.md, read that targeted fix plan as the execution source instead of failing immediately.
Step 1b: Success Criteria Verification (v5.0.2)
Read spec.md for any ## Success Criteria section. For EACH criterion:
- Verify it — run the check if possible (e.g.,
npm run build for performance)
- Or mark explicitly as "⚠️ Requires manual testing" with reason
Report in verify.md:
## Success Criteria
| SC | Criterion | Status | Method |
| ------ | ------------------- | ----------- | ------------------------ |
| SC-001 | Lighthouse 95+ | ⚠️ Manual | Requires browser testing |
| SC-002 | Theme toggle <100ms | ✅ Verified | Measured via code review |
Do NOT mark verify.md as PASS if mandatory success criteria exist but none were checked.
Step 2: Spec Compliance Review
Source: Steroid internal reference
"Your job is to compare the task's stated requirements against the actual code. Do NOT trust the implementer's report. Read the actual code."
For EACH acceptance criterion in spec.md:
- Find the code that implements it (grep for related functions, components, routes)
- Read the actual code — not just the file name, the implementation
- Determine status:
- ✅ IMPLEMENTED — Code exists AND handles the described scenario
- ⚠️ PARTIAL — Code exists but missing edge cases or error handling
- ❌ MISSING — No code found that addresses this criterion
- 🔄 EXTRA — Code does something NOT in the spec (flag for review)
Critical mindset (from Steroid Verifier): "Do NOT trust SUMMARY.md claims. SUMMARYs document what the AI SAID it did. You verify what ACTUALLY exists in the code. These often differ."
Step 3: Code Quality Review
Source: Steroid internal reference
Review all files created or modified during the feature. For each file, check:
- Single Responsibility — Does each file/function do one thing?
- Naming — Are names descriptive and consistent with project conventions?
- Error Handling — Are errors caught and handled appropriately?
- No Stubs — Are there any placeholder implementations?
Anti-Pattern Scanning (from Steroid Verifier):
node steroid-run.cjs fs-grep 'TODO|FIXME|HACK|PLACEHOLDER' <file>
node steroid-run.cjs fs-grep 'return null|return \{\}|return \[\]|=> \{\}' <file>
node steroid-run.cjs fs-grep 'console\.log' <file>
Categorize issues by severity:
- 🛑 Critical — Prevents feature from working (missing implementation, broken import)
- ⚠️ Important — Works but fragile (no error handling, hardcoded values)
- ℹ️ Minor — Cosmetic or style issues (naming, unused imports)
Step 3b: AI Code Smell Scan (optional deep verification)
AI models frequently produce code with invisible defects that non-technical users will never catch. Run these scans on the project:
1. Dead Code & Phantom Dependencies — via knip (MIT, 2M+ downloads)
node steroid-run.cjs 'npx knip --no-exit-code --reporter compact'
knip detects: unused files, unused exports, unused dependencies, AND missing dependencies (packages imported but not in package.json). It handles dynamic imports, TypeScript path aliases, and framework-specific patterns that grep cannot.
If knip reports missing dependencies → 🛑 Critical (app will crash on launch).
If knip reports unused dependencies → ⚠️ Important (bloated bundle).
2. Circular Dependencies — via madge (MIT)
node steroid-run.cjs 'npx madge --circular src/'
Circular imports (A → B → C → A) cause undefined values at runtime. AI-generated code creates these constantly because the AI doesn't see the global dependency graph. If madge finds any → 🛑 Critical.
3. Hardcoded Secrets — via gitleaks (MIT, 100+ patterns)
node steroid-run.cjs 'npx @ziul285/gitleaks detect --no-git --source .'
Covers AWS, Stripe, Twilio, Firebase, Supabase, SendGrid, GitHub tokens, and 90+ other services. If any secrets found → 🛑 Critical (security breach risk).
If gitleaks is unavailable (Go binary not supported on platform), fall back to:
node steroid-run.cjs fs-grep '(sk-|pk_live_|ghp_|AKIA|rk_live_|Bearer |password\s*=\s*\")' src --include=*.js --include=*.ts --include=*.jsx --include=*.tsx --include=*.py --limit=20
4. Placeholder Content & Deprecated APIs (grep — no good MIT tool exists)
node steroid-run.cjs fs-grep '(example\.com|lorem ipsum|placeholder|https?://api\.example)' src --include=*.js --include=*.ts --include=*.jsx --include=*.tsx --limit=20
node steroid-run.cjs fs-grep '(componentWillMount|componentWillReceiveProps|findDOMNode)' src --include=*.js --include=*.ts --include=*.jsx --include=*.tsx --limit=20
If placeholders found → ⚠️ Important. If deprecated APIs found → ⚠️ Important.
Verdict Rule: If ANY 🛑 Critical finding exists, the final verdict MUST be CONDITIONAL, not PASS. Document each finding with file path, line number, and explanation.
Step 4: Test Execution
Read the test framework from context.md. If tests exist:
node steroid-run.cjs '<test-command>'
Record:
- Whether tests pass or fail
- Number of tests run
- Any test failures with file + line
If NO test framework detected, note this as a gap but don't fail verification.
Test Enforcement (v5.0.2): If spec.md has acceptance criteria AND the test count is 0:
- Verdict MUST be CONDITIONAL, not PASS
- Add warning: "⚠️ No tests found. TDD mandate not followed."
- List which acceptance criteria lack test coverage
- Exception: If spec explicitly notes "No tests required" or project is static/docs-only
Step 5: Lint & Type Check (If Available)
node steroid-run.cjs 'npx tsc --noEmit'
node steroid-run.cjs 'npx eslint src/ --max-warnings=0'
Only run if the tools are detected in context.md / package.json.
Step 5a+: Language-Aware Verification (v5.4.0)
Read the tech stack from context.md and use the appropriate commands:
| Language | Build | Lint | Type Check | Test |
|---|
| JS/TS | npm run build | npx eslint src/ | npx tsc --noEmit | npm test |
| Python | python -m py_compile *.py | flake8 or ruff check . | mypy . | pytest |
| Rust | cargo build | cargo clippy | (built-in) | cargo test |
| Go | go build ./... | golangci-lint run | (built-in) | go test ./... |
| Java | mvn compile or gradle build | checkstyle | (compiler) | mvn test or gradle test |
| Ruby | (none) | rubocop | (none) | rspec or rake test |
| PHP | (none) | phpcs or phpstan | (none) | phpunit |
Wrap ALL commands in: node steroid-run.cjs '<command>'
Only run the checks that match the detected language. Skip unavailable tools gracefully.
Step 5b: Infrastructure Verification (v5.0.2)
Before writing the final verdict, check these physical items:
- Build —
node steroid-run.cjs 'npm run build' exits 0 (if build script exists)
- Lint warnings — Run the project's linter. Report warnings AND errors, not just errors.
- Dependencies —
node steroid-run.cjs 'npm ls --depth=0' — no unmet peer deps
- Config integrity —
.gitignore still contains steroid entries
- Progress updated —
.memory/progress.md Codebase Patterns is not "Unknown"
- Version —
package.json has a valid semver version field (v5.2.0)
- README exists — Project has a
README.md with install + run instructions (v5.2.0)
- License audit (v5.3.0) — If
license-checker is installed, run node steroid-run.cjs 'npx license-checker --summary'. If it is unavailable, record the check as SKIP instead of chaining a shell fallback. Flag GPL/AGPL (viral — may require open-sourcing), unlicensed, or deprecated packages. For non-technical users: "All dependencies use permissive licenses ✅" or "⚠️ Found GPL dependency"
Report each check in verify.md under ## Infrastructure.
Step 6: Determine Overall Status
PASS — All acceptance criteria IMPLEMENTED, no Critical issues, tests passing (if any)
FAIL — Any acceptance criterion MISSING, Critical issues found, or tests failing
CONDITIONAL — All criteria implemented but Important issues exist or no tests
Step 6b: Write review.md / review.json
Before final verification verdict output, persist the two-stage review results to:
.memory/changes/<feature>/review.md
.memory/changes/<feature>/review.json
These files are the durable review artifacts for the governed review-and-verify slice. They must summarize the Stage 1 and Stage 2 findings and preserve severity-based findings.
Step 7: Write verify.md / verify.json
Write results to .memory/changes/<feature>/verify.md and .memory/changes/<feature>/verify.json:
# Verification Report: <feature>
**Verified:** <timestamp>
**Status:** PASS | FAIL | CONDITIONAL
**Spec Score:** <implemented>/<total> criteria verified
## Spec Compliance
| # | Criterion | Status | Evidence |
| --- | -------------- | -------------- | -------------------------- |
| 1 | <from spec.md> | ✅ IMPLEMENTED | <file:line — what it does> |
| 2 | <from spec.md> | ❌ MISSING | <what's not there> |
## Code Quality
### Issues Found
| File | Line | Severity | Issue |
| ------ | ------ | ------------ | ------------- |
| <path> | <line> | 🛑 Critical | <description> |
| <path> | <line> | ⚠️ Important | <description> |
### Strengths
- <positive observations>
## Test Results
- **Framework:** <from context.md>
- **Result:** <pass/fail/no tests>
- **Tests Run:** <count>
- **Failures:** <count and details>
## Lint / Type Check
- **TypeScript:** <pass/fail/not applicable>
- **ESLint:** <pass/fail/not applicable>
## Anti-Patterns
| File | Line | Pattern | Impact |
| ------ | ------ | ----------------- | ----------------- |
| <path> | <line> | <TODO/stub/empty> | <what it affects> |
## Overall Assessment
<2-3 sentence summary. What works, what doesn't, what needs attention.>
---
_Verified: <timestamp>_
_Verifier: steroid-verify_
verify.json is the machine-readable verification verdict. When .memory/changes/<feature>/execution.json exists, the verdict must be attributable to that fresh execution evidence rather than to a completion claim alone.
Step 7b: Write completion.json
If verification status is PASS or CONDITIONAL, write .memory/changes/<feature>/completion.json.
This is the governed live completion receipt. It must be downstream of:
.memory/changes/<feature>/verify.json
.memory/progress.md
It must preserve the fixed completion options:
merge_back_locally
push_and_create_review
keep_workspace
discard_work
The receipt should record:
feature
status
source_artifacts: ["verify.json", "progress.md"]
options
summary
After Verification
If PASS:
- Output: "✅ Verification passed. Feature ready to archive."
.memory/changes/<feature>/completion.json must exist before archive handoff
- The archive command will now succeed (gate requires
verify.json with PASS)
If FAIL:
- Output: "❌ Verification failed. issues must be resolved."
- List the Critical/Missing items
- The engine must re-run to fix these items before re-verification
If CONDITIONAL:
- Output: "⚠️ Verification conditional. Feature works but has Important issues."
.memory/changes/<feature>/completion.json must exist before archive handoff
- Ask the user: "Archive now or fix first?"
The Silence Directive
The human at the keyboard is a non-technical System Builder. Do NOT dump raw test output, grep results, or lint errors to the main chat.
Instead:
- Summarize: "Found 2 issues in the login component that need fixing."
- Show the verify.md summary, not the raw evidence
Referenced Forks
Steroid internal reference — The complete goal-backward verification system (582 lines)
Steroid internal reference — Spec compliance review template (62 lines)
Steroid internal reference — Code quality review template (27 lines)
Steroid internal reference — Evidence-before-claims gate (140 lines)
Steroid internal reference — If verification reveals bugs, use this for diagnosis