Skip to content

Releases: vulca-org/vulca-visual-control-sdk

v0.23.0

Choose a tag to compare

@yha9806 yha9806 released this 01 May 19:12

First public PyPI release after v0.19.0. This release bundles the v0.20-v0.22 redraw hardening work, visual workflow skills, remote MCP profiles, platform distribution docs, cultural-term benchmark tooling, and hosted provider SDK aliases.

Highlights

  • Added /visual-discovery, /visual-brainstorm, /visual-spec, /visual-plan, and /evaluate skill surfaces for agent-native visual workflows.
  • Added remote-safe MCP profile support via vulca-mcp-remote for hosted clients such as ChatGPT-style remote MCP integrations.
  • Added target-aware redraw hardening: source-context edit mattes, generated evidence gating, local quality gates, route/geometry advisory fields, and target mask refinement helpers.
  • Added cultural-term efficacy benchmark tooling, including real-provider opt-in and signal-strengthening checks.
  • Added provider SDK image aliases: gemini-tools / nb2-tools for Google GenAI tool-backed image calls, and openai-responses for the OpenAI Responses API image generation tool.
  • Added vulca[providers] optional dependency group for hosted provider SDKs.
  • Refreshed README install pins from 0.17.11 to 0.23.0.

Compatibility

  • Existing vulca[mcp] installs continue to work.
  • Hosted provider SDKs remain optional; install vulca[providers] only when using Gemini/OpenAI hosted backends directly.
  • layers_redraw keeps backward-compatible defaults while surfacing new route, model, quality, and advisory controls for advanced callers.

Links

v0.19.0 — detection diagnostics: silent drops + near-miss capture

Choose a tag to compare

@yha9806 yha9806 released this 27 Apr 14:12
327fff3

Two diagnostic improvements to the orchestrated detection pipeline surfaced by a 7-entity dogfood run on IMG_6847.jpg. Detection behavior unchanged — only the reporting of misses is improved so callers can take targeted recovery actions instead of guessing.

Highlights

Person path — distinguish two failure modes that v0.18 lumped into no_detection_after_chain:

  • chain_returned_zero — chain found nothing
  • rank_exceeded_chain_pool — chain found N < K persons; this entity is rank K-1+. Carries entities_in_chain_pool and this_entity_rank so caller knows exactly how many detections exist

Object pathdetect_all_bboxes now returns {assigned, near_miss, nms_drops} (BREAKING for direct callers; migration recipe in CHANGELOG). Missed-branch reason refined:

  • dino_below_threshold (+ near_miss_candidates showing actual conf range; user can lower threshold)
  • dropped_by_within_label_nms (+ nms_drop_candidates)
  • dino_not_matched (true zero — preserved)

Motivation

Real dogfood on roadside photo IMG_6847.jpg surfaced 2 silent drops in 30 minutes:

  1. red_car rank-exceeded silently as no_detection_after_chain while sibling yellow_truck succeeded on identical chain — same attempts field, opposite outcome
  2. wildflower_clusters (multi_instance, threshold=0.18) reported dino_not_matched with no way to tell if DINO had below-threshold candidates

Both fixes give users actionable diagnostic signal so they can refine plan.json without reading the source.

Tests

10 new regression tests + existing 22/22 pass + real-DINO+SAM lanterns fixture pass.

Cross-validated by fresh codex GPT-5.4 + superpowers Claude parallel review — both flagged same P1 (id() set comparison fragility against future _nms_bboxes refactor → fixed value-based) and same nit (CHANGELOG test count → fixed).

Out of scope (v0.20 backlog)

  • Per-entity entity.threshold actually honored at DINO call (4th hidden bug)
  • Tiled/upscaled paths surfacing diagnostics_unavailable_tiled_path flag
  • Joint-pass threshold side-effect documented in CHANGELOG
  • Test boundary tightening (== 5 not <= 5)
  • NEAR_MISS_FLOOR constant migration to src/vulca/_segment.py

Migration

grep -rn 'detect_all_bboxes(' --include='*.py' .
# replace `result[label]` → `result["assigned"][label]`
# new diagnostic keys are optional: result["near_miss"], result["nms_drops"]

detect_bbox (legacy single-label wrapper) preserves return shape (bbox, score) — no migration needed.

