Add /opsx:porting-guide skill that generates detailed human-readable implementation guides as a companion to /opsx:export-spec. The AI spec targets the agent; the porting guide targets the human developer with design rationale, task-by-task notes, troubleshooting tables, and rollback plans. Generate the full NL XVA Pricer export bundle for CRC: - nlxva-pricer-spec.md (AI-targeted portable spec) - nlxva-pricer-openspec.md (OpenSpec proposal/design/tasks) - nlxva-pricer-porting-guide.md (human implementation guide) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
name, description, category, tags
| name | description | category | tags | |||
|---|---|---|---|---|---|---|
| OPSX: Porting Guide | Generate a detailed human-readable implementation guide for porting a feature to a target codebase | Workflow |
|
Generate a detailed human-readable porting guide for implementing an exported feature on a target codebase.
This is a companion to /opsx:export-spec. The export-spec is optimized for AI consumption (compact, precise). This guide is optimized for the human developer who needs to understand context, troubleshoot issues, and make judgment calls when the AI agent on the target hits problems.
Input: The argument after /opsx:porting-guide is a change name or feature name that has already been exported via /opsx:export-spec. If omitted, prompt for selection.
Prerequisites: An export-spec must already exist in openspec/exports/. This skill reads the export-spec to stay consistent with it.
Steps
-
Locate the export artifacts
a. Check
openspec/exports/for matching files:<name>-spec.md(portable spec — required)<name>-openspec.md(OpenSpec bundle — optional) b. If not found, prompt with AskUserQuestion tool:
"No export-spec found for ''. Available exports: [list]. Which one?" c. Read the export-spec fully — the porting guide must not contradict it.
-
Read the source material
Same sources as export-spec, but read for context and rationale rather than contracts: a. All archived change proposals, designs, and tasks in
openspec/changes/archive/b. All main specs inopenspec/specs/c. The actual implementation source files d. Any existing export-spec and OpenSpec bundleFocus on extracting:
- Decision rationale: WHY each design choice was made
- Rejected alternatives: what was considered and discarded
- Friction points: where the source implementation hit problems
- Implicit knowledge: things the source developer knew but didn't document
- Platform traps: runtime behaviors that aren't obvious from the code
-
Gather target context
If not already captured in the export-spec, use AskUserQuestion tool to learn:
"To write accurate porting notes, I need to understand the target:
- What patterns does the target use for DI registration? (manual, Scrutor, Autofac?)
- What's the deployment model? (Azure, on-prem, Docker?)
- Are there known constraints? (network restrictions, NuGet source limits, proxy requirements?)
- Who will be implementing — developer familiarity with the source stack?"
This shapes the level of explanation and which friction points to highlight.
-
Generate the porting guide
Create a comprehensive markdown document structured for a human reader. Use narrative prose where it aids understanding, tables for quick reference, and checklists for actionable steps.
Structure:
# Porting Guide: <Feature> → <Target> ## Source: <source project> | Export: <export-spec filename> ## How to Use This Guide Brief orientation: - Relationship to the AI-targeted export-spec - When to read this vs when to let the AI work - How sections are organized ## Architecture Overview 2-3 paragraphs a human can read in 5 minutes to understand the full feature. Written as narrative, not bullet points. Cover: - What the feature does end-to-end (user perspective) - How data flows through the system (request → processing → response) - What external dependencies exist and why - The "one thing you must understand" about this feature ## Design Decisions (Detailed) For EACH significant design decision: ### <Decision Title> **What we chose:** <the approach> **Why:** <rationale — the real reason, not the obvious one> **What we rejected:** - <Alternative A> — rejected because <specific reason> - <Alternative B> — rejected because <specific reason> **When you'd revisit this:** <conditions under which this decision should change> **Target adaptation:** <how this maps to the target's patterns, what might need adjusting> Decisions to always cover: - Framework/library choices (SK over raw HTTP, SSE over WebSocket, etc.) - Lifetime/scope decisions (singleton vs scoped vs transient) - State management approach - Streaming strategy - Security decisions (sanitization, auth, CORS) - File/folder organization ## Source → Target Mapping Side-by-side mapping table showing how source concepts translate to target: | Source (ChatAgent) | Target (CRC) | Notes | |---|---|---| | `ChatAgent.Api/` | `CRC.Server/` | CRC uses hosted model, not standalone API | | `ChatAgent.Client/` | `CRC.Client/` | Same WASM pattern | | `builder.Services.AddScoped<T>()` | Check if Scrutor handles this | CRC may auto-scan | | ... | ... | ... | Flag EVERY known divergence, no matter how small. The small ones cause the most debugging time. ## Task-by-Task Implementation Notes For EACH task in the OpenSpec tasks.md: ### <Task ID>: <Task Title> **Prerequisites:** What must be completed first and verified working. **Context:** Why this task exists and what it accomplishes in the bigger picture. A developer who understands the "why" makes better judgment calls when adapting. **Step-by-step:** 1. <Step with enough detail that someone unfamiliar with the source can follow> 2. <Step> 3. <Step> **Expected friction on target:** - <Specific thing that will likely need adaptation and why> - <CRC pattern that differs from the source approach> **Verify it works:** - <Concrete test: "Navigate to X, click Y, you should see Z"> - <Log check: "Watch for 'SK: Auto-invoking function' in Serilog output"> - <Build check: "dotnet build should produce 0 warnings related to this task"> **If it breaks — diagnostic checklist:** - Symptom: <what you'll see> Cause: <most likely reason> Fix: <specific remediation> - Symptom: <what you'll see> Cause: <most likely reason> Fix: <specific remediation> ## Troubleshooting Reference Comprehensive symptom → cause → fix table for known porting issues. Organized by category (network, DI, UI, streaming, auth, config). | Symptom | Likely Cause | Fix | |---|---|---| | 404 on /v1/chat/completions | Base URL missing `/v1` | Add `/v1` to `NlxvaPricer:LlmBaseUrl` | | CORS 403 on SSE endpoint | CORS policy doesn't cover `text/event-stream` | Add origin to CORS policy | | Streaming hangs, no tokens | `SetBrowserResponseStreamingEnabled` missing | Add to HttpRequestMessage | | `EndOfStream` throws | Synchronous peek on async-only WASM stream | Use `ReadLineAsync() != null` loop | | Markdown not rendering | MarkdownService not registered in DI | Add `AddSingleton<MarkdownService>()` | | Tools never called by LLM | Plugin not imported on request | Move ImportPluginFromObject into action method | | ... | ... | ... | Include at least 10-15 entries covering the most likely failure modes. ## Configuration Checklist Every config key the feature needs, organized as a checklist: - [ ] `NlxvaPricer:LlmBaseUrl` — Where: `appsettings.json` (CRC.Server) — Default: `http://localhost:8317/v1` — What happens if missing: Falls back to default, fails if proxy not running - [ ] `NlxvaPricer:LlmModel` — Where: `appsettings.json` — Default: `claude-sonnet-4-6` - [ ] ... (every key) ## Dependency & Package Notes For each new package: - Package name and version constraint - Why it's needed (one sentence) - .NET version compatibility notes - Known conflicts with packages the target might already have - NuGet source: public nuget.org or internal feed? (CRC uses internal GV Artifactory — flag if a package might not be available there) ## Rollback Plan If the feature needs to be removed: - Which files were added (safe to delete) - Which files were modified and what was added (revert specific sections) - Which NuGet packages were added (remove from csproj) - Which config keys were added (remove from appsettings.json) -
Cross-check against export-spec
Before writing, verify:
- Every contract in the export-spec is explained in the porting guide
- Every critical pattern has a troubleshooting entry
- No contradictions between the two documents
- The porting guide adds CONTEXT, not ALTERNATIVE instructions
-
Write the output
Save to:
openspec/exports/<name>-porting-guide.mdDisplay a summary of sections generated and key highlights.
Guardrails
- Narrative over telegraphic: This is for humans. Use complete sentences. Explain the "why."
- Never contradict the export-spec: The AI spec is the source of truth for contracts and patterns. The porting guide explains and contextualizes, it doesn't override.
- Anticipate the debugging session: For every task, imagine the developer hitting a wall. What would they need to know? Write that down.
- Be specific about the target: Generic advice ("check your config") is useless. Specific advice ("CRC uses
gv_web_config.csvfor primary config butappsettings.jsonfor secondary — LLM config goes in appsettings") saves hours. - Include the embarrassing details: The things that took 30 minutes to figure out in the source (like the
/v1URL requirement, orEndOfStreamhanging) — those are the most valuable entries. - Flag NuGet source issues: If the target uses an internal feed (like CRC's GV Artifactory with nuget.org disabled), flag every package that needs to come from a specific source.
- No code blocks for code's sake: The export-spec has the exact code. The porting guide references it ("see Critical Pattern #2 in the export-spec") rather than duplicating it. Only include code when it clarifies a specific porting concern.
- Version-stamp the guide: Include the date and source commit hash so the reader knows what state the guide reflects.
Anti-patterns
-
Don't duplicate the export-spec. The export-spec has exact contracts and code snippets. The porting guide has context, rationale, and troubleshooting. They complement each other.
-
Don't be abstract. "There might be DI issues" is useless. "CRC uses Scrutor for assembly scanning. If Scrutor auto-registers ExtractionPlugin before your manual AddScoped(), you'll get a duplicate registration. Check with
builder.Services.Where(s => s.ServiceType == typeof(ExtractionPlugin))in a breakpoint" is useful. -
Don't skip the obvious. The developer may be senior but unfamiliar with Semantic Kernel. Explain SK concepts (Kernel, plugins, FunctionChoiceBehavior) in plain language.
-
Don't assume the happy path. Network restrictions, proxy requirements, package feed limitations, and auth quirks are the norm in enterprise environments. Address them.
ARGUMENTS: $ARGUMENTS