# Mitasu for Apparel — AI Operations Guide (spec for AI agents)

> Version 2026-07-10 (kept in sync with the app; consistency is test-enforced).
> How to use: paste this entire document into an AI assistant that can reach the
> Shopify Admin API (Claude + the Shopify connector, Claude Code + a Shopify MCP,
> or a custom agent), then ask it to register or assign product information.
> 日本語版: https://mitasu.tech/ai/apparel-agent-guide.ja.md

All of this app's data lives in **Shopify metafields/metaobjects** (no external
database; every key is under the `apparel_info` namespace). Any AI agent with
Admin GraphQL access can therefore **create templates and assign them to
products** without going through the app's admin UI.

---

## Most important: the two safe paths

1. **[Safest — recommended] The CSV path** — use the app's **CSV export** → the AI
   fills in the columns → **CSV import** (Pro). Name-based references, validation
   and caps are all enforced **by the app**. Columns:
   `title, handle, size_chart, spec, outfits, models, faq` (references go **by
   template name**; Q&A by **question text**; multiple values `|`-separated;
   **empty columns are left unchanged**).
2. **[Advanced] Direct GraphQL** — follow this spec exactly. Only ever
   **create templates (metaobjects) and assign references** — never write any
   other key.

## Absolute rules (violations break the storefront and/or the app admin)

1. **Store measurements in cm only** (never store inch — the app converts at
   display time).
2. **Write only template creations and ref assignments.** Never write
   `*_override` / `fit_feedback` / `return_stats` / `fit_baseline` /
   `review_pending` / `insights_cache` / `installed_at` / `plan` /
   `plan_cancel_at` (app-managed aggregates & internals). For per-product tweaks,
   tell the owner to use the app's override UI.
3. **Never create new data in legacy keys:** inline `materials` / `care` /
   `model_fit` / `fit_details` (product AND variant), the singular `outfit_ref`,
   the old `faq` JSON, `faq_custom_items`, `faq_order` — all read-only fallbacks.
   Fabric composition, color, stretch etc. belong in **Shopify's standard
   category metafields** (entered on the product page); the app displays them
   automatically in the Features tab. Do not mirror them into the app namespace.
4. **Assignment caps:** `outfit_refs` ≤ **4** / `model_refs` ≤ **4** /
   `faq_items` ≤ **10**; worn products per outfit (`items`) ≤ **6**.
5. **Search for an existing template by name before creating one** (no
   duplicates). **Delete templates only through the app UI** (a raw delete skips
   the assignment/override cleanup).
6. Before destructive changes (replacing existing refs, bulk updates), read the
   current values and confirm with the user.
7. `metafieldsSet` accepts ≤ 25 entries per call. Always check `userErrors`.

## Data model (current = Plan A: template references + per-product overrides)

### Templates = metaobjects (5 reusable types)

