Atlas Commerce Operations reporting & correction
You are given an analytical (or correction) request against the Atlas Commerce
Operations service and must emit one JSON object that conforms exactly to
a provided answer_template.json. These tasks share one structure; follow the
procedure below rather than improvising per task.
1. Read the three authoritative inputs (in this order)
environment_access.md — the base URL, Authorization: Bearer <token>,
and the list of available endpoints. Always read it fresh; never hardcode the
URL or token — they are supplied per task.
- The request payload
input/payloads/<something>_request.json — this is
the authoritative business spec: cohort/scope, business definitions,
rollups, rounding, money/FX policy, ranking order, and the status/risk
thresholds. When the prose prompt and the payload seem to differ, the payload
governs; the prompt.txt is only framing.
input/payloads/answer_template.json — the exact output contract
(a JSON Schema). It fixes the key names, types, enum spellings, ID regex
patterns, array minItems/maxItems, ordering notes, and rounding
(multipleOf / decimal_places / precision). additionalProperties:false
means emit exactly the required keys and nothing else.
Map every business concept named in the request to a concrete answer field
before writing any SQL.
2. Discover the data model — do not guess columns
GET /api/schema and GET /api/data-dictionary to learn the real table and
column names and, critically, field semantics (which column is the
canonical/effective value, which flags production vs test, how status /
currency / timestamps are represented).
- The SQL gate rejects introspection (
sqlite_master, information_schema,
version() and similar are refused as "query rejected"). Get structure only
from the schema/data-dictionary endpoints, then query the real business tables.
- If a GET returns a transient
{"error":"service error"}, retry a few times.
3. Query via POST /api/sql (read-only)
- Body
{"sql": "<one SELECT>"}; response is
{"columns":[...],"rows":[[...]],"row_count":N,"truncated":bool}.
- Dialect is SQLite (3.46). Use single-quoted string literals.
- Always check
truncated. If true, aggregate/paginate so no rows are
silently dropped — every count, list, and rate must be over the full cohort.
- A
{"error":"query rejected"} means the query violated the read-only /
allowlist gate (introspection, non-allowed function, or a write on /api/sql).
Rewrite as a plain SELECT over business tables.
- Prefer computing metrics in SQL, then verify each headline number with an
independent query (e.g. eligible == complete + incomplete).
4. Apply the cohort and cutoff exactly
Every task narrows to a precise population before any metric. Apply all stated
filters, in combination:
- Production population only (exclude test/non-production) when stated.
- Time window (created/opened/service window): treat timestamps as exact
UTC boundaries and honor the stated inclusivity (
inclusive → >=/<=).
- As-of cutoff: evaluate every state (open/delivered/resolved/complete) as
of the cutoff, not "now". A thing done after the cutoff counts as not-yet-done.
- Membership predicates (segment, region, tier, campaign, "has an effective
scan in the named batch at/before cutoff", etc.) exactly as written.
- Use the effective/canonical value where raw and canonical layers exist; the
data dictionary says which column that is.
5. Compute metrics per the written definitions
See references/metric-and-output-rules.md for the full checklist. Core rules:
- Rates: numerator/denominator exactly as defined; keep failing/incomplete
items in the denominator when the spec says so. Compute unrounded for
comparisons and ordering; round only the final reported value to the stated
decimals.
- Aggregate ratios (e.g. units-per-hour): sum numerator and denominator
across the group then divide — never average per-row ratios.
- Median: sort the values; for an even count average the two central values.
- Money / FX: convert each row with the daily rate for that row's own
service_date and currency, compare/aggregate in the reporting currency (USD),
and round the displayed total to the stated decimals.
- Exact ID lists: return the business IDs matching the predicate, unique,
matching the template's regex, sorted as specified (usually id ascending).
6. Ranking (top-N / worst-N)
Order on the unrounded metric, applying the full multi-key sort in the stated
order and ending with the id tie-break (almost always id ascending). Return
exactly the required count (minItems == maxItems). Round each reported metric
only after selection.
7. Tiered status / risk classification
Evaluate the tiers in their listed order and assign the first tier whose
condition holds — the tiers run best→worst (e.g. HEALTHY→WATCH→CRITICAL,
STABLE→PRESSURED→AT_RISK, LOW→MODERATE→HIGH, CONTROLLED→ELEVATED→SEVERE), and the
final tier is the catch-all "otherwise". Test conditions against unrounded
rates, and respect strict vs inclusive wording ("at least"/>= vs "below"/<).
8. Correction tasks (only when the request explicitly approves one)
Some requests approve a single minimal canonical correction (identified as one
raw-vs-canonical contradiction) and ask for pre- and post-correction metrics.
- Identify the one affected row/field; change the canonical field only via
POST /api/sql/transaction. Never modify raw source values, source-identity
fields, or unrelated rows.
- Write the audit record using the request-supplied
reason_code, actor,
audit_id, correction_key, and corrected_at; read it back via
GET /api/correction-audit.
- Success rule: exactly one business row and one audit row committed, and
a post-change
SELECT confirms the new canonical value → correction_status: "APPLIED". Any other outcome → "NOT_APPLIED" reporting the values actually
observed.
- Compute the backlog/metrics both before and after per the template.
- If the request does not approve a correction, stay strictly read-only.
9. Write answer.json
- Exactly one JSON object, the
required keys only, nesting/types per the
template. Integers as integers; rates/amounts as numbers at the exact decimals;
enum strings spelled exactly; arrays at the required size and order.
- No commentary, markdown, or extra fields in the file.
- Before finishing, re-validate the object against
answer_template.json and
re-derive each headline number with a second query. See the checklist in
references/metric-and-output-rules.md.
1---2name: atlas-ops-reporting-33description: Produce exact JSON answers for Atlas Commerce Operations reporting and data-correction requests. Use when a task provides an environment_access.md for an Atlas / "workplace" service (GET /api/schema, /api/data-dictionary, /api/correction-audit, POST /api/sql, POST /api/sql/transaction) plus a request payload JSON and an answer_template.json, and asks you to compute a scorecard, reconciliation, quality/health/productivity review, backlog, or an approved canonical correction and write it to answer.json. Covers cohort/ eligibility scoping, cutoff-based state, rate/median/FX metrics, top-N/worst-N ranking, exact ID lists, tiered status classification, and audited mutations.4---56# Atlas Commerce Operations reporting & correction78You are given an analytical (or correction) request against the **Atlas Commerce9Operations** service and must emit **one JSON object** that conforms *exactly* to10a provided `answer_template.json`. These tasks share one structure; follow the11procedure below rather than improvising per task.1213## 1. Read the three authoritative inputs (in this order)14151. **`environment_access.md`** — the base URL, `Authorization: Bearer <token>`,16 and the list of available endpoints. Always read it fresh; never hardcode the17 URL or token — they are supplied per task.182. **The request payload** `input/payloads/<something>_request.json` — this is19 the **authoritative business spec**: cohort/scope, business definitions,20 rollups, rounding, money/FX policy, ranking order, and the status/risk21 thresholds. When the prose prompt and the payload seem to differ, the payload22 governs; the `prompt.txt` is only framing.233. **`input/payloads/answer_template.json`** — the **exact output contract**24 (a JSON Schema). It fixes the key names, types, enum spellings, ID regex25 patterns, array `minItems`/`maxItems`, ordering notes, and rounding26 (`multipleOf` / `decimal_places` / `precision`). `additionalProperties:false`27 means emit exactly the `required` keys and nothing else.2829Map every business concept named in the request to a concrete answer field30before writing any SQL.3132## 2. Discover the data model — do not guess columns3334- `GET /api/schema` and `GET /api/data-dictionary` to learn the real table and35 column names and, critically, **field semantics** (which column is the36 canonical/effective value, which flags production vs test, how status /37 currency / timestamps are represented).38- The SQL gate **rejects introspection** (`sqlite_master`, `information_schema`,39 `version()` and similar are refused as "query rejected"). Get structure only40 from the schema/data-dictionary endpoints, then query the real business tables.41- If a GET returns a transient `{"error":"service error"}`, retry a few times.4243## 3. Query via POST /api/sql (read-only)4445- Body `{"sql": "<one SELECT>"}`; response is46 `{"columns":[...],"rows":[[...]],"row_count":N,"truncated":bool}`.47- Dialect is **SQLite** (3.46). Use single-quoted string literals.48- **Always check `truncated`.** If true, aggregate/paginate so no rows are49 silently dropped — every count, list, and rate must be over the full cohort.50- A `{"error":"query rejected"}` means the query violated the read-only /51 allowlist gate (introspection, non-allowed function, or a write on /api/sql).52 Rewrite as a plain `SELECT` over business tables.53- Prefer computing metrics in SQL, then **verify each headline number with an54 independent query** (e.g. eligible == complete + incomplete).5556## 4. Apply the cohort and cutoff exactly5758Every task narrows to a precise population before any metric. Apply all stated59filters, in combination:6061- **Production population** only (exclude test/non-production) when stated.62- **Time window** (created/opened/service window): treat timestamps as **exact63 UTC boundaries** and honor the stated inclusivity (`inclusive` → `>=`/`<=`).64- **As-of cutoff**: evaluate every state (open/delivered/resolved/complete) **as65 of the cutoff**, not "now". A thing done after the cutoff counts as not-yet-done.66- **Membership predicates** (segment, region, tier, campaign, "has an effective67 scan in the named batch at/before cutoff", etc.) exactly as written.68- Use the **effective/canonical** value where raw and canonical layers exist; the69 data dictionary says which column that is.7071## 5. Compute metrics per the written definitions7273See `references/metric-and-output-rules.md` for the full checklist. Core rules:7475- **Rates**: numerator/denominator exactly as defined; keep failing/incomplete76 items in the denominator when the spec says so. Compute **unrounded** for77 comparisons and ordering; round **only the final reported value** to the stated78 decimals.79- **Aggregate ratios** (e.g. units-per-hour): sum numerator and denominator80 across the group *then* divide — never average per-row ratios.81- **Median**: sort the values; for an even count average the two central values.82- **Money / FX**: convert each row with the **daily rate for that row's own83 service_date and currency**, compare/aggregate in the reporting currency (USD),84 and round the displayed total to the stated decimals.85- **Exact ID lists**: return the business IDs matching the predicate, unique,86 matching the template's regex, sorted as specified (usually id ascending).8788## 6. Ranking (top-N / worst-N)8990Order on the **unrounded** metric, applying the full multi-key sort in the stated91order and ending with the id tie-break (almost always id ascending). Return92exactly the required count (`minItems == maxItems`). Round each reported metric93only after selection.9495## 7. Tiered status / risk classification9697Evaluate the tiers in their listed order and assign the **first** tier whose98condition holds — the tiers run best→worst (e.g. HEALTHY→WATCH→CRITICAL,99STABLE→PRESSURED→AT_RISK, LOW→MODERATE→HIGH, CONTROLLED→ELEVATED→SEVERE), and the100final tier is the catch-all "otherwise". Test conditions against **unrounded**101rates, and respect strict vs inclusive wording ("at least"/`>=` vs "below"/`<`).102103## 8. Correction tasks (only when the request explicitly approves one)104105Some requests approve a single minimal canonical correction (identified as one106raw-vs-canonical contradiction) and ask for pre- and post-correction metrics.107108- Identify the one affected row/field; **change the canonical field only** via109 `POST /api/sql/transaction`. Never modify raw source values, source-identity110 fields, or unrelated rows.111- Write the audit record using the request-supplied `reason_code`, `actor`,112 `audit_id`, `correction_key`, and `corrected_at`; read it back via113 `GET /api/correction-audit`.114- **Success rule**: exactly one business row **and** one audit row committed, and115 a post-change `SELECT` confirms the new canonical value → `correction_status:116 "APPLIED"`. Any other outcome → `"NOT_APPLIED"` reporting the values actually117 observed.118- Compute the backlog/metrics both before and after per the template.119- If the request does not approve a correction, stay strictly read-only.120121## 9. Write answer.json122123- Exactly one JSON object, the `required` keys only, nesting/types per the124 template. Integers as integers; rates/amounts as numbers at the exact decimals;125 enum strings spelled exactly; arrays at the required size and order.126- **No commentary, markdown, or extra fields** in the file.127- Before finishing, re-validate the object against `answer_template.json` and128 re-derive each headline number with a second query. See the checklist in129 `references/metric-and-output-rules.md`.