Overhaul extraction pipeline with new TradeItem model, conversation flow, and dedicated extraction endpoint. Add sidebar navigation with NavMenu component and landing page. Introduce few-shot prompting service and tests. Add prompt settings and email upload specs. Update OpenSpec tooling with improved export-spec and extract-feature commands. Archive completed changes and export full specs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.6 KiB
name, description, category, tags
| name | description | category | tags | |||
|---|---|---|---|---|---|---|
| OPSX: Export Spec | Export a feature as a compact, portable spec for AI-assisted reimplementation on a sandboxed machine | Workflow |
|
Export a feature as a portable spec for AI-assisted reimplementation.
Instead of retyping code, you retype a compact spec. The AI on the sandbox generates the code.
Input: The argument after /opsx:export-spec is a change name (active or archived), or a description of the feature. If omitted, prompt for selection.
Steps
-
Identify the source feature
Same selection logic as
/opsx:extract-feature:- Check active changes and archive for the change name
- If not found, prompt with AskUserQuestion tool
- Read all artifacts:
proposal.md,design.md,tasks.md, specs
-
Analyze dependency chain (cumulative mode)
Features often build on each other. Before generating the spec, determine what the target feature depends on.
a. Read all archived change proposals in
openspec/changes/archive/(sorted by date). b. Build a dependency graph: what does the target require? What's superseded? c. Ask the user:"This feature depends on earlier changes. How should I scope the spec?"
- Cumulative — include all foundation (recommended for fresh codebase)
- Delta only — just this change (target already has foundation)
- Custom — pick which dependencies to include
d. In cumulative mode: merge into one coherent spec, skip superseded components. e. In delta mode: add an "Assumes" section listing what must already exist.
-
Read the actual implementation
Read all source files created or modified by this feature (and dependencies if cumulative). The spec must reflect what was actually built, not just what was planned.
-
Determine the target context
Use AskUserQuestion tool to ask:
"Tell me about the target codebase:
- Project name / root namespace
- Existing stack (ASP.NET Core? Blazor? MudBlazor?)
- Does it already have any of these? (controllers, DI setup, chat endpoint)
- Does the target have OpenSpec? GitHub Copilot? Claude Code?"
This shapes what the spec assumes vs what it must specify.
-
Capture the target GUI layout
If the feature has a UI component, the spec MUST include the target's layout context. Without it, the AI will generate components that conflict with the existing shell.
Ask the user:
"Does the target app have an existing GUI shell? If so, share:
- A screenshot (drag/drop or file path) — most information-dense
- Or describe: AppBar (height? Dense?), Sidebar/Drawer (width? toggled?), MainContent area, any fixed elements"
If a screenshot is provided, extract:
- AppBar type and height (Dense=48px, Regular=64px, custom)
- Sidebar/Drawer presence, width, toggle behavior
- Main content area constraints
- Existing navigation items
Then ask:
"How should this feature integrate into the target?
- Feature name in the target (e.g., 'Sales Assistant' not 'Chat')
- Route path (e.g.,
/sales-assistant) - Navigation: new sidebar item? AppBar button? Floating panel?"
Generate an ASCII layout diagram showing exactly where the feature renders, and include it in both the spec and the OpenSpec design.md.
-
Generate the portable spec
Create a single markdown document that is:
- Compact: Target ~30-50 lines for a medium feature
- Precise: Unambiguous enough for an AI to implement correctly
- Self-contained: No references to external files or repos
- Stack-aware: Uses the right terminology for the target stack
Structure:
# Feature: <Name> ## Target: <project name> (<stack>) ## Assumes <what must already exist on the target> ## Integration Rule This feature is additive only. DO NOT modify existing files, components, services, or patterns in the target. If the target already has an equivalent service, use it instead of creating a new one. If a task conflicts with existing target code, skip it and note the conflict. Existing applicationX code takes precedence over this spec in all cases. ## Target Layout <ASCII diagram showing the target app shell and where this feature renders> <AppBar height, Sidebar width, MainContent constraints> <Feature name, route, navigation integration point> ## Packages <list with versions> ## Architecture <2-3 sentence overview> ## Components ### <Component>: <path hint> - <What it does> - <Key behavior> - <Interface/contract> ## Contracts <API shapes, model definitions — things that MUST be exact> ## Critical Patterns <Exact code snippets for traps the AI will otherwise get wrong> <Show the POSITIVE pattern to copy, not just "don't use X"> <Include WHY — the mechanism behind the trap> ## Wiring <DI registration, middleware order, config keys — dependency order> ## Behavior <Non-obvious requirements>Compression strategies:
- Use bullet points, not prose
- Specify contracts precisely (field names, types, API shapes)
- Let the AI infer standard patterns
- Only specify non-obvious behavior
- Omit anything the AI would do by default
-
Estimate typing effort
Count characters in the spec. Compare to the code recipe equivalent. Show the compression ratio.
-
Optionally generate an OpenSpec-compatible version
If the target has OpenSpec, also generate:
- A config.yaml template — adapted context for the target project, with placeholders
- A
proposal.md(minimal — 5-10 lines) - A
design.md— compact architectural decisions and rationale (why SSE vs WebSocket, why typed client vs raw, why per-request plugin import, etc.). Without this the AI has tasks but no rationale, and will guess wrong on non-obvious decisions. - A
tasks.md(implementation steps) - Setup instructions at the top: step-by-step procedure for the target machine
(create config.yaml, save proposal/design/tasks, run
/opsx:apply, reference the portable spec)
Save as:
openspec/exports/<change-name>-openspec.md -
Write the output
Save to:
openspec/exports/<change-name>-spec.mdDisplay the full content for review.
Guardrails
- Prioritize precision over brevity — ambiguity wastes more time than length
- Always include exact field names, types, and API shapes
- Include non-obvious gotchas (like /v1 base URL requirements)
- Mental test: could an AI implement this correctly without seeing the original code?
- If too complex for ~50 lines, split into multiple specs by component
- Always show the compression ratio
- Must be readable when printed in monospace — no wide tables or long lines
- In cumulative mode, the spec must read as one coherent feature, not a list of changes
- Skip superseded components — always describe the latest version
- In delta mode, add an "Assumes" section so the target AI knows what must exist
- In the output header, note which changes were included and which were skipped
Integration rule: adapt, never modify
The exported feature is a GUEST in the target application. Existing code, patterns, and conventions in the target take absolute precedence. The spec must include an explicit "Integration Rule" section that states:
- DO NOT modify existing files, components, layouts, services, or routing in the target
- DO NOT replace existing patterns with patterns from the source project (e.g., if the target uses a different HttpClient pattern, use theirs)
- DO add new files, new nav links, new routes, new DI registrations
- DO conform to the target's existing code style, naming conventions, and project structure
- If a task conflicts with existing target code, stop and notify the user — the user decides whether to skip, adapt, or redesign
- If the target already has an equivalent service (e.g., its own markdown renderer, HttpClient wrapper), use the existing one instead of creating a new one
When generating the spec, actively identify potential conflict points and add explicit "Adapt to target" notes. Common conflicts:
- Program.cs / DI registration style
- HttpClient patterns (typed client vs named client vs raw)
- Layout components (don't restructure MainLayout)
- CSS approach (isolation vs global vs utility classes)
- Error handling patterns
- Navigation structure
Anti-patterns learned from field use
These patterns cause the target AI to deviate from the spec even when the spec mentions them:
-
"Don't use X" warnings get ignored. AIs skip parenthetical negations buried in bullet lists because their training data overwhelmingly uses the standard pattern. Instead: add a "Critical Patterns" section with the exact code snippet to copy. Show the positive pattern, not just the negative warning. E.g., instead of "don't use EndOfStream", show the exact
while ((line = await ReadLineAsync()) != null)loop. -
Layout values that depend on other components break silently. Magic numbers like
calc(100vh - 48px)assume a specific AppBar height. Instead: document the dependency explicitly ("48px = MudAppBar Dense height"), suggest using a CSS variable as fallback, and note mobile viewport gotchas (100vhvs100dvh). -
Platform-specific runtime traps need the WHY. Saying "don't use EndOfStream" is not enough — the AI needs to know WHY (synchronous peek on an async-only stream). When the AI understands the mechanism, it's less likely to reach for an equivalent pattern that has the same problem.
ARGUMENTS: based on the above