fix(preflight): refine render_source_attribution regex + flip default (#209)#239
Merged
Merged
Conversation
…nt (#209) Plan B addresses #209: the v1 broad redaction regex (`\b[A-Z][a-z]+\b`) over-matches every capitalized lowercase token, including platform/tool names (Sprint, Linear, GitHub, etc.), breaking the agent's structural parsing of `source_ref`. Plan B replaces it with four POSITIONAL-cue patterns that require explicit cues (`· `, `, ` adjacent to a date, `^Speaker:\s`, `^From:\s`) to fire — context tokens never follow these cues by construction, so no allowlist is needed. After the refinement, flip the default in both: - context._DEFAULT_RENDER_ATTRIBUTION_MODE: "full" → "redacted" - setup_wizard YAML template: "render_source_attribution: full" → "redacted" Audit: round 1 VETO (2 binding: spec-drift on `_PLATFORM_TOKEN_ALLOWLIST` declared without consumer; test-failure on ambiguous test description) → round 2 PASS after dropping the allowlist (Path A: positional patterns are precise by construction) and rewriting the test to be unambiguously functional (invoke `_write_collaboration_config`, assert on rendered YAML). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l cues (#209) Replace the v1 broad name-redaction regex with four positional-cue patterns: - `(?<=· )[A-Z][a-z]+(?:[ \t]+[A-Z][a-z]+)*` — name after `· ` separator - `(?<=, )[A-Z][a-z]+(?:[ \t]+[A-Z][a-z]+)*(?=,?\s+\d{4}-\d{2}-\d{2})` — name before date - `(?<=^Speaker:\s)[A-Z][a-z]+(?:[ \t]+[A-Z][a-z]+)*` (re.MULTILINE) - `(?<=^From:\s)[A-Z][a-z]+(?:[ \t]+[A-Z][a-z]+)*` (re.MULTILINE) Names match only after explicit cues; context tokens (Sprint, Linear, GitHub, etc.) never follow these cues so they survive without an allowlist. Multi-word continuation uses `[ \t]+` (not `\s+`) to avoid swallowing text on subsequent lines through `\n`. Date pattern unchanged (`\b\d{4}-\d{2}-\d{2}\b` is correct). 10 new functional tests in `tests/test_preflight_attribution_redaction.py` covering the 4 positional cues, platform-token preservation, capitalized context-word preservation, no-attribution-shape passthrough, full + hidden mode regression locks, default-flip lock, and fresh-install YAML render. Updated 1 pre-existing test in `tests/test_preflight_render_source_attribution.py` to use the canonical attribution shape (`Sprint review · Brian, 2026-03-22`) since bare names without positional cues are no longer redacted by design. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Privacy-positive default flip per #200 audit finding A4. The deterministic gate (refined regex in handlers/preflight.py) is now precise enough to preserve agent structural parsing while redacting names and dates. Two sources-of-truth flip in lockstep: - context._DEFAULT_RENDER_ATTRIBUTION_MODE: "full" → "redacted" (loaded-code default when YAML is missing/malformed) - setup_wizard.py YAML template at line 1005: "render_source_attribution: full" → "render_source_attribution: redacted" (fresh-install default written to .bicameral/config.yaml) Banner print message updated to reflect the new default and reverse the opt-in direction (was "flip to redacted/hidden", now "flip to full/hidden"). Operators who relied on the verbatim default can opt back via `render_source_attribution: full` in `.bicameral/config.yaml`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
ruff format CI on PR #239 flagged context.py for reformatting. The default-flip comment line `_DEFAULT_RENDER_ATTRIBUTION_MODE = "redacted" # #209: ...` exceeded ruff's preferred line length and was wrapped. Pure formatter pass — no semantic changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Knapp-Kevin
added a commit
to Knapp-Kevin/bicameral-mcp
that referenced
this pull request
May 21, 2026
…icameralAI#225 + BicameralAI#226) Plan for the three compliance-posture stance declarations: - BicameralAI#220 / MCP-01: MCP host UX dependency (OWASP LLM-07) - BicameralAI#225 / NIST-RMF-01 + AI-ACT-02: prohibited-uses declaration - BicameralAI#226 / SOC2-02: availability stance (operator-run-only) All three bundle naturally because they share docs/policies/ + a single README cross-reference section. Pure-doc surface fully disjoint from in-flight code PRs (BicameralAI#237, BicameralAI#238, BicameralAI#239) — safe as a parallel PR. Audit: round 1 PASS (L1, doc-only). Doctrine interpretation locked: for markdown policy artifacts, the unit IS the document content; read_text() + assert "<commitment>" in content is genuine unit invocation per qor/references/doctrine-test-functionality.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #209. Refines the
render_source_attributionredaction regex from the v1 broad\b[A-Z][a-z]+\bto four POSITIONAL-cue patterns, then flips the default fromfulltoredacted(privacy-positive per #200 audit finding A4).Plan / Audit
plan-B-preflight-attribution-regex-209.md_PLATFORM_TOKEN_ALLOWLIST; ambiguous test description) → round 2 PASSWhat ships
handlers/preflight.py_NAME_PATTERNwith 4 positional-cue patterns:(?<=· )...,(?<=, )...(?=,?\s+\d{4}-\d{2}-\d{2}),(?<=^Speaker:\s)...,(?<=^From:\s).... Multi-word continuation uses[ \t]+(not\s+) to avoid line-spanningcontext.py:28_DEFAULT_RENDER_ATTRIBUTION_MODE = "redacted"(was"full")setup_wizard.py:1005render_source_attribution: redacted(wasfull)setup_wizard.py:972-974tests/test_preflight_attribution_redaction.pytests/test_preflight_render_source_attribution.pyWhy no platform-token allowlist
A curated allowlist (Sprint, Linear, GitHub, etc.) was considered as defense-in-depth. Rejected per round-1 audit finding 1: the positional-cue patterns require explicit cues to fire by construction. Context tokens like "Sprint" / "Linear" / "GitHub" appearing in
<context-words>position never follow these cues, so they survive without an allowlist. Tests directly verify this contract.Test plan
tests/test_preflight_attribution_redaction.py)ruff check+ruff format --checkcleanAcceptance per #209
redactedin both context.py default and setup_wizard fresh-install YAMLOWASP A04 positive contribution
Closes a fail-open privacy posture: the prior
fulldefault leaked names + dates verbatim to the agent's chat surface. The deterministic gate is in place; flipping the default is the privacy-positive move directed by #200 audit finding A4.🤖 Generated with Claude Code