skills/prototype-feature/SKILL.md
Dispatch N parallel variant agents to produce competing working skeletons from an approved proposal, score them via cheap validation phases, and capture human pick-and-choose feedback for convergence-aware refinement
npx skillsauth add jankneumann/agentic-coding-tools prototype-featureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Dispatch N parallel variant agents (default 3) that each produce a working skeleton from an already-approved OpenSpec proposal, score the skeletons via cheap /validate-feature phases, and capture per-aspect human pick-and-choose feedback so /iterate-on-plan --prototype-context can synthesize the best combination back into design.md and tasks.md.
This skill is the divergence stage on the generation side of the approval gate — the same way /parallel-review-plan and /parallel-review-implementation apply divergence to review.
$ARGUMENTS — <change-id> (required) plus optional flags:
--variants N — number of competing skeletons to dispatch. Default 3. Bounded 2 ≤ N ≤ 6. Out-of-range values fail fast.--angles "a,b,c" — comma-separated angle prompts (default simplest,extensible,pragmatic per D5). The count of angles MUST equal --variants exactly. When --variants ≠ 3 and --angles is omitted, the skill fails fast (silent guessing of fewer-than-3 angles is ambiguous).openspec/changes/<change-id>/ (proposal.md + design.md + specs/ + tasks.md). The skill never auto-triggers — it's only invoked explicitly by the operator or via /iterate-on-plan's advisory workflow.prototype-recommended finding.skills/worktree/scripts/worktree.py) supports --branch-prefix prototype (added by wp-worktree).synthesize_variants() available in skills/parallel-infrastructure/scripts/variant_descriptor.py.Use docs/coordination-detection-template.md as the shared detection preamble. When CAN_QUEUE_WORK=true, the skill emits per-variant work items so other operators can observe progress. Without coordinator the dispatch is direct via Task() agents.
Call dispatch_variants.plan_variants(change_id, variants, angles). The function enforces D2 (count bounds) and D5 (angle-count matching). On VariantPlanError, abort before any worktree creation — no partial state should leak.
from dispatch_variants import plan_variants
plan = plan_variants(
change_id=CHANGE_ID,
variants=int(args.variants or 3),
angles=args.angles.split(",") if args.angles else None,
)
The returned VariantPlan carries a VariantSpec(variant_id, angle, branch, worktree_relpath) per variant — every downstream step consumes this structure.
Spec scenarios covered: PrototypeFeatureSkill.default-variant-dispatch, custom-variant-count-and-angles, variant-count-out-of-bounds.
Query vendor_health.check_all_vendors(). Sort the healthy vendors by their order in the report (which the report itself sorts by health). Pass them to dispatch_variants.resolve_vendor_assignment(plan, available_vendors).
from vendor_health import check_all_vendors
from dispatch_variants import resolve_vendor_assignment
report = check_all_vendors()
healthy = [v.agent_id for v in report.vendors if v.healthy]
assignment = resolve_vendor_assignment(plan, healthy)
Per D3:
assignment.fallback == False.assignment.fallback == True. Inject temperature + seed variation in the per-variant prompts so style still diverges.VariantPlanError. Operator must wait for at least one vendor to recover.assignment.per_variant (variant_id → vendor) and assignment.fallback are persisted onto each VariantDescriptor in step 5.
Spec scenarios covered: VendorDiversityPolicy.sufficient, insufficient, recorded.
For each VariantSpec, call worktree.py setup with the new prototype prefix:
python3 skills/worktree/scripts/worktree.py setup "${CHANGE_ID}" \
--agent-id "${VARIANT_ID}" \
--branch-prefix prototype \
--no-bootstrap
This produces (per wp-worktree):
prototype/<change-id>/v<n> (note / separator, not --).git-worktrees/<change-id>/v<n>//cleanup-feature runsVariant agents NEVER write to the feature branch or to each other's branches — the worktree boundary enforces isolation.
Spec scenarios covered: PrototypeFeatureSkill.isolated-worktree-per-variant.
For each variant, dispatch a Task() agent rooted in its worktree:
Task(
subagent_type="general-purpose",
description=f"Variant {variant_id}: {angle} angle",
prompt=f"""You are variant {variant_id} for OpenSpec change {change_id}.
## Angle (your design value)
{angle_prompt_from_angles_yaml}
## Context
- proposal.md, design.md, specs/, tasks.md from the approved proposal
- worktree: {worktree_relpath}
- branch: {branch} (you commit here; never touch other branches)
## Goal
Produce a *working skeleton* that demonstrates how your angle would
shape the implementation. Skeletons need not be feature-complete — they
must compile/run cheaply enough that ``/validate-feature --phase smoke,spec``
can score them.
## Constraints
- Do not modify openspec/changes/{change_id}/ — the proposal is fixed.
- Commit incrementally with conventional messages.
- Stop after producing the skeleton; do NOT iterate based on test failures
unless the failure is a syntactic mistake in your own code.
""",
run_in_background=True,
)
Wait for all N agents to complete (or report failure). Failures are recorded, not raised — D7 says even a partially-failed dispatch should still feed pick-and-choose with the surviving variants.
Per D6, scoring uses existing validation phases. For each variant:
cd .git-worktrees/${CHANGE_ID}/${VARIANT_ID}
/validate-feature ${CHANGE_ID} --phase smoke,spec
Capture the per-phase pass/fail and the covered/total/missing numbers. A failed smoke phase IS a valid scoring outcome — record it and continue.
Spec scenarios covered: VariantScoring.smoke-and-spec, skeleton-fails-to-deploy.
Per D7, present the four-aspect choice via AskUserQuestion with multiSelect=true:
AskUserQuestion(
questions=[
{
"question": "Which variants' data model should carry forward?",
"options": [{"label": v.variant_id, ...} for v in plan.variants]
+ [{"label": "rewrite", ...}],
"multiSelect": True,
"header": "data_model",
},
# ... same shape for api / tests / layout ...
]
)
Convert the operator's selections into a human_picks dict per variant:
human_picks = {
"data_model": variant_id in selected_for_data_model,
"api": variant_id in selected_for_api,
"tests": variant_id in selected_for_tests,
"layout": variant_id in selected_for_layout,
}
Optionally collect a free-form synthesis_hint per variant (e.g. "prefer v1 data model but steal v3 test naming") — this carries forward into synthesis_notes in the synthesis plan.
Spec scenarios covered: PrototypeFindingsArtifact.human-pick-and-choose.
For each variant, assemble the descriptor and persist:
from collect_outcomes import build_descriptor, write_findings_file
descriptors = [
build_descriptor(
variant_id=spec.variant_id,
angle=spec.angle,
vendor=assignment.per_variant[spec.variant_id],
change_id=CHANGE_ID,
scoring=scoring_results[spec.variant_id],
human_picks=human_picks_by_variant[spec.variant_id],
vendor_fallback=assignment.fallback,
synthesis_hint=hints_by_variant.get(spec.variant_id),
)
for spec in plan.variants
]
write_findings_file(
change_dir=Path("openspec/changes") / CHANGE_ID,
descriptors=descriptors,
)
The output file openspec/changes/<change-id>/prototype-findings.md carries:
contracts/schemas/variant-descriptor.schema.json for machine consumption by /iterate-on-plan --prototype-contextSpec scenarios covered: PrototypeFindingsArtifact.findings-artifact-produced.
Print the next-step pointer:
Next: /iterate-on-plan <change-id> --prototype-context <change-id>
/iterate-on-plan --prototype-context reads prototype-findings.md, loads each variant's branch diff against main, and emits convergence.* findings to refine design.md and tasks.md before /implement-feature runs.
The prototype/<change-id>/v* branches and worktrees are kept (auto-pinned) until /cleanup-feature deletes them as part of feature cleanup (per D4).
openspec/changes/<change-id>/prototype-findings.md — single source of truth for variant outcomes + human picksprototype/<change-id>/v<n> branches (one per variant).git-worktrees/<change-id>/v<n>/ worktrees (auto-pinned, kept for /cleanup-feature)VariantPlanError before any worktree creation.automated_scores.smoke.pass=False and excluded from assignment.per_variant rendering, but the surviving variants still proceed to scoring + human pick-and-choose. Synthesis runs on whoever made it.testing
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
tools
Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.
data-ai
Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.
tools
Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections. Use when working with .canvas files, creating visual canvases, mind maps, flowcharts, or when the user mentions Canvas files in Obsidian.