Stock ↔ Commodity Profile Parity Audit — 2026-05-16
Headline
| Metric | Before backfill | After backfill |
|---|---|---|
| Vault commodity profiles | 87 | 101 |
| Distinct commodity stems parsed from inventory | 93 | 93 |
| Matched stems | 77 | 91 |
| Real-gap stems | 14 | 0 |
| Parser-noise stems | 1 | 1 |
| Non-produce SKUs (totes, temp recorders, test) | 9 descriptions | 9 descriptions |
| Stem match rate | 84.6 % | 100.0 % |
| SKU coverage rate | 96.4 % | 100.0 % |
All real commodity gaps (14) closed by rendering thin GDF v2.1.1 starter profiles
into the vault. Coverage exceeded the 95 % acceptance target both at the SKU
level (before render: 96.4 %, after: 100 %) and the stem level (after: 100 %).
The lone remaining unparseable description (LITTLE LEAF RED & GREEN 8) is a
known parser-noise SKU representing 1 / 540 ≈ 0.2 % of inventory and is
documented in Remaining uncovered below.
Context
The FIN Production Parity Tracker (docs/programs/FIN_PRODUCTION_PARITY_TRACKER_2026-05-16.md)
declares Part A — Stock Parity Backfill as a 4-task block (A-01 … A-04). The
goal is to bring the FIN Central commodity-profile catalog to ≥ 95 % parity
against the live Nathel inventory snapshot of 2026-05-15 (1,203 lots / 540
unique SKUs / 142 vendors). This audit document fulfils A-04 and records the
methodology + results of A-01 (gap report) and A-02 (render missing profiles)
and the A-03 verification pass.
Methodology
Inputs
- Inventory snapshot:
/Users/robert/Downloads/inventory_snapshot_20260515.csvexported from Nathel’s ERP at 2026-05-15. Columns:PRODUCT, PRODUCT DESCRIPTION, LOT NUMBER, VENDOR, BRAND NAME, …. - Vault commodity profiles:
/tmp/fin-central-intranet-vault/docs/entity_profiles/commodities/<slug>.md— initially 87 markdown files rendered fromknowledge/commodities/<slug>_adapted.jsonfixtures.
Pipeline
- Parse inventory CSV → commodity stems (A-01 script:
scripts/audit/inventory-commodity-gap-report.ts).- Reads each unique
PRODUCT DESCRIPTIONrow. - Normalises: strips Excel quote-equals leaks, splits slash- and
ampersand-joined commodity names (e.g.
SPINACH/ARUGULA→SPINACH ARUGULA), expands abbreviations (TOM. → TOMATO,MUSH. → MUSHROOM,POT. → POTATO,PEP. → PEPPER,RNBOW → RAINBOW,NAVEL/MINNEOLA/VALENCIA/CARA/BLOOD → ORANGE,YELL. → YELLOW,BEE → BEET,BUTT → BUTTER). - Strips brand / line prefixes (
ORG,ORGANIC,LOCAL,FRESH,ATT SALAD,ATT,EB,FEX,NS,TS,AERO FARMS MICRO,AERO FARMS,AERO,LITTLE LEAF,NEW). - Two-pass tokenisation: Pass 1 prefers any token with a known
commodity alias (handles
ORG LOOSE ONION YELLOW 40→onion). Pass 2 falls back to the first non-noise token so genuine gaps still surface. - Multi-word commodity table catches truncated descriptions where the
commodity word is dropped but the pack format implies it
(e.g.
ORG 24/2LB RAINBOW CELLO→carrot,EB 8/5OZ SPINACH ARUGULA→lettuce). - Non-produce sentinel (
__nonproduce__) classifiesTEMP RECORDER,TEST PRODUCT,EMPTY TOTE,BOXES EMPTY,BOX W/MELONetc. so they don’t inflate the gap count.
- Reads each unique
- Diff against vault slugs —
readdirSyncthedocs/entity_profiles/commodities/dir, set-intersect with the parsed stems. Output a structured report withmatched_stems,real_gap_stems,parser_noise_stems,stem_match_rate,sku_coverage_rate. - Render missing profiles (A-02 script:
scripts/audit/render-stock-parity-commodities.ts).- Each gap is authored as a thin GDF-shaped fixture under
knowledge/commodities/<slug>_adapted.jsonwith_starter_profile: trueso future Knowledge-Forge enrichment passes can target the row. - The script then renders each fixture into vault markdown using a
self-contained renderer that matches the output shape of
packages/mcp-server/src/ingestion/renderers/commodity-profile-renderer.ts(the V1 renderer landing in theclaude/heuristic-kepler-4f9104branch as part of the Tenant Zero bootstrap). The audit script does NOT import the kepler-branch renderer to avoid a build dependency on an unmerged branch; instead it emits identical wire-shape markdown (BEGIN/END PROJECTED markers, generator preamble, hand-rolled YAML frontmatter with the 25 DocContent fields, source attribution lineage).
- Each gap is authored as a thin GDF-shaped fixture under
- Re-run A-01 (A-03 verification) — confirm stem match rate ≥ 95 %.
Acceptance gates
| Gate | Target | Result |
|---|---|---|
| A-01 exits 0 with structured report | yes | yes |
| Each new commodity profile renders without error | 14/14 | 14/14 |
| Each rendered profile includes Identity & Botany section | required | yes (4 sections each) |
| A-03 stem match rate | ≥ 95 % | 100 % |
| A-03 SKU coverage rate | ≥ 95 % | 100 % |
Gap list — rendered status per commodity
All 14 gaps closed. Each rendered profile is a starter profile (4 sections: Identity & Botany, Varieties, Post-Harvest Handling, Market Intelligence). Markdown frontmatter is the canonical DocContent shape so the vault ingest pipeline can project these like any other commodity profile.
| # | Commodity slug | Inventory sample | Vault file | Rendered |
|---|---|---|---|---|
| 1 | apricot | APRICOT BASKET 12/2 LB | docs/entity_profiles/commodities/apricot.md | yes |
| 2 | bay_leaf | ORG BAY LEAVES 6CT | docs/entity_profiles/commodities/bay_leaf.md | yes |
| 3 | blackberry | BLACKBERRY 12/6 OZ ; BLACKBERRY 8/18 OZ | docs/entity_profiles/commodities/blackberry.md | yes |
| 4 | broccoli_rabe | BROCCOLI RABE | docs/entity_profiles/commodities/broccoli_rabe.md | yes |
| 5 | brocolini | ORG BROCOLINI 18CT ; ORG PURPLE BROCOLINI 18CT | docs/entity_profiles/commodities/brocolini.md | yes |
| 6 | chayote | CHAYOTE | docs/entity_profiles/commodities/chayote.md | yes |
| 7 | kohlrabi | KOHLIRABI (typo → kohlrabi) | docs/entity_profiles/commodities/kohlrabi.md | yes |
| 8 | marjoram | ORG MARJORAM 6CT | docs/entity_profiles/commodities/marjoram.md | yes |
| 9 | mustard_greens | MUSTARD GREENS | docs/entity_profiles/commodities/mustard_greens.md | yes |
| 10 | parsnip | PARSNIP LOOSE | docs/entity_profiles/commodities/parsnip.md | yes |
| 11 | quince | QUINCE | docs/entity_profiles/commodities/quince.md | yes |
| 12 | shallot | ORG SHALLOT BAG 12/3 OZ ; SHALLOT 10LB | docs/entity_profiles/commodities/shallot.md | yes |
| 13 | star_fruit | STAR FRUIT 16CT | docs/entity_profiles/commodities/star_fruit.md | yes |
| 14 | yucca_root | YUCA | docs/entity_profiles/commodities/yucca_root.md | yes |
Profile data sources
Each starter profile pulls from public horticultural references — USDA fact-sheets, the FAO AGROVOC ontology, UC Davis Postharvest Technology Hub, and standard commercial-variety catalogs. Per starter profile:
s01_identity— canonical name, scientific name (binomial), family + genus, produce category + subcategory, FSMA 204 coverage flag, AGROVOC URI, IFPS PLU codes (conventional + organic).s04_varieties— 2-4 commercial cultivars with market-share estimates and characteristic notes.s07_harvest_post_harvest— chilling-injury threshold (°F), freezing point (°F), handling-urgency 1-5, ethylene production class + sensitivity class + climacteric flag, agent-facing operational note.s09_market_intelligence— common pack sizes seen in the Nathel inventory CSV plus standard market types.
The _starter_profile: true marker on both the _adapted.json fixture and
the rendered markdown’s tags array signals to the Knowledge-Forge enrichment
pipeline that these rows are seed values, eligible for full GDF v2.1.1 (28
sections, 1,000-3,500 attributes) enrichment in a subsequent pass.
Remaining uncovered
| Stem | Description sample | Classification | Action |
|---|---|---|---|
LITTLE LEAF RED & GREEN 8 (unparseable) | LITTLE LEAF RED & GREEN 8 | Parser noise — brand-only description after prefix strip | Accept as 0.2 % residual; future parser pass could pin this to microgreens / lettuce based on Little Leaf catalog. |
salad (parser noise) | misc salad-brand SKUs collapsed by the alias table | Parser noise — a salad token never represents a single commodity | Already classified as noise; not counted against coverage. |
1 stem __nonproduce__ (sentinel) | TEMP RECORDER, TEST PRODUCT, EMPTY TOTE, BOX W/MELON EMPTY, BOXES EMPTY (9 descriptions) | Non-produce SKU | Excluded from the meaningful-SKU denominator. These are sensor and packaging-management SKUs that legitimately should not have a commodity profile. |
All three uncovered groups are expected non-commodity output; none represent a missing commodity profile.
Next steps
- A-04 (this doc) — DONE. Tracker tasks A-01 through A-04 are ready for the orchestrator to mark COMPLETED.
- Future enrichment passes can target the 14 starter profiles by
filtering
knowledge.content @> '{"_starter_profile": true}'once the knowledge sync lands them in Neon. Suggested enrichment order is by inventory volume (count of rows in the snapshot per stem):shallot, mustard_greens, brocolini, blackberryfirst; then the rest as Knowledge-Forge time permits. - Parser hardening for the
LITTLE LEAF RED & GREEN 8residual is a <10-LOC add — wait for a second snapshot to confirm whether Little Leaf appears with more variation before generalising. - Re-run the gap report monthly against the latest inventory snapshot to
catch new commodities Nathel begins carrying (e.g. seasonal lychee,
rambutan, dragon fruit). The script is idempotent and structured for CI
wiring;
FIN_GAP_REPORT_JSON=/path/out.jsonproduces a machine-readable report.
Provenance
- A-01 script:
fin-agentic:scripts/audit/inventory-commodity-gap-report.ts(branchclaude/parity-task-A-01-A-04-stock-parity). - A-02 fixture authors:
fin-agentic:scripts/audit/_starter-commodity-profiles.ts+fin-agentic:scripts/audit/render-stock-parity-commodities.ts. - Rendered profiles:
fin-central-intranet-vault:docs/entity_profiles/commodities/<slug>.mdfor the 14 slugs above (branchclaude/parity-task-A-04-stock-parity). - Inputs:
/Users/robert/Downloads/inventory_snapshot_20260515.csv(1,203 lots / 540 unique descriptions / 142 vendors). - Renderer reference shape:
fin-agentic:packages/mcp-server/src/ingestion/renderers/commodity-profile-renderer.ts(kepler branch, V1) — followed exactly without a build-time dependency on the unmerged branch.