KB-7753

90000x · 03 — MARK Integration writer surface (Migration 038)

8 min read Revision 1
iu-core90000xmark-integrationfn_iu_mark_create_manifestdot_iu_mark_articlemigration-038authored-ready2026-05-25

90000x · 03 — MARK Integration writer surface

Phase: C Status: AUTHORED-READY Migration: 038 D9 delta after apply: +1 fn (fn_iu_mark_create_manifest), +1 DOT (dot_iu_mark_article).

Why this surface exists

The mission requires Agent MARK to write into No-Vector Staging Zone, not into KB and not into IU. The existing dot_iu_staging_create is a generic creator — it does not know about cut_manifest M1-M16 fields, doesn't compose the 3-part payload (cut_manifest + mark_report + coverage_proof), and doesn't enforce the mark_manifest kind. fn_iu_mark_create_manifest is the purpose-built MARK writer.

Contract

Property Value
Inputs manifest jsonb, mark_report_md text, coverage_proof jsonb, determinism_digest text, source_kind, source_ref, idempotency_key, actor
Side effects 1 row iu_core.iu_staging_record (kind=mark_manifest, status=pending_review, expires_at=now+15d, vector_excluded=true) + 3 rows iu_core.iu_staging_payload (cut_manifest, mark_report, coverage_proof) + 1 audit row in dot_iu_command_run
Idempotency idempotency_key unique per staging_kind='mark_manifest'. Replay returns same staging_record_id, ok=true, idempotent_replay=true.
Refusals Returns {ok:false, reason:'manifest missing M1/M2/M3/M4 or pieces'} if manifest is missing manifest_version, source_id, manifest_digest, source_bytes, or pieces.
Never does Create IU pieces. Insert into knowledge_documents. Insert into production_documents. Set vector_excluded=false. Upload anything to Qdrant. Skip the staging tier.
Lifecycle out pending_review (NOT pending) — MARK is intentionally pending_review because the manifest is already proposal-ready and Phase D is what gates approval. pending is reserved for partial drafts not yet ready for review.

Migration 038 — authored

-- IU Core 90000x · Migration 038 · MARK Writer Surface
BEGIN;

CREATE OR REPLACE FUNCTION fn_iu_mark_create_manifest(
  p_manifest          jsonb,
  p_mark_report_md    text,
  p_coverage_proof    jsonb,
  p_determinism_digest text,
  p_source_kind       text,
  p_source_ref        text,
  p_idempotency_key   text,
  p_actor             text DEFAULT 'agent_mark'
) RETURNS jsonb LANGUAGE plpgsql AS $$
DECLARE v_staging_id uuid; v_content_hash text; v_now timestamptz := now();
BEGIN
  SELECT staging_record_id INTO v_staging_id
  FROM iu_core.iu_staging_record
  WHERE idempotency_key = p_idempotency_key AND staging_kind = 'mark_manifest';
  IF v_staging_id IS NOT NULL THEN
    RETURN jsonb_build_object('ok',true,'idempotent_replay',true,'staging_record_id',v_staging_id);
  END IF;

  IF NOT (p_manifest ? 'manifest_version' AND p_manifest ? 'source_id'
          AND p_manifest ? 'manifest_digest' AND p_manifest ? 'source_bytes'
          AND p_manifest ? 'pieces') THEN
    RETURN jsonb_build_object('ok',false,'reason','manifest missing M1/M2/M3/M4 or pieces');
  END IF;

  v_content_hash := md5(p_manifest::text || '|' || p_mark_report_md || '|' || p_coverage_proof::text);
  v_staging_id := gen_random_uuid();

  INSERT INTO iu_core.iu_staging_record (
    staging_record_id, staging_kind, payload_type, purpose,
    lifecycle_status, owner_actor, source_kind, source_ref, idempotency_key,
    content_hash, byte_len, part_count, metadata, referenced_iu_ids,
    created_at, expires_at, vector_excluded
  ) VALUES (
    v_staging_id, 'mark_manifest', 'application/json', 'cut_manifest_for_review',
    'pending_review', p_actor, p_source_kind, p_source_ref, p_idempotency_key,
    v_content_hash, octet_length(p_manifest::text), 3,
    p_manifest || jsonb_build_object('determinism_digest', p_determinism_digest), NULL,
    v_now, v_now + INTERVAL '15 days', true
  );

  INSERT INTO iu_core.iu_staging_payload (staging_payload_id, staging_record_id, part_index, part_name, payload_kind, payload_json, content_hash, created_at)
  VALUES
    (gen_random_uuid(), v_staging_id, 1, 'cut_manifest',   'json',     p_manifest, md5(p_manifest::text), v_now),
    (gen_random_uuid(), v_staging_id, 2, 'mark_report',    'markdown', jsonb_build_object('md', p_mark_report_md), md5(p_mark_report_md), v_now),
    (gen_random_uuid(), v_staging_id, 3, 'coverage_proof', 'json',     p_coverage_proof, md5(p_coverage_proof::text), v_now);

  INSERT INTO dot_iu_command_run (command_name, payload_json, actor, status)
  VALUES ('dot_iu_mark_article',
          jsonb_build_object('staging_record_id', v_staging_id,
                             'manifest_digest', p_manifest->>'manifest_digest',
                             'source_ref', p_source_ref),
          p_actor, 'ok');

  RETURN jsonb_build_object(
    'ok', true,
    'staging_record_id', v_staging_id,
    'lifecycle_status', 'pending_review',
    'expires_at', v_now + INTERVAL '15 days',
    'manifest_digest', p_manifest->>'manifest_digest'
  );
