feat(incogni): provider-declared attribution markers unioned across providers (ADR-0033) #81

Merged
dominik.polakovics merged 1 commit from afk/75 into main 2026-07-09 22:41:39 +02:00

One ScrubPatterns declaration, two enforcement points, unioned across all registered providers — per the design pinned in #75 and documented in ADR-0033.

What changed

  • provider: NewRegistry now validates every registered provider's ScrubPatterns compile as case-insensitive Go regexps (the BRE∩RE2 common dialect) — an unenforceable marker set fails at boot — and precomputes the cross-provider unions: UnionScrubPatterns(), UnionSeededPathPatterns(), ScrubRegexps(). New shared compiler provider.CompileScrubPatterns (the (?i) twin of the hook's grep -i).
  • agentapi: sanitizeBody now drops a line when it matches ANY compiled union pattern; the hardcoded attributionLine (claude shapes in core) is deleted. agentapi.New takes the compiled set, wired from providerReg.ScrubRegexps() in cmd/lab (nil registry → content-inert pass-through, like the hook). Seam-repair mechanics (blank-collapse, code-fence runs, non-incogni byte-identity, runs after ensureCloses) are unchanged and still pinned.
  • reposvc: incogniSeedMeta's per-repo effective-provider resolution is replaced by the registry union — the pre-push hook now screens every registered provider's scrub AND seeded-path patterns regardless of which provider a session ran, closing the ADR-0030 per-spawn-override hole. Empty registry degrades to a content-inert guard instead of erroring.
  • arch test: TestCoreAttributionNeutrality (Go twin of the SPA's providerNeutral.test.ts) scans all non-test core string literals for the attribution-marker tokens (anthropic, claude-session, co-authored-by, generated with) outside internal/provider/claudecode and providertest; no allowlist. Its first run caught the incogni seed-prompt sentence spelling Co-Authored-By — reworded to name the shapes generically.
  • Pattern-set reconciliation (deliberate): the sanitizer previously stripped a bare anthropic.com mention after a co-authored-by: prefix; the declared pattern requires the bracketed email (ADR-0012's stable discriminator). The declared set is adopted unchanged — the claude hook golden stays byte-identical — and the narrowed sanitizer coverage is pinned by a new test case.

Acceptance (issue #75)

  • sanitizeBody strips every registered provider's markers: proven with a codex-shaped fixture set and a claude+codex union test (internal/agentapi/sanitize_test.go), no Codex account needed.
  • Hook rejects any registered provider's markers regardless of the pushing session's provider: TestIncogniHookUnionsAllRegisteredProviders pins a repo whose own provider is codex-fake still carrying claude's patterns.
  • Core grep-clean: TestCoreAttributionNeutrality, 129 non-test files scanned, _test.go/testdata/claudecode/providertest exempt.
  • Invariants: non-incogni byte-identity, Closes #N untouched, code-fence blank runs untouched, TestPrePushHookScript_claudeGolden byte-identical — all green.
  • ADR: docs/adr/0033-provider-declared-attribution-markers.md; CONTEXT.md incogni entry updated.

go build ./..., go vet ./..., gofmt and the full go test ./... suite are green (golangci-lint unavailable in the sandbox; CI covers it).

Closes #75

One `ScrubPatterns` declaration, two enforcement points, unioned across all registered providers — per the design pinned in #75 and documented in **ADR-0033**. ## What changed - **provider**: `NewRegistry` now validates every registered provider's `ScrubPatterns` compile as case-insensitive Go regexps (the BRE∩RE2 common dialect) — an unenforceable marker set fails at boot — and precomputes the cross-provider unions: `UnionScrubPatterns()`, `UnionSeededPathPatterns()`, `ScrubRegexps()`. New shared compiler `provider.CompileScrubPatterns` (the `(?i)` twin of the hook's `grep -i`). - **agentapi**: `sanitizeBody` now drops a line when it matches ANY compiled union pattern; the hardcoded `attributionLine` (claude shapes in core) is deleted. `agentapi.New` takes the compiled set, wired from `providerReg.ScrubRegexps()` in `cmd/lab` (nil registry → content-inert pass-through, like the hook). Seam-repair mechanics (blank-collapse, code-fence runs, non-incogni byte-identity, runs after `ensureCloses`) are unchanged and still pinned. - **reposvc**: `incogniSeedMeta`'s per-repo effective-provider resolution is replaced by the registry union — the pre-push hook now screens every registered provider's scrub AND seeded-path patterns regardless of which provider a session ran, closing the ADR-0030 per-spawn-override hole. Empty registry degrades to a content-inert guard instead of erroring. - **arch test**: `TestCoreAttributionNeutrality` (Go twin of the SPA's `providerNeutral.test.ts`) scans all non-test core string literals for the attribution-marker tokens (`anthropic`, `claude-session`, `co-authored-by`, `generated with`) outside `internal/provider/claudecode` and `providertest`; no allowlist. Its first run caught the incogni seed-prompt sentence spelling `Co-Authored-By` — reworded to name the shapes generically. - **Pattern-set reconciliation (deliberate)**: the sanitizer previously stripped a bare `anthropic.com` mention after a `co-authored-by:` prefix; the declared pattern requires the bracketed email (ADR-0012's stable discriminator). The declared set is adopted unchanged — the claude hook golden stays **byte-identical** — and the narrowed sanitizer coverage is pinned by a new test case. ## Acceptance (issue #75) - `sanitizeBody` strips every registered provider's markers: proven with a codex-shaped fixture set and a claude+codex union test (`internal/agentapi/sanitize_test.go`), no Codex account needed. - Hook rejects any registered provider's markers regardless of the pushing session's provider: `TestIncogniHookUnionsAllRegisteredProviders` pins a repo whose own provider is codex-fake still carrying claude's patterns. - Core grep-clean: `TestCoreAttributionNeutrality`, 129 non-test files scanned, `_test.go`/testdata/claudecode/providertest exempt. - Invariants: non-incogni byte-identity, `Closes #N` untouched, code-fence blank runs untouched, `TestPrePushHookScript_claudeGolden` byte-identical — all green. - ADR: `docs/adr/0033-provider-declared-attribution-markers.md`; CONTEXT.md incogni entry updated. `go build ./...`, `go vet ./...`, `gofmt` and the full `go test ./...` suite are green (golangci-lint unavailable in the sandbox; CI covers it). Closes #75
feat(incogni): provider-declared attribution markers, unioned across providers (ADR-0033)
All checks were successful
ci / native (pull_request) Successful in 4m46s
43ad7d884d
One ScrubPatterns declaration now feeds BOTH incogni enforcement points
(issue #75), and both apply the union across every registered provider:

- provider: NewRegistry validates each provider's ScrubPatterns compile
  as case-insensitive Go regexps (the BRE∩RE2 common dialect) and caches
  the cross-provider unions (UnionScrubPatterns, UnionSeededPathPatterns,
  ScrubRegexps). CompileScrubPatterns is the shared (?i) compiler.
- agentapi: sanitizeBody's per-line predicate is the compiled union
  injected at wiring; the hardcoded attributionLine is deleted. Coverage
  is reconciled to the declared set: an unbracketed anthropic.com mention
  after a co-authored-by prefix is now kept (the bracketed email is the
  ADR-0012 discriminator) — pinned by a test case.
- reposvc: the pre-push hook renders the union of every registered
  provider's scrub + seeded-path patterns instead of resolving the repo's
  effective provider, closing the ADR-0030 per-session-override hole; an
  empty registry degrades to a content-inert guard instead of erroring.
- arch test: non-test core string literals must stay free of the
  attribution-marker tokens (anthropic, claude-session, co-authored-by,
  generated with) outside internal/provider/claudecode and providertest;
  the incogni seed-prompt sentence is reworded to name the shapes
  generically so core prose carries no marker token either.
- the claude pre-push hook golden stays byte-identical; non-incogni
  byte-identity, Closes-injection ordering, and code-fence blank-run
  invariants are unchanged and still pinned.

Closes #75

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWk5s2k1aaUosuBoUDfBkL
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab!81
No description provided.