KB-5D6D

19 — SB-1/SB-2 Rehearsal Plan & Results (author-mode, no live execution, 2026-06-01)

13 min read Revision 1
one-roof-governanceimplementation-indexsb-1sb-2rehearsalbegin-rollbackauthor-modeoperator-handoffadditivity-proofno-mutationstatement-timeoutentry-exitdesign-only2026-06-01

19 — SB-1 / SB-2 Rehearsal Plan & Results

Tier: rehearsal plan + static proof + read-only pre-flight; no live BEGIN..ROLLBACK was executed. Mutation footprint: read-only PG pre-flight + this KB doc; zero committed PG/Directus/Qdrant/Nuxt/law/approval mutation; no COMMIT, no DDL/DML run live. Evidence base: doc 18 (live read-only, 2026-06-01). Discipline source: house-law live-apply hard gate + prior-practice BEGIN..ROLLBACK conventions (statement_timeout, entry==exit, no idle txn).


0. Rehearsal posture — why live execution is NOT run in this macro

The mission permits a BEGIN..ROLLBACK rehearsal only if explicitly safe and fully rolled back, and is otherwise design-only / KB-docs-only. Live execution is deliberately not performed here, for four converging reasons:

  1. Channel reality. The only PG channel available to this agent is query_pg — AST-validated, READ ONLY role, no writes/DDL (doc 18 §0). It cannot run a write transaction even one that ends in ROLLBACK. A real rehearsal would require a write-capable psql (e.g. ssh contabo → docker exec postgres psql -U workflow_admin), which is not part of this design-only macro's channel.
  2. House-law Decision Bank §3.3. "If retention/deploy/mutation not approved, dry-run or author-mode only." No approval (C-1/C-2/H-1) exists; os_proposal_approvals=0 ⇒ COMMIT_FORBIDDEN.
  3. Trigger side-effects. Even a rolled-back rehearsal of SB-1 fires fn_birth_registry_auto + fn_description_birth_guard + fn_auto_label_provenance on apr_action_types (doc 18 §1.2); opening a write channel to a production DB to exercise these, purely for an optional rehearsal, exceeds what a substrate design needs.
  4. The rehearsal's purpose is already met statically. Its goal — prove additivity + reversibility + no-migration-risk — is established by the live read-only pre-flight (§1) + the static additivity proof (§4) + docs 16 §2 / 17 §7. The executable script is provided author-mode, paste-ready (§2–3) for the operator to run under the proper gate (§5).

This is OPERATOR_HANDOFF_MODE (house-law branch classification), not a skipped deliverable. Acceptance criterion #9 ("rehearsal safely completed or explicitly not needed") is met via this explicit posture.


1. Read-only pre-flight assertions (LIVE, executed 2026-06-01)

These are the assertions a rehearsal would check before any write; they were run read-only and all pass:

assertion query result verdict
SB-1 codes do not collide count(apr_action_types WHERE action_code IN (4 codes)) = 0 ✔ additive
SB-2 table absent to_regclass('governance_object_ownership') = null ✔ greenfield
SB-2 scope ref absent to_regclass('governance_responsibility_scope') = null ✔ greenfield
owner-agency FK targets present count(governance_registry WHERE code IN (COUNCIL,SIV,DOT,KG-SYS,NRM-SYS,MOUT)) = 6 ✔ FK valid
GOV-IU absent (OP-B) count(... code='GOV-IU') = 0 ✔ (IU owner deferred)
relations CHECK unchanged target chk_relations_*_type ∈ {law,agency} (unchanged) ✔ not widened
trigger inventory known apr_action_types: 4 triggers; governance_relations: 2; approval_requests: 6 (incl. quorum/auto-approve/block-unimplemented) ✔ accounted for

2. SB-1 rehearsal script (AUTHOR-MODE — paste-ready, do not run without C-2 + approval)

Registers the 4 action-types fail-closed (handler_ref='unimplemented'), asserts, and rolls back. Illustrative; codes/descriptions subject to C-2.

