---
name: create-tms-manifold
description: Use when the user asks to build, generate, scaffold, or author a TMS entity_profile manifold for an item, supplier, commodity group, or supplier category. Walks a PO-line silver table through the full L0 summary, L1 geometry, L2 telemetry preview, token_budget, and lineage envelope. TMS v1.2.
---

# create-tms-manifold

Build a Tabular Manifold Spec (TMS) v1.2 entity_profile manifold for one
of: `ca_item`, `supplier`, `commodity_group`, `supplier_category`. Output
is a single JSON document that an agent can consume progressively (L0
first, L1 on demand, L2 for forensics).

- Full TMS spec: https://canonicalresearch.dev/spec/tms
- Companion QPS spec (provenance): https://canonicalresearch.dev/spec/qps
- Live worked manifolds: https://canonicalresearch.dev/spec/tms#reference-examples

## When to use this skill

Use this skill when the user wants to ship a manifold for procurement,
spend-intelligence, or supplier-risk workflows and the source is a
transactional PO-line table (silver-layer, one row per PO line) plus
optional supplier-consolidation and item-categorization joins.

## What you produce

A single JSON object with these top-level keys, in this order:

```json
{
  "artifact_type": "tabular_manifold",
  "artifact_version": "1.2",
  "manifold_kind": "entity_profile",
  "subject": { },
  "time_window": { },
  "level_0_summary": { },
  "level_1_geometry": { },
  "level_2_telemetry": { },
  "token_budget": { },
  "lineage": { }
}
```

Use `references/envelope.json` as the empty starting skeleton.

L0 must include `reliability` and `quality_flags`. L1 is optional but
recommended for time-windowed entities. L2 must declare a `strategy` and
a `retrieval` block even when the preview is empty.

## Examples

### Example 1: Supplier manifold

User prompt:

> Build a TMS entity_profile manifold for supplier CAP-7a3f9e2b4d8c1062
> over the last 24 months.

Abbreviated output shape (full file: `examples/supplier-minimal.json`):

```json
{
  "artifact_type": "tabular_manifold",
  "artifact_version": "1.2",
  "manifold_kind": "entity_profile",
  "subject": {
    "entity_type": "supplier",
    "parent_supplier_id": "CAP-7a3f9e2b4d8c1062",
    "final_supplier_name": "Helvian Specialty Polymers GmbH"
  },
  "time_window": {"start": "2024-05-01", "end": "2026-04-30", "granularity": "month"},
  "level_0_summary": {
    "observation_count": 180,
    "distribution": {"cv": 1.06},
    "reliability": {"sample_size_class": "robust", "sample_size_n": 180},
    "quality_flags": {"suspected_outliers": true, "level_1_item_truncated": true},
    "item_concentration": {"item_count": 18, "hhi": 0.42, "top_item_pct": 0.61, "top_3": ["..."]},
    "price_stability": {"weighted_avg_item_cv": 0.04, "discipline_rating": "Excellent"},
    "interpretation_hints": ["...3 actionable sentences..."]
  },
  "level_1_geometry": {"monthly_timeseries": "...", "item_rollup": "...", "commodity_rollup": "..."},
  "level_2_telemetry": {"row_count_total": 180, "strategy": "preview_outliers", "...": "..."},
  "token_budget": {"...": "..."},
  "lineage": {"manifold_id": "mfld_supplier_CAP-7a3f9e2b4d8c1062_20260501", "...": "..."}
}
```

### Example 2: Supplier-category manifold

User prompt:

> Generate a TMS entity_profile manifold for the "Specialty Chemicals &
> Additives" supplier category for the same window.

Distinct features for this kind (vs. supplier), full file at
`examples/supplier-category-minimal.json`:

- `subject.entity_type` = `"supplier_category"`, plus `sub_commodity_label`
- L0 requires `direct_indirect_mix` (direct_spend, indirect_spend,
  unknown_spend, plus `classification` band)
- L0 carries `industry_breakdown` and `item_diversity` instead of
  `item_concentration` / `commodity_concentration`
- L1 adds `industry_rollup` alongside supplier_rollup and item_rollup
- HHI bands read differently at the category grain (~57 suppliers,
  HHI 0.20 is healthy)

## Inputs you need from the user

Ask up front, in one round-trip if possible:

