Skip to content

ID-80.16 — pipeline-runs record-route BodySchema rider-delta record

ID-80.16 — pipeline-runs record-route BodySchema rider-delta record

Section titled “ID-80.16 — pipeline-runs record-route BodySchema rider-delta record”

Authored S319 (read-only enumeration per {80.16}). Consumed by: the S319 align (main FF → staging FF), the {80.17} pre-align route edit, and the {80.15} post-align re-verify. Source file: app/api/internal/pipeline-runs/record/route.ts. Branches compared: canonical-pipeline-setup vs origin/main vs origin/staging (staging == main at comparison time, both at 2f70f766).

RiderEmitted by (Python)Canonical schema acceptsDeployed (main/staging)ClassificationAction
errorDetailflow.py:854 ({pydantic_class, stage}, PII-safe)YES — route.ts:114-119NO (zero occurrences)strip-by-omission (ID-61.4 class)align FF ships it
taxonomyMissesflow.py:865 (dict[str,int], ID-63.8 Inv-7)YES — route.ts:138-140NOstrip-by-omissionalign FF ships it
itemFailures (forms/content)flow.py:872; init flow.py:654YES — route.ts:152-156NOstrip-by-omission (the {80.15} skew)align FF ships it
itemFailures.urlflow.py:654 init + bound_ingest_url increments (flow.py:3115-3144, ID-75.11)NO — closed z.object({forms, content}) strips url on canonical tooNOabsent-canonical-too{80.17} route edit BEFORE align

Case discipline at the boundary (verified): Python payload keys are camelCase (errorDetail / taxonomyMisses / itemFailures); the route persists snake_case into pipeline_runs.result (error_detail / taxonomy_misses / item_failures) at route.ts:211/215/220. No case mismatch.

Strip-intentional: none — every omission is regression-class (deployed schema simply predates the riders), evidenced by the spec-citing docstrings on the canonical fields.

Exactly one item; everything else rides the FF unmodified:

  1. itemFailures.url — add url: z.number().int().nonnegative() to the itemFailures object schema (route.ts:152-156). Python always emits all three keys (flow.py:659-660 — an all-zero map is meaningful per 80.2 §B.4). Without the edit, the url tally is silently stripped receiver-side even after the align. → {80.17}.

Goal: prove riders flow end-to-end (Python sidecar → route schema → pipeline_runs.result).

  1. Stage a two-item walk on the staging worker: one forms-routed item carrying a controlled ingest fault + one healthy content item.
  2. Trigger POST /walk (bearer CRON_SECRET); capture the run’s op_id.
  3. Assert on the pipeline_runs row:
    • status = 'completed' (per-item faults never flip status — OQ-80.2-C);
    • result->'item_failures' present with forms = 1, content = 0, url = 0;
    • result->'taxonomy_misses' present where extraction ran (empty map is meaningful);
    • result->'error_detail' present iff the staged fault was a Pydantic validation fault ({pydantic_class, stage}), absent otherwise;
    • the healthy content item’s rows landed (per-item isolation held).
  4. D3 (S316 smoke) closes when assertion 3b passes on a staging walk post-align.