-- SB-1 vocabulary-registration rehearsal (ROLLBACK-only)
SET statement_timeout = '5s';
SET lock_timeout = '2s';
SET idle_in_transaction_session_timeout = '10s';
BEGIN;
  -- entry count
  SELECT count(*) AS entry_action_types FROM apr_action_types;            -- expect 6

  -- additive INSERTs (fail-closed: handler_ref='unimplemented' -> fn_apr_block_unimplemented_handler blocks any use)
  INSERT INTO apr_action_types (action_code, description, handler_ref, risk_level, status, _dot_origin) VALUES
    ('assign_governance_owner', 'Assign accountable owner for (governed object x scope) [SB-1/Đ37 §4.15-bis]', 'unimplemented', 'high', 'active', 'SB-1-DESIGN-T3'),
    ('grant_governance_exception', 'Grant 11-field governed exception [SB-1/M-DEF-6]', 'unimplemented', 'high', 'active', 'SB-1-DESIGN-T3'),
    ('delegate_authority', 'Time-boxed delegation of a responsibility scope [SB-1/C-5]', 'unimplemented', 'high', 'active', 'SB-1-DESIGN-T3'),
    ('assign_axis_owner', 'Assign accountable owner of an axis (governed object) [SB-1/M-DEF-8]', 'unimplemented', 'high', 'active', 'SB-1-DESIGN-T3');
  -- NB: fires fn_birth_registry_auto + fn_description_birth_guard + fn_auto_label_provenance per row

  -- assertions
  SELECT count(*) AS after_insert FROM apr_action_types;                  -- expect 10
  SELECT count(*) AS fail_closed FROM apr_action_types
    WHERE action_code IN ('assign_governance_owner','grant_governance_exception','delegate_authority','assign_axis_owner')
      AND handler_ref='unimplemented';                                    -- expect 4
  -- negative test: an APR using one of these must be blocked (do in a sub-test, expect RAISE 'Reserve-only')
ROLLBACK;
-- exit verification (separate connection / after rollback)
SELECT count(*) AS exit_action_types FROM apr_action_types;               -- expect 6 == entry
SELECT count(*) FROM pg_stat_activity WHERE state='idle in transaction';  -- expect 0

Expected outcome (when run live by operator): entry=6, after_insert=10, fail_closed=4, exit=6 (==entry), idle-in-txn=0. Proves: registration is additive (only +4 rows), reversible (ROLLBACK restores 6), and fail-closed (the 4 are inert until a real handler is set).


3. SB-2 rehearsal script (AUTHOR-MODE — paste-ready, do not run without C-1 + approval)

Creates the scope ref + ownership table + resolution views, asserts the 8 live edges are untouched, rolls back. Illustrative contract (not final DDL).

-- SB-2 ownership-substrate rehearsal (ROLLBACK-only)
SET statement_timeout = '5s'; SET lock_timeout = '2s'; SET idle_in_transaction_session_timeout = '10s';
BEGIN;
  -- entry counts (the live substrate we must NOT disturb)
  SELECT count(*) AS entry_relations FROM governance_relations;          -- expect 8
  SELECT count(*) AS entry_reg FROM governance_registry;                 -- expect 9

  -- additive scope reference (6 law-defined scopes)
  CREATE TABLE governance_responsibility_scope (
    scope_code text PRIMARY KEY,
    description text,
    default_owner_hint text REFERENCES governance_registry(code),
    status text NOT NULL DEFAULT 'active');
  INSERT INTO governance_responsibility_scope(scope_code, description, default_owner_hint) VALUES
    ('policy','Policy authority','GOV-COUNCIL'),('health','Health/integrity','GOV-SIV'),
    ('execution','DOT execution','GOV-DOT'),('render','Display/render','GOV-MOUT'),
    ('approval','Approval routing','GOV-COUNCIL'),('audit','Audit','GOV-SIV');

  -- additive ownership table (contract; see doc 17 §2)
  CREATE TABLE governance_object_ownership (
    id bigserial PRIMARY KEY,
    object_type text NOT NULL, object_ref text NOT NULL,
    scope text NOT NULL REFERENCES governance_responsibility_scope(scope_code),
    owner_kind text NOT NULL CHECK (owner_kind IN ('accountable','supporting','delegated','exception')),
    owner_gov_code text NOT NULL REFERENCES governance_registry(code),
    is_inherited_anchor boolean NOT NULL DEFAULT false,
    effective_from timestamptz NOT NULL DEFAULT now(), effective_to timestamptz,
    lifecycle_status text NOT NULL DEFAULT 'active' CHECK (lifecycle_status IN ('active','superseded','revoked','expired')),
    approval_ref text, audit_ref text, rollback_ref text,
    source_law_ref text, source_design_ref text, supersedes_id bigint REFERENCES governance_object_ownership(id),
    created_at timestamptz NOT NULL DEFAULT now(), created_by text, updated_at timestamptz, updated_by text);
  CREATE UNIQUE INDEX uq_gov_obj_accountable
    ON governance_object_ownership(object_type, object_ref, scope)
    WHERE owner_kind='accountable' AND lifecycle_status='active';

  -- resolution + gap views (contract sketch)
  CREATE VIEW v_object_effective_owner AS
    SELECT object_type, object_ref, scope, owner_gov_code, owner_kind
    FROM governance_object_ownership WHERE owner_kind='accountable' AND lifecycle_status='active';
  -- (full inheritance walk + v_object_owner_gap omitted for brevity; see doc 17 §4-5)

  -- smoke INSERT (one anchor) + uniqueness negative test
  INSERT INTO governance_object_ownership(object_type,object_ref,scope,owner_kind,owner_gov_code,is_inherited_anchor,approval_ref)
    VALUES ('pivot','registries-pivot','policy','accountable','GOV-COUNCIL',true,'APR-REHEARSAL');
  -- second accountable for same (object,scope) MUST fail the unique index (expect ERROR)

  -- INVARIANT: the live governance substrate is untouched
  SELECT count(*) AS exit_relations FROM governance_relations;           -- expect 8 == entry
