agentsclimarketplace

Backlog intake

Skill darylmcd/Roslyn-Backed-MCP/.claude/skills/backlog-intake

Consolidate deep-review artifacts (mcp-server-audit, experimental-promotion, roslyn-mcp-retro) into ai_docs/backlog.md with anchor verification, dedupe, priority classification, and Rule 1/3/4/5 sizing for the backlog-sweep-plan.md planner prompt. Use when: a deep-review / audit wave has produced `*_mcp-server-audit.md` / `*_roslyn-mcp-retro.md` / `*_experimental-promotion.md` files across sibling repos (or this one) and you want them reviewed, deduped, and merged into the backlog as properly-sized initiative rows.From its SKILL.md

Install
npx -y skills add darylmcd/Roslyn-Backed-MCP --skill backlog-intake

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

26.2 KB, as published. Nobody here has run it

Backlog intake

You are triaging a batch of deep-review artifacts into ai_docs/backlog.md. Your job is to turn raw audit / retro / experimental-promotion markdown files into properly-sized, anchor-verified, de-duplicated, priority-ranked rows that the backlog-sweep-plan.md planner prompt can plan against without re-processing.

This skill replaces the eng/new-deep-review-batch.ps1 → sync-deep-review-backlog.ps1 pipeline. The PowerShell pipeline handled only *_mcp-server-audit.md, did literal-text dedupe, and couldn't verify anchors or size rows to Rule 1/3/4. The judgment work belongs in an LLM; the mechanical file-staging is delegated to eng/stage-review-inbox.ps1.

Server discovery

This skill edits repository files, shells out to pwsh / gh / git, and uses Roslyn MCP read-only tools (symbol_search, find_references, get_source_text) to verify anchors. No *_apply / *_preview writers. If you find yourself calling a writer, you are in the wrong skill — stop and hand back.

Input

$ARGUMENTS is optional. Supported flags:

FlagEffect
--stageExplicit staging pass: always run eng/stage-review-inbox.ps1 before triage, even if review-inbox/ already has files.
--skip-stageSkip staging entirely — triage whatever is already in review-inbox/.
--skip-verifySkip the "already shipped?" cross-check against CHANGELOG + recent plans. Faster but riskier.
--no-commitWrite the updated ai_docs/backlog.md but do not create a branch or commit.
--sibling-parent <path>Override the sibling-repo scan root (forwarded to the PS1).
--publishAfter the batch is finalized, file each accepted row as a public GitHub Issue at darylmcd/Roslyn-Backed-MCP via gh issue create. Uses the shared renderer skills/mcp-server-surface-test/lib/render-finding.ps1 so the public Issue body is byte-identical to what /mcp-server-surface-test --auto-file emits. Refuses to file rows whose severity == P0 or area == security — those print to stdout with the security-advisory escalation banner instead. Requires gh on PATH and gh auth status reporting authenticated; falls back to stdout-print with a warning otherwise.

Default (no flags): stage if review-inbox/ is empty, verify against CHANGELOG, commit to a fresh branch off main.

Preconditions (HARD GATES — refuse if any fail)

  1. git CLI on PATH. If not, refuse.
  2. pwsh CLI on PATH (used by the staging script). If not, refuse.
  3. Working tree clean OR the only dirty paths are review-inbox/ + ai_docs/backlog.md. If other paths are dirty, refuse: "Working tree has unrelated changes — commit or stash before intake."
  4. main up to date with origin/main (git fetch origin main first). Refuse if main diverged in a way that requires manual resolution.
  5. ai_docs/backlog.md exists with the ## P2 / P3 / P4 — open work + ## Refs structure. If the file is missing or shape-wrong, refuse: "backlog.md shape is unexpected — hand edit before re-running this skill."

Workflow

Phase 0 — Stage artifacts

Skip this phase if --skip-stage is set.

