KB-2D56

Operator Runbook — C1 Governed Dry-Run Enablement (DOT-100%, capability-first) 2026-06-22

16 min read Revision 1
dot-managec1-dryrunoperator-runbookregistrargovernedcapability-first

Operator Runbook — C1 Governed Dry-Run Enablement

Macro: GOVERNED_C1_DRYRUN_READINESS_CAPABILITY_FIRST Date: 2026-06-22 Status: C1_DRYRUN_HOLD_REGISTRAR_EXECUTION_CHANNEL_MISSING → operator action required Audience: operator with VPS shell + deploy/CI access to the on-deploy DOT registrar REGISTRATION_HOLD · CAN_PROCEED=NO until this runbook is executed · 0 governed mutations performed by agent


0. Why this runbook exists (the single blocker)

The agent (Claude) has no lawful execution channel to run the governed registrar from its environment: query_pg is read-only, the Docker socket is mounted read-only (no docker exec), write_file is docs-only, directus_create is items-only + allowlist-denied for governance collections, and none of the 100 Directus flows is a triggerable registrar (every [DOT-REG] … -> AD flow is an event-triggered CDC sync to Agent Data, downstream of registration — not a creator).

The governed registrar DOT-REGISTER (dot-dot-register) is trigger=on-deploy and must be invoked from a host with deploy/shell access. That host is you, the operator. Secret Manager works and admin credentials exist — credentials are not the blocker; the execution channel is.

HARD LOCK — DOT 100% (applies to every step below)

  • Every governed action (birth, governance, registration, registry/catalog/handbook update, schema/collection/ function change, grant/ownership, dry-run authorization) must go through DOT or a DOT-approved deploy/registrar path.
  • No manual governed SQL DDL/DML. No manual Directus schema/collection edit. No manual dot_tools / dot_agent_api_contract / table_registry / meta_catalog row insert. Any of these = REJECT, not progress.
  • Secret Manager credentials are keys to operate the lawful DOT path only — never a license to bypass DOT.
  • The DB enforces this independently: iu_create.gateway block-after-guard, canonical-writer marker, fn_assert_safe_for_dot_action, fn_birth_gate guard-block manual writes even with a PG-superuser.

1. Verified starting state (live, 2026-06-22 — re-verify before you start)

Surface Value Source
Postgres schemas (directus db) information_schema, iu_core, pg_catalog, publicno c1 query_pg
governance_canonical_operation_vocab table absent (0) query_pg
dot_tools total / C1-like 309 / 0 query_pg
dot_agent_api_contract 2 = DOT_KG_EXPLAIN, DOT_KG_EXPLAIN_VERIFY; C1 = 0 query_pg
DOT-REGISTER (dot-dot-register) present, trigger=on-deploy, file_path=bin/dot/dot-dot-register.ts, last_executed=NULL dot_tools
Executor incomex-agent-api-executor Up (healthy), :8090, serves DOT_KG only list_docker + contract endpoint_ref
Secret Manager / gcloud PRESENT, project github-chatgpt-ggcloud gcloud

Registrar-family DOTs already registered (REUSE AS-IS — do not recreate):

DOT code name file_path role in this runbook
DOT-REGISTER dot-dot-register bin/dot/dot-dot-register.ts umbrella on-deploy registrar
DOT_SCHEMA_ENSURE dot-schema-ensure opt/incomex/dot/bin/dot-schema-ensure create/ensure c1 schema + vocab table
DOT_SCHEMA_TABLE_REGISTRY_ENSURE dot-schema-table-registry-ensure opt/incomex/dot/bin/dot-schema-table-registry-ensure register table in table_registry
DOT_COLLECTION_REGISTER dot-collection-register opt/incomex/dot/bin/dot-collection-register register Directus collection metadata
DOT_COLLECTION_CREATE dot-collection-create opt/incomex/dot/bin/dot-collection-create create Directus collection (if needed)
DOT_SCHEMA_META_CATALOG_ENSURE dot-schema-meta-catalog-ensure opt/incomex/dot/bin/dot-schema-meta-catalog-ensure CAT-006 meta_catalog ensure
DOT-015 dot-catalog-sync bin/dot/dot-catalog-sync catalog sync after registration

