spec/lifecycle.ts reads that table rather than maintaining a second set of edges.
Collect and validate answers
You begin atINITIATED, issue a manifest at MANIFEST_ISSUED, then receive answers at PAYLOAD_SUBMITTED. A priced Estimate remains non-binding in either review mode.
If inputs are incomplete, move to MUTATION_REQUIRED and collect a resubmission at PAYLOAD_SUBMITTED. Validated inputs move to VALIDATED_PENDING_REVIEW. For laser removal, you must use the separate unpriced manual-review result when intake gates fail, not invent a priced Estimate.
Review before issuing a quote
FromVALIDATED_PENDING_REVIEW, you can request changes through MUTATION_REQUIRED, decline through DECLINED, or issue QUOTED after artist review.
At QUOTED, you provide a binding Quote with valid_until. You retain its price range, sessions, deposit policies, confidence, assumptions and audit trail. You supply the validity period as a business setting; the protocol imposes no default validity period.
Record the outcome
FromQUOTED, you can move only to ACCEPTED, DECLINED or EXPIRED. Those states are terminal in this draft; you do not add a checkout-handoff state.
The transition helper rejects illegal edges. To enter QUOTED or ACCEPTED, you provide a valid deadline that has not passed. To enter EXPIRED, the current time must be strictly later than valid_until.
To accept, you obtain explicit client approval of the payment amount, currency and policies before external handoff. The helper checks approved: true, an exact amount match and an exact ordered policy match against a nonempty deposit policy list. You must also enforce the binding’s currency and other request-validation requirements; the helper alone is not complete payment authorization.