eng/stage-review-inbox.ps1 discovers artifacts from this repo and configured siblings. The canonical list of recognized shapes lives in that script's .DESCRIPTION → Recognized shapes block — read it there; do not re-list the globs here. Those shapes fall into TWO handling categories:

  1. Prose audit / retro / promotion reports — moved into review-inbox/ for the existing extraction flow.
  2. backlog.d/<finding-id>.md fragments — discovered at <sibling-repo-root>/backlog.d/*.md and at this repo's backlog.d/. Disambiguated from prose reports by the severity: frontmatter key; canonical schema at ai_docs/items/backlog-d-fragment-schema.md.
pwsh -File eng/stage-review-inbox.ps1 -DryRun

Review the dry-run output. If the file list looks right:

pwsh -File eng/stage-review-inbox.ps1

If --stage was passed OR review-inbox/ is empty at the start of the run, also run the real command. If the PS1 finishes with "No new artifacts found" AND review-inbox/ is empty AND no backlog.d/ fragments exist anywhere, refuse: "Nothing to triage. Produce audits first via /mcp-server-stress (bundled prompt at .claude/skills/mcp-server-stress/prompts/maintainer-overlay.md), then re-run."

Record the count: N reports + F fragments staged from M repos for the final summary.

Phase 0.5 — Consume fragments (backlog.d/ pattern)

Fragments take a different path from prose reports. They are not moved into review-inbox/; instead intake reads them in place from each source repo's backlog.d/, dedupes, appends new rows, and deletes the consumed fragments at the source. The deletion IS the consumption record — there is no manifest file.

For each configured sibling repo (and this repo) with a backlog.d/ directory:

  1. Walk <repo>/backlog.d/*.md. For each file, parse YAML frontmatter; require id, source_audit, source_repo, severity, area, server_version, anchors (per ai_docs/items/backlog-d-fragment-schema.md). If any required key is missing OR severity / area is outside the documented enum OR anchors is empty OR the filename does not match id, skip that fragment with a warning — leave it on disk for the audit operator to fix. Do NOT delete malformed fragments.
  2. Dedupe each remaining fragment against existing ai_docs/backlog.md rows in this order:
    • Exact (source_repo, id) match — if a backlog row already cites the same source_repo and the same row id, the fragment is a duplicate. Drop it from the candidate list AND delete the source fragment (the row already represents this finding).
    • Anchor-set similarity — compare each fragment's anchors against existing rows. When ≥50 % of anchor paths overlap on the same shared code (typical for cross-repo audits hitting the same Roslyn-MCP server bug from two reporters), fold the fragment into the existing row's do cell — append the new source_repo and any unique anchors. Delete the source fragment after folding.
    • Already-shipped check — same Phase 2 logic that runs on prose-report candidates (CHANGELOG / recent plans / git log).
  3. Append any non-duplicate, non-shipped fragments as new rows in ai_docs/backlog.md, classified by their severity field into the matching priority band. Use the body paragraph (finding + repro + proposed fix sketch) as the seed for the row's do cell; rewrite into the standard cell shape during Phase 4.
  4. Delete each consumed source fragment with git rm (when the sibling repo is git-tracked) or Remove-Item (when it is not). Track deletions for the final commit message.

Idempotency contract: re-running intake on a clean backlog.d/ (no fragments, or only fragments already represented in ai_docs/backlog.md) is a no-op. The deletion is what makes this true — once consumed, the fragment is gone, so the next pass sees nothing to consume.

Cross-repo mutation note: intake mutates audited sibling repos by deleting fragments under their backlog.d/. This is intentional — it is how the consume-and-track pattern works without a manifest file. The audited repos' authors are expected to be aware that intake has this side effect; if a sibling repo wants to retain a record of what was reported, the prose *_mcp-server-audit.md under its ai_docs/audit-reports/ is preserved and acts as the historical record.

The existing prose-report ingestion flow (Phases 1–6) continues unchanged for review-inbox/*.md artifacts. Fragments and prose reports coexist; they are not mutually exclusive.

Phase 0.6 — Consume aggregated promotion scorecard proposals

If audit-reports/_aggregated-promotion-scorecard.json exists, run:

pwsh -NoProfile -File eng/propose-promotion-scorecard-backlog-rows.ps1

This script is read-only: it emits stable backlog-row proposals for aggregated promotion-scorecard entries whose verdict is promote: blocked or needs-more-evidence, and it lists promote: ready entries as skipped so they continue through /promote-tier.

For each proposal:

  1. If action == "add-new", append the row to the matching priority band using the emitted id, pri, deps, and do fields.
  2. If action == "update-existing", update the existing row's do cell only when the proposal contains new blockers, source repos, or rationale that the row does not already mention.
  3. Preserve idempotency: rerunning the script after a row is represented must produce update-existing, not a duplicate row.
  4. If you intentionally skip a proposal, add a maintainer-readable note to the final summary explaining why it was skipped. Do not silently drop blocked or needs-more-evidence scorecard entries.

The generated do cell cites audit-reports/_aggregated-promotion-scorecard.json; keep that anchor unless you move the scorecard into a different durable location as part of the same batch.

Phase 1 — Extract actionable items (subagent)

Invoke the dedicated backlog-intake-extractor subagent:

Agent(subagent_type: "backlog-intake-extractor", prompt: <<<
reviewInboxPath: <absolute path to review-inbox/>
existingBacklogPath: <absolute path to ai_docs/backlog.md>
>>>)

The agent encapsulates the extraction / filter / dedupe / classify / cross-check flow with a strict Read/Glob/Grep tool policy (no writers) and returns a <<<RESULT>>> envelope containing the deduped row list + notes. See .claude/agents/backlog-intake-extractor.md for the agent's own contract.

Parse the envelope. Capture dedupedRows / dedupeRatio / rawCandidates for the Phase 7 summary. Capture the row list for Phase 2.

Fallback (environments without .claude/agents/ support): spawn a general-purpose subagent and inline the agent's body as the prompt. The agent file is the canonical source of that prompt.

Phase 2 — Verify-not-already-shipped

Skip this phase if --skip-verify is set.

For each candidate row, cross-check:

  1. CHANGELOG.md [Unreleased] + last 3 versions — grep for the tool name, service, or symbol the row cites.
  2. Newest backlog-sweep plan under ai_docs/plans/*_backlog-sweep/ — read its state.json and plan.md. Does any shipped initiative describe the same fix?
  3. Git log, last 100 commits — git log --oneline -n 100 | grep -i <keyword> on tool / service / symbol names.
  4. Code spot-check for rows flagged by 1-3 — open the named service / tool file and confirm the specific behavior still reproduces. For example, if the row says symbol_search("") overflows, grep SymbolSearchService.cs for an empty-query guard.

Don't spot-check every row's code — only the ones where prior evidence suggests the fix may have landed. Budget: ~1 minute per candidate flagged, ~0 for rows with no CHANGELOG / plan / log hit.

If this phase finds a row already shipped, drop it from the candidate list and record "dropped (already shipped per <evidence>)" in the final summary.

Phase 3 — Fix anchors

For each remaining row, verify every service class, tool file, and file:line anchor resolves:

  1. For service-class names (e.g. DeadCodeService, CodeActionService): confirm the .cs file exists at the cited path. If the row says src/RoslynMcp.Roslyn/Services/FooService.cs but only src/RoslynMcp.Roslyn/Services/BarService.cs exists, rewrite the row to cite the real file. Common mistakes the extraction subagent makes:
    • CodeActionsService (plural) → actual is CodeActionService.cs
    • MoveTypeService → actual is TypeMoveService.cs
    • SemanticSearchService → logic lives in CodePatternAnalyzer.cs
    • Hallucinated ServerInfoService / PackageReferenceService / RevertService — tools-layer-only, see src/RoslynMcp.Host.Stdio/Tools/ or the unified service (e.g. UndoService.cs for revert).
  2. For tool registrations (e.g. find_references_bulk): grep src/RoslynMcp.Host.Stdio/Tools/ for Name = "<tool_name>" and cite the real file + line. The PS1 pipeline NEVER did this; it's a distinctive value-add of this skill.
  3. For file:line references (e.g. CompileCheckService.cs:155): run get_source_text on that span to confirm the referenced code is still there.

Rewrite each row's do text to cite both the core service (under src/RoslynMcp.Roslyn/Services/) and the tool registration (under src/RoslynMcp.Host.Stdio/Tools/). Executors can then land on the right file immediately.

If an anchor genuinely cannot be resolved, tag the row with [stale — cited anchor not found; executor may use synthetic examples] per backlog-sweep-plan.md Step 3's anchor-verification guidance, rather than dropping the row.

Phase 4 — Split heroic rows

Apply backlog-sweep-plan.md Rule 1 to each row. A row is heroic (and must be split) if any of:

  • It describes two or more distinct bugs that live in different code paths (different functions, different files).
  • It asks for ≥4 production-file edits to fulfill.
  • Its regression tests are not trivially-additive variants of one shape.
  • Its "do" field contains a numbered "(1) fix A, (2) fix B, (3) fix C" list where each item is a different code change.

Common heroic shapes to watch for:

ShapeSplit strategy
"Fix tool X has 3 issues: schema drift + perf + empty data field"Three rows, one per concern. Often different priorities (schema=P3, perf=P3, empty=P4).
"Scaffolder emits invalid C# because (a) identifier bug, (b) static target, (c) ctor args"Three rows — each touches a different code path in the service.
"Tool A and Tool B both need summary-mode paging"Two rows — different tool files, different handlers, even if the shape is similar.
"Guard X in WorkspaceManager AND in every tool wrapper"Tighten to the single choke point; usually WorkspaceManager alone covers all callers.

For each split, give each child a distinct kebab-case id (prefix with the original id where readable — e.g. scaffold-test-preview-dotted-identifier / -static-target-body / -ctor-arg-stubs).

Phase 5 — Ensure planner-prompt refs

Before writing, verify the Refs table in ai_docs/backlog.md includes these entries (add any missing). Note: the backlog-sweep planner/executor prompts are NOT repo Refs entries — they live globally in ~/.claude/prompts/ (backlog-sweep-plan.md, backlog-sweep-execute.md) and are loaded by the /backlog-sweep:* commands, so do NOT add repo-local rows for them:

PathRole (template text)
ai_docs/bootstrap-read-tool-primer.mdSelf-edit read-only tool primer (Roslyn-MCP read-side tools preferred over Bash/Grep).
ai_docs/runtime.mdBootstrap scope policy — main-checkout self-edit (no *_apply) vs worktree/parallel-subagent sessions.
review-inbox/Source evidence for the open rows. Keep until each row is closed or superseded.

Phase 6 — Archive processed files, write backlog.md, commit

  1. Update updated_at: to current UTC. Record this timestamp as the batch id in the form YYYYMMDDTHHMMSSZ (e.g. 20260424T031936Z).
  2. Re-sort each priority band alphabetically by id.
  3. Ensure the "Standing rules" section includes the initiative-sizing rule: "Size every row to a single backlog-sweep-plan.md initiative: one code path, ≤4 production files, ≤3 test files, one regression-test shape." (add if missing).
  4. Archive the processed review files. Only the files that produced rows this batch — do NOT touch any existing review-inbox/archive/<prior-batch>/ subdirectories.
    mkdir -p review-inbox/archive/{BATCH_ID}
    for f in review-inbox/*.md; do git mv "$f" "review-inbox/archive/{BATCH_ID}/$(basename "$f")"; done
    
    The flat review-inbox/ directory is now empty (save for the archive/ subdirectory) and ready for the next batch to stage into.
  5. Rewrite any review-inbox/<file> citations in the new backlog rows to point at the archive path: review-inbox/archive/{BATCH_ID}/<file>. This keeps anchors resolvable after the move. Use Edit with exact-string replace on each affected row.
  6. Verify the Refs table in ai_docs/backlog.md describes both the flat review-inbox/ (staging) and review-inbox/archive/<batch-ts>/ (processed evidence) roles. The contract: row citations point into the archive; the flat directory is always the next batch's inbox.
  7. Skip the commit if --no-commit; otherwise:
    git switch main
    git pull --ff-only
    git switch -c chore/backlog-audit-intake-{YYYYMMDD}
    git add ai_docs/backlog.md review-inbox/
    git commit -m "..."
    
    Commit message template:
    chore(backlog): intake cross-repo audit + retro batch ({YYYY-MM-DD})
    
    Consolidates actionable items from {N} review files across {M} repos into
    ai_docs/backlog.md. Archived processed files under
    review-inbox/archive/{BATCH_ID}/ so the flat review-inbox/ stays empty for
    the next batch.
    
    Backlog now: {P2-count} P2 + {P3-count} P3 + {P4-count} P4 = {total} open
    rows (up from {prior}). Rows anchored to both core services (src/RoslynMcp.Roslyn/Services/)
    and tool registrations (src/RoslynMcp.Host.Stdio/Tools/) so first executor lands
    on the right file without a scavenger hunt.
    
    - Splits applied: {list of heroic rows that were split}
    - Dropped (already shipped): {list, if any}
    - Verified against CHANGELOG [Unreleased] + last 3 versions + newest backlog-sweep plan.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    
  8. Do NOT push unless the user asked. Leave the branch local.

Why archive instead of a manifest or renamed-in-place

  • Anchor integrity: backlog rows cite review-inbox/… paths. A move + per-batch subdirectory keeps those paths resolvable (and git log --follow preserves history).
  • Next-batch cleanliness: Phase 0's staging-then-triage flow only reads the flat review-inbox/. By the time the next batch stages, the flat dir is empty and the extractor subagent reads only the NEW files — no need for the extractor to filter against a manifest or frontmatter stamp.
  • Context savings: the extractor subagent's directory scan ignores archive/ by default (no recursion). Skipping thousands of already-processed lines per batch.

Phase 6.5 — Publish accepted rows to GitHub Issues (when --publish is set)

Skip this phase if --publish is not set.

For every row appended to ai_docs/backlog.md in this batch (Phase 4's deduped + split set, after Phase 6 wrote the file), file a public GitHub Issue against darylmcd/Roslyn-Backed-MCP using the shared renderer. This validates the schema + issue template by exercising it on every accepted finding — the user's load-bearing reason for hooking publish into intake rather than a separate skill.

  1. Preconditions. gh is on PATH AND gh auth status reports authenticated. If either fails, emit one warning line per row (gh unavailable — printed body to stdout instead) and fall back to print-only for the whole phase. Do not raise.
  2. Dot-source the renderer.
    pwsh -NoProfile -Command ". '${CLAUDE_PLUGIN_ROOT}/skills/mcp-server-surface-test/lib/render-finding.ps1'; <render-and-file logic>"
    
    The renderer is the source of truth. Do NOT hand-roll a body — drift between the consumer auto-file path and the maintainer publish path is the failure mode this Row 2 design exists to prevent.
  3. Per-row loop. For each accepted row:
    • Construct a finding hashtable from the row's fields (id, source_repo, severity, area, server_version, anchors, finding, repro, proposed_fix). The source_audit field is the basename of the prose audit report this row was extracted from (or the empty string when the row was created from a sweep retro instead of an audit).
    • Call Test-FindingShouldRefusePublicFile -Finding $f. If $true, do not call gh. Print the rendered Issue body to stdout with the SECURITY/P0 escalation banner already prepended by Render-FindingIssue. Add (refused — pre-disclosure safeguard) to the row's audit-trail entry in the final summary.
    • Dedup pre-check (load-bearing). Before filing, query the issue tracker for a prior filing of the same row. The shared renderer's bodies always include a Closes <row-id> in ai_docs/backlog.md line, so the row id is the canonical fingerprint:
      gh issue list --repo darylmcd/Roslyn-Backed-MCP \
        --state all \
        --search "Closes ${rowId} in ai_docs/backlog.md in:body" \
        --json number,state,title --limit 5
      
      Apply these rules in order:
      • Open hit: skip filing. Capture the existing Issue URL and use it (instead of a freshly-filed one) when annotating the backlog row's do cell. Emit → skipped: already tracked as #<N> (open) in the audit trail.
      • Closed hit: skip filing. Emit → skipped: previously resolved as #<N> (closed). Do not refile or reuse the URL — closed issues with the same row id imply a prior fix that's now regressing, and the operator should re-open manually if appropriate.
      • No hit: proceed to Render-FindingIssue + gh issue create. As a belt-and-braces secondary check, also do a title-keyword search (<primary tool name> in:title) and skip with a warning if a strong title near-match is found on an open issue (covers the rare case where a sibling skill auto-filed before backlog-intake ran). The row-id check is the primary gate; this is the fallback for cross-skill collisions.
    • Otherwise call Render-FindingIssue -Finding $f to get {title, labels, body, refusedPublic}. Write body to a tempfile, then:
      gh issue create --repo darylmcd/Roslyn-Backed-MCP \
        --title "<title>" \
        --label "area:<area>" --label "severity:<severity>" \
        --body-file <tempfile>
      
    • Capture the returned Issue URL (or the deduped existing URL from the pre-check) and append it to the row's body inside ai_docs/backlog.md so the planner can cite the public Issue (Closes #N) when the row is sized into an initiative. Use Edit with exact-string replace; do NOT regenerate the whole file.
  4. Recommit when rows changed. If any row gained an Issue URL, the working tree now diverges from Phase 6's commit. Amend the Phase 6 commit OR add a follow-up commit on the same branch — your call which is cleaner. Do NOT push without explicit user confirmation.
  5. Report counts in Phase 7. Add a Published line: Published: {filed} GitHub Issues + {refused} P0/security refused (printed only).

The two auto-file destinations (this skill and /mcp-server-surface-test --auto-file) MUST emit byte-identical bodies. The shared renderer is the contract; the renderer's tests at tests/RoslynMcp.Tests/Skills/RenderFindingScriptTests.cs enforce determinism.

Phase 7 — Report

Emit a final summary:

Backlog intake complete.
  Staged: {N} files from {M} repos (review-inbox/)
  Extracted: {raw} candidate items
  Deduped: {deduped} rows ({ratio}:1 dedupe)
  Dropped (already shipped): {shipped-count}
  Anchor fixes applied: {anchor-fix-count}
  Heroic splits: {split-count} rows → {split-total}
  Final: {P2} P2 + {P3} P3 + {P4} P4 = {total} open rows
  Commit: {SHA} on branch {branch-name} (local-only; push when ready)

Refusal cases (explicit)

  • review-inbox/ empty AND staging found nothing → refuse per Phase 0.
  • Working tree dirty beyond backlog.md + review-inbox/ → refuse per Precondition 3.
  • backlog.md shape unexpected → refuse per Precondition 5.
  • Subagent returns 0 rows → do NOT write an empty commit. Report "no actionable items extracted from {N} files" and exit.
  • Subagent returns > 60 rows after dedupe → stop and ask the user whether to proceed with a clearly-under-deduped result, rather than silently writing a heroic backlog.

Why a subagent for Phase 1

Each review file is 200-800 lines; a 14-file batch is 6000+ lines. Reading them all in-context would consume 30-50K tokens before any judgment work starts. The extraction subagent returns a compact structured list (typically 1-2K tokens), leaving the main agent's context free for the anchor-verify / heroic-split / commit phases, which require reading this repo's source files.

If the batch is small (≤3 files, ≤1000 total lines), skip the subagent and read directly — the overhead isn't worth it.

Distinct from related skills

  • close-backlog-rows: removes specific row ids from the open table after their PRs ship. This skill (backlog-intake) ADDS rows from raw audit evidence. Use close-backlog-rows after a ship, this one after an audit wave.
  • reconcile-backlog-sweep-plan: updates a backlog-sweep plan's state.json when its PRs have merged. Different file, different concern.
  • draft-changelog-entry: drafts one changelog fragment per PR from commit metadata. Different artifact.
  • backlog-sweep-plan.md (prompt, not skill): consumes the backlog this skill produces. Run backlog-intake first, then the sweep planner.

Historical note

This skill replaces five PowerShell scripts that were deleted when it shipped: compare-external-audit-sources.ps1, import-deep-review-audit.ps1, new-deep-review-batch.ps1, new-deep-review-rollup.ps1, sync-deep-review-backlog.ps1. The last (the "sync" script) was the lossiest — it did literal-text dedupe via PowerShell regex and couldn't verify anchors, dedupe semantically, cross-check against CHANGELOG, or size rows to Rule 1/3/4. The only piece worth keeping from the pipeline was file staging, which is now a 150-line eng/stage-review-inbox.ps1.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.