Local Brandkit state routing

Store approval state in the active project's brandkit/state.json. Drafts never enter it. The bundled script writes atomically and tracks independent logo, palette, typography, visual-axis, and downstream-element revisions.

Use the path variables established by SKILL.md:

python3 "$SKILL_ROOT/scripts/brandkit.py" state \
  --state-file "$BRANDKIT_STATE" \
  --action ACTION [--input "$BRANDKIT_WORKDIR/input.json"]

Create payload files as JSON under "$BRANDKIT_WORKDIR". Never interpolate user text into a shell command argument. Before the first state write, load exact state payloads and replace values, not keys or nesting.

Persistence

Call moments

Start of every Brandkit turn

python3 "$SKILL_ROOT/scripts/brandkit.py" state \
  --state-file "$BRANDKIT_STATE" --action get_status

Lock user-supplied official assets

Immediately after asset analysis, call only the matching action:

lock_authoritative_logo       {"source_summary": "...", "logo": {...}}
lock_authoritative_palette    {"source_summary": "...", "palette": {...}}
lock_authoritative_typography {"source_summary": "...", "typography": {...}}

These actions preserve official assets. They do not approve generated drafts, and a generated choice cannot replace an authoritative slot.

Persist visual axes

Call set_visual_axes with:

{
  "visual_axes": {
    "restrained_expressive": 50,
    "geometric_organic": 50,
    "familiar_experimental": 50
  }
}

Read only the required slot

Never make get_essential_kit a universal gate for partial outputs.

Approve generated foundation slots

After an explicit user selection:

approve_logo       {"approval_summary": "...", "logo": {...}}
approve_palette    {"approval_summary": "...", "palette": {...}}
approve_typography {"approval_summary": "...", "typography": {...}}

A generated logo records the active palette revision. Replacing that palette removes the generated logo and invalidates logo-dependent outputs. Replacing typography does not invalidate a symbol-only logo.

Browse and approve downstream elements

Call list_brandbook_elements, then get_brandbook_element with:

{ "key": "exact-element-key" }

After explicit approval, call approve_brandbook_element with the exact slots used:

{
  "approval_summary": "User approved the primary mockup.",
  "required_slots": ["logo", "palette"],
  "brandbook_element": {
    "key": "mockup-primary",
    "kind": "mockup",
    "name": "Primary packaging mockup",
    "asset": {
      "path": "/absolute/path/to/mockup.png"
    }
  }
}

Never