Kashi · Folder 60 · Doctrine Sign-off

Communication Policy Console

The 18-prompt console is built. Three decisions need your explicit yes — here is each one, verified against the real code, with the honest caveats.

2026-06-11 · P01–P18 complete · PRs #486–#501 · prepared while you were away · every claim below was adversarially re-checked against the actual source (the audit deliberately tried to refute each safety claim, and ran the eval + tests on the real branches).

Everything waits on one thing: you

16 of the 18 pull requests are stacked DRAFTs that physically cannot merge until the 5 database tables exist — and creating them needs you to paste one SQL file into the Supabase dashboard. Nothing is live. Nothing auto-deploys. Your three sign-offs + one dashboard apply unblock the whole stack.

The three decisions at a glance

ItemWhat you're approvingWhose callMy read
P03
#486
The database schema — 5 new empty tables. This is the gate. you approve the SQL (PR needs a rebase first — see below)
P16
#499
The runtime-binding machinery + pre-blessing the future step that turns it on and changes the eval baseline once. you approve the layer; gate the future wiring on a signed eval diff
P17
#500
The emergency-pause kill-switch semantics (pause ≠ rollback/publish/delete). you approve the semantics; know the live wiring lands later

The other 13 PRs (P04–P15, P18) are ordinary build work and merge automatically once P03 lands — they don't need a separate sign-off.


P03 — The database schema

PR #486 · branch feat/f60-p03-db-migration · the gate

Adds one new SQL file that creates five empty tables for the console (policy history, audit log, simulator runs, worker-notice versions, emergency pauses). Until you paste it into Supabase, the codebase references tables that don't exist — so the whole stack is blocked on it.

Verified safe (read line-by-line + greps)

  • Genuinely additive. All 266 lines read; every destructive verb grepped. Zero DROP/TRUNCATE, zero edits to any existing table. The only ALTERs are "enable row-level security" on the new tables. A wrong approval cannot touch existing customer data.
  • Published policies are immutable — a database trigger blocks any rewrite of an active/retired snapshot, and blocks rolling an active policy back to draft.
  • Audit log is append-only — triggers hard-block edit and delete on the audit table for everyone, including admins.
  • One active + one draft per org enforced by the database itself (two partial unique indexes), not just app code.
  • Tenant isolation — every read/write is org-scoped; cross-org reads return "not found" with no existence leak. RLS dependencies (current_org_id, hr_compliance role, FK targets) all already exist on main.

