ワンクリックで
opsx-verify
Verify implementation matches change artifacts before archiving
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Verify implementation matches change artifacts before archiving
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Reset the OpenRegister development environment (stop, remove volumes, restart, install apps)
Create a Pull Request from the current branch — runs local checks, picks target branch, and opens the PR on GitHub
Analyze a project's OpenSpec from 8 persona perspectives and suggest additional features
Detect admin settings Vue components registered in the vue-router. Admin settings are rendered by Nextcloud's settings framework via `AdminSettings.php`; adding their Vue components to the in-app router exposes them as publicly-accessible frontend routes, bypassing all server-side access checks. ADR-004 hard rule. Observed 2026-04-30 on doriath where `/settings → AdminRoot` was a route in `src/router/index.js` (commit c7c72e9).
Run `composer audit` to check composer.lock dependencies for known CVEs. Invoked by the builder before push and the reviewer's mandatory block. Mirrors the orchestrator's `composer-audit` quality gate.
Scan lib/ for forbidden debug helpers (var_dump / die / error_log / print_r / dd / dump) that should not ship. Invoked by the builder before push, by the reviewer as Mandatory Step 2, and by the fixer during a retry. Mirrors the orchestrator's `forbidden-patterns` quality gate.
| name | opsx-verify |
| description | Verify implementation matches change artifacts before archiving |
| metadata | {"category":"Workflow","tags":["workflow","verify","experimental"]} |
Check the active model from your system context (it appears as "You are powered by the model named…").
"This command requires Sonnet or Opus — verifying implementation against specs and running tests needs stronger reasoning than Haiku can reliably provide. Please switch to Sonnet (
/model sonnet) or Opus (/model opus) and re-run."
Verify that an implementation matches the change artifacts (specs, tasks, design).
/opsx-verify <change-name> or /opsx-verify (prompts). Verifies a single OpenSpec change against its artifacts. This is the mode used during normal feature work, before archiving./opsx-verify --app <slug>. Runs the retrofit "definition of done" check across an entire retrofitted app. Walks all retrofit ghost changes under {app}/openspec/changes/archive/retrofit-*, scans for dangling @spec paths, audits cohort frontmatter, etc. Required by the retrofit playbook "When the retrofit is done" section.Mode dispatch:
--app , follow the App Mode steps in §A1–A6 below; skip the per-change Steps 1–11.openregister), ask once via AskUserQuestion whether they meant --app openregister (retrofit DoD) or the change literally named openregister (likely doesn't exist). Default to --app for the canonical Nextcloud app slugs (openregister, procest, pipelinq, decidesk, docudesk, openconnector, nldesign, mydash, softwarecatalog, larpingapp, zaakafhandelapp, opencatalogi).--app <slug>)Designed to satisfy the playbook's "When the retrofit is done" checklist mechanically, without depending on openspec status (which only knows active changes — archived retrofits would be invisible to it).
<workspace>/{slug}/{slug}/openspec/ is a directoryfind {app}/openspec/changes -maxdepth 3 -type d -name 'retrofit-*' | sort
Include both {app}/openspec/changes/retrofit-* (active — should normally be empty after archive) and {app}/openspec/changes/archive/retrofit-*. Anything matching is a "retrofit ghost change" for the report.
For each retrofit folder R:
| Check | Expected | Failure level |
|---|---|---|
R/proposal.md exists | always | CRITICAL |
R/tasks.md exists | always | CRITICAL |
All tasks [x] | always (retrofit convention — code already exists) | CRITICAL |
R/design.md exists | reverse-spec runs (cluster/extend) only — annotate runs and cross-ref ghosts are exempt | WARNING for missing on reverse-spec; not flagged otherwise |
R/specs/{cap}/spec.md exists | reverse-spec runs only | WARNING for missing on reverse-spec; not flagged otherwise |
@spec openspec/changes/{R-basename} count in lib/ + src/ | annotate runs: large (≥ 50). Reverse-spec runs: ≥ 1 method per task. Private-helper inheritance retrofits: 0 is intentional — read R/proposal.md first to confirm | WARNING if 0 on a non-inheritance retrofit |
Annotate-vs-reverse-spec detection: if R matches retrofit-*-annotate-*, treat as annotate. Otherwise treat as reverse-spec unless R/proposal.md explicitly says "cross-ref" or "private helper".
Dangling @spec scan: any @spec openspec/changes/<X> reference in lib//src/ whose <X> doesn't resolve to a folder in either {app}/openspec/changes/ or {app}/openspec/changes/archive/.
grep -roh "@spec openspec/changes/[a-z0-9-]*" {app}/lib/ {app}/src/ \
--include="*.php" --include="*.js" --include="*.ts" --include="*.vue" 2>/dev/null \
| sed 's|^@spec openspec/changes/||' | sort -u | while read change; do
[ -d "{app}/openspec/changes/$change" ] || [ -d "{app}/openspec/changes/archive/$change" ] || echo "DANGLING: $change"
done
Any output is CRITICAL.
Symlink scan: any symlink under {app}/openspec/changes/ is an anti-pattern (legacy of the 2026-05-01-retrofit-X-2026-05-01 half-archive workflow).
find {app}/openspec/changes -maxdepth 1 -type l
Any output is CRITICAL.
Naming convention: every retrofit folder must match retrofit-{YYYY-MM-DD}-{descriptor} (date right after retrofit-).
ls {app}/openspec/changes/archive/ | grep -E '^retrofit-' \
| grep -vE '^retrofit-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z][a-z0-9-]*$'
Any output is CRITICAL — usually means a retrofit was created before the convention switched (e.g. retrofit-{descriptor}-{date} order or the redundant 2026-05-01-retrofit-X-2026-05-01 form). Rename via git mv and update text references.
Cohort frontmatter coverage: every capability that received new retrofit-derived REQs must carry the cohort flag on its master spec. Documentation-only retrofits do NOT require frontmatter — the cohort flag is for tracking REQ provenance, not annotation provenance.
Step 1: classify each retrofit ghost change. Walk every R and decide:
R/specs/{cap}/spec.md with at least one ### REQ-NNN: heading. The capability {cap} enters the cohort and MUST carry frontmatter.specs/ delta, OR the proposal.md explicitly says one of: "no new REQs", "no new REQs needed", "no new REQs drafted", "no new REQs required", "behaviors are fully covered". Examples: cross-capability annotation patches (b2b-crossrefs), private-helper inheritance retrofits (schema-hooks), scanner-misclassification cleanups (tenant-isolation-audit). These do NOT require cohort frontmatter on any capability.retrofit-{date}-annotate-{app}. Never adds REQs; never requires frontmatter.Step 2: build the cohort set. Union of {cap} values from REQ-adding retrofits only.
Step 3: verify each cohort capability has retrofit: true (cluster) or retrofit_extensions: [...] (extend) in {app}/openspec/specs/{cap}/spec.md frontmatter.
Step 4: format check. retrofit_extensions MUST be block YAML with bare REQ-IDs (per /opsx-reverse-spec SKILL.md Step 8). Inline [REQ-005] or quoted ["REQ-005"] is WARNING; full requirement-text values are CRITICAL.
Missing cohort flag on a REQ-adding capability is CRITICAL — sync_spec_content.py won't tag the capability as retrofit cohort in Specter. Missing cohort flag on a documentation-only capability is expected and not a finding.
Coverage report freshness (informational only): if {app}/openspec/coverage-report.json exists, compare its generated_at timestamp to the most recent retrofit ghost change date. Stale report ≠ failure, but worth reporting.
## Retrofit Verify: {app}
### App-level checks
| Check | Status | Detail |
|---|:-:|---|
| Retrofit ghost changes | ✅ N found, M archived | Newest: <date> |
| Tasks completion | ✅ all [x] / ⚠️ N incomplete | |
| Dangling @spec paths | ✅ 0 / ❌ N | <list> |
| Symlinks under changes/ | ✅ 0 / ❌ N | <list> |
| Naming convention | ✅ N/N / ❌ N malformed | <list> |
| Cohort frontmatter | ✅ K/K / 🟡 K/K (missing: <caps>) | |
| Frontmatter format | ✅ block YAML / ⚠️ N inline / ❌ N full-text | |
### Per-retrofit details
(table with proposal/tasks/design/spec-delta/tasks-done/@spec-count per retrofit)
### Verdict
- ✅ **Retrofit complete** — all checks pass
- 🟡 **Retrofit partial** — only WARNINGs and informational items
- ❌ **Retrofit incomplete** — CRITICAL items remain (list them)
{app}. Safe to mark the playbook checklist complete."retrofit: / retrofit_extensions: to {app}/openspec/specs/{cap}/spec.md and re-run python3 concurrentie-analyse/scripts/sync_spec_content.py {app}.git mv to canonical form + update text references.@spec → either restore the missing change folder, or update the dangling annotations to point at an existing change.App Mode does not invoke /opsx-archive and does not propose fixes interactively — it is a read-only DoD audit.
The remaining steps describe the original per-change verify. Skipped when --app is specified.
Steps
If no change name provided, prompt for selection
Run openspec list --json to get available changes. Use the AskUserQuestion tool to let the user select.
Show changes that have implementation tasks (tasks artifact exists). Include the schema used for each change if available. Mark changes with incomplete tasks as "(In Progress)".
IMPORTANT: Do NOT guess or auto-select a change. Always let the user choose.
Check status to understand the schema
openspec status --change "<name>" --json
Parse the JSON to understand:
schemaName: The workflow being used (e.g., "spec-driven")Get the change directory and load artifacts
openspec instructions apply --change "<name>" --json
This returns the change directory and context files. Read all available artifacts from contextFiles.
Additionally, load optional artifacts if present:
openspec/changes/<name>/test-plan.md — pre-defined test cases mapped to spec scenarios; use as the primary oracle for scenario coverage and testingopenspec/changes/<name>/contract.md — formal API contract; if present, it is the authoritative interface definition and takes precedence over design.md for API verificationInitialize verification report structure
Create a report structure with three dimensions:
Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.
Verify Completeness
Task Completion:
- [ ] (incomplete) vs - [x] (complete)[x] in tasks.md but whose plan.json status is not "done", treat it as just-completed and run the full GitHub sync below. If plan.json does not exist, skip all GitHub sync steps silently.[x] in tasks.md[x] in tasks.md[x] in tasks.md (whether already complete before this run, or just completed above), if plan.json exists and that task's status in plan.json is not "done":
- [ ] **1.1 Task title**), change it to - [x]; then scan every immediately following line — for each line starting with - [ ] (2-space indent), change it to - [x]; stop scanning at any line that is NOT an indented sub-checkbox (blank line, new parent checkbox, section header, etc.)get_issue → {owner, repo, issue_number: <tracking_issue>} → apply the above changes for all tasks → update_issue → {owner, repo, issue_number: <tracking_issue>, body: <updated_body>}gh issue view <tracking_issue> --repo <repo> --json body --jq '.body' → apply the above changes for all tasks → gh issue edit <tracking_issue> --repo <repo> --body "<updated_body>"update_issue call — fetch the body once, apply all checkbox changes, then write it back once.plan.json: set "status": "done" for that taskSpec Coverage:
openspec/changes/<name>/specs/:
Verify Correctness
Requirement Implementation Mapping:
Scenario Coverage:
test command field — use it in step 8 to run the right test typeVerify Coherence
Contract Adherence (checked first if contract.md exists):
Design Adherence:
Code Pattern Consistency:
Frontend Pattern Adherence (run if the change touched any .vue/.js/.ts files in src/):
These four checks mirror the mechanical gates 10–13 from scripts/run-hydra-gates.sh. Run them as part of verify so issues are caught at archive time even when the gate run was skipped or the change predates the gates. Each is a CRITICAL finding when violated — they map to ADR-004 hard rules.
Initial state, not DOM (mirrors gate-10):
grep -rnE "getElementById\\s*\\([^)]+\\)[^.]*\\.dataset\\b" src/ \
--include='*.vue' --include='*.js' --include='*.ts' 2>/dev/null
IInitialState::provideInitialState() + loadState() from @nextcloud/initial-state"No admin in vue-router (mirrors gate-11):
for f in src/router/index.js src/router/index.ts src/router.js src/router.ts; do
[ -f "$f" ] || continue
grep -nE "from\\s+['\"][^'\"]*(/Admin[A-Z][A-Za-z]*\\.vue|views/settings/)" "$f"
grep -nE "path\\s*:\\s*['\"]/(settings|admin)\\b" "$f"
done
AdminSettings.php only, never as a vue-router route"NcSelect labels (mirrors gate-12):
find src -name '*.vue' | while read v; do
tr '\n' ' ' < "$v" | grep -oE '<NcSelect[^>]*>' \
| grep -vE '(input-label|inputLabel|aria-label-combobox|ariaLabelCombobox)' \
| sed "s|^|$v: |"
done
inputLabel/ariaLabelCombobox at — breaks WCAG 1.3.1 / 4.1.2; remove any manual <label> and use the built-in prop"Modal/dialog file isolation (mirrors gate-13):
find src -name '*.vue' | grep -vE '^src/(modals|dialogs)/' | while read v; do
grep -lE '<NcModal[ \t>/]|<NcDialog[ \t>/]' "$v" 2>/dev/null
done
src/modals/<Name>.vue (NcModal) or src/dialogs/<Name>.vue (NcDialog) and import in the parent"Test Coverage:
tests/Unit/ or tests/unit/Documentation:
Ask about API and browser testing
After the code-level verification, use AskUserQuestion to ask: "Would you also like to run API and/or browser tests against the specs and implementation?"
Options:
If API testing selected:
a. Discover endpoints — Read {app}/appinfo/routes.php to find endpoints affected by this change. Cross-reference with the specs to identify which endpoints should exist.
b. Test CRUD operations — For each affected resource endpoint, test with curl:
# CREATE
curl -s -u admin:admin -X POST -H "Content-Type: application/json" \
-d '{"name":"Verify Test"}' http://nextcloud.local/index.php/apps/{app}/api/{resource}
# Returns 201 with created object including id
# READ
curl -s -u admin:admin http://nextcloud.local/index.php/apps/{app}/api/{resource}/{id}
# Returns 200 with full object; 404 for non-existent
# LIST
curl -s -u admin:admin http://nextcloud.local/index.php/apps/{app}/api/{resource}
# Returns 200 with array and pagination metadata
# UPDATE
curl -s -u admin:admin -X PUT -H "Content-Type: application/json" \
-d '{"name":"Updated"}' http://nextcloud.local/index.php/apps/{app}/api/{resource}/{id}
# DELETE
curl -s -u admin:admin -X DELETE http://nextcloud.local/index.php/apps/{app}/api/{resource}/{id}
c. Verify against spec scenarios — For each GIVEN/WHEN/THEN scenario in the specs, craft a curl request that exercises it. Check response codes, payloads, and error messages match expectations.
d. NLGov compliance spot-check — Verify the basics:
total, page, pages)message or detail field with proper HTTP statusContent-Type: application/json on all responsese. Add findings as CRITICAL (endpoint broken/missing), WARNING (non-compliant), or SUGGESTION (improvement).
If browser testing selected:
a. Set up browser session — Use browser-1 tools (mcp__browser-1__*):
1. browser_resize → width: 1920, height: 1080
2. browser_navigate → http://nextcloud.local/index.php/apps/{app}
3. If redirected to login:
- browser_fill_form with username: admin, password: admin
- Submit the form
4. browser_snapshot → confirm app loaded
b. Test spec scenarios via browser — For each GIVEN/WHEN/THEN scenario from the specs:
browser_click, browser_type, browser_fill_formbrowser_snapshot to verify expected outcome, browser_take_screenshot with filename: test-results/verify/{change-name}-{scenario-slug}.pngc. Monitor for errors during testing:
browser_console_messages (level: "error") after each actionbrowser_network_requests to catch failed API calls (4xx/5xx)d. Test core flows relevant to the change:
e. Add findings with screenshot evidence. CRITICAL for broken flows, WARNING for degraded UX, SUGGESTION for polish.
Generate Verification Report
Summary Scorecard:
## Verification Report: <change-name>
### Summary
| Dimension | Status |
|--------------|------------------|
| Completeness | X/Y tasks, N reqs|
| Correctness | M/N reqs covered |
| Coherence | Followed/Issues |
| API Tests | Passed/Failed/Skipped |
| Browser Tests| Passed/Failed/Skipped |
Issues by Priority:
CRITICAL (Must fix before archive):
WARNING (Should fix):
SUGGESTION (Nice to fix):
Fix loop — resolve issues and re-verify
If CRITICAL or WARNING issues found:
If fixing:
FIRST: Re-check task completion — regardless of other findings, re-read tasks.md and count - [ ] items:
- [ ]: do NOT offer archive. Show:
⚠️ N task(s) still incomplete — archive is blocked until all tasks are done:
- Task X: <description> (incomplete criteria: ...)
End the session without offering archive.If all tasks [x] AND CRITICAL issues remain (user chose not to fix):
If all tasks [x] AND only SUGGESTION issues or all clear:
## Pipeline Progress, update via PATCH if found, create if not):
## Pipeline Progress
| Stage | Status | Details |
|-------|--------|---------|
| Implementation | ✓ Complete | All N tasks done |
| Quality Checks | ✓ Pass | lint, phpcs, phpstan clean |
| Verification | ✓ Pass | Completeness, correctness, coherence |
| Archive | ready | |
*Updated: YYYY-MM-DD HH:MM UTC*
add_issue_comment → {owner, repo, issue_number: <tracking_issue>, body: "✓ Verified by /opsx-verify — all checks passed"}gh issue comment <tracking_issue> --repo <repo> --body "✓ Verified by /opsx-verify — all checks passed"/opsx-archive for this change/opsx-sync then /opsx-archiveIf all tasks [x] AND only WARNING issues remain (user chose not to fix):
/opsx-archive for this change/opsx-sync then /opsx-archiveVerification Heuristics
Graceful Degradation
Fix Loop Behavior
Output Format
Use clear markdown with:
file.ts:123💡 If you switched models to run this command, don't forget to switch back to your preferred model with
/model <name>(e.g./model defaultor/model sonnet) when done.