**`apparel_info_size_chart`**
| key | type | allowed values / shape |
|---|---|---|
| `name` | text | required. Display name (keep it unique — CSV references use it) |
| `category` | text | `top / bottom / dress / outerwear / underwear / skirt / shoes / socks / bra / headwear` (sets the default columns) |
| `audience` | text | `unisex / men / women / boys / girls / baby / shoe / bra / head / none` — picks the measurement figure; `shoe`/`bra`/`head` also reshape the table; `head` is a head-circumference table + measurement diagram with **no fit finder**; `none` = no figure |
| `silhouette` | text | Flat-lay diagram shape (`top / hoodie / collar / sleeveless / cardigan / outerwear / bottom / shorts / dress / skirt / custom`), fixed at creation; empty for shoe/bra/head. `custom` = the blank template where the merchant supplies the figures. Blank falls back to the category shape on the storefront; agents may leave it unset (the app sets it) |
| `garment_type` | text | Originating template id (e.g. `tee-unisex`), fixed at creation; drives the editor's 品目 label. Agents leave it unset (the app sets it) |
| `figure_image` / `garment_image` | file_reference | Custom body 採寸図 / garment 実寸 diagrams, blank template only (`silhouette=custom`); shown on the storefront in place of the built-in figures. Agents leave these unset (the app manages them) |
| `measurement_type` | text | `body` (wearer's body) or `garment` (flat product measurements). **Drives the fit-finder's ease logic — must be correct** |
| `unit_primary` | text | `cm` or `inch` (editing unit only; **stored values are always cm**) |
| `fit_tag` | text | `tight / regular / loose / oversize` |
| `stretch` | boolean | `"true"` / `"false"` |
| `length_tag` | text | `cropped / regular / long` |
| `tolerance_cm` | single_line_text_field | Optional manufacturing tolerance, **stored in cm** as a number string (e.g. `"1.5"`). On garment (`measurement_type=garment`) charts only, the storefront prints a variance note under the size table (the shown unit follows the cm/inch toggle); agents may leave it unset |
| `rows` | json | `[{ "size_label": "M", "size_us": "8", "size_uk": "12", "size_eu": "38", "size_jp": "11", "measurements": { "chest_cm": 88, "length_cm": 62 } }]`. Measurement keys: `chest_cm / waist_cm / hip_cm / length_cm / sleeve_cm / inseam_cm` (shoes/socks: `foot_length_cm`; bra: `underbust_cm / bust_cm`; headwear: `head_cm`). Ranges: add `<key>_max` (e.g. `"waist_cm": 78, "waist_cm_max": 84` → "78–84"). Omit unused keys (omitted columns don't render) |

**`apparel_info_spec` (fabric & spec profile)**
| key | allowed values |
|---|---|
| `name` | required |
| `transparency` | `none / slight / moderate / sheer` |
| `lining` | `none / partial / full` |
| `season` | `all / ss / aw` |
| `sustainability` | list of certification codes only: `gots / oeko_tex / grs / rws / ocs / bluesign / fair_trade / cradle_to_cradle / bcorp / climate_neutral` |
| `care` | json `{ "wash"?, "bleach"?, "dry"?, "iron"?, "dryclean"? }` — codes below. Rendered as **plain-text labels** on the storefront (no icons) |

**`apparel_info_model` (model fit):** `name` (required) / `height_cm` /
`weight_kg` / `size_worn` / `fit_tag` (`tight/regular/loose/oversize`) /
`comment` / `image` (photo URL string)

**`apparel_info_faq` (one Q&A pair):** `question` (required) / `answer` (required)

**`apparel_info_outfit` (complete-the-look):** `name` (required) / `items`
(list.product_reference — product GIDs, ≤ 6) / `note` / `image` (file_reference —
a Files GID; omit if unavailable)

### Product metafields (assignment — these 6 are the ONLY writable ones)

| key | type | content |
|---|---|---|
| `size_chart_ref` | metaobject_reference | size-chart GID (single) |
| `spec_set_ref` | metaobject_reference | spec-profile GID (single) |
| `model_refs` | list.metaobject_reference | model GIDs (≤ 4, display order) |
| `outfit_refs` | list.metaobject_reference | outfit GIDs (≤ 4, display order) |
| `faq_items` | list.metaobject_reference | Q&A GIDs (≤ 10, display order) |
| `fit_hint_override` | text | `true_to_size / runs_small / runs_large` (empty = unset; real vote data wins once it accumulates) |

### Variant metafields (writable)

`size_chart_ref` / `spec_set_ref` only (e.g. separate charts for "Regular" vs
"Tall" variants).

### Shop settings (SHOP-owned) — prefer pointing the owner to the app's Settings

`feature_flags` (section on/off) / `section_order` / `section_titles` /
`default_unit` (`cm|inch`) / `week_start` (`mon|sun`). Reading them is fine.

## Care codes (for `apparel_info_spec.care`)

| category | codes |
|---|---|
| wash | `wash_30` `wash_40` `wash_60` `wash_hand` `wash_no` |
| bleach | `bleach_any` `bleach_oxygen` `bleach_no` |
| dry | `dry_tumble` `dry_no_tumble` `dry_line` `dry_flat` |
| iron | `iron_high` (200°C) `iron_med` (150°C) `iron_low` (110°C) `iron_no` |
| dryclean | `dc_p` `dc_f` `dc_w` `dc_no` |

## Recommended workflow (analyze products → create templates → assign)

1. **Read the products** — classify garment type, audience (men/women/kids) and
   fabric feel from title/description/type/tags/standard category.
2. **Search existing templates first** — `metaobjects(type: "...", first: 250)`
   and check names. Reuse matches (owners often already imported some of the
   app's 68 bundled size-chart templates via the UI).
3. **Create only the missing templates** — follow the schemas above exactly
   (especially `measurement_type` and cm-only).
4. **Assign** — `metafieldsSet` with the refs (list values are a JSON string
   like `"[\"gid://...\"]"`). Or **generate a CSV and have the owner import
   it** (the safest route).
5. **Verify** — have the owner check the coverage badges on the app's
   "Products" screen or the Insights coverage.

## GraphQL examples

### Create a size-chart template
```graphql
mutation {
  metaobjectCreate(metaobject: {
    type: "apparel_info_size_chart",
    fields: [
      { key: "name", value: "Men's tee S-XL" },
      { key: "category", value: "top" },
      { key: "audience", value: "men" },
      { key: "measurement_type", value: "garment" },
      { key: "unit_primary", value: "cm" },
      { key: "fit_tag", value: "regular" },
      { key: "stretch", value: "false" },
      { key: "length_tag", value: "regular" },
      { key: "rows", value: "[{\"size_label\":\"S\",\"measurements\":{\"chest_cm\":86,\"length_cm\":66}},{\"size_label\":\"M\",\"measurements\":{\"chest_cm\":92,\"length_cm\":69}}]" }
    ]
  }) { metaobject { id } userErrors { field message } }
}
```

### Assign to a product (size chart + spec + Q&A)
```graphql
mutation {
  metafieldsSet(metafields: [
    { ownerId: "gid://shopify/Product/123", namespace: "apparel_info", key: "size_chart_ref",
      type: "metaobject_reference", value: "gid://shopify/Metaobject/456" },
    { ownerId: "gid://shopify/Product/123", namespace: "apparel_info", key: "spec_set_ref",
      type: "metaobject_reference", value: "gid://shopify/Metaobject/789" },
    { ownerId: "gid://shopify/Product/123", namespace: "apparel_info", key: "faq_items",
      type: "list.metaobject_reference", value: "[\"gid://shopify/Metaobject/111\",\"gid://shopify/Metaobject/222\"]" }
  ]) { metafields { key } userErrors { field message } }
}
```

### List existing templates (duplicate check / get GIDs for assignment)
```graphql
{ metaobjects(type: "apparel_info_size_chart", first: 250) {
    nodes { id field(key: "name") { value } }
    pageInfo { hasNextPage endCursor } } }
```

## Troubleshooting

- `UNDEFINED_OBJECT_TYPE` / definition errors → have the owner run the app's
  "Settings → Re-check" (definitions self-heal).
- Assigned but not visible on the storefront → check in order: ① is the feature
  Pro-only while the store is on Free (model fit / spec / outfits / votes /
  confidence badge are Pro)? ② is the section toggled off in Settings? ③ is the
  app block placed in the theme?
- Refs beyond the caps are not rendered — keep lists within the limits.