Honest caveats the audit caught

  • The PR edits more than the migration. The migration file touches nothing existing — but the PR also makes small, additive, safety-tightening edits to ~7 existing files, including two sensitive ones: demo/analyze/route.ts (a comment only) and demo-display-model.ts (adds 3 forbidden-claim words — strengthens safety, doesn't loosen it). Safe, but worth knowing it's not only the schema.
  • "Enforced by the DB" is read-confirmed, not test-confirmed. The only automated test runs against an in-memory mock that mimics the rules — there is no live-Postgres test and zero automated RLS coverage on the 5 new tables. The SQL is correct on careful reading; if you want DB-level proof, the migration should be run against a real Postgres/RLS harness first.
  • The PR is currently conflicting with main. Because P01/P02 already merged separately, branch #486 carries an older copy of 6 P02 files that now clash. The schema SQL itself merges cleanly, but the PR can't merge until the stack is rebased. (I did not rebase 16 stacked branches unattended — see "what's still on you" at the bottom. It's not on the critical path: merge waits on your dashboard apply anyway.)

What only you can decide

  • The access model: admin + ceo can read and write everything; hr_compliance can read policy/audit/notices but cannot create or edit policies, simulator runs, or pauses. Is read-only-for-compliance what you want? (It's intentional in the code, but it's a real governance choice.)
  • That the 7-day pause max and the role split match your doctrine.

If you approve — the steps

  1. Skim supabase/migrations/0050_communication_policy_console.sql once — confirm you see only create / enable RLS, no drop/insert/backfill.
  2. Supabase dashboard (acaylar@keio.jp) → SQL Editor → New query → paste the entire 0050 file → Run. It's one transaction: it fully applies or fully rolls back.
  3. Table editor → confirm 5 new communication_policy_* tables, each with the green "RLS enabled" shield.
  4. Tell me — I'll resolve the stack rebase and start merging P04–P18 against the real tables.
My read: the schema content is safe to sign off on its merits. Approve the SQL after eyeballing the role split; the conflict + the "no live-DB test" are mine to handle, not blockers to your decision.

P16 — Runtime binding + the eval re-baseline

PR #499 · branch feat/f60-p16-runtime-binding · ⚠ sign-off

Builds the machinery to stamp every governed output with the policy that produced it, plus the database columns to store it — but deliberately does not turn it on inside the live demo yet. That's why the demo's output is provably unchanged today. Your sign-off pre-blesses the future step that wires it in and changes the eval baseline once.

Verified safe (the audit ran the eval on both branches)

  • Provably inert today. The audit ran tsx scripts/eval.ts on both the P15 and P16 branches → output byte-for-byte identical, both 3/3. The display model is unchanged; zero code anywhere imports the new modules (only the test does). Approving P16 cannot change what anyone sees today.
  • Conservative by construction: picks the most restrictive routing across every rule; weak evidence can't reach a review queue; missing/low-quality data grades to "blocked"/"insufficient" rather than overclaiming; every review surface carries "requires human review."
  • Never silently falls back to an unsafe/default policy — it throws if the active policy is missing or invalid.
  • Migration 0051 is additive — new nullable columns; existing rows default to legacy_unbound and are never falsely rebound; no backfill.
  • No identifying text rides along — the stored binding context carries no transcript / quote / name / speaker-id (test-checked).

Correction the audit forced

  • One detector can reach a review surface on its own. An earlier description said "no single detector can escalate a person to review" — that's wrong. Two detectors (floor_time_imbalance, agreement_asymmetry) cap below review at trend-monitoring, but intrusive_interruption caps at neutral_review, which is a review surface (the test asserts this). The accurate statement: those two cap below any review; intrusive_interruption caps at neutral review and can never independently reach the restricted review surface. Decide if that's the doctrine you intend — you're the owner.
  • Minor: the PR says "21 tests"; the real count is 20 (all pass). Harmless.

What only you can decide

  • This sign-off authorizes two things: (1) applying migration 0051 now, and (2) pre-blessing the later PR that actually wires binding into the demo and legitimately changes the eval baseline once.
  • Make the future wiring conditional: before that PR merges, demand a signed eval diff — old vs new output, every changed line explained, you agree it's intended — and a fresh 4-lens adversarial gate. This is the exact change-class that on 2026-06-06 passed green CI yet leaked transcript tokens and crashed the public render. That lesson is why this guardrail is non-optional.
My read: approve the layer + migration 0051 now (it's inert and safe). Approve the concept of the re-baseline, but make the actual wiring PR earn it with a signed eval diff + adversarial gate.

P17 — Emergency-pause kill-switch

PR #500 · branch feat/f60-p17-emergency-pause · ⚠ sign-off

A time-limited "pause" that temporarily suppresses selected policy surfaces (employee self-view, manager mirror, trend monitoring, review queues, external notifications) — without ever changing, rolling back, publishing, or deleting any policy, evidence, or history.

Verified safe — all 8 hard rules hold (audit ran 21/21)

  • No deletes, no policy mutation, no publish, no rollback. The audit grepped every destructive path: the pause code only ever touches its own table. Disabling a pause is a non-destructive UPDATE (status → disabled); the row is retained, never deleted (mutation-proven in tests).
  • Time-bounded: ≤ 7 days, must be in the future; a lapsed pause stops applying automatically (filtered at read time).
  • Admin/CEO only on both endpoints; hr_compliance sees read-only. Cross-org access returns "not found" (no leak).

Two honest gaps the audit insisted I surface

  • "Fully audited" overstates it. Both actions attempt an audit write, but the writer is best-effort: if the insert fails it logs a correlation id and the pause still proceeds (returns 200). So a pause can exist without a persisted audit row. Decide whether the kill-switch must be fail-closed ("no audit = no action") for sign-off, or whether best-effort + error-log is acceptable (a stronger same-transaction guarantee is a noted follow-up).
  • The pause doesn't actually withhold output yet. On this branch the pause is recorded, shown in the admin console, and the "suppress" overlay is computed — but no live employee/manager/external screen or analysis pipeline reads it to actually go dark. The withhold logic exists but is wired only into tests. Treat "suppresses surfaces" as intent + data today, not proven live behavior. The real enforcement turns on with the same future wiring step as P16 (see below) — so it's a sequencing question, not a defect.
My read: the semantics are safe to sign off — pause genuinely never mutates/deletes/publishes. Before you call it a working production kill-switch, settle the audit fail-closed question and know the "go dark" wiring lands with the P16 step.

The one thing the audit made obvious

P16 (binding) and P17 (pause) both ship the machinery now, but neither changes live behavior on its own. The demo is byte-identical; the pause doesn't yet darken any screen.

The live behavior for both turns on in one future "wiring" PR — the same step that changes the eval baseline. So the honest framing of your sign-off is: "approve the machinery now; the live effects switch on together, behind a signed eval diff + a fresh adversarial gate." That keeps the riskiest moment (payload-shaping) gated exactly where the 2026-06-06 lesson says it must be.

What's still on you (I can't do these)

I deliberately did not merge anything, deploy anything, or rebase the 16-branch stack unattended — none of it is on the critical path until you apply 0050, and a blind stack-rebase is exactly the kind of move that silently reverts work.


Built this session: P14 #497 · P15 #498 · P16 #499 · P17 #500 · P18 #501 — each with tsc 0, its own green suite, eval byte-identical.
F60 stack: P01 #484 ✓merged · P02 #485 ✓merged · P03 #486 … P18 #501 (16 DRAFTs).
Verification: 6-agent extract→adversarial-refute pass over the 3 sign-off items; the refuters ran the real eval + tests and tried to disprove every safety claim. Corrections above are theirs.
Docs: docs/communication-policy-console.md + …-test-plan.md (in the P18 PR).
Prepared by Claude · 2026-06-11 · for Justine.