Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e84f6e1
feat: pre-workflow prototyping skill for exploring multiple ideas (#42)
striderZA May 5, 2026
92651a5
feat: /start command Path E for pre-workflow exploration (#46)
striderZA May 5, 2026
2cf8c74
feat: Workflow Selection Gate for Hybrid vs Full OCGS (#43)
striderZA May 5, 2026
44ffbf7
docs: artifact promotion rules for prototype-to-production transition…
striderZA May 5, 2026
cc6a036
docs: decision criteria and case studies for Hybrid vs Full OCGS (#45)
striderZA May 5, 2026
b385a6c
feat: Workflow Selection Gate for Hybrid vs Full OCGS (#43)
striderZA May 5, 2026
a25ed9c
docs: Artifact promotion rules for prototype-to-production transition…
striderZA May 5, 2026
05cee5f
docs: Decision criteria and case studies for Hybrid vs Full OCGS (#45)
striderZA May 5, 2026
c12403d
test: Workflow integrity test suite — cross-references, paths, gates,…
striderZA May 5, 2026
4c8b2cc
docs: Update README and CONTRIBUTING for workflow test suite
striderZA May 5, 2026
4a9bc7a
docs: Clean up README framing and stale counts
striderZA May 5, 2026
0e95865
feat: Art bible now exports machine-readable palette, typography, AI …
striderZA May 5, 2026
6503d1d
fix: Update skill-testing-framework paths, add missing skills, valida…
striderZA May 5, 2026
71f22ea
fix: Address PR review comments
striderZA May 5, 2026
1bbeed0
docs: Aseprite MCP integration design doc
striderZA May 7, 2026
500b80f
feat: add aseprite-mcp submodule at tools/aseprite-mcp
striderZA May 7, 2026
4f46157
feat: add project-scoped MCP config for aseprite and godot
striderZA May 7, 2026
a464fe2
feat: add asset output directories for art-generate skill
striderZA May 7, 2026
bef673d
feat: add art-generate skill for programmatic placeholder art
striderZA May 7, 2026
0da728c
docs: aseprite integration plan
striderZA May 7, 2026
733f340
fix: register art-generate skill with command file and catalog
striderZA May 7, 2026
9bb448f
fix: move ISSUE_TEMPLATE to correct .github/ location, add feature re…
striderZA May 7, 2026
9914766
fix: address PR review — portability, timeout, missing bug-report.md,…
striderZA May 7, 2026
9040bdb
merge: resolve conflicts with master
striderZA May 7, 2026
5ae61b8
fix: use correct config option syntax for environment variables
striderZA May 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .github/workflows/ISSUE_TEMPLATE/config.yml

This file was deleted.

4 changes: 4 additions & 0 deletions .github/workflows/agent-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ jobs:
name: Agent Framework Validation
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-node@v4
with:
node-version: 20
Expand All @@ -29,6 +31,8 @@ jobs:
name: Workflow Integrity
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ desktop.ini
*.swo
*~
tests/agents/validation-report.md

# Submodule dependencies
tools/aseprite-mcp/.venv/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "tools/aseprite-mcp"]
path = tools/aseprite-mcp
url = https://github.com/striderZA/aseprite-mcp.git
8 changes: 8 additions & 0 deletions .opencode/commands/art-generate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: art-generate
description: "Generate placeholder art from asset specs using the Aseprite MCP"
skill: art-generate
category: design
---

Invokes `/art-generate` skill.
321 changes: 321 additions & 0 deletions .opencode/skills/art-generate/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
---
name: art-generate
description: "Generates placeholder .aseprite files from asset specs using the Aseprite MCP. Reads asset specs and art bible, creates sprites with correct dimensions/palette/layers, exports PNGs. Run after /asset-spec has produced specs and /art-bible exists."
argument-hint: "[system:<name> | level:<name> | character:<name> | path/to/spec.md]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, question
---

If no argument is provided, read `design/assets/asset-manifest.md`:
- If it exists: find the first target with any asset at `Status: Needed` and use `question`:
- Prompt: "The next unspecced target is **[target]**. Generate placeholder art for it?"
- Options: `[A] Yes — generate for [target]` / `[B] Pick a different target` / `[C] Stop here`
- If no manifest: fail with:
> "No asset manifest found. Run `/asset-spec [target]` first — I need asset specs to generate art from."

---

## Phase 0: Parse Target

Resolve the target:
1. If argument matches `system:<name>` → spec at `design/assets/specs/[name]-assets.md`
2. If argument matches `level:<name>` → spec at `design/assets/specs/[name]-assets.md`
3. If argument matches `character:<name>` → spec at `design/assets/specs/[name]-assets.md`
4. If argument is a path → read that file directly
5. If argument is a path to a .md file → treat as spec file

Fail if the spec file does not exist:
> "No asset spec found at `[path]`. Run `/asset-spec [target]` first."

---

## Phase 1: Gather Context

Read all source material before generating anything.

### Required reads:
- **Asset spec**: Read the resolved spec file. Extract all `ASSET-NNN` entries. For each, extract: Category, Dimensions, Format, Naming, Visual Description.
- **Art bible**: Read `design/art/art-bible.md` — fail if missing:
> "No art bible found. Run `/art-bible` first — I need the palette and shape language to generate art."
Extract: Color System (Section 2), Shape Language (Section 3), Asset Standards (Section 8 — dimension tiers).
- **Asset manifest**: Read `design/assets/asset-manifest.md` — note which assets already have placeholders. Filter to assets with `Status: Needed`.

### Present context summary:
> **art-generate: [Target Type] — [Target Name]**
> - Spec: [path] — [N] assets identified
> - Art bible: found — [N] palette colors, shape language: [style]
> - Assets to generate: [N] (filtered from [N] total — [N] already have placeholders)
> - Output: assets/source/[target]/ and assets/sprites/[target]/

---

## Phase 2: Per-Asset Generation

For each asset with `Status: Needed`, execute the following pipeline. **Process one asset at a time — do NOT batch MCP calls.**

### Step 2a: Create Canvas

Construct the filename as `assets/source/[target]/[naming]` (replace `.png` or similar with `.aseprite`).

Use the `create_canvas` MCP tool:
```
create_canvas(width, height, filename)
```

Wait for success. If it fails, stop this asset and report.

### Step 2b: Apply Palette

Load the art bible palette. If the art bible specifies a named palette resource (e.g., "DB16", "RPG"), use:

```
load_palette_from_resource(filename, resource_name)
```

Otherwise extract hex colors from the art bible's Color System section and apply:

```
set_palette(filename, [hex_colors_array])
```

### Step 2c: Create Layer Structure

Create layers matching the asset category template:

**Sprite / 2D Art:**
```
add_layer(filename, "body")
set_layer(filename, "body")
set_layer_label_color(filename, "body", color_hex)
add_layer(filename, "details")
add_layer(filename, "outline")
```

**UI Icon:**
```
add_layer(filename, "icon")
```

**VFX:**
```
add_layer(filename, "core")
set_layer_blend_mode(filename, "core", "normal")
add_layer(filename, "glow")
set_layer_blend_mode(filename, "glow", "add")
add_layer(filename, "sparks")
```

**Environment:**
```
add_layer(filename, "base")
add_layer(filename, "shading")
add_layer(filename, "details")
```

**Character Sprite:**
```
add_layer(filename, "body")
add_layer(filename, "head")
add_layer(filename, "arms")
add_layer(filename, "legs")
add_layer(filename, "outline")
```

### Step 2d: Draw Placeholder Content

Draw shapes on each layer following the art bible's shape language. Use the semantic color from the art bible for the asset's role.

General approach per layer:
1. `set_layer(filename, layer_name)` — activate the layer
2. `set_frame(filename, 1)` — draw on frame 1
3. Draw shapes:
- **Body/base**: Fill a rectangle/circle/polygon covering ~80% of the canvas at the body center position
- **Details**: Smaller shapes offset from center, using secondary/accent colors from the palette
- **Outline**: Thin rectangle around the body bounds using a dark color

Use these drawing tools as appropriate:
- `draw_rectangle_at(filename, layer, frame, x, y, w, h, color, fill=true)` for blocky shapes
- `draw_circle_at(filename, layer, frame, cx, cy, r, color, fill=true)` for round shapes
- `draw_polygon(filename, layer, frame, points, color, fill=true)` for angular shapes (character limbs)
- `fill_area_at(filename, layer, frame, cx, cy, color)` for filled regions
- `apply_gradient_rect(filename, layer, frame, x, y, w, h, start, end, horizontal)` for gradient fills

### Step 2e: Handle Animation

If the spec indicates multiple frames (e.g., "4-frame sprite sheet"):

```
add_frames(filename, count=3, duration_ms=200) # frame 1 already exists
set_frame_duration(filename, 1, 200)
```

For each additional frame, duplicate frame 1 and add minor position offsets for limbs:
```
copy_frame(filename, source_frame=1, target_frame=N)
```

Then tag the animation:
```
set_tag(filename, name="default", from_frame=1, to_frame=N, direction="forward")
```

If not animated, skip this step.

### Step 2f: Export

```
export_sprite(filename, output_path="assets/sprites/[target]/[naming]")
```

### Step 2g: Verify

Use the quality tools to check the output:

```
validate_scene(filename, required_layers=[list from step 2c])
```

Expected: JSON confirming all layers and frames exist.

Also verify the exported file exists:
```
Test-Path "assets/sprites/[target]/[naming]"
```

Expected: `True`

### Error Handling

If any MCP tool call fails:
```
Question: "Tool [tool_name] failed for ASSET-[NNN] ([asset name]): [error]. Options:"
A) Retry this asset
B) Skip this asset, continue with next
C) Stop generation entirely
```

---

## Phase 3: Update Manifest

After all assets are generated (or after partial completion), update `design/assets/asset-manifest.md`.

For each generated asset, change its status from `Needed` to `Placeholder Created`. Add a `Source` column if it doesn't exist:

```
| ASSET-001 | hero-sprite | Sprite | Placeholder Created | design/assets/specs/hero-assets.md | assets/source/hero/ASSET-001-hero-sprite.aseprite |
```

If the manifest doesn't have a `Source` column yet, rewrite the header to include it.

---

## Phase 4: Summary Report

Present a completion summary:

> **art-generate complete for [target]:**
> - [N]/[M] assets generated successfully
> - [N] failed (skipped)
> - Output: assets/source/[target]/ (source .aseprite files)
> - Output: assets/sprites/[target]/ (exported PNGs)
> - Manifest updated: design/assets/asset-manifest.md

---

## Phase 5: Next Steps

Use `question`:
- Prompt: "Placeholder art generated for **[target]**. What's next?"
- Options:
- `[A] Generate another target — /art-generate [next-target]`
- `[B] Run /asset-audit — validate generated assets against specs`
- `[C] Review generated art manually`
- `[D] Stop here`

---

## Per-Category Drawing Templates

### Sprite / 2D Asset (Default)

```
Canvas: spec dimensions (e.g. 256x256)
Layers: body, details, outline

Frame 1:
layer=body: fill_rect(32, 32, 192, 192, body_color)
layer=details: draw_rect(48, 48, 160, 160, accent_color, fill=false)
layer=outline: draw_rect(30, 30, 196, 196, outline_color, fill=false)
```

### UI Icon

```
Canvas: 32x32 or 64x64
Layers: icon

Frame 1:
layer=icon: fill_rect(4, 4, 24, 24, palette[0])
```

### VFX

```
Canvas: matching target sprite dimensions
Layers: core, glow, sparks

Frame 1:
layer=core: circle(center, radius*0.3, core_color, fill=true)
layer=glow: circle(center, radius, glow_color, fill=true, set opacity=128)
```

### Environment Prop

```
Canvas: tile dimensions
Layers: base, shading, details

Frame 1:
layer=base: fill_rect(0, 0, w, h, base_color)
layer=shading: gradient_rect(0, 0, w, h, shade_top, shade_bottom)
```

### Character Sprite

```
Canvas: sprite sheet width, frame height
Layers: body, head, arms, legs, outline

Frame 1 (idle pose):
layer=body: fill_rect(24, 40, 16, 24, body_color)
layer=head: fill_rect(28, 24, 8, 12, skin_color)
layer=arms: fill_rect(16, 44, 8, 8, skin_color)
draw_rect(40, 44, 8, 8, skin_color)
layer=legs: fill_rect(24, 64, 6, 12, leg_color)
fill_rect(34, 64, 6, 12, leg_color)
layer=outline: draw_rect(22, 22, 20, 54, outline)

Frame 2 (walk frame 1): copy_frame(1, 2)
layer=legs: offset legs by +2 on x to show stride
```

---

## Error Recovery

| Error | Recovery |
|-------|----------|
| Spec file not found | Fail with clear message pointing to /asset-spec |
| Art bible not found | Fail — generation without palette produces wrong colors |
| MCP tool timeout | Report tool + args that failed, offer retry/skip/stop |
| Palette resource unknown | Fall back to `set_palette` with hex colors from art bible |
| Export fails | Check file path permissions, suggest manual export |
| validate_scene fails | Report which layers/frames are missing, offer to fix via ensure_layers_present |

## Collaborative Protocol

- Never generate without user confirming the target
- Report each asset's success/failure immediately after processing it
- Write the manifest update only after explicit approval
- If the art bible's palette has changed since the spec was written, ask which to use
2 changes: 1 addition & 1 deletion .opencode/skills/help/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ argument-hint: "[optional: what you just finished, e.g. 'finished design-review'
user-invocable: true
allowed-tools: Read, Glob, Grep
context: |
!echo "=== Live Project State ===" && echo "Stage: $(cat production/stage.txt 2>/dev/null | tr -d '[:space:]' || echo 'not set')" && echo "Latest sprint: $(ls -t production/sprints/*.md 2>/dev/null | head -1 || echo 'none')" && echo "Session state: $(head -5 production/session-state/active.md 2>/dev/null || echo 'none')"
Static help skill — reads production artifacts directly to determine project state and next steps.
model: opencode-go/deepseek-v4-flash
---

Expand Down
Empty file added assets/source/.gitkeep
Empty file.
Empty file added assets/sprites/.gitkeep
Empty file.
Loading
Loading