🤖 Authored by Claude Opus 4.7 + Codex GPT-5.4 + Superpowers Claude (parallel review)

v0.18.0 — layers_redraw default flip + layers_split multi_instance

Choose a tag to compare

@yha9806 yha9806 released this 27 Apr 11:35

v0.18.0 (2026-04-26)

Two paired changes that close the largest hand-cuts surfaced by the γ Scottish carousel (2026-04-25): layers_redraw defaults flipped to the safe path (no more silent in-place overwrite + no more alpha-sparse hallucination by default), and layers_split orchestrated mode grew first-class multi-instance support so a "row of 6 lanterns" plan no longer collapses into one fragmented union mask.

The migration is two-tier for callers who relied on the legacy layers_redraw behavior: most users only need to add in_place=True to keep their file-overwriting workflow; the small minority who depended on the legacy transparent background passthrough plus alpha drop must add all three kwargs (in_place=True, background_strategy="transparent", preserve_alpha=False) for byte-identical v0.17.x parity. Everything else is additive.

Breaking changes

layers_redraw defaults flipped — three parameters now choose the safe path by default:

Parameter v0.17.x default v0.18.0 default
Output path in-place overwrite <layer>_redrawn.png (input untouched)
background_strategy "transparent" "cream"
preserve_alpha False True

A new parameter in_place: bool = False is the explicit opt-out for callers who need the legacy in-place write. Most users only need this single kwarg — pass in_place=True to keep your v0.17.x file-overwriting workflow while inheriting the new safer background_strategy="cream" and preserve_alpha=True defaults (which improve, not regress, output quality on alpha-sparse layers).

To restore v0.17.x behavior byte-for-byte (rare; required only if you depended on the legacy transparent background passthrough plus alpha drop):

layers_redraw(
    artwork_dir, layer="lanterns", instruction="...",
    in_place=True,
    background_strategy="transparent",
    preserve_alpha=False,
)

Why: v0.17.14 introduced the opt-in defenses (background_strategy="cream", preserve_alpha=True, output_layer_name) but left legacy as the default — making the trap (silent input destruction + scene hallucination on alpha-sparse layers) the path of least resistance. The γ Scottish Part 2 showcase confirmed the trap is easy to fall into even when the implementer knew about it. v0.18 makes the safe path the default; the unsafe path requires explicit opt-out. See commit 7679b488 (kwarg + 3-way path resolution) and 9631adf2 (atomic default flip).

Note: layers_redraw(merge=True, layers="a,b,...") does not yet honor the in_place kwarg — only the single-layer path. The merge path always writes the merged result to a new file. Tracked for v0.18.1+.

Added

layers_split orchestrated mode now supports multi-instance entities. Plan JSON entities accept an optional multi_instance: true flag. When set, Grounding DINO returns up to 8 bboxes for that label (instead of top-1) and SAM segments each independently. The orchestrator emits N flat sibling layers named <label>_0..N-1 sorted by DINO det_score descending (the ordering is fixed at NMS time in _nms_bboxes before SAM runs, so SAM scores do not influence sibling order).

{
  "entities": [
    { "name": "lanterns", "label": "red paper lantern", "multi_instance": true }
  ]
}

(The schema key is entities on the Plan model; some prior design docs used object_entities informally — the actual Plan.from_file() JSON path is entities.)

Edge cases:

  • DINO returns 0 bboxes → 0 layers emitted; manifest carries quality_flags: ["multi_instance_no_detection"].
  • DINO returns exactly 1 bbox → 1 layer named <label> (no _0 suffix); manifest carries quality_flags: ["multi_instance_degraded"]. The keystone naming contract: _0 suffix means "instance 0 of N≥2"; never "lone instance".
  • DINO returns >8 bboxes → top-8 by score retained, rest dropped.
  • z_index of subsequent entities in the plan is auto-pushed by (N-1) so the multi-instance fan-out doesn't collide downstream.

Closes the multi-instance gap deferred from v0.17.13. The plan JSON schema extension is additive; existing plans without multi_instance are byte-for-byte unaffected. See commits c82880dd (detection-layer multi_instance), ae6471fe (orchestrator wire + I-1 fail-fast), bdc9d32e (entity-loop refactor).

