--- name: "OPSX: Porting Guide" description: Generate a detailed human-readable implementation guide for porting a feature to a target codebase category: Workflow tags: [workflow, portability, experimental] --- 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** 1. **Locate the export artifacts** a. Check `openspec/exports/` for matching files: - `-spec.md` (portable spec — required) - `-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. 2. **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 in `openspec/specs/` c. The actual implementation source files d. Any existing export-spec and OpenSpec bundle Focus 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 3. **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: > 1. What patterns does the target use for DI registration? (manual, Scrutor, Autofac?) > 2. What's the deployment model? (Azure, on-prem, Docker?) > 3. Are there known constraints? (network restrictions, NuGet source limits, proxy requirements?) > 4. Who will be implementing — developer familiarity with the source stack?" This shapes the level of explanation and which friction points to highlight. 4. **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: ```markdown # Porting Guide: ## Source: | Export: ## 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: ### **What we chose:** **Why:** **What we rejected:** - — rejected because - — rejected because **When you'd revisit this:** **Target adaptation:** 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()` | 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: ### : **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. 2. 3. **Expected friction on target:** - - **Verify it works:** - - - **If it breaks — diagnostic checklist:** - Symptom: Cause: Fix: - Symptom: Cause: Fix: ## 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()` | | 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) ``` 5. **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 6. **Write the output** Save to: `openspec/exports/-porting-guide.md` Display 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.csv` for primary config but `appsettings.json` for 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 `/v1` URL requirement, or `EndOfStream` hanging) — 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** 1. **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. 2. **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. 3. **Don't skip the obvious.** The developer may be senior but unfamiliar with Semantic Kernel. Explain SK concepts (Kernel, plugins, FunctionChoiceBehavior) in plain language. 4. **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