Incogni: provider-declared attribution markers — one ScrubPatterns declaration feeding hook AND body sanitizer, unioned across providers #75
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#75
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Two incogni enforcement points exist for AI-attribution markers, but only one is provider-declared (ADR-0012, ADR-0026 / issue #51 decision 8):
SeedMeta.ScrubPatterns(internal/seeder/hook.go) — already generalized.sanitizeBody→attributionLine,internal/agentapi/handlers.go:929) still hardcodes Claude shapes: aco-authored-by:trailer starting withclaudeor containinganthropic.com,claude-session:,generated with…claude.Under a Codex provider (#2), a
Co-authored-by: ChatGPT <…@openai.com>footer in a PR/issue/comment body would pass straight to the tracker on an incogni repo. #2's acceptance requires incogni parity and a grep-clean core, so this is a precursor — the same role #6 played for the DeepLinker seam.A second, related hole:
incogniSeedMeta(internal/reposvc/reposvc.go) renders the hook from the repo's resolved default provider only. With three-level provider selection (ADR-0030), a per-session provider override can push commits screened by the wrong provider's markers.Design
One declaration, two enforcement points, unioned.
SeedMeta.ScrubPatterns's contract: consumed by BOTH the pre-push hook (grep -iBRE in sh, as today) and the body sanitizer (compiled as case-insensitive Go regexps, applied per line). Patterns must stay in the BRE∩RE2 common dialect — claude-code's four already do ([[:space:]],[^>]*are valid in both). A test pins that every registered provider's patterns compile as Go regexps; the existing hook golden pins the sh side.sanitizeBodykeeps core's line-walk + seam-repair mechanism (stripAttribution— blank-collapse at removal seams, edge trims, code-fence blank runs untouched, non-incogni bodies byte-identical, runs afterensureCloses). Only the per-line predicate changes: a line is dropped when it matches ANY registered provider's compiled patterns.attributionLine's hardcoded logic is deleted.incogniSeedMetareturns the union of all registered providers' ScrubPatterns (and keeps SeededPathPatterns per the same union or repo default — decide in implementation; over-matching is safe for the message scan, path patterns may stay per-provider if union would over-reject). The hook install/reconcile paths pick this up unchanged.anthropic.comafter the trailer prefix; the hook pattern requires the bracketed email — reconcile the pattern set explicitly).Non-goals: no new interface method — a provider declares markers, core owns both mechanisms (seam-v2 idiom). If a future provider's attribution is not line-shaped, an optional capability (ADR-0017 pattern) can override the declarative path then; not built speculatively.
Acceptance
sanitizeBodystrips markers of EVERY registered provider on incogni repos; provider fakes prove it with a non-claude pattern set (no Codex account needed).internal/provider/claudecode(test-fixture literals exempt).Closes #Nuntouched, code-fence blank runs untouched, claude hook golden byte-identical (or deliberately re-pinned if the pattern set is reconciled).Design resolution from the provider-seam grill (2026-07-09), settling the question this issue left open: SeededPathPatterns are unioned across all registered providers too, same as ScrubPatterns — not kept per-provider.
Rationale: with per-session provider override (ADR-0030), a Codex session on a claude-default repo seeds that provider's files; a hook carrying only the repo-default provider's path patterns wouldn't block them if committed. False-reject risk is negligible because context-file names must be lab-owned/never-tracked by hard rule (#79). One symmetric rule, no per-repo conditionals, no hook reinstall on session-level override.
PR #81 validation — verdict: PASS
Ran the
/land-prflow against PR #81 (afk/75,feat(incogni): provider-declared attribution markers unioned across providers).Verification signal relied on: Forgejo CI combined status = success on head
43ad7d8— required checkci / nativegreen (runsgo test -tags ui ./..., SPA lint/format/test/build, golangci-lint). Theci-nixhermetic gate was correctly not triggered: it is path-gated to**/*.nix/flake.lock/go.mod/go.sum, and this diff touches none of them, so the native gate fully covers the diff's reach. Did not re-run — CI already vouches.Conventions: Conventional Commits title ✓. AFK contract ✓ —
Closes #75present and valid on branchafk/75.Diff review (23 files, +1120/-134) against issue #75 intent:
ScrubPatternsdeclaration → two enforcement points, unioned across all registered providers.NewRegistryprecomputesUnionScrubPatterns/UnionSeededPathPatterns/ScrubRegexpsand validates every provider's patterns compile as RE2 at boot (unenforceable marker set fails fast). ✓sanitizeBodynow drops any line matching the compiled union; hardcodedattributionLinedeleted;agentapi.Newtakes the compiled set, wired fromproviderReg.ScrubRegexps(). Seam-repair mechanics unchanged. ✓reposvc.incogniPatterns()screens the union (scrub + seeded-path) regardless of the session's provider — closes the ADR-0030 per-spawn-override hole. Per the 2026-07-09 grill comment, SeededPathPatterns are unioned too. ✓co-authored-by:.*<[^>]*@anthropic\.com>requires the bracketed email (narrows the old bareanthropic.commatch); claudecode patterns unchanged vsmain, so the pre-push hook golden stays byte-identical. Pinned by a new sanitize test case. ✓TestCoreAttributionNeutrality(Go twin of the SPA neutrality test) scans core string literals for attribution tokens outsideclaudecode/providertest. ✓Mergeability: merges cleanly into
origin/main(abed41d) — no conflicts.No blockers. Awaiting free-text merge confirmation.