Files
SlabUploader/docs/contracts/CONTENT-WOO.md
Ty 2d12cbcfbd docs(m3): rewrite CONTENT-WOO for clarity
The file repeated requirement IDs on nearly every line, carried defensive
negations, mixed 'description' with 'long description', and left a cross
reference and the payload shape incomplete.

- Cite requirement IDs once in the Requirements impact table.
- Name the seven leaves as the synced WooCommerce wood-category leaves.
- Keep the length ft/in split with the short-description pattern it serves.
- Use 'description' only, matching the Woo field.
- Complete the cross references with section pointers.
- Follow the Woo v3 product shape and add an example submission whose
  taxonomy values are placeholders, since the synced cache supplies them.
2026-09-19 13:17:37 -07:00

7.9 KiB

Listing copy and payload intent

Status: SPEC · 2026-09-18. Owns how listing copy is produced and the intent of the create payload.

Requirements impact

Requirement Impact on this design
METADATA-5, METADATA-10, METADATA-15, METADATA-30, METADATA-55, METADATA-60, METADATA-65, METADATA-66, METADATA-70, METADATA-75, METADATA-80, METADATA-85, METADATA-90, METADATA-95, METADATA-110 taxonomy, copy production, Call 2 inputs, inference-off path, primary category, dimension fact block, logging, non-blocking
REVIEW-10, REVIEW-15, REVIEW-40, REVIEW-50 prose fields, primary category, editability, field limits
PUBLISH-5, PUBLISH-10, PUBLISH-15, PUBLISH-20, PUBLISH-25, PUBLISH-30, PUBLISH-31, PUBLISH-40, PUBLISH-45, PUBLISH-50, PUBLISH-55, PUBLISH-60 payload fields, draft rule, duplicate SKU, images, published meaning, quantity
SETTINGS-30, SETTINGS-65 brand voice, geo context, create status

The wire shape is docs/contracts/WOO-API.md; the create sequence is docs/contracts/API.md; prompts are docs/contracts/PROMPTS.md.

1. The three copy fields

The product carries name, short_description, and description (docs/contracts/WOO-API.md §3).

name and short_description are built by the server from the primary wood category's patterns and the dimension fact block. description is written by Call 2, or by the server when inference is off (METADATA-80, METADATA-70).

The primary wood category is the one the owner declares in review. It selects the title pattern, the short-description pattern, and the Call 2 prompt (METADATA-85, REVIEW-15).

The owner can edit all three fields until create. Length limits are in docs/contracts/WOO-API.md §9 (REVIEW-50).

2. Deterministic title and short description

The patterns interpolate the dimension fact block with {field} placeholders. They read only the synced taxonomy terms and the capture facts (METADATA-80, METADATA-90).

The form is the convention a working mill store uses: descriptor-led, dimension-light titles, with the measurements carried in the short description. See "Provenance" below.

2.1 Title

[Figure] {species} [Live Edge] {noun} [(dims)]
  1. Figure leads as a Title-Case adjective.
  2. Grade is not a title slot.
  3. Live Edge appears for leaves where the edge type is part of the product form.
  4. Slots run together with no separator.
  5. Turning leaves carry (L x W x T) at the end; slab, lumber, and cap leaves carry no dimensions.

The seven leaves below are the WooCommerce wood-category leaf terms. They come from the synced taxonomy only (METADATA-5, METADATA-10); parents group and are not assigned.

Leaf Pattern Example
Live edge wood [Figure] {species} Live Edge Slab Figured Black Walnut Live Edge Slab
Dimensional wood [Figure] {species} [Live Edge] Dimensional Figured Red Oak Dimensional
Knife blanks [Figure] {species} Knife Blank (L x W x T) Figured Mirindiba Knife Blank (12 x 6.5 x 1.5 in)
Bowl blanks [Figure] {species} [Live Edge] Bowl Blank (L x W x T) Spalted Cherry Bowl Blank (8 x 8 x 3 in)
logs and caps [Figure] {species} Log Cap Figured Black Walnut Log Cap
Pen blanks [Figure] {species} Pen Blank (L x W x T) Figured Purpleheart Pen Blank (5.5 x 1.1 x 1.1 in)
Pepper mill blanks [Figure] {species} Pepper Mill Blank (L x W x T) Birdseye Olive Pepper Mill Blank (10 x 3.2 x 3 in)

Specialty cuts has no M3 pattern.

An unset Figure drops its slot; the title starts at {species}.

2.2 Short description

One spec line, carrying the measurements the title omits:

