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.
This commit is contained in:
@@ -1,66 +1,48 @@
|
|||||||
# Listing copy and payload intent
|
# Listing copy and payload intent
|
||||||
|
|
||||||
Status: SPEC · 2026-09-18.
|
Status: SPEC · 2026-09-18.
|
||||||
Owns how listing copy is produced and the intent of the create payload. The wire shape is
|
Owns how listing copy is produced and the intent of the create payload.
|
||||||
`docs/contracts/WOO-API.md`; the create sequence is `docs/contracts/API.md`; prompts are
|
|
||||||
`docs/contracts/PROMPTS.md`.
|
|
||||||
|
|
||||||
## Requirements impact
|
## Requirements impact
|
||||||
|
|
||||||
| Requirement | Impact on this design |
|
| Requirement | Impact on this design |
|
||||||
|---|---|
|
|---|---|
|
||||||
| REVIEW-10, REVIEW-15, REVIEW-40, REVIEW-50 | required prose, primary category, editability, limits |
|
| 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 |
|
||||||
| METADATA-55, METADATA-60, METADATA-65, METADATA-66 | Call 2, inputs, dimension safety, logging |
|
| REVIEW-10, REVIEW-15, REVIEW-40, REVIEW-50 | prose fields, primary category, editability, field limits |
|
||||||
| METADATA-70, METADATA-75, METADATA-80, METADATA-85, METADATA-90, METADATA-95, METADATA-110 | deterministic copy, inference-off path, pattern selection, fact block, overlay exclusion, control |
|
| 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 |
|
||||||
| 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 and create outcomes |
|
| SETTINGS-30, SETTINGS-65 | brand voice, geo context, create status |
|
||||||
| SETTINGS-30, SETTINGS-65 | brand voice and geo context; create status |
|
|
||||||
| METADATA-10, METADATA-15, METADATA-30 | categories, attributes, tags on the payload |
|
|
||||||
|
|
||||||
## 1. Copy sources
|
The wire shape is `docs/contracts/WOO-API.md`; the create sequence is `docs/contracts/API.md`; prompts are `docs/contracts/PROMPTS.md`.
|
||||||
|
|
||||||
Three fields, three sources (`REVIEW-10`):
|
## 1. The three copy fields
|
||||||
|
|
||||||
1. **name** — assembled deterministically by the server from the primary wood category's title
|
The product carries `name`, `short_description`, and `description` (`docs/contracts/WOO-API.md` §3).
|
||||||
pattern and the dimension fact block (`METADATA-80`). The model does not write it.
|
|
||||||
2. **short_description** — assembled deterministically as a spec line from the primary wood
|
|
||||||
category's short-description pattern (`METADATA-80`). The model does not write it.
|
|
||||||
3. **description** — written by Call 2 when it runs (`METADATA-55`), from the inputs in
|
|
||||||
`METADATA-60`; with inference off the server produces it (`METADATA-70`).
|
|
||||||
|
|
||||||
The primary wood category selects the title pattern, the short-description pattern, and the Call 2
|
`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`).
|
||||||
prompt (`METADATA-85`, `REVIEW-15`). The owner can edit any field until create (`REVIEW-40`), and
|
|
||||||
every field respects the limits in `docs/contracts/WOO-API.md` §9 (`REVIEW-50`).
|
|
||||||
|
|
||||||
The model writes the long description only, from the fact block; it never invents a dimension
|
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`).
|
||||||
(`METADATA-65`, `METADATA-90`). The dimension-overlay image is never sent (`METADATA-95`). The
|
|
||||||
Generate text control appears only when content generation is enabled and the endpoint is
|
The owner can edit all three fields until create. Length limits are in `docs/contracts/WOO-API.md` §9 (`REVIEW-50`).
|
||||||
reachable (`METADATA-110`); a failed generation never blocks create (`METADATA-75`). Every
|
|
||||||
generation is logged (`METADATA-66`).
|
|
||||||
|
|
||||||
## 2. Deterministic title and short description
|
## 2. Deterministic title and short description
|
||||||
|
|
||||||
Both patterns are assembled by the server and use only synced taxonomy terms and capture facts
|
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`).
|
||||||
(`METADATA-80`). Placeholders use `{field}`; every number comes from the deterministic pipeline,
|
|
||||||
never the model (`METADATA-90`).
|
|
||||||
|
|
||||||
The shape follows the convention a working mill store uses: descriptor-led, dimension-light titles,
|
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.
|
||||||
with the measurements carried separately. See "Provenance" below.
|
|
||||||
|
|
||||||
### 2.1 Title
|
### 2.1 Title
|
||||||
|
|
||||||
Slot order:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
[Figure] {species} [Live Edge] {noun} [(dims)]
|
[Figure] {species} [Live Edge] {noun} [(dims)]
|
||||||
```
|
```
|
||||||
|
|
||||||
1. `Figure` leads as a Title-Case adjective and is omitted when the Figure term is `plain`.
|
1. `Figure` leads as a Title-Case adjective.
|
||||||
2. Grade is not used in the title.
|
2. Grade is not a title slot.
|
||||||
3. `Live Edge` appears only when the Edge Type term is Live Edge.
|
3. `Live Edge` appears for leaves where the edge type is part of the product form.
|
||||||
4. There is no separator between slots.
|
4. Slots run together with no separator.
|
||||||
5. Dimensions ride in the title only for the turning leaves, as a trailing `(L x W x T)`.
|
5. Turning leaves carry `(L x W x T)` at the end; slab, lumber, and cap leaves carry no dimensions.
|
||||||
|
|
||||||
Per-leaf patterns:
|
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 |
|
| Leaf | Pattern | Example |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -74,16 +56,18 @@ Per-leaf patterns:
|
|||||||
|
|
||||||
`Specialty cuts` has no M3 pattern.
|
`Specialty cuts` has no M3 pattern.
|
||||||
|
|
||||||
`length_ft = floor(length_in / 12)`, `length_in_remainder = length_in mod 12` (1 dp).
|
An unset Figure drops its slot; the title starts at `{species}`.
|
||||||
|
|
||||||
### 2.2 Short description
|
### 2.2 Short description
|
||||||
|
|
||||||
One spec line, so the measurements appear even when the title omits them:
|
One spec line, carrying the measurements the title omits:
|
||||||
|
|
||||||
```
|
```
|
||||||
[Figure] {species} {noun}, {length} x {width} x {thickness}, {bdft} bdft
|
[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 |
|
| Leaf | Example |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Live edge wood | `Figured Black Walnut Live Edge Slab, 9ft 6in x 24.3in x 1.75in, 18.4 bdft` |
|
| Live edge wood | `Figured Black Walnut Live Edge Slab, 9ft 6in x 24.3in x 1.75in, 18.4 bdft` |
|
||||||
@@ -92,36 +76,54 @@ One spec line, so the measurements appear even when the title omits them:
|
|||||||
|
|
||||||
### 2.3 Description
|
### 2.3 Description
|
||||||
|
|
||||||
The long description is the model's prose when Call 2 runs (`METADATA-55`); with inference off the
|
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).
|
||||||
server produces it (`METADATA-70`). The per-leaf prose templates that guide Call 2 are authored
|
|
||||||
with that slice and are not defined here.
|
|
||||||
|
|
||||||
### 2.4 Provenance
|
### 2.4 Provenance
|
||||||
|
|
||||||
The title and short-description form was modeled on the live product titles of Cook Woods
|
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.
|
||||||
(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, which are not used in
|
|
||||||
our titles.
|
|
||||||
|
|
||||||
## 3. Payload intent
|
## 3. Payload intent
|
||||||
|
|
||||||
The exact wire shape is `docs/contracts/WOO-API.md`. Intent:
|
The exact wire shape is `docs/contracts/WOO-API.md` §3–§5. Intent:
|
||||||
|
|
||||||
- Only non-null fields are sent (`PUBLISH-55`).
|
1. Only non-null fields are sent (`PUBLISH-55`).
|
||||||
- The payload carries an explicit `slug`: the sanitized product name plus the lowercased SKU.
|
2. The payload carries an explicit `slug`: the sanitized product name plus the lowercased SKU (`PUBLISH-55`).
|
||||||
Dimensions never appear in the slug (`PUBLISH-55`).
|
3. `status` comes from `woo_create_status` (default draft); a `SLAB-UAT-*` SKU creates a draft (`PUBLISH-10`, `SETTINGS-65`).
|
||||||
- `status` comes from `woo_create_status` (default draft); `SLAB-UAT-*` always draft
|
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`).
|
||||||
(`SETTINGS-65`, `PUBLISH-10`).
|
5. Images are the processed transparent PNGs in photos-ready order, with no cap (`PUBLISH-40`, `PUBLISH-45`).
|
||||||
- Categories are the species leaf plus each wood-category leaf; attributes are the five locked
|
6. `sold_individually` is true; each product is one slab (`PUBLISH-60`).
|
||||||
attributes by synced term; tags are fig-* and feat-* (`METADATA-10`, `METADATA-15`,
|
7. Create checks the SKU first and stops on a duplicate; a stale value is a field-level error (`PUBLISH-15`, `PUBLISH-20`).
|
||||||
`METADATA-30`). Missing attributes or terms are skipped, never created (`METADATA-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`).
|
||||||
- Images are the processed transparent PNGs in photos-ready order, with no cap (`PUBLISH-40`,
|
|
||||||
`PUBLISH-45`).
|
### 3.1 Example submission
|
||||||
- `sold_individually` is true; each product is one slab (`PUBLISH-60`).
|
|
||||||
- Create checks the SKU first and blocks on a duplicate (`PUBLISH-15`); a stale value is a
|
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.
|
||||||
field-level error (`PUBLISH-20`). Success purges photos and deletes the local row
|
|
||||||
(`PUBLISH-25`); failure retains photos and logs (`PUBLISH-30`), including the orphaned-media
|
```json
|
||||||
cleanup note (`PUBLISH-31`). Published means the create succeeded, not that it is live
|
{
|
||||||
(`PUBLISH-50`).
|
"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.
|
||||||
|
|||||||
Reference in New Issue
Block a user