Limitation: tiled / upscaled detection paths

layers_split orchestrated mode raises NotImplementedError early when multi_instance: true is requested and the input image triggers DINO's tiled or upscaled path (extreme aspect ratio, or dimensions outside the standard window). The error message is actionable: it tells the user to either disable multi_instance for that image or pre-crop to a non-extreme aspect ratio. Forwarding multi_instance kwargs through the tiled/upscaled wrappers is v0.18.1+ scope.

Internal

  • New src/vulca/_segment.py module hosts pure-Python NMS helpers (_iou, _nms_bboxes) extracted from scripts/claude_orchestrated_pipeline.py so they can be unit-tested without import torch (mirrors the v0.17.14 hotfix discipline for _quality_gate).
  • New fixture tests/fixtures/multi_instance/lanterns_6.jpg (440×700, ≈86 KB) — γ Scottish lanterns crop, anchored as the multi-instance regression baseline.
  • New l4_local pytest marker for local-only model-weight tests; CI skips automatically via pytest.importorskip("torch"). The pre-existing real_provider and local_provider markers are also now registered in pyproject.toml, eliminating PytestUnknownMarkWarning noise on every run.

v0.17.15 — maintenance: AST test rewrite + Node 24 actions bump

Choose a tag to compare

@yha9806 yha9806 released this 26 Apr 13:43

v0.17.15 (2026-04-26)

Maintenance release. Pure internal hardening — no API changes, no user-visible behavior changes. Two items closed from the v0.17.14-CI-hotfix backlog plus one GitHub deprecation tracker.

Changed

  • tests/test_quality_gate.py: migrated test_person_path_invokes_compute_quality_flags from string-grep (Path.read_text() + str.index()) to ast.parse() walk. Same invariant (the person loop in process() must contain a Call to compute_quality_flags), but structurally rigorous — comments and string literals containing the function name no longer satisfy the assertion. Closes the codex P2 from the 2026-04-26 v0.17.14-CI-hotfix review.
  • .github/workflows/ci.yml: bump actions/checkout@v4 → @v5 and actions/setup-python@v5 → @v6. GitHub will force Node.js 24 default on Actions runners 2026-06-02 and remove Node 20 entirely 2026-09-16; v4/v5 are Node-20-pinned. v5/v6 are the first majors that support Node 24.

Notes

  • compute_quality_flags was extracted to vulca._quality_gate in the post-tag CI hotfix during v0.17.14 (commit b5088caa, 2026-04-26) — see retro entry below.

v0.17.14 — native mask-inpaint + layers_redraw + paste_back

Choose a tag to compare

@yha9806 yha9806 released this 25 Apr 22:20

Surgical 5-patch release closing the P0/P1 gaps surfaced by the parallel codex + superpowers review of the γ Scottish carousel workflow on 2026-04-25. The carousel's slide-4 mask-edit flow is now fully native — no out-of-band Python scaffolding required.

Patches

  • P1 inpaint_artwork(mask_path=...) — native precision-mask path via OpenAI /v1/images/edits. Pass an RGBA PNG where alpha=0 marks pixels to edit and alpha=255 marks pixels to preserve. Gemini/ComfyUI fail loud (NotImplementedError with hint). Legacy region= path unchanged.
  • P2 layers_redraw recontract — opt-in via output_layer_name= for non-destructive output; background_strategy=cream|white|sample_median|transparent to flatten alpha-sparse layers before redraw and stop hallucination of new content into empty regions; preserve_alpha=True to re-apply source alpha. Provider-aware api_key wiring closes the GOOGLE_API_KEY leak that was forcing the wrong env var into every provider.
  • P3 layers_paste_back — new MCP glue verb for the open-loop "edit one layer, paste back into source" flow that previously required manual Image.composite() in Python. Three blend modes (alpha / feathered / hard), pure PIL.
  • P4 Person-path quality gate — mirror v0.17.13 compute_quality_flags into the orchestrated pipeline's person loop. Same silent-success bug closed for symmetry.
  • P5 layers_composite non-destructive — gate the legacy ensure_alpha writeback behind force_alpha_writeback=True. A preview call no longer mutates source layer files.

Review fixes (post-patch)