[Figure] {species} {noun}, {length} x {width} x {thickness}, {bdft} bdft

The line expresses length in feet and inches, so it splits length_in: {length_ft}ft {length_in_remainder}in, where length_ft = floor(length_in / 12) and length_in_remainder = length_in mod 12, to 1 dp. The title uses the same split for its length slot.

Leaf Example
Live edge wood Figured Black Walnut Live Edge Slab, 9ft 6in x 24.3in x 1.75in, 18.4 bdft
Dimensional wood Figured Red Oak Dimensional, 8ft 0in x 5.8in x 1.25in, 4.8 bdft
Pepper mill blanks Birdseye Olive Pepper Mill Blank, 10in x 3.2in x 3in, 0.7 bdft

2.3 Description

Call 2 writes the description using the specialized prompt selected by the primary wood category (METADATA-85). The prompt receives the processed photos, the review-confirmed metadata, the primary and secondary wood categories, the parent-category path, the dimension fact block, and brand/geo context (METADATA-60). With inference off the server produces the description (METADATA-70). The field carries HTML, as WooCommerce expects on description (docs/contracts/WOO-API.md §3).

2.4 Provenance

The title and short-description form was modeled on the live product titles of Cook Woods (cookwoods.com), captured 2026-09-19. Borrowed: descriptor-led titles; dimension-free titles for slabs, lumber, and caps; parenthetical dimensions only for turning stock; no separator; title case. Not borrowed: their size-class nouns (Mini Slab, Table, Micro Lumber, Long) and pack counts (5 Pack), which have no synced taxonomy term, and their grade adjectives.

3. Payload intent

The exact wire shape is docs/contracts/WOO-API.md §3–§5. Intent:

  1. Only non-null fields are sent (PUBLISH-55).
  2. The payload carries an explicit slug: the sanitized product name plus the lowercased SKU (PUBLISH-55).
  3. status comes from woo_create_status (default draft); a SLAB-UAT-* SKU creates a draft (PUBLISH-10, SETTINGS-65).
  4. Categories are the species leaf plus each wood-category leaf; attributes are the five locked attributes by synced term; tags are the fig-* and feat-* families (METADATA-10, METADATA-15, METADATA-30).
  5. Images are the processed transparent PNGs in photos-ready order, with no cap (PUBLISH-40, PUBLISH-45).
  6. sold_individually is true; each product is one slab (PUBLISH-60).
  7. Create checks the SKU first and stops on a duplicate; a stale value is a field-level error (PUBLISH-15, PUBLISH-20).
  8. Success purges photos and deletes the local row; failure retains photos and writes sync_log, including the orphaned-media cleanup note (PUBLISH-25, PUBLISH-30, PUBLISH-31). Published means the create succeeded, not that the listing is live (PUBLISH-50).

3.1 Example submission

The structure below is the WooCommerce product shape this app sends. Woo ids and term names come from the synced taxonomy at runtime; the values shown are illustrative.

{
  "name": "Figured Black Walnut Live Edge Slab",
  "type": "simple",
  "status": "draft",
  "sku": "<SKU>",
  "slug": "figured-black-walnut-live-edge-slab-<lowercased sku>",
  "regular_price": "<bdft x species rate, 2 dp>",
  "description": "<p>Prose written by Call 2.</p>",
  "short_description": "Figured Black Walnut Live Edge Slab, 9ft 6in x 24.3in x 1.75in, 18.4 bdft",
  "categories": [{ "id": "<species leaf id>" }, { "id": "<wood-category leaf id>" }],
  "tags": [{ "id": "<fig-* tag id>" }, { "id": "<feat-* tag id>" }],
  "images": [{ "id": "<attachment id>" }],
  "attributes": [
    { "id": "<Edge Type id>", "position": 0, "visible": true, "variation": false, "options": ["<edge term>"] },
    { "id": "<Figure id>", "position": 1, "visible": true, "variation": false, "options": ["<figure term>"] },
    { "id": "<Grade id>", "position": 2, "visible": true, "variation": false, "options": ["<grade term>"] },
    { "id": "<Thickness id>", "position": 3, "visible": true, "variation": false, "options": ["<thickness term>"] },
    { "id": "<Moisture id>", "position": 4, "visible": true, "variation": false, "options": ["<moisture term>"] }
  ],
  "virtual": false,
  "downloadable": false,
  "catalog_visibility": "visible",
  "sold_individually": true
}

Only non-null fields are sent, so a listing without feat-* tags omits them from tags, and each attributes element carries a single options value.