91000x · 03 — Bounded MARK + VERIFY-MARK proof (Phase C PARTIAL_PASS, BEGIN/ROLLBACK)
91000x · 03 — Bounded MARK + VERIFY-MARK proof
Phase: C
Status: PARTIAL_PASS — steps 1-2 (MARK + VERIFY-MARK) PASS live; steps 4-5 (CUT + VERIFY-CUT) DEFERRED (040/041 not applied)
Date: 2026-05-26
Mode: BEGIN/ROLLBACK — no permanent state change
Fixture: FIXTURE-NVSZ-PROOF-1 (2-piece kho?n text)
Pre snapshot (inside TX)
pre | staging_records | staging_payloads | vector_sync | dot_run_rows
----+-----------------+------------------+-------------+--------------
pre | 3 | 4 | 152 | 18
Step 1 — MARK (fn_iu_mark_create_manifest)
Input: 2-piece manifest (clauses 1 and 2), source text 'Khoan 1. Day la khoan dau tien.\nKhoan 2. Day la khoan thu hai.', manifest_digest = md5('FIXTURE-NVSZ-PROOF-1:v0.6:2pieces:91000x-deterministic').
STEP1 MARK: {
"ok": true,
"expires_at": "2026-06-10T01:21:35.356574+00:00",
"manifest_digest": "15b38e0fdca8b0b0ff1ea1fe44cd0b72",
"lifecycle_status": "pending_review",
"staging_record_id": "cf183532-457b-42d5-844c-ddd58c3de179"
}
✅ ok=true
✅ lifecycle = pending_review (NEW vocab introduced by 037)
✅ expires_at = +15 days from now
✅ manifest_digest 32-hex
Staging row inspection
STEP1 staging row: lifecycle=pending_review owner=iu-core-91000x-proof
source_ref=FIXTURE-NVSZ-PROOF-1
expires=2026-06-10 01:21:35.356574+00 vec_excluded=t part_count=3
✅ vector_excluded=true (CHECK enforced — no-vector guarantee Layer 1)
✅ part_count=3
Payload parts (3-payload contract)
STEP1 payload part 1: name=cut_manifest kind=json bytes=716
STEP1 payload part 2: name=mark_report kind=text bytes=96
STEP1 payload part 3: name=coverage_proof kind=json bytes=21
✅ Exactly 3 parts (cut_manifest, mark_report, coverage_proof) — matches 80000x doctrine + [[feedback-mark-staging-record-has-three-payloads]]
✅ All parts have byte_len set (NOT NULL satisfied)
✅ mark_report uses payload_text (text kind) — exclusive_chk satisfied
Step 2a — VERIFY-MARK dry-run (fn_iu_verify_mark p_apply:=false)
STEP2a verify dry-run: {
"ok": true, "verdict": "approved",
"axis_a_ok": true, "axis_b_ok": true, "axis_c_ok": true
}
✅ All 3 axes PASS
✅ Dry-run — no state change
Step 2b — VERIFY-MARK apply (fn_iu_verify_mark p_apply:=true)
With p_approval_doc_id + p_approver supplied:
STEP2b verify apply: {
"ok": true, "verdict": "approved",
"axis_a_ok": true, "axis_b_ok": true, "axis_c_ok": true
}
STEP2b post-approve: lifecycle=approved
appr_at_set=t
approver=iu-core-91000x-operator
appr_doc_set=t
✅ Lifecycle transitioned pending_review → approved
✅ approved_at, approved_by, approval_doc_id all set — satisfies tightened CHECK from 037 (consumed_consistency requires all 4)
Refusal proofs
REFUSAL_LIFECYCLE: {
"ok": false, "live": "approved",
"reason": "lifecycle must be pending_review"
}
✅ Already-approved row correctly refuses re-verify.
REFUSAL_NOT_FOUND: {"ok": false, "reason": "not_found"}
✅ Unknown UUID correctly returns not_found.
Audit rows (dot_iu_command_run writes)
AUDIT dot_iu_mark_article: cat=piece mode=apply status=applied result=NULL
AUDIT dot_iu_verify_mark_manifest: cat=health mode=verify status=verified result=approved
✅ Both DOTs registered with live vocab (piece + health categories; apply/verify modes; applied/verified statuses).
✅ Evidence jsonb captures staging_record_id, manifest_digest, source_ref, approval_doc_id.
Cleanup dry-run
CLEANUP dry-run rows: 0
✅ Pass 1 (pending/pending_review past expires_at): 0 (all rows within 15d window).
✅ Pass 2 (expired/rejected older than 15d): 0 (no rows old enough — proof rejected row from 25000x is only 12h old, the consumed mark_manifest row is 12h old).
✅ Pass 3 (consumed older than 30d): 0.
15-day cleanup proof is dry-run only; no rows touched.
Step 3 (refusal matrix) — partially covered
The two refusal scenarios above (lifecycle-mismatch + not_found) exercise the same fn surface that CUT will need (G3 not_approved + G1 not_found). Additional G2/G4/G5/G6/G7 refusals require fn_iu_cut_from_manifest which is deferred (mig 040 not applied).
Step 4 — CUT FROM APPROVED MANIFEST — NOT EXECUTED
fn_iu_cut_from_manifest does not exist (mig 040 not applied). Per user rule, no re-author this run.
Step 5 — VERIFY CUT — NOT EXECUTED
fn_iu_verify_cut does not exist (mig 041 not applied).
Step 6 — CLEANUP DRY-RUN — covered above
Already exercised within the same proof TX. Result: 0 eligible. ✅
Step 7 — POST snapshot (after ROLLBACK)
post_rollback | staging_records | staging_payloads | vector_sync | dot_run_rows
--------------+-----------------+------------------+-------------+--------------
post_rollback | 3 | 4 | 152 | 18
✅ All counts equal pre exactly. ROLLBACK clean. Zero permanent state pollution.
PASS criteria (per 90000x report 07)
| Check | Required | Observed | Verdict |
|---|---|---|---|
input_to_staging |
step 1 returns ok:true, lifecycle_status:pending_review | yes | ✅ PASS |
mark |
step 1 produced 3 payload rows + 1 staging row | yes (3 parts visible) | ✅ PASS |
verify_mark |
step 2 returns verdict:approved; updates approved_at/approved_by/approval_doc_id | yes | ✅ PASS |
approve |
staging row lifecycle_status='approved' | yes | ✅ PASS |
cut_from_approved_manifest |
step 4 applied:true, pieces_created_count=2 | fn doesn't exist | ⏸ DEFERRED |
verify_cut |
step 5 verdict:verified, axes ok | fn doesn't exist | ⏸ DEFERRED |
cleanup_dry_run_15d |
step 6 no rows eligible | 0 rows | ✅ PASS |
no_vector_pollution |
step 7 vector_sync_post == vector_sync_pre | 152 = 152 | ✅ PASS |
production_untouched |
step 7 prod docs unchanged | N/A (production_documents not present in directus DB; structurally untouched) | ✅ PASS |
Phase C verdict: PARTIAL_PASS — 6/8 checks PASS, 2/8 DEFERRED on 040/041 apply gap.
Why this is a proof, not a smoke test
Every step ran against the production-config PostgreSQL with live workflow_admin role in the actual directus database. The fns called were the CREATEd functions from this macro's apply — not stubs or mocks. The only safety wrapper was the outer BEGIN; … ROLLBACK; which guarantees zero permanent state change. The same fns called outside a TX would mutate state identically — proof shows the contract works.
Cross-links
- [[feedback-staging-lifecycle-includes-pending-review]] — verified live.
- [[feedback-mark-staging-record-has-three-payloads]] — verified live (3 parts: cut_manifest+mark_report+coverage_proof).
- [[feedback-iu-vector-sync-point-has-no-staging-path]] — verified by structural-absence (no staging_record_id column in iu_vector_sync_point).