5 P1 + 5 P2 fixes from the double-review pass — z_index round-trip parity, bbox-from-mask (no more hardcoded {0,0,100,100}), paste_back RGB clamp against alpha=0 black-bleed, provider default rollback for legacy region path (silent billing flip averted), sample_median warning, redraw_merged aspect symmetry, HARD_THRESHOLD module constant, mask convention docstring simplification.

Stats

7 commits, 14 files changed. 35 new tests + 5 review-driven regression tests. 82/82 passing across the v0.17.14 surface.

v0.17.13 — transparency gate symmetry for orchestrated DINO-object path

Choose a tag to compare

@yha9806 yha9806 released this 25 Apr 15:37

Transparency fix surfaced from the same γ Scottish dogfood session as v0.17.12. Parallel superpowers:code-reviewer + Codex review of the orchestrated decompose pipeline found that the DINO-object path was missing the SAM-quality gate that the hint-entity path had. Result: low-confidence detections (sam_score < 0.70, bbox_fill < 0.30) were silently marked status: \"detected\" and overall success_rate: 1.0 — leaving calling agents with no signal to inspect the bad mask.

Real-world impact: the lanterns entity in our dogfood plan returned a mask of building structure (sam_score 0.609, bbox_fill 0.256) but reported success.

Fixed

  • scripts/claude_orchestrated_pipeline.py: extract DINO-object quality gate into compute_quality_flags() helper; mirror the hint-path semantics (empty_mask, low_sam_score, low_bbox_fill, mask_outside_bbox) onto the DINO branch. Low-confidence object detections now correctly downgrade to status: \"suspect\" with quality_flags: [...], and the overall manifest status cascades to \"partial\" when any object is suspect.

Added

  • tests/test_quality_gate.py: 8 regression tests pinning the gate's threshold calibration (sam_score 0.70 / bbox_fill 0.30 / inside_ratio 0.60 / pct 0.05) against the γ Scottish 9-entity baseline. 8 clean entities pass at sam ≥ 0.93 / fill ≥ 0.55; lanterns (sam 0.609 / fill 0.256) flips to suspect. Future refactors must update this test explicitly to change the gate.

Out of scope (deferred to v0.18)

The underlying multi-instance segmentation gap (single-bbox-per-label structural limit in detect_all_bboxes) is not fixed here — that's v0.18 scope. v0.17.13 only fixes the transparency bug so the gap is now visible to callers instead of silent.

Other v0.18 items already triaged from the same review:

  • inpaint_artwork(mask_path=...) mask overload — currently the tool only accepts a region-string and runs VLM bbox-detect → rectangular crop → feathered paste; cannot consume a precise mask.
  • layers_redraw alpha-aware preprocessing — currently the prompt explicitly asks the model to fill the entire canvas, which causes hallucinated content for alpha-sparse layer inputs.
  • layers_paste_back glue verb for "edit one layer of a foreign image, paste back preserving everything else."
  • Person-path quality gate (also missing — codex finding).

Install

```bash
pip install vulca==0.17.13
```

For the orchestrated decompose pipeline:

```bash
pip install "vulca[sam,mcp,layers]==0.17.13"
```

Provenance

Surfaced and reviewed in the same dogfood session as v0.17.12, by parallel superpowers:code-reviewer + Codex audit. Both reviewers independently identified the asymmetric gate as a transparency bug separate from the multi-instance architectural gap. The fix is ~30 LOC of code + 8 LOC of regression tests.

v0.17.12 — bugfix rollup + parallel-review hardening

Choose a tag to compare

@yha9806 yha9806 released this 25 Apr 09:52

