R2-D2 Channel Decision Packet — B2 Inspect Producer (LEGO, design-only, 2026-06-18)
R2-D2 Channel Decision Packet — B2 Inspect Producer
Date: 2026-06-18 · Workstream: LEGO-PILOT-SLICE-0-R2-B2-PLANNING-BUNDLE-2026-06-18 (Deliverable A of five) · Editorial revision: rev1
Class: design-only / channel-comparison / decision-support · READ-ONLY · NON-ENACTING · NON-AUTHORIZING · NOT remediation · NOT technical design · NOT implementation · NO channel selected · NO blocker resolved · NO runtime touched.
Metadata convention. This body uses editorial revision (rev1) only. AgentData storage revision and
content_lengthare authoritative in AgentData metadata at read time; they are deliberately not pinned in this body.
Channel-decision lock. This packet compares the candidate invocation channels for the B2 inspect producer and classifies them for a later Owner decision. It selects no channel as authority, specifies no scheduler/runner, installs nothing, enables nothing, and builds nothing. The channel is an internal of B2 (B2-AC-7); whichever is later chosen must stay inside the block so the contract is unaffected.
0. Status and non-authorization
STATUS: PASS — engineering / design-only. This is a complete design-only channel comparison for the B2 inspect producer: a comparison matrix across five candidate channels, a per-channel analysis, a LEGO-replaceability comparison, an evidence/observability comparison, a rollback/delete comparison, the Owner-gated future-work list, and a recommendation-only summary. It builds nothing, mutates nothing, authorizes nothing, and chooses nothing.
Engineering PASS ≠ authority PASS. A PASS here means the channel options are completely and fairly compared on paper. It is not an Owner authorization to select a channel, to design-in-detail, to write technical design, to install an extension, to promote a contract, to enable a worker, or to build a producer. Default disposition: HOLD.
Pipeline position (downstream-only).
Accepted R1a/R2a root-cause baseline (Codex
PASS_WITH_CAVEATS) → Owner Decision Packet (Option D, accepted) → R1/R2 Modular LEGO Architecture Scoping (accepted) → R1-K ∥ R2-B block-contract packets (accepted) → Registries/Pivot LEGO Interface TD-prep (accepted) → R2-B2 Inspect Producer TD-prep (accepted, CodexPASS_WITH_CAVEATS) → this R2-D2 standalone channel decision packet (Deliverable A of the Pilot-Slice-0 planning bundle) → (only if separately authorized) actual B2 technical design with a chosen channel → (only if separately authorized again) producer build / write-enabled remediation.
This packet deepens §11 of the accepted R2-B2 TD-prep packet (its conceptual channel matrix) into a standalone decision packet. It opens no next package and selects no channel.
Non-authorization (explicit). This document does not, and cannot: run any DB write / DDL / DML; restart or reload any container or service; run any worker / cron / job; trigger DOT / KG / birth / certify / promote / repair execution; set inspect_pen / inspect_stamp / inspect_gate; set certified=true; flip app.birth_gate_mode or any dot_config gate; assign a governance owner; install pg_cron or any extension; promote any agent-api contract DRY_RUN→REAL_RUN; enable any queue worker / master switch; write env / config files; patch source code; patch any source law / draft / note / prior report; create a current corpus or staging corpus; write technical design; implement; resolve any blocker; select or wire a channel; overwrite the v0.1-stable / FIX7 V3 baseline; promote or use Tool-Kiem-Thu v0.2-hardening as authority.
Evidence basis — INHERITED_EVIDENCE. No runtime was queried in this run. Every runtime fact cited is inherited from the accepted read-only reports (R2a root-cause, R2 readiness scope, Phase-1, Phase-1B) and accepted design packets. AgentData metadata is authoritative at read time. CAV-3 / CAV-4 / CAV-5 bound what is provable about each channel.
Reading discipline (Codex operational caveat, honored). All sources were read directly from AgentData KB, in bounded, sequential, single-document batch_read (full) calls, by the main process — no parallel reader-agents, no background reader-agents, no sub-agent outsourcing, no inference from local prose. One oversized source was decoded locally by the main process only to render its already-fetched bytes readable; no reading was outsourced.
1. Purpose
Compare host cron, agent-api executor, pg_cron, job_queue worker, and manual one-shot as B2 invocation channels, and classify them for a later Owner decision without selecting one as authority. The packet answers:
- Which channels are candidate / risky / rejected? — §5–§10, §15.
- What evidence is needed for each before a build? — §6–§10, §12.
- What Owner gate is needed for each? — §6–§10, §14.
- What rollback unit would apply to each? — §6–§10, §13.
- Which channel best preserves LEGO replaceability? — §11.
- What must be proven before actual B2 TD? — §15, §16.
The one rule, above all detail. The channel is a replaceable internal of B2, not the block boundary. B2's contract — read uncertified birth_registry rows → write inspect_* only, genuine per-stage, fail-closed — is channel-independent (B2-AC-7). This packet may compare channels; it may not let any channel leak into the contract, and it may not promote any channel to authority.
2. Sources read
All sources read first-hand, directly from AgentData KB, via batch_read (single path, full: true), one document per call, sequentially, by the main process — no parallel reader-agents, no background agents, no sub-agents, no local-prose inference. None SOURCE_NOT_READ. AgentData storage revision / content_length authoritative in metadata at read time.
| # | Source (prefix knowledge/dev/ omitted) |
Status | Used for |
|---|---|---|---|
| 1 | laws-new/newlaws/consolidation/r2-b2-inspect-producer-td-prep-lego-2026-06-18.md |
READ (full) | the accepted B2 contract; §11 channel matrix this packet deepens; B2-AC-7 (channel internal) |
| 2 | laws-new/newlaws/reports/r2-b2-inspect-producer-td-prep-lego-execution-report-2026-06-18.md |
READ (full) | B2 completion criteria; channel-conceptual-only posture |
| 3 | laws-new/reports/codex/codex-review-r2-b2-inspect-producer-td-prep-lego-2026-06-18.md |
READ (full) | B2 PASS_WITH_CAVEATS; "channel matrix conceptual only; no channel selected as authority" |
| 4 | laws-new/newlaws/consolidation/registries-pivot-lego-interface-td-prep-2026-06-18.md |
READ (full) | S3/S4/S7/S8 surfaces; B2's interface access line; channel-is-internal |
| 5 | laws-new/reports/codex/codex-review-registries-pivot-lego-interface-td-prep-2026-06-18.md |
READ (full) | the no-parallel-reader-agents process caveat |
| 6 | laws-new/newlaws/consolidation/r2-b-block-contract-packet-lego-2026-06-18.md |
READ (full) | B2/B3/B4/B5/B7 contracts; channel-is-internal; B5/B7 kept separate |
| 7 | laws-new/reports/codex/codex-review-r1-k-r2-b-block-contract-packets-lego-2026-06-18.md |
READ (full) | B2 = "channel remains later TD-prep decision, correctly kept inside block" |
| 8 | laws-new/newlaws/consolidation/r1-r2-modular-lego-architecture-scoping-2026-06-18.md |
READ (full) | block map; R2-D2 channel as internal; anti-coupling AC-1…12 |
| 9 | laws-new/reports/codex/codex-review-r1-r2-modular-lego-architecture-scoping-2026-06-18.md |
READ (full) | design-only altitude; channel deferred as future TD-prep |
| 10 | laws-new/newlaws/reports/r2a-birth-inspection-runner-cron-log-root-cause-2026-06-18.md |
READ (full) | the channel evidence (containers; pg_cron absent; host cron map; master switches; queue idle; agent-api :8090; tool-boundary) |
| 11 | laws-new/reports/codex/codex-review-r1a-r2a-runner-cron-log-root-cause-2026-06-18.md |
READ (full) | 6 caveats; 3 wording constraints; "net-new governed build, not restart" |
| 12 | laws-new/newlaws/reports/r2-birth-certify-canonical-stamp-readiness-scope-2026-06-17.md |
READ (full) | birth_registry schema; no live inspect_* setter; consumer starved |
| 13 | laws-new/newlaws/consolidation/phase1b-runtime-truth-blocker-decision-packet-2026-06-17.md |
READ (full) | all OPEN blockers; HOLD-2 PARTIAL; R2 macro framing |
| 14 | architecture/birth-registry-law.md (Điều 0-G v1.0) |
READ (full) | the PEN/STAMP/GATE rule-set the chosen channel must run; one-column-per-inspector |
| 15 | laws-new/newlaws/notes/dieu4-birth-process-compatibility-note.md (rev1) |
READ (full) | birth ≠ canonical; certify is not the channel's job |
| 16 | laws-new/newlaws/notes/dieu32-approval-owner-gate-compatibility-note.md (rev1) |
READ (full) | Owner gate; no-Stamp-bypass |
| 17 | laws/dieu32-approval-law.md (v1.1) |
READ (full) | §2.1 DOT-100% / no manual SQL / no curl bypass; §2.4 new/fix DOT in scope |
| 18 | laws-new/newlaws/notes/dieu35-dot-governance-compatibility-note.md (rev1) |
READ (full) | scanner=list-only; warn-vs-block §10; reuse-pattern-not-turnkey |
| 19 | ssot/operating-rules.md (v7.58) |
READ (full) | Assembly First; fail-closed default; AP-CLOSE evidence; out-of-scope-blocker STOP |
3. Tool/packet lock
Carried exactly, no change:
| Item | Status |
|---|---|
| Tool/packet currently built by T1 = v0.1-stable / FIX7 V3 baseline | Carried. May continue to be used for FIX7 Recheck-9 / current Codex packet. Must not be overwritten. Use only as reproducibility / comparison / regression fixture. |
| Tool-Kiem-Thu v0.2-hardening | Carried. Separate development track on a separate dev surface. May inherit lessons from V3 (black-box oracle, fail-open regression, manifest-laundering prevention). Not authority for FIX7 until it passes regression and Owner/User promotes it. |
This packet builds, runs, promotes, overwrites, and relies on neither tool. A v0.2-hardening result offered as authority for FIX7 is rejected (mirrored in Deliverable D, bad-input case BAD-10).
4. Accepted channel baseline (carried, not re-derived)
Carried in substance from §11 of the accepted R2-B2 Inspect Producer TD-prep packet (Codex PASS_WITH_CAVEATS) and from the R2a root-cause study (Codex PASS_WITH_CAVEATS). This packet deepens that matrix; it does not change it.
The channel is internal (B2-AC-7). Per the accepted B2 contract: "Producer channel is internal & swappable; contract = write inspect_* only." Codex's acceptance of B2 reads: "Producer not built; channel remains later TD-prep decision, correctly kept inside block." The five channels named across the accepted chain are: host cron · agent-api executor · pg_cron · job_queue worker · manual one-shot.
Runtime substrate the channels must live in (INHERITED_EVIDENCE, R2a §3–§9):
- Containers:
postgres(Up 2 months, healthy — hostsbirth_registry,trg_birth_auto_certify, 192 birth triggers),incomex-directus(Up 5 weeks, healthy — births fire on its INSERTs),incomex-agent-api-executor(agent-api-executor-local:v1, Up 13 days, healthy,:8090/dispatch— a generic DOT dispatch runner, not bound to any birth DOT). There is no dedicated birth-inspection service/container. - Master switches OFF:
process_dot_runtime.execute_enabled=false,real_run_enabled=false,dry_run_only=true;queue.worker.enabled=false;queue.job_substrate.enabled=false. - pg_cron NOT installed:
pg_extension=btree_gist,pgcrypto,plpgsql,postgres_fdwonly. - Queue idle:
queue_heartbeatlast tick 2026-05-22→26 (3 executors, none birth-related);event_outboxgrows live to 215,588 rows (≈215,227system/issue_opened) but is undrained and carries no birth/certify events. - Host cron (
wf_host_crontab_snapshot, observed 2026-06-17 02:10:04, 54 entries, allstatus=OBSERVED): the0 6 * * *slot belongs todot-nrm-lifecycle, not birth-verify. Sibling scanner/maintenance DOTs run here —dot-hc-executor(0 */3),dot-orphan-scanner,dot-misclass-scanner,dot-nrm-verify/sync/lifecycle/discover,dot-sync-orphan-scan,dot-trigger-guard,dot-matrix-health,dot-gov-verify,dot-vector-audit,dot-pivot-health,dot-accuracy-verify,fn_expire_stale_approvals(0 5),auto_apply_approval(30 4), matview-refresh, backups, certbot. No host cron entry references birth / inspect / certify. - agent-api contract today: the only
dot_agent_api_contractbindings are the KG EXPLAIN pair (DOT_KG_EXPLAIN, DRY_RUN pilot, 2026-06-04 →:8090/dispatch). The inspector DOTsDOT-TAC-BIRTH-VERIFY(cron 0 6metadata) /-GATE(event) are unwired stubs (engine_unclassified/requires_runner, nofile_path, no contract,last_executed=NULL). - Tool-boundary (CAV-3/CAV-4): no
crontab -l/systemctl/docker exec/docker inspecttool exists in the available surface;read_fileis allowlisted to/opt/incomex/docs,/opt/incomex/dot/specs,/var/log/nginxonly;/opt/incomex/dot/binand env files are not readable on the VPS; container logs are tail-only (≤500 lines), so deep liveness of any channel is provable only via DB-captured snapshots.
The job the chosen channel invokes (Điều 0-G, carried). Whatever the channel, it must invoke a producer that runs the three Điều 0-G inspections in strict PEN → STAMP → GATE order, each writing only its own inspect_* column on a genuine per-stage pass, fail→audit-queue, idempotent. The channel never changes that rule-set.
5. Channel comparison matrix
Conceptual comparison only. No channel is selected, specified, scheduled, installed, enabled, or built. Each row is FUTURE_TECHNICAL_DESIGN_REQUIRED for any build. Dispositions match the accepted §11 matrix.
| Channel | Possible role | LEGO boundary risk | Evidence requirement (before TD) | Observability | Rollback unit | Owner gate needed | TD required later | Disposition |
|---|---|---|---|---|---|---|---|---|
| host cron | Scheduled trigger that invokes the inspector pass (the proven channel for the sibling scanner DOTs) | Low — a cron entry is outside the block and swappable; not transactional with PG; opaque except via the DB-captured snapshot | Cron entry visible in wf_host_crontab_snapshot; per-run S7 append |
Indirect (snapshot table); not in-txn | Remove the one cron entry; one producer run | Điều 32 + S2 owner | Yes — the wiring spec | candidate (lowest blast radius; proven for siblings) |
agent-api executor (:8090) |
Dispatch the inspector via an agent-api contract, as the KG EXPLAIN pilot does | Low–Medium — contract-bound and observable (governance-aligned); but shared infra (also serves the KG lane) and master-switch-gated | agent-api contract bound + dispatch records + master-switch state + S7 append | Strong (contract + dispatch records) | Unbind / disable the contract (return to DRY_RUN); one producer run | Điều 32 + S2 + contract promotion DRY_RUN→REAL_RUN |
Yes — the contract + wiring | candidate (existing healthy runner; contract pattern proven) — gated by master switch + promotion |
| pg_cron | In-database scheduler running the inspector pass | Medium–High — in-DB and transactional with the inspect_* writes (clean for atomicity) but requires installing a new extension (not installed today) → infra dependency / higher blast radius |
pg_cron installed + job catalog + S7 append | Strong (in-DB job catalog) | Unschedule the job; (extension removal = infra) | Điều 32 + infra/extension-install approval | Yes | risky / future-gated (net-new extension install) |
| job_queue worker | Enqueue inspection jobs drained by a worker | High — substrate exists but disabled/idle; the "queue that nobody drains" failure mode (event_outbox 215k undrained) is already observed here |
job_queue rows + worker heartbeat + master-switch state + S7 append |
Medium (heartbeat + queue rows), currently dead | Disable the worker; drain/purge the queue; one producer run | Điều 32 + enable worker / master-switch flip | Yes | risky / future-gated (substrate idle/disabled; undrained-queue failure mode present) |
| manual one-shot | Operator-run bring-up (the 2026-03-21 SSH + docker exec pattern) |
Disqualifying as a standing channel — not testable/replaceable/rollbackable as a block; violates Điều 32 §2.1 (no manual SQL / no curl bypass); is the vehicle of the fused INSERT | Ad hoc only | None (no standing artifact) | None clean | Would still need Điều 32, but is structurally unfit as a standing channel | n/a (anti-pattern) | reject as a standing channel |
Convergent reading of the matrix. Two channels are standing-fit candidates (host cron, agent-api executor); two are standing but currently-blocked/heavier (pg_cron needs an extension install; job_queue worker sits on an idle/undrained substrate); one is structurally unfit as a standing channel (manual one-shot). No row is promoted to authority here.
6. Host cron analysis
Possible role. A host-crontab entry that periodically invokes the B2 inspector pass — the same channel the sibling scanner DOTs already use (dot-orphan-scanner, dot-misclass-scanner, dot-nrm-*, dot-hc-executor, etc., per wf_host_crontab_snapshot). The inspector's nature — a periodic scan over uncertified rows — matches a cron cadence.
LEGO boundary fit (strong). A cron entry lives outside the block; it merely invokes the producer. Swapping host cron for another channel changes nothing in the B3 inspect_* contract. This is exactly the replaceable-internal that B2-AC-7 requires. The 0 6 * * * slot is already taken by dot-nrm-lifecycle, so a birth-inspector would need its own slot — a wiring detail, not written here.
LEGO boundary risk (low, with one caveat). Cron is not transactional with the inspect_* writes (the producer must own its own per-stage atomicity and idempotency), and it is opaque to in-DB observability — visible only via the DB-captured wf_host_crontab_snapshot, never via a live crontab -l (no such tool; CAV-3/CAV-4). So "is the cron actually installed and firing?" is provable only through the snapshot + the S7 run-evidence, not directly.
Evidence needed before TD. (a) A cron entry present in wf_host_crontab_snapshot bound to the inspector; (b) per-run S7 evidence (counts/ids/timestamps/rule-set hash) confirming the producer ran; (c) confirmation that the producer is genuinely idempotent (re-firing the cron must not double-stamp).
Owner gate. Điều 32 (the producer build is a new/fix DOT, §2.4) + an assigned S2 producer owner. The cron wiring itself is part of the producer's governed build, never a manual crontab -e.
Rollback unit. Remove the single cron entry; one producer run is the rollback unit (S8). Clean and bounded.
Residual. FUTURE_TECHNICAL_DESIGN_REQUIRED for the exact slot, command, and idempotency guard — not written here (no cron spec, no command sequence).
7. Agent-api executor analysis
Possible role. Dispatch the B2 inspector via a dot_agent_api_contract binding to incomex-agent-api-executor (:8090/dispatch), the same mechanism the KG EXPLAIN pilot uses (DOT_KG_EXPLAIN). The executor exists, is healthy, and has been Up 13 days, but is not bound to any birth DOT today.
LEGO boundary fit (strong, governance-aligned). A contract-bound dispatch is the most observable and Điều-32-promotable channel: the binding, the mode (DRY_RUN/REAL_RUN), and the dispatch records are all in-DB and governed. It aligns with Điều 35's "DOT is the gate" and Điều 32 §2.1's "no manual SQL / no curl bypass." The channel still stays inside B2 (the contract is unchanged whether dispatch is cron or agent-api).
LEGO boundary risk (low–medium). Two caveats: (a) the executor is shared infra — it also serves the KG lane — so a birth binding must not couple the birth lane to the KG lane (AC-7 stays intact because the contract is per-DOT, not a shared body); (b) it is currently fail-closed: master switches are OFF (execute_enabled/real_run_enabled=false, dry_run_only=true), and a contract promotion DRY_RUN→REAL_RUN is itself Owner-gated. CAV-5 applies to any GUC/switch claim.
Evidence needed before TD. (a) A dot_agent_api_contract row binding the inspector DOT to :8090; (b) the master-switch state (must be intentionally flipped, Owner-gated, before REAL_RUN); (c) dispatch records + per-run S7 evidence; (d) proof the binding does not entangle the KG-lane contract.
Owner gate. Điều 32 + S2 owner + a contract promotion DRY_RUN→REAL_RUN (a distinct Owner gate of its own).
Rollback unit. Unbind or disable the contract (return to DRY_RUN); one producer run is the rollback unit (S8). The executor itself is untouched.
Residual. FUTURE_TECHNICAL_DESIGN_REQUIRED for the contract shape, dispatch payload, and master-switch sequence — not written here.
8. pg_cron analysis
Possible role. An in-database scheduler (pg_cron) that runs the inspector pass on a schedule, transactional with the inspect_* writes.
LEGO boundary fit (clean for atomicity, heavy for infra). Because pg_cron runs in-DB, the inspector pass and its inspect_* writes can share a transaction — attractive for per-stage atomicity. But pg_cron is NOT installed (pg_extension shows only btree_gist, pgcrypto, plpgsql, postgres_fdw), so choosing it means a net-new extension install — an infrastructure change with a larger blast radius than a cron entry or a contract row.
LEGO boundary risk (medium–high). The extension install is a privileged infra action outside the block, with its own failure and rollback surface. It is heavier than the two candidate channels precisely because it adds a dependency that does not exist today (Assembly First disfavors standing up new infra when an existing channel suffices).
Evidence needed before TD. (a) An infra decision + approval to install pg_cron; (b) the cron.job catalog entry bound to the inspector; (c) per-run S7 evidence; (d) a tested extension-removal/rollback path.
Owner gate. Điều 32 + a separate infra / extension-install approval.
Rollback unit. Unschedule the job (bounded); extension removal is an infra-level rollback (heavier, separate).
Disposition. risky / future-gated — not rejected, but deprioritized relative to host cron / agent-api because of the net-new extension dependency. FUTURE_TECHNICAL_DESIGN_REQUIRED; no install authorized or planned here.
9. job_queue worker analysis
Possible role. Enqueue inspection jobs into job_queue, drained by a worker that runs the inspector pass.
LEGO boundary fit (decoupled, but on a dead substrate). A queue+worker decouples scheduling from execution cleanly. But the queue substrate is disabled/idle: queue.worker.enabled=false, queue.job_substrate.enabled=false, no queue_heartbeat tick since 2026-05-26.
LEGO boundary risk (high — a failure mode already observed here). The "queue that nobody drains" failure mode is not hypothetical in this substrate: event_outbox already grows to ~215,588 rows undrained. Choosing a queue channel for B2 risks reproducing exactly that pattern — inspection jobs piling up with no live drainer — which would leave the producer silently starved (the very condition R2 is trying to fix).
Evidence needed before TD. (a) The worker + job substrate enabled and proven to drain (a live heartbeat, not a config flag); (b) job_queue rows consumed end-to-end on a sample; (c) per-run S7 evidence; (d) an explicit guard against the undrained-queue failure mode.
Owner gate. Điều 32 + enabling the worker / flipping the master switch (queue.worker.enabled / queue.job_substrate.enabled).
Rollback unit. Disable the worker; drain/purge the queue; one producer run (S8).
Disposition. risky / future-gated — not rejected, but the idle/undrained substrate makes it the least-ready standing channel today. FUTURE_TECHNICAL_DESIGN_REQUIRED; no worker enabled here.
10. Manual one-shot analysis
What it was (carried, R2a §7). The 2026-03-21 06:00–08:00 certification was an operator-run S157-A bootstrap: dot-birth-backfill (+ an s157b seed) executed via SSH + docker exec → psql, stamping all three inspect_* and certified=true directly in the INSERT (… 'backfill:dot-birth-backfill', true, now(), now(), now(), now() … ON CONFLICT (entity_code) DO NOTHING).
Why it is rejected as a standing channel.
- Not a standing producer — it cannot be scheduled, tested in isolation, replaced, or rolled back as a block; it ran once and never recurred by construction.
- Violates Điều 32 §2.1 — manual SQL via SSH +
docker execis exactly "insert SQL tay / curl bypass," explicitly forbidden ("mọi approval request phải được tạo qua DOT hợp pháp"). - It is the vehicle of the fused INSERT — the anti-pattern B2-AC-5/AC-6 reject (faked
inspect_*=now()+ fused B1+B2+B3+B4).
The single legitimate residual one-shot. A bounded, Owner-approved one-time historical backlog pass is B5, a separate block — it runs once over the 1.21M historical uncertified rows through the same fail-closed B3 contract and Điều 0-G rules (never the fused shortcut). B5 is a dependency boundary, not part of B2's channel decision — this packet does not open B5 (see §16). Reading the residual one-shot as "manual one-shot is fine after all" is the SCOPE_CREEP error and is rejected.
Disposition. reject as a standing channel for B2.
11. LEGO replaceability comparison
The LEGO test for a channel: can B2 be deleted and rebuilt on a different channel without touching B1, B3, B4, or any shared surface, with the B3 inspect_* contract invariant across the swap?
| Channel | Swappable without touching the contract? | Blast radius of choosing it | Blast radius of replacing it later | Replaceability verdict |
|---|---|---|---|---|
| host cron | Yes — a cron entry is external and removable | Lowest (one crontab line) | Lowest (remove the line, wire another channel) | Best replaceability |
| agent-api executor | Yes — a contract row is external and unbindable | Low (one contract row; shared executor untouched) | Low (unbind, return to DRY_RUN, wire another channel) | Strong replaceability (most observable) |
| pg_cron | Yes for the job; the extension is sticky | Medium–high (net-new extension) | Medium (unschedule job easy; extension removal heavier) | Good for the job, heavier for the dependency |
| job_queue worker | Yes — worker/queue are external | High (idle substrate to revive) | Medium (disable worker; purge queue) | Decoupled but substrate-fragile |
| manual one-shot | No — not a standing artifact to swap | n/a (anti-pattern) | n/a | Not replaceable (disqualified) |
Conclusion (replaceability lens only, not a selection). host cron preserves LEGO replaceability best (smallest external artifact, lowest swap cost), with agent-api executor close behind and more observable. Both keep the channel a true replaceable internal. pg_cron and job_queue worker are swappable in principle but add a heavier or fragile dependency; manual one-shot is not a replaceable block at all. This is a replaceability comparison, not a channel choice.
12. Evidence and observability comparison
What each channel can prove about itself, bounded by the tool-boundary caveats (CAV-3/CAV-4: no crontab -l/systemctl/docker exec; logs tail-only; /opt/incomex/dot/bin + env unreadable).
| Channel | "Is it installed?" provable via | "Did it run?" provable via | In-transaction with inspect_*? |
Observability strength |
|---|---|---|---|---|
| host cron | wf_host_crontab_snapshot (DB-captured; not live crontab -l) |
per-run S7 evidence + snapshot | No | Medium (indirect) |
| agent-api executor | dot_agent_api_contract row + master-switch state |
dispatch records + S7 evidence | No (dispatch is out-of-band) | Strong (governed, in-DB contract) |
| pg_cron | pg_extension + cron.job catalog |
cron.job_run_details + S7 |
Yes (in-DB) | Strong (in-DB) |
| job_queue worker | dot_config switches + worker heartbeat |
job_queue rows + heartbeat + S7 |
No | Medium (and currently dead) |
| manual one-shot | nothing standing | ad hoc only | (was in-INSERT — the anti-pattern) | None |
Shared evidence floor (all channels). Regardless of channel, B2 must append the same S7 run-evidence — rows scanned/passed/failed per stage, runner id, channel id, rule-set version/hash, run start/end, and per-failure audit records. S7 records; it does not decide (no channel's evidence may act as an approval or certify signal). The channel id in S7 is what makes a later channel swap auditable.
13. Rollback / delete comparison
The rollback unit for every channel is one producer run (S8 discipline); the channels differ only in how the invocation is undone. No rollback script, DELETE/UPDATE sequence, or command list is written here (B2-AC-9 / RP-AC-8).
| Channel | Undo the invocation by | Undo one producer run by | Downstream-certify caveat |
|---|---|---|---|
| host cron | Remove the cron entry | (S8 per-run rollback unit; mechanism is FUTURE_TECHNICAL_DESIGN_REQUIRED) |
If a run completes all three inspect_* on a row, B4 independently auto-certifies — outside B2 |
| agent-api executor | Unbind / disable the contract (→ DRY_RUN) | (same S8 unit) | same |
| pg_cron | Unschedule the job (extension removal = infra) | (same S8 unit) | same |
| job_queue worker | Disable the worker; drain/purge the queue | (same S8 unit) | same |
| manual one-shot | (no clean undo — disqualifying) | (no clean per-run boundary) | the fused INSERT certified directly — unrollbackable block-by-block |
The downstream-certify subtlety (carried, not resolved). Because completing all three inspect_* on a row legitimately triggers B4's independent auto-certify, the rollback of "one producer run" has a downstream effect (a triggered certified=true) that lies outside B2 — identical across all channels. Whether/how to unwind a triggered certify is FUTURE_TECHNICAL_DESIGN_REQUIRED and Owner-gated. HOLD-2 is OPEN: there is no atomic end-to-end birth-certify promote transaction today. No channel choice resolves HOLD-2.
14. Owner-gated future work
Every action below is forbidden now (OWNER_GATE_REQUIRED). Listing is scoping, not authorization.
| Future write | Gate required | Forbidden now? |
|---|---|---|
| Select the B2 invocation channel | Owner decision (after this comparison) | Yes |
| Wire host cron for the inspector | Điều 32 + S2 owner | Yes |
Bind/promote the agent-api contract (DRY_RUN→REAL_RUN) |
Điều 32 + S2 + contract promotion | Yes |
| Install pg_cron (extension) | Điều 32 + infra/extension approval | Yes |
| Enable the job_queue worker / master switch | Điều 32 + master-switch flip | Yes |
| Run any chosen channel against live rows | Điều 32 + standing B2 producer | Yes |
| Assign the birth-producer governance owner (S2) | Điều 37 → Điều 32 | Yes |
Confirm transient app.birth_gate_mode/app.bypass_birth_gate (CAV-5) |
Owner out-of-band — read-only, not a runtime write | Yes (not done here) |
15. Recommendation-only summary
RECOMMENDATION_ONLY — NOT AUTHORITY — OWNER_GATE_REQUIRED — FUTURE_TECHNICAL_DESIGN_REQUIRED.
| Channel | Disposition | Authority status |
|---|---|---|
| host cron | candidate — lowest blast radius; the proven channel for the sibling scanner DOTs; matches the inspector's periodic-scan nature; best LEGO replaceability | Not selected |
agent-api executor (:8090) |
candidate — existing healthy runner; contract-bound and most observable / Điều-32-promotable; gated by master switch + DRY_RUN→REAL_RUN promotion |
Not selected |
| pg_cron | risky / future-gated — clean in-DB atomicity but a net-new extension install (not installed today) → higher infra blast radius | Not selected |
| job_queue worker | risky / future-gated — decoupled, but the substrate is disabled/idle and the undrained-queue failure mode is already present in this system | Not selected |
| manual one-shot | reject as a standing channel — not testable/replaceable/rollbackable; violates Điều 32 §2.1; is the fused-INSERT vehicle (the only legitimate residual one-shot is B5, a separate Owner-gated backlog pass) | Rejected as standing channel |
If the Owner later opens B2's technical design, the two viable standing candidates are host cron (lowest blast radius / Assembly First) and the agent-api executor (most governance-aligned and observable). This is a comparison for a later Owner decision; no channel is selected here, and whichever is chosen must remain inside B2 so the contract is unaffected (B2-AC-7). Selecting a channel here would be CHANNEL_AUTHORITY_DRIFT and is refused.
16. What remains unresolved
- CHANNEL not selected (by design). The Owner decision among the candidates is deliberately not made here; this packet only classifies.
FUTURE_TECHNICAL_DESIGN_REQUIREDfor any chosen channel's build. - Substrate currently fail-closed. Master switches OFF, queue idle, no birth cron, pg_cron absent — every standing channel that uses the runner/queue substrate is presently disabled and would require an Owner-gated enable.
- SOURCE_RECOVERY_REQUIRED — Điều 0-G rule-set. The PEN/STAMP/GATE check definitions the chosen channel must invoke live in
architecture/birth-registry-law.md(a temporary working source; the Constitution referencelaw-00g-birth.mdis broken). Authoritative re-establishment is Owner-controlled and out-of-band (external S6). - CAV-3 / CAV-4 / CAV-5 carried. Channel liveness is provable only via DB-captured snapshots (no
crontab -l/systemctl/docker exectool;/opt/incomex/dot/bin+ env unreadable); the transient GUC layer is unreadable. No overclaim is made about any channel's live state. - B5 / B7 remain dependencies only, not opened. The one-time backlog pass (B5) and the warn→block GUC policy (B7) are referenced as dependency boundaries; their designs are not opened here (SCOPE_CREEP guarded).
- HOLD-2 OPEN — no atomic end-to-end birth-certify promote transaction today; no channel resolves it.
- Blockers — all OPEN, none resolved: CONS-002, CONS-003, CELL-003/004/007, HOLD-1, HOLD-2, RISK-BYPASS, GOV-016/017, GOV-REUSE-001, Điều 39 runtime-EMPTY (2199 edges / 0 provenance), Điều 35 production-readiness FAIL.
- FUTURE_TECHNICAL_DESIGN_REQUIRED (explicitly NOT written here): any scheduler/runner/cron implementation, contract shape, dispatch payload, command sequence, extension-install plan, worker-enable plan, or rollback script.
17. Ready for GPT/Codex review
Yes.
Core rule, kept above all detail: the B2 invocation channel is a replaceable internal, not the block boundary; B2's contract (read uncertified → write inspect_* only, fail-closed) is channel-independent. This packet compares host cron, agent-api executor, pg_cron, job_queue worker, and manual one-shot, and classifies them — host cron / agent-api = candidates, pg_cron / job_queue = risky-future-gated, manual one-shot = rejected-as-standing — without selecting any as authority.
Default disposition: HOLD. Engineering PASS = a complete, fair channel comparison; it is not an Owner authorization to select a channel, install, promote, enable, or build. No PASS authorizes writes. All blockers remain OPEN.