KB-6C5D

80000x · 04 — Review / approval checklist (R0-R11, decision template)

8 min read Revision 1
iu-core80000xreview-approval-checklistR0-R11operatorapproved-manifestapproval-doc-idstable-immutable-kb-pathiu_core_approval_authorityaxis-aaxis-baxis-cvocab-freshness

04 — Review / approval checklist

Audience: the operator (or DOT review function) deciding whether a cut_manifest is ready for CUT.

The reviewer's job is to catch the things the Agent could not catch by re-reading its own output: source mis-attribution, boundary errors, Axis B drift, parent-child confusion. The CUT stage refuses to run without an approval record produced by this checklist.

1. Inputs to the review

  • The manifest JSON (path: KB or local scratch).
  • The mark_report.md.
  • The current source (re-fetched at review time).
  • The substrate vocab (live DB if available; otherwise the snapshot in 02 §6).

2. Mandatory checks

Run them in order. Stop at the first FAIL; record it; route back to the Agent.

R0 — Manifest format

  • manifest_format_version is supported ("1.0" at time of this package).
  • manifest_digest is present and recomputes to the same value.
  • manifest_id is unique within the KB (no prior approved manifest re-using this id).
  • approval.status == "pending" at intake. (Not approved — that means the Agent forged the approval.)

R1 — Source identity

  • source.url_or_file is what the user requested (compare with the original user message).
  • Fresh fetch of the URL returns a body whose sha256 matches source.source_hash. If the source has moved/changed, document and decide whether a re-MARK is needed.
  • source.retrieved_at is within the freshness window (≤ 24 h by default).

R2 — Article boundary

For each articles[] entry:

  • article_label is one the user requested (no extra articles, no fewer).
  • boundary.start_quote appears verbatim at the article's start in the source.
  • boundary.end_quote appears verbatim at the article's end (or right before the next article header / EOF).
  • Nothing before start_quote was included in any piece.
  • Nothing after end_quote was included in any piece.

R3 — Piece count plausibility

  • The piece count is not absurd. Rule of thumb: most legal articles produce 2–10 pieces (title + 1–8 clauses/sub-points). If the manifest has 1 piece or >20 pieces for a single article, scrutinize.
  • Every clause/numbered paragraph in the source appears as a piece. No clause silently absorbed into a sibling.

R4 — Axis A (source order)

  • source_position is dense (1..N, no gaps).
  • source_position is monotonic (strictly increasing).
  • source_position is unique within the article.
  • Sorted concat matches the article body's normalized form (reconstruction preview byte-equal — see R6).

R5 — Axis B (professional)

  • Every piece has axis_b.unit_kind in {design_doc_section, law_unit}.
  • Every piece has axis_b.section_type in the live substrate vocab.
  • Every piece has axis_b.legal_document set OR a flag explaining absence.
  • professional_tags[] are not invented — each tag is either obvious from the source or empty.
  • No second source of truth: Axis B never duplicates a value the substrate already encodes elsewhere.

R6 — Axis C (parent / child / grandchild)

  • Exactly one piece has parent_local_piece_id = null per article (the title / root).
  • Every other piece's parent_local_piece_id resolves to a piece in the same article.
  • depth values are consistent: depth(p) == depth(parent(p)) + 1.
  • Max depth ≤ 2 (root → clause → sub-point). Deeper than 2 is allowed only with explicit reviewer sign-off and an uncertainty_flag.
  • No cycles in the parent graph.

R7 — Reconstruction preview

  • reconstruction.expected_digest equals each article's original_text_hash.
  • reconstruction.preview (first 400 chars) reads like the start of the article when eyeballed.
  • reconstruction.rerun_byte_identical is true.

R8 — Uncertainty flags

  • Every uncertainty_flags[] entry is either:
    • explicitly resolved (reviewer writes a one-line decision next to it), OR
    • downgraded to "operator-accepted" (acceptable to ship), OR
    • escalated back to Agent for a re-MARK.
  • No flag is silently ignored.

R9 — Corpus uniqueness

  • doc_code is unique in the existing IU corpus (no prior information_unit.canonical_address starts with the same prefix unless this is an explicit version update).
  • No piece's text_hash already exists in an enacted IU (duplicate-cut guard). If a duplicate exists, flag it and decide whether to re-use the existing IU instead of minting a new one.

R10 — Substrate vocab freshness

  • unit_kind, section_type, piece_role, link_role values are in the live DB vocab at review time (not just the snapshot). Verify with:
SELECT pg_get_constraintdef(c.oid)
FROM pg_constraint c
JOIN pg_class t ON c.conrelid = t.oid
WHERE t.relname = 'information_unit' AND c.contype = 'c';
-- and similar for iu_sql_link.link_role

If vocab has drifted, recommend a re-MARK with the updated terms.

R11 — No forbidden side effects observed

  • No cut_record already filled in (must be null at REVIEW time).
  • No verify_record already filled in.
  • No iu_ids_created[] claimed.
  • No dot_command_run_id set.

If any are present, the Agent cheated and self-advanced. Reject and re-MARK.

3. Decision

If all R0–R11 PASS:

approval:
  status:           approved
  approved_by:      <operator-handle@org or DOT identity>
  approved_at:      <ISO-8601 UTC, current>
  approval_doc_id:  <KB doc id of this review record>
  rejection_reason: null

Re-upload the manifest to a stable, immutable KB path:

knowledge/dev/laws/<doc-folder>/approved-manifests/<manifest_id>.json

The CUT stage will read from this exact path.

Else:

approval:
  status:           rejected
  approved_by:      null
  approved_at:      null
  approval_doc_id:  null
  rejection_reason: "<one-line summary; full detail in the review report>"

Send back to the Agent with the failed check labels (e.g., "R4 source_position has a gap at lp-004"). The Agent re-runs MARK; loop.

4. Review report template

Save under knowledge/dev/laws/<doc-folder>/mark-reviews/<UTC-timestamp>-<manifest_id>.md:

# Review of manifest <manifest_id>

- Reviewer: <handle>
- Reviewed at: <UTC>
- Manifest digest: <sha256>
- Articles: <N> (Điều 37, 38, 39)

## Checks

| Check | Result | Note |
|-------|--------|------|
| R0 format | PASS | |
| R1 source identity | PASS | re-fetched, hash match |
| R2 boundary | PASS | |
| R3 piece plausibility | PASS | 4 pieces per article, all clauses present |
| R4 Axis A | PASS | 1..N dense |
| R5 Axis B | PASS | unit_kind=law_unit, section_type all valid |
| R6 Axis C | PASS | depth max=2 |
| R7 reconstruction | PASS | byte-equal |
| R8 uncertainty | PASS | flags empty |
| R9 corpus uniqueness | PASS | no duplicates |
| R10 vocab freshness | PASS | verified live |
| R11 no forbidden side effects | PASS | cut_record/verify_record null |

## Decision

APPROVED. Next: CUT via `dot_iu_cut_from_manifest --manifest <path> --approval-doc-id <this-doc-id>`.

5. Authority

A reviewer must be authorized to approve manifests for the relevant doc_code. The KB stores an iu_core_approval_authority registry mapping operator identities to allowed doc_code prefixes. If the registry is absent, default to the team's standing operator (user) until the registry is populated.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-operational-cut-workflow-mark-review-cut-verify/04-review-approval-checklist.md