원클릭으로
opsx-annotate
Apply Bucket 1 `@spec` tags from a coverage report — creates a ghost change and opens an annotation-only PR (Experimental)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Apply Bucket 1 `@spec` tags from a coverage report — creates a ghost change and opens an annotation-only PR (Experimental)
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-annotate |
| description | Apply Bucket 1 `@spec` tags from a coverage report — creates a ghost change and opens an annotation-only PR (Experimental) |
| metadata | {"category":"Retrofit","tags":["retrofit","annotate","experimental"]} |
Check the active model from your system context.
"This command requires Sonnet or Opus — applying spec annotations correctly across many files needs stronger reasoning than Haiku can reliably provide. Please switch to Sonnet or Opus and re-run."
Apply @spec openspec/changes/{change}/tasks.md#task-N PHPDoc tags to the Bucket 1 entries from a coverage report. Creates one ghost change per run and points all annotations at its tasks. Produces an annotation-only PR — no logic changes, no refactors, no formatting cleanups.
Part of the retrofit playbook. Run /opsx-coverage-scan {app} first.
Legacy code doesn't have a change artifact to point at. This skill creates one:
retrofit-{YYYY-MM-DD}-annotate-{app}proposal.md: "Retrofit — annotate {N} existing methods against {M} REQs across {K} capabilities"specs/ delta: empty (all REQs already exist in openspec/specs/)tasks.md: one task per REQ with Bucket 1 matches (format: - [x] task-N: {capability}#{REQ-NNN} — {REQ title} (retroactive annotation))The change is archived at the end of the run so it lands in openspec/changes/archive/. Tag paths remain valid because @spec openspec/changes/... is a textual reference, not a live lookup.
Input: {app} — app slug. Must have openspec/coverage-report.json < 24h old.
Steps
Verify prereqs
{app}/openspec/coverage-report.json exists and its generated_at field is < 24h old (use generated_at, not filesystem mtime). Missing/stale → stop, run /opsx-coverage-scan {app} first..opsx-ignore is honored transitively — this skill never re-reads {app}/.opsx-ignore; it trusts the coverage-scan to have already filtered Bucket 1. If the user adds entries to .opsx-ignore and expects them to take effect during annotation, they MUST re-run /opsx-coverage-scan {app} first.lib/**/*.php and src/**/*.js for @spec openspec/changes/retrofit-*-annotate-{app} tags. If any are found, extract the date suffix from the ghost change name (e.g., retrofit-2026-04-23-annotate-{app} → 2026-04-23). If that date is newer than the coverage report's generated_at date, warn the user:
"⚠️ Found annotations from
retrofit-{date}-annotate-{app}that post-date this coverage report (generated{generated_at}). The report may have been generated before those annotations were applied, so Bucket 1 could include already-annotated methods. Re-running/opsx-coverage-scan {app}is strongly recommended before proceeding." Show the count of already-annotated methods and proceed only if user confirms.
git status --porcelain empty). Refuse dirty trees.coverage-report.json.branch).retrofit/annotate-{app}-{YYYY-MM-DD}. If it exists, reuse it.1.5. Idempotent-rerun guard
Grep lib/**/*.php and src/**/*.js for @spec openspec/changes/retrofit-*-annotate- tags. Also list any openspec/changes/archive/retrofit-*-annotate-{app} directories on disk. If any tags or archived ghost changes are found, a prior run has already annotated this app.
Display what was found:
retrofit-*-annotate-{app} tags, and which ghost change names they referenceopenspec/changes/archive/retrofit-{date}-annotate-{app}/ directories presentAsk via AskUserQuestion:
@spec openspec/changes/retrofit-*-annotate-{app} tag (regardless of date) will be skipped — only unannotated methods from the current report are touchedDo not proceed silently — a second ghost change mints duplicate tasks and produces a confusing PR.
Load the plan from JSON
Read openspec/coverage-report.json. Extract buckets.bucket_1.
needs_review: true entries. Tell user how many were skipped.annotated bucket already separates them out, but double-check during the edit pass (defensive).Group Bucket 1 by capability → req_id → list of methods. This becomes the task layout.
Announce the plan and confirm
## Annotation Plan — {app}
Ghost change: retrofit-{YYYY-MM-DD}-annotate-{app}
Tasks to create: {M} (one per REQ with matches)
Files to touch: {F}
Methods to tag: {N}
Capabilities: {list}
Skipped (NEEDS-REVIEW): {K}
Use AskUserQuestion:
Bootstrap labels on the target repo (once per repo)
Check whether retrofit and annotation-only labels exist:
gh label list --repo ConductionNL/{app} | grep -E "^(retrofit|annotation-only)\b" || true
If missing, create them:
gh label create retrofit --color 5319E7 --repo ConductionNL/{app} || true
gh label create annotation-only --color C5DEF5 --repo ConductionNL/{app} || true
Create the ghost change scaffold
Prefer the existing skill (handles schema + scaffolding):
/opsx-new retrofit-{YYYY-MM-DD}-annotate-{app}
If /opsx-new isn't available, create the directory manually:
{app}/openspec/changes/retrofit-{YYYY-MM-DD}-annotate-{app}/
proposal.md
tasks.md
Fill in:
proposal.md:
# Retrofit — annotate {app} against existing specs
Retroactive annotation of {N} methods across {F} files against {M} REQs in {K} capabilities. No code logic changes. No spec deltas (all REQs already exist in openspec/specs/).
Source: openspec/coverage-report.md generated {YYYY-MM-DD} (Bucket 1 only).
See [retrofit playbook](../../../.github/docs/claude/retrofit.md).
tasks.md — one task per REQ, numbered by encounter order. All tasks arrive [x] because the code is pre-existing:
# Tasks
- [x] task-1: meeting-management#REQ-001 — Meetings are listed chronologically (retroactive annotation)
- [x] task-2: meeting-management#REQ-003 — Meetings can be cancelled (retroactive annotation)
- [x] task-3: motion-and-voting#REQ-012 — Motions collect votes until close (retroactive annotation)
Record the task-number-for-each-REQ map — you'll need it for annotation.
Annotate code — one file at a time, single Edit pass per file
For each unique file in Bucket 1:
a. Read the file.
b. Determine the set of @spec tags this file needs. Collect every req_id for methods in this file + any helpers that inherited REQs from this file's methods. Map each to its task-N from step 5. The file docblock needs one @spec tag per distinct task.
c. Apply file-docblock edits:
/** */ block immediately above class, namespace, or first declaration).@spec openspec/changes/retrofit-{YYYY-MM-DD}-annotate-{app}/tasks.md#task-N tags after the @link tag per the hydra-gate-spdx format. One tag per distinct task. Preserve the existing tag order.@category, @package, @author, @copyright, @license, @link, @spec tag(s)).@spec tags pointing at non-retrofit changes, leave them — append the retrofit ones after.d. Apply method-docblock edits: For each method in this file that's in Bucket 1 or inherited-from-Bucket-1:
@spec openspec/changes/retrofit-*-annotate-{app}. If found (any date suffix), skip this method entirely — log: [skip] {ClassName}::{method}() — already has retrofit-annotate tag. Do not add a second tag, do not remove the old tag. This prevents accumulating duplicate @spec lines across re-runs./** {one-line description}\n * @spec ... */).@spec openspec/changes/retrofit-{YYYY-MM-DD}-annotate-{app}/tasks.md#task-N after any existing @param/@return/@throws/@spec tags.*) between the last non-@spec tag and the @spec tag. Always insert * before the first @spec if any tag precedes it. Example:
* @return Configuration[] Array of entities
*
* @spec openspec/changes/.../tasks.md#task-N
Missing the blank line causes Expected 1 blank line before summary; 0 found PHPCS errors. Run phpcbf to auto-fix indentation; blank-line errors must be inserted manually.e. Write the file via Edit tool. Never sed/awk/python. If the linter hook reverts the Edit, rewrite the whole file via Write (project rule: high probability of breaking code when scripting edits).
One file at a time, sequential — Edit tool's file-state tracking doesn't batch safely.
Run the linter gates
From the workspace root:
cd {app} && composer phpcs 2>&1
For frontend-heavy apps, also:
cd {app} && npm run lint 2>&1
Also run Hydra's mechanical gates (they're what the reviewer checks against):
/hydra-gates
If any gate fails due to tag ordering/placement: do not reorder tags to satisfy the linter. The ADR-003 + hydra-gate-spdx format is fixed. Fix the PHPCS config instead. Stop, report the specific rule, wait for guidance.
Commit annotations + ghost change
cd {app}
git add -A
git commit -m "retrofit: annotate {N} methods across {F} files (Bucket 1)
Applied @spec tags pointing at ghost change retrofit-{YYYY-MM-DD}-annotate-{app}.
No logic changes. Source: openspec/coverage-report.md."
Capture the commit SHA.
Update .git-blame-ignore-revs
Append the annotation commit's SHA:
printf '# Retrofit annotation commit (opsx-annotate, {YYYY-MM-DD})\n{SHA}\n' >> .git-blame-ignore-revs
git add .git-blame-ignore-revs
git commit -m "retrofit: add annotation commit to blame-ignore-revs"
Tell the user (don't run automatically — per-developer choice):
"Each developer cloning this repo must enable it once:
git config blame.ignoreRevsFile .git-blame-ignore-revs"
Archive the ghost change
/opsx-archive retrofit-{YYYY-MM-DD}-annotate-{app}
Moves the change dir to openspec/changes/archive/retrofit-*-annotate-.../. Since the ghost change has no spec deltas, no capability specs are modified.
Sanity check — verify annotations
Re-read openspec/coverage-report.json (it's stale, but still shows Bucket 1 items). Grep each file for the expected @spec ... retrofit-{YYYY-MM-DD}-annotate-{app} tag. Count annotations and compare against the Bucket 1 count. Mismatch → stop, investigate before pushing.
Do NOT call /opsx-coverage-scan again here — it's expensive and the sanity check above is sufficient.
Push and create PR
git push -u origin retrofit/annotate-{app}-{YYYY-MM-DD}
Invoke /create-pr (or gh pr create directly). PR title:
retrofit: annotate {app} Bucket 1 (N methods / M REQs)
PR body:
## Retrofit — Annotation Only
Applies `@spec openspec/changes/retrofit-{date}-annotate-{app}/tasks.md#task-N` tags per [ADR-003 §Spec traceability](hydra/openspec/architecture/adr-003-backend.md).
Ghost change: `openspec/changes/archive/retrofit-{date}-annotate-{app}/` (empty spec delta, {M} tasks).
### What this PR does
- Creates ghost change with {M} tasks (one per REQ with Bucket 1 matches)
- Adds {N} method-level `@spec` tags across {F} files
- Adds file-docblock `@spec` tags where missing
- Adds this commit to `.git-blame-ignore-revs`
### What this PR does NOT do
- No logic changes
- No formatting / whitespace / reordering
- No Bucket 2 (see follow-up `/opsx-reverse-spec` PRs)
- No Bucket 3/4 (separate follow-ups)
### Verification
- [ ] `composer phpcs` / `npm run lint` passes
- [ ] `/hydra-gates` passes
- [ ] Diff is annotations + ghost change only
- [ ] `.git-blame-ignore-revs` includes the annotation commit
Source: `openspec/coverage-report.md` generated {YYYY-MM-DD}
Labels: retrofit, annotation-only.
Summary
## Annotation Complete — {app}
Ghost change: retrofit-{YYYY-MM-DD}-annotate-{app} (archived)
Tasks created: {M}
Files touched: {F}
Methods tagged: {N}
Skipped (NEEDS-REVIEW): {K}
Branch: retrofit/annotate-{app}-{YYYY-MM-DD}
PR: {url}
Next:
1. Merge this PR before proceeding to Bucket 2
2. For each Bucket 2a cluster: `/opsx-reverse-spec {app} --extend <capability>`
3. For each Bucket 2b cluster: `/opsx-reverse-spec {app} --cluster <name>`
4. Optionally re-run `/opsx-coverage-scan {app}` after merge to refresh the report
Guardrails
@license + @copyright + @spec all in the same block, never as // SPDX-... line comments.@spec openspec/changes/retrofit-*-annotate-{app} tag (from any prior dated run), skip it entirely — do not add a second annotation-pass tag. You may still add tags from opsx-reverse-spec ghost changes (e.g., retrofit-2026-04-30-chat-ai) alongside an existing annotate-pass tag; those are reverse-spec tags, not annotation-pass tags. Don't rewrite or remove old tags.After the pass, route each new observation through the two-stage buffer:
High-confidence observation (directly confirmed this run, matches an existing pattern, or fixes a measured eval failure in evals/grading.json) → append directly to learnings.md under the appropriate section: Patterns That Work, Mistakes to Avoid, Domain Knowledge, or Open Questions.
Unverified observation (only seen once, feels useful but not yet confirmed) → append to learning-candidates.md. Entries are promoted to learnings.md once the promotion criteria are met (confirmed in 3+ executions, resolve a measured eval failure, or receive explicit user endorsement) and discarded after 30 days otherwise.
Categories to capture:
Each entry must start with today's date in YYYY-MM-DD format. One insight per bullet. Skip entirely if nothing new was learned.
Consolidation trigger — if learnings.md exceeds ~80–100 entries, run a consolidation pass: merge duplicates, remove outdated items, and promote any pattern confirmed in 3+ entries into the Consolidated Principles section. Principles there are candidates for promotion to SKILL.md Guardrails on the next edit.
💡 Switch models back with
/model <name>when done.