Deployed paths resolve under /opt/incomex/dot/bin/...; repo paths under <repo-root>/bin/dot/.... Exact CLI flags are not visible to the agent (the scripts are TS/bin outside its read allowlist). Confirm each invocation with --help / --dry-run at the shell before running for real. The DOT codes, paths, trigger types, and contract shape below are live-verified; the flag spellings are the one thing you must confirm.


2. Execution sequence (all through DOT / on-deploy registrar)

Run from the deploy host. Authenticate to Secret Manager first; never echo secret values.

# Secrets are keys to the lawful path only. Export into env for the registrar; do not print.
export DIRECTUS_ADMIN_TOKEN="$(gcloud secrets versions access latest --secret=DIRECTUS_ADMIN_TOKEN --project=github-chatgpt-ggcloud)"
export PG_PASSWORD="$(gcloud secrets versions access latest --secret=PG_PASSWORD --project=github-chatgpt-ggcloud)"
# (plus POSTGRES_* / MCP_* as the registrar requires — confirm names with: gcloud secrets list --project=github-chatgpt-ggcloud)

Step 1 — Run the governed registrar (umbrella)

# DOT-REGISTER / dot-dot-register — on-deploy registrar. Confirm flags with --help first.
cd <repo-root>
node bin/dot/dot-dot-register.ts --help        # confirm the real interface
node bin/dot/dot-dot-register.ts --dry-run      # preview what it will register (no writes)
node bin/dot/dot-dot-register.ts                # governed registration pass

This is the only authorized entry point. Everything in Steps 2–5 is invoked through the registrar or the registered DOT bins it dispatches — not by hand.

Step 2 — Create + register the C1 surface (governance_canonical_operation_vocab)

Invoke the reuse-as-is ensure/register family via the registrar (or directly via the DOT bins if the registrar delegates). Confirm flags with --help.

# 2a. Ensure schema c1 + the vocab table (composite PK (operation_code, protocol_version) + write-once trigger)
/opt/incomex/dot/bin/dot-schema-ensure        --schema c1 --object governance_canonical_operation_vocab   # confirm flags

# 2b. Register the table in table_registry (DOT-only registry write)
/opt/incomex/dot/bin/dot-schema-table-registry-ensure --schema c1 --table governance_canonical_operation_vocab

# 2c. Register the Directus collection metadata for the vocab table
/opt/incomex/dot/bin/dot-collection-register  --collection governance_canonical_operation_vocab
#     (use dot-collection-create first if the collection does not yet exist)

Vocab table contract (from the proven sandbox schema): composite PK (operation_code, protocol_version), write-once trigger blocking semantic rewrite, audit column(s). Field definitions come from the C1 schema DOT spec, not hand-written DDL.

Step 3 — Deploy the C1 no-mutation endpoint on the executor

The DB dispatcher (fn_process_agent_api_dispatch) refuses DRY_RUN when endpoint_ref is NULL and refuses REAL_RUN unconditionally (gates execute_enabled=false, real_run_enabled=false, dry_run_only=true). For a governed C1 dry-run the executor must answer a no-mutation C1 route at the same endpoint the KG contract uses.

# Extend the agent-api-executor image to handle the C1 vocab build/verify op at /dispatch (no-mutation, read-only).
# Mirror the existing DOT_KG_EXPLAIN handler. Then redeploy:
docker compose -f <deploy-compose> up -d --build incomex-agent-api-executor
# Health:
curl -fsS http://incomex-agent-api-executor:8090/health   # or the route used for KG

Target endpoint_ref for the C1 producer contract: http://incomex-agent-api-executor:8090/dispatch (identical host:port as DOT_KG_EXPLAIN; the route discriminates by DOT code/operation).

Step 4 — Register DOT_C1_VOCAB_BUILD / DOT_C1_VOCAB_VERIFY (born → governed → registered → cataloged → ledgered)

