23-P3D4C0 — New Piece + Document Batch Notification Design Report
23-P3D4C0 — New Piece + Document Batch Notification Design Report
Date: 2026-05-08 Prompt: knowledge/dev/laws/dieu44-trien-khai/prompts/23-p3d4c0-new-piece-document-batch-notification-design-prompt.md (rev2) Design note: knowledge/dev/laws/dieu44-trien-khai/design/23-p3d4c0-new-piece-document-batch-notification-design.md Executor: Claude Opus 4.7 (1M) VPS: 38.242.240.89, container=postgres, db=directus Status: PASS
Verification
phase_status=PASS
birth_notification_gap=CONFIRMED
batch_grouping_required=true
source_document_identifier=NOT_FOUND
import_batch_identifier=NOT_FOUND
debounce_mechanism_recommended=PG_CRON_STAGING
debounce_window_configurable=true
batch_piece_threshold_configurable=true
recommended_event_taxonomy=new_piece_created,document_imported,comment_added,draft_created,version_applied
recommended_grouping_strategy=HYBRID
recommended_hook=UV_SEQ1_TRIGGER
creator_implicit_self_read_applies=true
hot_path_operations=staging_append_only_single_insert_with_pk_subselect
hot_path_joins=0
hot_path_aggregations=0
hot_path_expected_complexity=O(1)
derived_processing_window_seconds=90_120
expected_ai_pg_latency_impact=LOW
p3d2_trigger_hot_path_review=PASS
p3d2_trigger_heavy_work_found=false
p3d4c_directus_exposure_status=PAUSE_UNTIL_BIRTH_BATCH_DESIGN
no_pg_mutation=true
no_directus_mutation=true
no_nuxt_code=true
no_new_tool_created=true
no_external_scheduler=true
no_heavy_trigger_logic=true
next_required_pack=P3D4C1_STAGING_OUTBOX_AND_WORKER_IMPLEMENTATION
Pre-Read
Mandatory documents consulted:
- P3D2 notification triggers report (PASS, 16 tests, Variant A)
- P3D4 design review (PASS) and P3D4B DOT package review (GO)
- Prompt rev2 hot-path constraints
PG Read-Only Inventory (Evidence)
information_unit columns
id, canonical_address, unit_kind, lifecycle_status, content_anchor_ref,
version_anchor_ref, owner_ref, parent_or_container_ref, conformance_status,
identity_profile (jsonb), created_at, updated_at, created_by, updated_by,
deleted_at, sort_order
- 12 rows total;
parent_or_container_refpopulated for 0/12. - Source/batch/import columns: NONE matching ILIKE %source%, %batch%, %import%.
unit_version
version_seqexists; unique(unit_id, version_seq).created_bypresent (Variant A).- Distribution: seq=1 → 12 rows (one per IU), seq=2 → 6, seq=3 → 1.
iu_notification_event (durable, P3D2)
event_typeCHECK currently allows:comment_added,draft_created,version_applied.- Partial unique
uq_notif_event_type_ref ON (event_type, ref_id) WHERE ref_id IS NOT NULL.
Notification triggers (P3D2)
trg_aa_iu_notif_commentonunit_edit_commenttrg_aa_iu_notif_draftonunit_edit_drafttrg_aa_iu_notif_versiononunit_version- All AFTER INSERT FOR EACH ROW; functions O(1) (single INSERT + at most 1 PK sub-SELECT).
Birth gap evidence
fn_iu_notif_versionbody:IF NEW.version_seq <= 1 THEN RETURN NEW; END IF;— birth births are explicitly skipped.- No
fn_iu_notif_birth/trg_*_birth_notifexists. - P3D2 report Test T9: "Birth (version_seq=1) excluded — 0 events" (PASS, by design).
Extensions
pg_cronNOT installed (SELECT extname FROM pg_extensionreturned 0 rows for pg_cron / pg_partman).
Staging table
iu_notification_pendingdoes NOT exist.
8 Design Questions — Answer Summary
| Q | Answer |
|---|---|
| Q1 Birth identification | unit_version.version_seq=1 is the universal birth marker (12/12 IUs). Use AFTER INSERT trigger with WHEN clause. |
| Q2 Source/batch identifier | NOT FOUND. Recommend adding nullable source_document_ref text, import_batch_ref text on information_unit. |
| Q3 Three scenarios | Discriminator = stable key + count within window. Without stable key, scenarios 2 & 3 indistinguishable. |
| Q4 Event taxonomy | Add new_piece_created, document_imported to existing update stream. |
| Q5 Debounce | pg_cron + staging table preferred. Prerequisite: install pg_cron. Default window 90s, configurable. |
| Q6 Grouping | HYBRID. Threshold default 2 (configurable). Creator implicit self-read inherited from existing board. |
| Q7 Hook | UV_SEQ1_TRIGGER — least bypassable, already-correct relation, O(1). |
| Q8 P3D2 hot-path | PASS. No heavy work. Single INSERT + at most 1 PK sub-SELECT per trigger. |
P3D2 Trigger Hot-Path Review
| Function | INSERT count | Sub-SELECT | JOIN | Aggregation | Complexity |
|---|---|---|---|---|---|
fn_iu_notif_draft |
1 | 0 | 0 | 0 | O(1) |
fn_iu_notif_version |
1 | 1 (PK lookup) | 0 | 0 | O(1) |
fn_iu_notif_comment |
1 | 1 (PK lookup) | 0 | 0 | O(1) |
p3d2_trigger_hot_path_review=PASS, p3d2_trigger_heavy_work_found=false.
No mutation recommended in this pack.
Recommendation
DESIGN_STAGING_OUTBOX_FIRST — see Section H of design note for full justification.
Architecture:
- Hot path: AFTER INSERT trigger on
unit_versionWHEN seq=1 → O(1) append toiu_notification_pending. - Worker: pg_cron tick every 90–120s reads pending, groups by stable key + threshold, writes durable events, marks processed.
- Read: existing
iu_notification_event+ future board view.
3-layer separation strictly enforced. No computation on hot path.
Hard Boundaries — Confirmed
- ✅ No PG mutation (read-only inventory queries only)
- ✅ No Directus mutation
- ✅ No Nuxt code
- ✅ No Hermes
- ✅ No Codex dispatch
- ✅ No new tool
- ✅ No external scheduler (pg_cron is PG-native)
- ✅ No heavy trigger logic proposed (O(1) staging append only)
- ✅ No direct PG from Nuxt
- ✅ Board completeness NOT claimed — exposure paused
Next Required Pack
P3D4C1_STAGING_OUTBOX_AND_WORKER_IMPLEMENTATION
Sequenced steps documented in design note Section "Next Required Pack". Prerequisites flagged:
- Install
pg_cronextension (admin/superuser action) - Add 2 nullable text columns to
information_unit
Directus exposure (former P3D4C scope) resumes only after P3D4C1 PASS, as P3D4C2.
P3D4C0 PASS | Design only | Hot path O(1) verified | birth gap CONFIRMED | source/batch NOT_FOUND | staging+pg_cron recommended | Directus exposure PAUSED