ROLLBACK;
-- post-rollback (separate connection)
SELECT to_regclass('public.governance_object_ownership');                -- expect NULL
SELECT count(*) FROM governance_relations;                               -- expect 8
SELECT count(*) FROM pg_stat_activity WHERE state='idle in transaction'; -- expect 0

Expected outcome: entry_relations=8 == exit_relations=8 (live edges untouched); the second accountable insert ERRORs on uq_gov_obj_accountable (uniqueness proven); after ROLLBACK the table is gone (to_regclass=NULL), idle-in-txn=0. Proves additivity, owner-per-scope uniqueness, and no disturbance to governance_relations.


4. Static additivity / reversibility proof (independent of execution)

Even without running the scripts, additivity is proven from the live schema (doc 18) + the design:

  • SB-1: the only operation is INSERT … apr_action_types (4 rows) — no ALTER, no constraint change, no touch to other rows. action_code PK + the FK from approval_requests mean the new rows are isolated additions; nothing references them until an APR opts in. Reversible by DELETE WHERE _dot_origin='SB-1-DESIGN-T3' (or never-committed via ROLLBACK).
  • SB-2: the only operations are CREATE TABLE/CREATE VIEW/CREATE INDEX (greenfield, to_regclass=null) + optional seed INSERT. No ALTER on governance_relations/governance_registry; new FKs validate against existing parent rows (no-op on empty child). Reversible by DROP TABLE/VIEW.
  • No-migration-risk: the 8 agency→law edges, their 2 CHECKs, their UNIQUE, and their 2 triggers are not in any statement above. The set of objects the rehearsal mutates ∩ the set of live governance objects = (except the additive children).

5. Operator handoff — how to run the rehearsal safely (only under the gate)

When C-1/C-2 are ruled and the human approval phase (H-1) authorises a rehearsal:

  1. Channel: ssh contabodocker exec -it postgres psql -U workflow_admin -d directus (PG 16.13).
  2. Set statement_timeout='5s', lock_timeout='2s', idle_in_transaction_session_timeout='10s' first.
  3. Run §2 then §3 inside a single BEGIN … ROLLBACK each; capture entry/after/exit counts.
  4. Verify exit==entry, to_regclass(new table)=NULL post-rollback, and pg_stat_activity shows 0 idle in transaction.
  5. Take a pg_dump of apr_action_types, governance_relations, governance_registry before any committed apply (T11 only).
  6. Record the rehearsal log back into this package (append 19a-…), never as a COMMIT.

6. Acceptance

✔ Rehearsal plan complete (paste-ready §2–3); ✔ read-only pre-flight executed live and green (§1); ✔ static additivity + no-migration-risk proven (§4); ✔ live execution explicitly deferred with reason (§0) — satisfies acceptance #9 ("safely completed or explicitly not needed"); ✔ operator handoff defined (§5); ✔ zero committed mutation. Rehearsal verdict: PLAN-COMPLETE / LIVE-DEFERRED (OPERATOR_HANDOFF_MODE).

Back to Knowledge Hub knowledge/dev/reports/architecture/one-roof-governance-technical-addendum-and-implementation-index-2026-06-01/19-sb1-sb2-rehearsal-plan-and-results.md