Bugfix rollup release from the 2026-04-24 γ Scottish showcase Part 1 session (dogfood of Vulca's brainstorm → spec → plan triad on a real Scottish street → Song-dynasty gongbi additive overlay), validated against parallel superpowers:code-reviewer + Codex review of PR #17.

Fixed

  • openai_provider: gate input_fidelity / quality / output_format by per-model capability (#12) — gpt-image-2 GA rejected input_fidelity unconditionally before this fix.
  • openai_provider: capture actual cost_usd from response.usage (#12); log at INFO when a model has no pricing entry instead of silently returning None.
  • openai_provider: normalize quality vocabulary across model families — DALL-E-3 receives `"standard"/"hd"` while gpt-image-* keeps `"high"/"auto"/"medium"/"low"` (post-review hardening).
  • prompting: `compose_prompt_from_design` now handles `tradition: null` (a valid resolved-design state) and reads frozen `C.tradition_tokens` from the artifact when present rather than re-deriving from the live registry (post-review hardening — the artifact is the source of truth for a resolved spec).
  • mcp_server: `compose_prompt_from_design` MCP wrapper raises an actionable error when given a relative path that does not resolve against the server CWD (post-review).
  • [sam] extra: pulls `segment-anything` + `timm>=1.0` so the orchestrated decompose pipeline imports cleanly; see `docs/INSTALL-RECIPE.md`. Critical: do NOT install `[sam,sam3]` together — `transformers==4.49` vs `>=4.50` hard pin conflict; pick one extra per environment until v0.18.

Added

  • MCP tool `compose_prompt_from_design` (#13) — expose Vulca's structured prompt-composition value standalone for non-MCP consumers. Also re-exported as `from vulca import compose_prompt_from_design` for SDK usage.
  • `evaluate_artwork` `mode="rubric_only"` (#14) — agent-native scoring without VLM backend dependency (consumer agents already have vision).
  • `evaluate_artwork` `vlm_model` runtime kwarg (#15) — bypass `VULCA_VLM_MODEL` env + MCP restart for runtime provider switching.

Provenance

  • 4 issue fixes implemented by Codex (task-modjrdmx-br2641, 9m 34s background dispatch).
  • Foundation commit `6e5c38bc` (segment-anything + timm dep gap) closed orchestrated-pipeline import gap surfaced in showcase Part 1 sanity-check.
  • 2 post-review fix commits added regression tests (`design_null_tradition.md` + `design_with_artifact_tokens.md`) so the P1 paths can not silently re-regress.

A/B evidence

The session captured the data point that motivates #13: same `gpt-image-2` API, same source photo, same target intent — Vulca-mediated structured prompt produces additive gongbi overlay (photo preservation honored); bare-curl with naive prompt produces unified-wash filter. That is the buyable differentiator.

Install

```bash
pip install vulca==0.17.12
```

For the full orchestrated decompose pipeline:

```bash
pip install "vulca[sam,mcp,layers]==0.17.12"
```

(See `docs/INSTALL-RECIPE.md` for SAM checkpoint + MCP-Python setup.)

v0.17.11 — honesty + quality-of-life patch

Choose a tag to compare

@yha9806 yha9806 released this 24 Apr 13:50

Summary

Dogfooding-driven honesty + quality-of-life release. 4 commits addressing real bugs + UX gaps surfaced by today's (2026-04-23) Scottish-Chinese fusion showcase + parallel codex + superpowers:code-reviewer product audit. User asked "我们的产品好不好?使用起来有bug吗?" — here's the answer.

What's in

1. Style-Treatment 7th question-bank dimension (commit `69dbd5d1`)

  • `/visual-brainstorm` now asks a mandatory 7th dimension: how the tradition is applied — `additive` (photo preserved, elements painted on top) / `unified` (whole-image transformation) / `collage` (visible cut-outs) / `wash` (global filter).
  • Closes the UX gap where gpt-image-1.5 smoke test produced a whole-image painterly overlay when user wanted additive treatment — the 6-dim question bank simply didn't ask about style application mode.
  • Propagated to `/visual-spec` C.prompt derivation + S4 invariant. `proposal.md` frontmatter now 8 fields (`style_treatment` added).

2. Provider error messages normalized (commit `437f4dc0`)

  • Gemini — classifies empty `response.candidates` into quota-exhaustion vs content-policy vs generic via `prompt_feedback.block_reason`. Points to aistudio.google.com for free-tier quota hits.
  • OpenAI — user-facing messages for 402 billing + 400 content-policy + 429 rate-limit on top of existing 403 Org-verify. Retryability preserved via (fragile) string-match — hardening in v0.17.12.
  • ComfyUI — execution-error extractor surfaces first meaningful message from `status.messages`; invalid-image hint explains likely checkpoint/VAE failure.

3. MCP surface cleanup (commit `5bf4b1ca`)

  • BREAKING: `create_artwork.ref_type` parameter removed — dead code that silently dropped user input. SDK-level `ref_type` unchanged in this release (scoped v0.18+).
  • `layers_split.plan` now documented in Args block; `layers_edit` visible/locked split into 2 lines.
  • Hardcoded `/Users/yhryzy/` paths in shipped docs replaced with `` placeholders.

4. README + BP honesty (commit `856ce54c`)

  • README: "Try it in 60 seconds" → "Quick start" with realistic time breakdown (~1 min if Claude Code + `uv` ready, ~5-10 min from scratch).
  • BP §5.4 moat claim softened: "24 个月以上难以复制" → "12 个月以上需专门投入" + explicit "3 cultural consultants for a quarter" reality check.
  • `.gitignore` adds `/gen_.png`, `/gen_.jpg`, `tmp-shipgate-/` (75 gen_.png removed from repo root).

Review consensus

Both reviewers say ship-with-caveats, no hard blockers.

  • Code: B+ → A-
  • Skill design: B → A-
  • UX: C+ → B
  • Docs: C → B

Known follow-ups (v0.17.12)

  • `/visual-plan` Phase 3 reads `C.style_treatment` (currently declared in design.md but inert in execution; `/visual-spec` governance puts the directive in `base_prompt` so effect exists, just undocumented)
  • `openai_provider._is_retryable` robustness (replace string-match with exception subclass chain)
  • SDK-level `create_artwork.ref_type` cleanup (mirror MCP surface removal)

Tests

1920 passed / 12 pre-existing baseline failures / zero regressions (same baseline as v0.17.10).

Install

```bash
pip install vulca[mcp]==0.17.11
```

Or via uvx in Claude Code MCP config:

```json
{"mcpServers": {"vulca": {"command": "uvx", "args": ["--from", "vulca[mcp]==0.17.11", "vulca-mcp"]}}}
```

v0.17.10 — Superpowers skill alignment + gpt-image-2 bundle

Choose a tag to compare

@yha9806 yha9806 released this 23 Apr 21:26

Summary

Two dogfooding-driven changes bundled in one release.

1. OpenAI gpt-image-2 support (v0.17.9, never shipped separately)

  • `OpenAIImageProvider` now accepts `model="gpt-image-2"` (released by OpenAI 2026-04-21).
  • New Optional kwargs plumbed through MCP `generate_image` + provider + Protocol:
    • `input_fidelity: "high" | "low"` — preserves reference composition (edits endpoint only)
    • `quality: "low" | "medium" | "high" | "auto"`
    • `output_format: "png" | "webp" | "jpeg"`
  • Size set extended with portrait/landscape: `(1024, 1536)`, `(1536, 1024)`.
  • Friendly error detection on OpenAI 403 with "organization must be verified" message.

2. Skill alignment with Superpowers design patterns (v0.17.10)

  • 3 skill descriptions rewritten from descriptive `Triggers: /slash` to imperative `Use when X / You MUST use this before X` — mirrors `superpowers:brainstorming` pattern.
  • New meta-skill `.claude/skills/using-vulca-skills/SKILL.md` (~50 lines) — intent-routing for the triad, normalized finalize vocabulary, red-flag checklist.
  • SessionStart hook (`hooks/hooks.json` + `.claude-plugin/plugin.json`) preloads the meta-skill automatically at session start so agents match user intent without requiring slash commands.
  • Finalize vocabulary normalized: Brainstorm/Spec use `{finalize, done, ready, lock it, approve}`; Plan uses `accept all` exact-match.
  • Cap-hit prompt fix in Plan: `"Turn cap reached. 'accept all' or 'deep review'?"` (was incorrectly `"finalize or deep review?"`).

Why 0.17.8 → 0.17.10 (skipping 0.17.9)

v0.17.9 commit (`8d1a84f8`) was prepared locally as the gpt-image-2 patch but never shipped to PyPI. v0.17.10 bundles both. Users upgrading from v0.17.8 get both in one jump.

Both changes came from real user dogfooding

2026-04-23 attempted to run `/visual-plan` on a real Scottish street photo for a Xiaohongshu showcase. Two blockers surfaced:

  1. openai_provider hardcoded to gpt-image-1 → v0.17.9 fix
  2. Skills required slash commands (broke the "AI agent auto-invokes" UX promise) → v0.17.10 fix

Saved as memory `feedback_dogfood_showcase_through_triad.md` — user-facing showcases MUST run through the triad, never one-off scripts.

Test gate

  • 81/81 pass on visual-plan + visual-spec + MCP-ext tests
  • Full repo: 1920 passed (+3 from v0.17.8 baseline) / 12 pre-existing baseline failures / zero regressions

Deferred to v0.18

Protocol body compression (200-430 lines → 60-170 lines matching Superpowers) flagged by code-reviewer as "long bodies dilute their own descriptions". Not blocking auto-invoke fix; monitor only.

Install

```bash
pip install vulca[mcp]==0.17.10
```

Or via uvx in Claude Code MCP config:

```json
{"mcpServers": {"vulca": {"command": "uvx", "args": ["--from", "vulca[mcp]==0.17.10", "vulca-mcp"]}}}
```

v0.17.8 — MCP metadata forward fix + 12-item clarity patch

Choose a tag to compare

@yha9806 yha9806 released this 23 Apr 20:16

Summary

Bug fix + clarity-gap backlog closure release. Two coupled changes:

1. MCP generate_image metadata forwarding (BUG FIX)

v0.17.6 landed mock-provider echo of `seed/steps/cfg_scale/negative_prompt` into `ImageResult.metadata`, but the MCP wrapper at `src/vulca/mcp_server.py:1216-1221` only extracted `cost_usd` and dropped everything else. Meaning: agents calling MCP could never actually observe the 4 new kwargs round-trip — the v0.17.6 feature was half-shipped.

Surfaced by /visual-plan Layer C v2 live ship-gate on 2026-04-23. Fix is a 1-line addition: `"metadata": dict(result.metadata) if result.metadata else {}` in the return dict. Backward-compat: additive; existing 4-key callers unaffected.

2. /visual-plan SKILL.md clarity patch (12 items)

All 13 clarity-gap candidates from v0.17.7 Layer C v2 (8 items) + v0.17.5 Layer B simulated (5 items) folded in. One item absorbed into `_version.py` fix. Notable:

  • §Handoff 8 → 9 variants: Err #16 content-guard abort split from user-interrupt for downstream grep.
  • `evaluate_artwork` dimensions shape pinned: mock flat-float vs live nested-dict contract with unwrap recipe.
  • MCP metadata agent-hint: Phase 3 pseudocode now notes mock provider echoes MCP kwargs for round-trip verification.
  • Phase 1 tightenings: slug path convention (reject `/` and absolute), traceback guard on Err #1, FIRST-violation precedence on Err #4 (tradition wins over domain), Err #3 + fresh-lockfile rule, stale-lock K=0 semantic.
  • Phase 2 tightenings: Err #8 Write suppression bold, "compact form" definition (`[unchanged sections: …]` 1-liner), redundant-Write symmetry note.
  • Phase 4: overage_pct negative formatting (`"under budget (-%)"` vs raw `-0.9988`).
  • Iter `` semantic paragraph: aborted variants 7-9 use K = iter_idx that WOULD have run.

3. Stale _version.py drift fix

`src/vulca/_version.py` had been stuck at `"0.15.1"` since v0.15.1; `pyproject.toml` was authoritative. `python -c "import vulca; print(vulca.version)"` now correctly reports `0.17.8`.

Test coverage delta

  • New: `test_mcp_wrapper_passes_metadata_through` + `test_mcp_wrapper_metadata_backward_compat_empty_dict` — covering the wrapper-level contract that direct-provider tests missed.
  • 1917 passed full-repo (+2 from v0.17.7 baseline) + 12 pre-existing baseline failures (unchanged).

Backlog status

Clarity-gap backlog from v0.17.5 + v0.17.7 ship-gates: CLOSED. All 13 items folded.

Install

```bash
pip install vulca[mcp]==0.17.8
```

Or via uvx in Claude Code MCP config:

```json
{"mcpServers": {"vulca": {"command": "uvx", "args": ["--from", "vulca[mcp]==0.17.8", "vulca-mcp"]}}}
```