Spec deviation during bid
Spec deviation is the canonical "let the buyer evaluate, don't self-disqualify" workflow. Per Mike's standing rule (memory: feedback_bid_spec_deviation_notes), the right move when our spec doesn't exactly match the bid spec is to submit the price anyway with a vague submission note, let the buyer evaluate, and queue the conversation for post-award.
The workflow exists to make that rule deterministic — when the AI detects a deviation during the bid response build, it doesn't halt; it logs and flags.
Risk level 2 (low). No NS writes, no customer-facing changes. The submission note is the only externally-visible artifact.
Trigger conditions
- A bid response workflow step detects a pack/format mismatch on a line.
- Spec audit comparing bid requirement against our spec_items finds a difference.
- Manual flag from Mike when reviewing the bid response pre-submission.
- A bid amendment changes the spec mid-bid and our line no longer matches exactly.
Severity classification (minor / material) drives the submission note tone. Minor (pack count off by 1) gets a one-liner. Material (different ingredient profile, different format) gets a more careful sentence — still vague, never self-disqualifying.
The 2 beats
-
01
Log deviation on bid_line
UPDATE
bid_lines SET deviation_flagged=1, deviation_notes=? WHERE id=?. The bid response render reads deviation_notes to construct the submission note. -
02
Post-award discussion flag
A
proposed_actionsrow stages withaction_type=bid_post_award_discussion. If we win, this becomes a kickoff talking point.
What's different after the workflow runs
- bid_lines row has deviation_flagged=1 + deviation_notes populated.
- A post-award discussion is queued in proposed_actions.
- The bid response render uses the vague submission note from deviation_notes.
- reflexion_log carries a
spec_deviationtagged row.
What can go wrong and how to recover
Sometimes the AI flags a non-deviation (e.g. trailing whitespace in pack size). The classifier marks it minor, the note is one word, post-award flag is informational only.
If a deviation is truly disqualifying (e.g. wrong allergen profile), the standing rule says still submit — but Mike should override and pull the line. Manual escalation path: POST /admin/bid_lines/?id/remove.
Sometimes an amendment changes the bid spec to match ours. The deviation_flagged remains as historical context but no longer affects submission.
Adjacent workflows + diagrams
Code paths + invariants
| Concern | Where |
|---|---|
| Workflow contract | workflow_definitions WHERE workflow_type='spec_deviation_flagged' |
| Standing rule | feedback_bid_spec_deviation_notes (memory) |
| Deviation field | bid_lines.deviation_flagged + deviation_notes |
| Post-award marker | proposed_actions.action_type='bid_post_award_discussion' |
| Reflexion tag | spec_deviation |
| Risk level | 2 |
| Expected duration | ~5 min |
| Trigger | event · sources=bid_response_workflow_step |
Dated trail · spot stale claims
Dated trail of when this doc was last touched, what changed, and what to look at if it feels stale.
| Date | Round | Change | Touched by |
|---|---|---|---|
2026-05-26 | R586 | Added CHANGELOG · SCHEMA · RUNBOOK · BACKLOG sections — wiki became best-in-class operating documentation. | Mike + Claude |
2026-05-25 | R584/R585 | Wiki originally shipped — 8-section structure (hero / what / when / steps / outcomes / failure-modes / related / for-developers). | Mike + Claude |
workflow_definitions WHERE workflow_type='spec_deviation_flagged' before acting on these claims.The machine-readable spec
Canonical fields, table names, endpoint signatures. What code should match, what tests should assert. workflow_type · spec_deviation_flagged · risk_level · 3.
Inputs (required + optional)
| Field | Type | Description |
|---|---|---|
item_id | integer | Required. |
bid_id | integer? | Optional context. |
deviation_type | string | 'pack' | 'format' | 'ingredient' | 'cert' |
deviation_detail | string | Description. |
D1 tables written
| Table | Operation | Trigger |
|---|---|---|
spec_deviations | INSERT | Deviation record |
proposed_actions | INSERT | Resolution (accept, reprice, reject) |
spec_items | UPDATE (post-HITL) | If deviation accepted, update spec |
events | INSERT (spec.deviated) | downstream alert |
Endpoints called
| Method | Path | Purpose |
|---|---|---|
POST | /api/workflow/execute | Runner entrypoint |
GET | /api/spec-deviations/open | Open deviations dashboard |
Events fired
| event_type | When | Subscribers |
|---|---|---|
spec.deviated | On flag | downstream — could block bid award |
spec.deviation.resolved | On resolve | audit |
It broke at 2am — what now
Different from "how do I use this." This is the page Mike pulls up when something is wrong: logs to check, recovery steps, who to escalate to.
Scenario · Deviation flagged but spec_items wasn't updated
Update is post-HITL only. Stay open until Mike decides.
- Check:
SELECT * FROM spec_deviations WHERE id=<id> - Mike decides: Approve in /proposed-actions.html with intent (accept/reprice/reject).
Scenario · Same deviation flagged repeatedly
No dedupe per (item_id, deviation_type).
- Find dupes:
SELECT item_id, deviation_type, COUNT(*) FROM spec_deviations WHERE status='open' GROUP BY 1,2 HAVING COUNT(*) > 1 - Merge or close: Keep oldest open; close newer with status=duplicate.
Scenario · Bid submitted despite open deviation
Deviation doesn't block bid response today.
- Check submission: If bid is already in flight, communicate to buyer ASAP.
- Decide: Accept deviation pricing impact or pull line.
- Long-term: Bid submission should check open deviations.
Logs to check
workflow_run_log· top-level run auditworkflow_step_log· per-step traceworkflow_verify_results· post-window verify outcomescron_locks· stuck cron lock detectionevents· workflow.completed / workflow.failed event trailreflexion_log· per-run narrative (if reflexion_enabled)npx wrangler tail· live Worker logs
Kill switch · emergency stop
If this workflow is misbehaving in a high-impact way (creating bad proposed_actions in volume, pushing wrong things to NS), flip a kill switch:
kill:ns_writes· stops every NS push platform-widekill:proposed_apply· stops HITL approvals from executing fan-outkill:high_risk_ops· stops risk_level >= 4 fan-out
See kill-switches-state-machine.html for the full state machine + recovery procedure.
Escalation
Primary: Mike Levine (single-admin) · mikelevine@globalfoodsolutions.co. For prolonged outage during business hours, notify warehouse lead + accounting lead so they can defer dependent work.
What's not done · what's uncertain
What's not done, what's uncertain, what we punted. Captured so it survives context switches and doesn't die in someone's head.
-
STUB
Bid submission deviation block
Today no check. Open deviation should warn or block.
-
OPEN
Per-deviation_type playbook
Pack mismatch has different remediation than cert mismatch. Today single workflow.
-
DEFER
Customer notification on accepted deviation
If we accept a pack mismatch with a price tweak, customer should know.