1. **Entity type and ID.** One of `ca_item` (ca_item_number), `supplier`
   (parent_supplier_id), `commodity_group` (commodity_group_label),
   `supplier_category` (sub_commodity_label).
2. **Source table** and dialect (Databricks SQL / Snowflake / DuckDB /
   Postgres). At minimum, a PO-line silver table; ideally also the
   supplier-mapping and item-categorization views.
3. **Time window.** Default to the last 24 months ending on the most
   recent observation.
4. **Granularity** for L1. Default to `month` for windows >= 6 months,
   `day` for shorter windows.

If anything is missing and you can infer a sensible default, state the
default and proceed. Do not stall on optional parameters.

## Process

### 1. Confirm scope and pull headline numbers

Run a single aggregate query to confirm the entity exists in the window
and to size the work:

```sql
SELECT
  COUNT(*)                                AS po_line_count,
  COUNT(DISTINCT po_num)                  AS po_count,
  MIN(purchase_order_date)                AS first_purchase,
  MAX(purchase_order_date)                AS last_purchase,
  SUM(spend)                              AS total_spend_usd
FROM <table>
WHERE <entity_predicate>
  AND purchase_order_date BETWEEN :start AND :end;
```

If `po_line_count < 30`, mark `sample_size_class: "sparse"` and warn the
user that L0 stats will be unreliable. Do not refuse; emit the manifold
anyway with the flag set.

### 2. Build `level_0_summary`

Required sub-blocks:

- **`observation_count`** = po_line_count from step 1.
- **`time_coverage`** = first/last purchase + window_days.
- **`distribution`** = min, max, mean, median, stddev, cv on `unit_price`.
- **`reliability`** = sample_size_class, confidence_in_mean (95%),
  data_quality_score (1 minus the share of rows with imputed or null
  unit_price), staleness block.
- **`quality_flags`** = booleans. Trigger rules:
  - `low_sample_size`: sample_size_class == "sparse"
  - `data_staleness`: staleness.is_stale == true
  - `high_variance`: distribution.cv > 0.3 (item only; skip for
    supplier and supplier_category where global CV is mechanically large)
  - `suspected_outliers`: any row with |z_score| > 3
  - `low_supplier_diversity`: (ca_item only) supplier_count == 1
  - `high_supplier_concentration`: HHI > 0.25
  - `high_item_concentration`: top_item_pct > 0.5
  - `level_1_*_truncated`: set when the Pareto truncation in step 3
    dropped rows
- **`financial_summary`** = total_spend_usd, total_qty_received, po_count,
  po_line_count, avg_spend_per_po_line, pct_of_total_spend,
  population_rank, population_size.
- **Concentration blocks** per entity type:
  - `ca_item` -> `supplier_concentration` (HHI, top_supplier_pct, top_3)
  - `supplier` -> `item_concentration` + `commodity_concentration`
  - `commodity_group` -> `supplier_concentration` + `item_diversity` +
    `sub_category_breakdown`
  - `supplier_category` -> `supplier_concentration` + `item_diversity` +
    `industry_breakdown` + `direct_indirect_mix`
- **`price_stability`** = global cv, weighted_avg_item_cv (spend-weighted
  per-item CV over items with >=2 PO lines), discipline_rating, plus a
  `rating_basis` object documenting thresholds and method. See
  `references/calculations.md` for the bands and weighted-CV formula.
- **`relationship`** = first/last purchase, relationship_days,
  avg_monthly_po_frequency.
- **`interpretation_hints`** = 3-4 sentences naming the dominant signal
  with one quantitative anchor each. Lead with the actionable finding,
  not the metric definition.

### 3. Build `level_1_geometry`

`monthly_timeseries`: one row per month in the window. Columns:
`period`, `n`, `spend`, `qty`, `mean_unit_price`, optional
`stddev_unit_price`. Include `missing_periods: []` if the window is
contiguous; otherwise list the gaps.

Then add one or two rollups per entity type:

- `ca_item` -> `supplier_rollup`
- `supplier` -> `item_rollup` + `commodity_rollup`
- `commodity_group` -> `supplier_rollup` + `item_rollup` +
  `sub_category_rollup`
- `supplier_category` -> `supplier_rollup` + `item_rollup` +
  `industry_rollup`

Apply **Pareto truncation** to each rollup. The algorithm, default
coverage targets, tie-break rule, and tail_summary structure are in
`references/calculations.md`.

