feat: add porting-guide skill and NL XVA Pricer export bundle
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>
This commit is contained in:
233
.claude/commands/opsx/porting-guide.md
Normal file
233
.claude/commands/opsx/porting-guide.md
Normal file
@@ -0,0 +1,233 @@
|
||||
---
|
||||
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:
|
||||
- `<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 '<name>'. 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: <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)
|
||||
```
|
||||
|
||||
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/<name>-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<ExtractionPlugin>(), 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
|
||||
Reference in New Issue
Block a user