These are new DOTs, so they must traverse the full lifecycle (see §4). Registration is performed only by the registrar — never by manual row insert. The contract rows must clone the live DOT_KG_EXPLAIN pair shape:

dot_agent_api_contract producer/verifier shape to reproduce for C1:

DOT_C1_VOCAB_BUILD   (producer): operation=build,  role=producer, paired_dot=DOT_C1_VOCAB_VERIFY,
                                 mode=DRY_RUN,  output_namespace=DRYRUN-NS:dot:c1:vocab,
                                 no_mutation_assertion=true,
                                 endpoint_ref=http://incomex-agent-api-executor:8090/dispatch,
                                 error_behavior=fail_closed_no_mutation,
                                 observation_write_policy=SIMULATED_DRY_RUN_ONLY_UNTIL_ENDPOINT,
                                 contract_status=endpoint_bound
DOT_C1_VOCAB_VERIFY  (verifier): operation=verify, role=verifier, paired_dot=DOT_C1_VOCAB_BUILD,
                                 mode=VERIFY_ONLY, output_namespace=DRYRUN-NS:dot:c1:vocab,
                                 no_mutation_assertion=true, endpoint_ref=NULL,
                                 error_behavior=fail_closed_no_mutation,
                                 observation_write_policy=SIMULATED_DRY_RUN_ONLY_UNTIL_ENDPOINT,
                                 contract_status=contract_ready

Then update the registries through DOT bins only:

node bin/dot/dot-dot-register.ts            # registers DOT_C1_* into dot_tools (CAT-006 category) + contract
/opt/incomex/dot/bin/dot-schema-meta-catalog-ensure   # CAT-006 meta_catalog entry/status
node bin/dot/dot-catalog-sync               # DOT-015: sync catalog after registration

Step 5 — Mint the C1-scoped grant + ownership binding (governed)

A single-use, manifest-bound, plan-bound grant with expiry/revocation and rollback_plan_ref, plus an ownership row. Mint through the governed authorization path (the governance_build_authorization surface written by a DOT / Owner-gate path) — not a manual INSERT.

grant: scope=C1 only · single_use=true · manifest_ref=<sha256 from Step-6 dry-run manifest, cser-v1> ·
       plan_ref=<C1 build plan id> · status=active · expiry=<short> · rollback_plan_ref=<retire-not-delete> ·
       binds_to=DOT_C1_VOCAB_BUILD
ownership: object=c1.governance_canonical_operation_vocab · owner=<governance owner> · authority=DOT-bound

If no governed grant-minting DOT exists yet, do not hand-insert the grant — born one via §4, or use the Owner GATE governance-authorization path. The grant must reject: no-grant, generic grant, wrong-carrier, wrong-lane, wrong-plan, stale, expired, revoked, and already-consumed.


3. Gates — what you do NOT need to touch

  • The governed DRY_RUN does not require flipping execute_enabled / real_run_enabled. dry_run_only=true already permits a no-state dry-run once the contract is endpoint_bound. Leave the gates closed.
  • Do not open broad P2, adopt the current corpus, build C2–C7, or touch production. This runbook is C1-only, dry-run-readiness only.

4. Lifecycle obligation for the new DOT_C1_* (must be complete, in order)

Each new DOT_C1_* must show all of:

  1. Birth / khai sinh — created by a DOT (birth DOT), not hand-authored into the registry.
  2. Governance / admission — admission record + authority binding through the governed path.
  3. RegistrationDOT-REGISTER writes dot_tools + dot_agent_api_contract (endpoint-bound).
  4. Catalog / registry update — CAT-006 (meta_catalog) entry/status + dot-catalog-sync.
  5. DOT-manage handbook/ledger update — status addendum recorded as governed DOT-management evidence.
  6. Readback proof — re-query each surface and confirm the row exists with expected values.

No orphan DOT, no report-only DOT, no sandbox-only DOT treated as governed. Reuse frozen/forbidden legacy birth DOTs is prohibited (handbook §13 marks 3 birth DOTs FROZEN/MONITORED — do not reuse).


5. Post-run verification checklist (operator runs; then hand back to Claude)