### 4. Build `level_2_telemetry`

Set `row_count_total` to the total PO lines in the window. Choose a
`strategy`:

- `preview_outliers` if any |z_score| > 2 rows exist (recommended default)
- `preview_recent` for stable entities with no outliers
- `preview_concentration_evidence` for high-concentration commodities
- `full_inline` only if row_count_total < 50
- `none` if downstream agents will always retrieve

Cap inline_rows at the limit you record in `token_budget`. Each row
should include: rn, po_num, date, site, supplier_name, ca_item_number
(or part_description), qty, qty_uom, unit_price, spend, z_score, flag.
See `references/calculations.md` for the z_score formula and the flag
vocabulary used in the live TechnoFlex examples.

Add a `retrieval` block. For agents, prefer `method: "mcp_tool"` with
tool_name and tool_args. For human auditors, also include
`sql_fallback` with the verbatim query_template and query_params used
to populate the inline preview.

### 5. Write the `token_budget` block

Estimate L0 / L1 / L2 token costs (UTF-8 chars / 4 is a usable
approximation). Always emit `compression_ratio_l1_vs_l2` and
`compression_ratio_l0_vs_l2`. Write a one-sentence
`recommended_strategy` describing what an agent should read first.

### 6. Write the `lineage` block

`manifold_id` format: `mfld_<kind>_<entity_id>_<YYYYMMDD>`.

Include `qps_entry_id` (a parallel ID for the Query Provenance Store
companion spec). List each input dataset with `dataset_id`, `version`
(or as_of_timestamp), `row_count`, and the `as_of_timestamp` used.
List `filters_applied` (each as `{field, operator, value}`) and
`transformations` (one prose line per transformation). Compute a
`checksum` over the sorted, serialized telemetry rows
(`method: "sha256_row_hash"`).

## Validation checklist

Before returning the manifold, verify:

- [ ] `artifact_type == "tabular_manifold"` and `artifact_version` set.
- [ ] `manifold_kind == "entity_profile"`.
- [ ] `level_0_summary.reliability` and `level_0_summary.quality_flags`
      both present.
- [ ] HHI math: sum of `(spend_i / total_spend)^2` across the
      concentration grain, INCLUDING the truncated tail. Sanity: HHI <= 1.0.
- [ ] All top_3 / top_5 rows sorted DESC by spend.
- [ ] `pct_of_spend` in any rollup plus its tail_summary sums to ~1.0
      (allow rounding).
- [ ] Every monthly_timeseries period falls inside `time_window`.
- [ ] `level_2_telemetry.strategy` is one of the documented enum values.
- [ ] `lineage.inputs[]` is non-empty.
- [ ] `quality_flags.level_1_*_truncated` matches whether any rollup
      actually truncated.
- [ ] No null values in required fields. Use empty strings or 0 only
      where the spec allows.

## What not to do

- Do not collapse the global CV and the weighted_avg_item_cv into a
  single number. They measure different things and the user will read
  them differently. Always emit both with `rating_basis.note`.
- Do not emit `quality_flags.high_variance` for supplier and
  supplier_category manifolds based on the global CV. Their product
  mix makes the global metric mechanically large; use the weighted
  per-item metric instead, or omit the flag.
- Do not invent values for fields the source cannot support. Set the
  relevant `quality_flag` and let the agent decide.
- Do not interpolate parameters into the SQL `query_template`. Use
  parameterized templates with `:name` placeholders and provide
  `query_params` separately. The QPS spec rejects interpolated SQL on
  purpose.
- Do not include PII in `level_2_telemetry.inline_rows`. The preview
  is meant for outlier evidence, not full record dumps.

## References

- `references/envelope.json`: empty starting envelope, ready to fill.
- `references/calculations.md`: HHI math (including the truncated-tail
  rule), discipline-rating bands, weighted-CV formula, Pareto truncation
  algorithm with defaults, tail_summary structure, z_score formula, and
  the flag vocabulary.
- `examples/supplier-minimal.json`: worked supplier manifold with
  realistic values.
- `examples/supplier-category-minimal.json`: worked supplier-category
  manifold demonstrating direct_indirect_mix and industry_rollup.
- TMS spec: https://canonicalresearch.dev/spec/tms
- QPS spec: https://canonicalresearch.dev/spec/qps
- Live full manifolds: https://canonicalresearch.dev/spec/tms#reference-examples