END; $$;

INSERT INTO dot_iu_command_catalog (command_name, category, mutating, reversible, target_functions, registered_at)
VALUES ('dot_iu_mark_article', 'mark', true, false, ARRAY['fn_iu_mark_create_manifest']::text[], now());

COMMIT;

Rollback 038

BEGIN;
DELETE FROM dot_iu_command_catalog WHERE command_name = 'dot_iu_mark_article';
DROP FUNCTION IF EXISTS fn_iu_mark_create_manifest(jsonb,text,jsonb,text,text,text,text,text);
COMMIT;

Why pending_review not pending

  • pending = partial intake; the agent may still be building the manifest.
  • pending_review = the manifest exists, has manifest_digest, and is awaiting fn_iu_verify_mark.
  • The expiry clock starts the same instant in both. Cleanup treats them identically.

Refusals exercised at write time

Caller mistake Returns
manifest_version missing {ok:false, reason:'manifest missing M1/M2/M3/M4 or pieces'}
pieces=[] (passes 038 surface — Phase D rejects on empty pieces)
same idempotency_key twice {ok:true, idempotent_replay:true, staging_record_id: <existing>}
expires_at > created_at + 30d (caller tries to bypass via metadata) impossible — fn sets expires_at = now + 15d ignoring caller input

What MARK NEVER writes to

Target Why blocked
knowledge_documents (KB table) fn signature has no path; Agent MARK has no upload_document permission for mark_manifest paths.
iu.information_unit fn body does not insert; pieces are born only by fn_iu_create called from fn_iu_cut_from_manifest after approval.
iu_vector_sync_point vector_excluded=true CHECK + structural absence of path.
production_documents (Directus) no write surface here at all.
Qdrant fn cannot call extension; no pg_qdrant extension installed.
  • [[project_dot_iu_cutter_v0_6_iu_core_80000x_operational_cut_workflow_mark_review_cut_verify_mark_review_cut_verify]] — 02-agent-mark-instructions.md is the 12-step Agent procedure that produces the inputs for this function.
  • [[project_dot_iu_cutter_v0_6_iu_core_80000x_operational_cut_workflow_mark_review_cut_verify_mark_review_cut_verify]] — 03-cut-manifest-schema.md is the M1-M16 schema this fn validates against (minimally).
  • [[feedback-idempotency-key-for-event-driven-compose]] — idempotency_key pattern (md5(event_id||':'||template_id||':'||suffix)) applies analogously to MARK (md5(source_ref||':'||manifest_digest||':'||agent_run_id)).
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-90000x-mark-to-cut-automated-pipeline-hardening/03-mark-integration.md