Run these read-only checks (query_pg against db directus). All must pass before requesting Codex.

-- V1: c1 schema + vocab table exist
SELECT
  (SELECT count(*) FROM information_schema.schemata WHERE schema_name='c1')                                AS schema_c1,      -- expect 1
  (SELECT count(*) FROM information_schema.tables   WHERE table_schema='c1'
        AND table_name='governance_canonical_operation_vocab')                                             AS vocab_tbl;      -- expect 1

-- V2: composite PK + write-once enforcement present
SELECT conname, contype FROM pg_constraint
WHERE conrelid = 'c1.governance_canonical_operation_vocab'::regclass AND contype='p';                       -- expect PK on (operation_code, protocol_version)

-- V3: table_registry row registered
SELECT count(*) FROM public.table_registry WHERE table_name='governance_canonical_operation_vocab';         -- expect >=1

-- V4: DOT_C1_* in dot_tools (was 309/0)
SELECT code, name, category, coverage_status FROM public.dot_tools
WHERE code IN ('DOT_C1_VOCAB_BUILD','DOT_C1_VOCAB_VERIFY');                                                 -- expect 2 rows

-- V5: DOT_C1_* contracts bound (was 2 rows, KG only)
SELECT dot_code, role, mode, output_namespace, no_mutation_assertion, endpoint_ref, contract_status
FROM public.dot_agent_api_contract WHERE dot_code LIKE 'DOT_C1_%';                                          -- expect BUILD endpoint_bound, VERIFY contract_ready

-- V6: CAT-006 catalog entry
SELECT count(*) FROM public.meta_catalog WHERE code='CAT-006';                                              -- catalog present/updated

-- V7: grant + ownership exist, scoped + single-use
SELECT count(*) FROM public.governance_build_authorization
WHERE status='active' AND single_use=true;                                                                 -- expect 1 (C1-scoped)

Endpoint + route-level readiness (no mutation):

curl -fsS http://incomex-agent-api-executor:8090/health
# Route-level dry-run readiness is exercised by Claude via the DB dispatcher (PLAN_ONLY / write_obs=false),
# which must return validated:true, endpoint_present:true, true_dry_run_possible:true, 0 writes.

6. Hand-back: what Claude does after you finish

When V1–V7 pass and the endpoint is healthy, hand back. Claude will re-verify the full C1 readiness gate (non-mutating): C1 surface readback · DOT_C1 registry + contract readback · grant/ownership readback · preflight READY · route-level governed DRY_RUN readiness (dispatcher PLAN_ONLY, 0 writes) · bad-input fail-closed matrix (missing manifest, wrong hash, extra/missing value, duplicate op, wrong protocol_version, semantic rewrite, wrong carrier/lane/plan, no/generic/expired/revoked/reused grant, real-run attempt, production/C2 target, rollback-delete) · before/after diff · DOT-manage ledger readback · internal Codex-style negative review (A1–A18).

Only if every check passes does Claude propose verdict GOVERNED_C1_DRYRUN_READY_FOR_CODEX_FINAL_CONFIRMATION and recommend sending to Codex. If any check fails, Claude reports the precise HOLD/REJECT — never a READY overclaim. The final governed C1 dry-run itself stays gated behind explicit Owner authorization after Codex confirms.


7. Self-check (DOT 100% coverage)

Birth ✔ governance ✔ registration ✔ registry/catalog/handbook ✔ schema ✔ Directus collection ✔ grant/ownership ✔ preflight ✔ dry-run readiness ✔ — all routed through DOT / on-deploy registrar; zero manual governed writes. If the operator cannot complete any step through a DOT/registrar path, stop at that step and report — do not substitute a manual write.

Companion to the standing HOLD record reports/governed-dot-c1-dryrun-p0-p6/; supersedes nothing, adds the executable operator path. No duplicate 16-file HOLD package was generated.

Back to Knowledge Hub knowledge/dev/laws-new/reports/governed-c1-dryrun-readiness-capability-first/operator-runbook-c1-governed-dryrun-enablement-2026-06-22.md