Skip to content

feat(privacy): preflight render-attribution + bypass-tracking config knobs (#200 Phase 3)#208

Merged
Knapp-Kevin merged 2 commits into
devfrom
200-phase3-preflight-config
May 6, 2026
Merged

feat(privacy): preflight render-attribution + bypass-tracking config knobs (#200 Phase 3)#208
Knapp-Kevin merged 2 commits into
devfrom
200-phase3-preflight-config

Conversation

@Knapp-Kevin

Copy link
Copy Markdown
Collaborator

Phase 3 (PR C, FINAL) of plan-200-skills-audit-hardening. Closes the preflight A4 findings via two new deterministic config gates.

Deterministic gate #1render_source_attribution (.bicameral/config.yaml)

  • Modes: full (legacy verbatim), redacted (default — name + date placeholders), hidden (blank source_ref)
  • Server-side enforcement in handlers.preflight._apply_attribution_policy — agent receives pre-filtered output
  • Privacy-positive default: redacted strips personal-attribution detail while preserving structural shape

Deterministic gate #2preflight_bypass_tracking (.bicameral/config.yaml)

Config schema unification: context.py refactored to share a generic _read_yaml_string_field helper across all three Phase 2/3 readers (signer_email_fallback, render_source_attribution, preflight_bypass_tracking).

SKILL.md updates: telemetry transparency note added above HITL prompts; config-field docs inserted inline; preflight_bypass_tracking note appended to bypass-semantics list.

Refs #200 (A4 finding on preflight); refs BicameralAI/bicameral-daemon#34 (governance lift; this PR adopts max-deterministic-where-tractable).

10/10 Phase 2+3 tests pass; ruff/mypy/format clean. Final of three planned PRs from plan-200; plan-200-skills-audit-hardening fully closed when this lands.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Generated with Claude Code.

…knobs (#200 Phase 3)

Closes A4 of #200's preflight findings via two new deterministic config
gates that filter what data flows from server to agent / disk.

Deterministic gate #1 — render_source_attribution:
- New BicameralContext.render_source_attribution field (modes: full,
  redacted (default), hidden) read from .bicameral/config.yaml at
  config-load.
- New handlers.preflight._apply_attribution_policy applies the mode to
  DecisionMatch.source_ref before the response leaves the server. The
  agent receives pre-filtered output and renders verbatim.
  - full: legacy passthrough
  - redacted: replace `[A-Z][a-z]+` (names) with <NAME_REDACTED>,
    `\d{4}-\d{2}-\d{2}` (dates) with <DATE_REDACTED>; preserves
    structural shape so operator sees "<NAME_REDACTED> review ·
    <NAME_REDACTED>, <DATE_REDACTED>" instead of full attribution
  - hidden: blank source_ref entirely

Deterministic gate #2 — preflight_bypass_tracking:
- New BicameralContext.preflight_bypass_tracking field (modes: enabled
  (default), disabled).
- handlers.record_bypass.handle_record_bypass short-circuits BEFORE the
  preflight_telemetry.write_bypass_event call when ctx setting is
  disabled. Returns recorded=False, reason="tracking_disabled". When
  disabled, ~/.bicameral/preflight_events.jsonl gets no writes; engine's
  recency read sees no events → no escalation drop, which matches the
  user's privacy choice.

Config schema:
- context.py refactored to share a generic _read_yaml_string_field
  helper across the three Phase 2/3 config readers
  (signer_email_fallback, render_source_attribution,
  preflight_bypass_tracking). Each is a fail-soft string-with-valid-set
  read with documented privacy-positive defaults.
- setup_wizard.py writes both new fields to fresh .bicameral/config.yaml
  with their defaults.

SKILL.md updates:
- skills/bicameral-preflight/SKILL.md: telemetry transparency note
  added above HITL prompts; render_source_attribution doc inserted
  inline ("the deterministic gate is the config field, not this
  instruction"); preflight_bypass_tracking note appended to the
  bypass-semantics list.

Tests (5 new):
- tests/test_preflight_render_source_attribution.py: 3 tests for
  full/redacted/hidden modes against the pure helper.
- tests/test_preflight_bypass_tracking.py: 2 tests for enabled/disabled
  paths through the handler with monkeypatched preflight_telemetry.

10/10 Phase 2+3 tests pass; ruff/mypy/format clean.

Phase 3 of plan-200-skills-audit-hardening (PR C of three — completes
the plan). After merge, the queued workstream is the e2e security audit
across all #205 compliance standards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Knapp-Kevin Knapp-Kevin added flow:feature Standard feature/fix PR targeting BicameralAI/dev (the default flow) P1 High: ship this milestone; user-impacting bug or committed feature test Test infrastructure, fixtures, or coverage work feat Feature work or user-visible capability skill Skill instructions or workflow guidance surface labels May 6, 2026
@Knapp-Kevin Knapp-Kevin had a problem deploying to recording-approval May 6, 2026 07:11 — with GitHub Actions Failure
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 31266486-23c5-4ccd-bed2-5c74652c7fe9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 200-phase3-preflight-config

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…egex overbroad (#200 Phase 3 fixup)

The v1 redaction regex `re.compile(r'\b[A-Z][a-z]+\b')` replaces ALL
capitalized words, including meaningful structural tokens like "Sprint",
"Linear", "Slack", "Notion". Result on e2e Flow 3: agent loses
source_ref parseability and the downstream binding+commit chain breaks
(post-hoc ledger query shows zero compliance_check rows; the agent
made only 1 bicameral call instead of the expected
preflight+link_commit chain).

The deterministic gate is still in place. Users who want privacy-
positive rendering can flip `render_source_attribution: redacted` or
`hidden` in `.bicameral/config.yaml`. The default flips to `redacted`
once the regex is refined to match only true name/date patterns
without stripping platform/tool tokens; tracked in #209.

Concrete example of the v1 overreach:
  Input:  "Sprint 14 architecture review · Ian, 2026-03-12"
  Output: "<NAME_REDACTED> 14 <NAME_REDACTED> <NAME_REDACTED> ·
           <NAME_REDACTED>, <DATE_REDACTED>"

The agent can't parse "what kind of source is this" from the redacted
form, so downstream reasoning fails. PR #208's commit added an
inline note in `context.py` explaining the v1 default tradeoff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Knapp-Kevin Knapp-Kevin had a problem deploying to recording-approval May 6, 2026 07:41 — with GitHub Actions Failure
@Knapp-Kevin Knapp-Kevin merged commit d5d6541 into dev May 6, 2026
7 of 8 checks passed
@Knapp-Kevin Knapp-Kevin deleted the 200-phase3-preflight-config branch May 6, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Feature work or user-visible capability flow:feature Standard feature/fix PR targeting BicameralAI/dev (the default flow) P1 High: ship this milestone; user-impacting bug or committed feature skill Skill instructions or workflow guidance surface test Test infrastructure, fixtures, or coverage work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant