Conversation
…ector lint backlog (Aaron 2026-04-28) Captures the recurring failure mode caught in PR #24 review: when stripping named attribution from code-surface text per Otto-279, the mechanical replacement `<Name> ferry-N` -> `courier-ferry-N absorb` leaves orphan role-refs that lose semantic weight. Better path: remove the attribution clause entirely OR replace with self-contained principle name. Two artifacts: - memory/feedback_orphan_role_ref_after_name_stripping_aaron_2026_04_28.md — the substrate capturing the pattern + detection regex sketch + composition with Otto-279 + Otto-357 + Otto-341 + prompt-protector - docs/backlog/P2/B-0070-orphan-role-ref-detector-lint-aaron-2026-04-28.md — backlog row for the structural fix (lint script under tools/hygiene/ wired into CI gate as soft-fail initially, same pattern as audit-memory-index-duplicates.sh) Aaron explicit: 'not sure if you can update to find things like that that don't make sense in the future like look for courrier-ferrrrry or whatever IDK just thinking out out for your future self and the review agentsd' Aaron's framing names BOTH future-self AND review agents as audiences for the lint — which matches how Copilot/Codex review threads on PR #24 caught the under-stripped versions, but missed the over-stripped (orphan) versions. The lint would catch BOTH directions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds substrate artifacts capturing the “orphan role-ref after name-stripping” failure mode and backlogs a lint to detect it on code-surface text.
Changes:
- Added a new memory entry documenting the orphan-role-ref pattern, examples, and mitigation discipline.
- Added a P2 backlog row (B-0070) describing a future hygiene lint (scope, regex candidates, and CI wiring intent).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| memory/feedback_orphan_role_ref_after_name_stripping_aaron_2026_04_28.md | Documents the failure mode and proposed detection approach for future prevention. |
| docs/backlog/P2/B-0070-orphan-role-ref-detector-lint-aaron-2026-04-28.md | Backlogs the structural fix: a hygiene lint to catch orphan ferry refs / unstripped attribution. |
| --- | ||
| id: B-0070 | ||
| priority: P2 | ||
| slug: orphan-role-ref-detector-lint | ||
| status: backlog | ||
| created: 2026-04-28 | ||
| maintainer: aaron | ||
| ownership: otto | ||
| title: Orphan role-ref detector lint — catch ferry-N without named source on code surfaces (Aaron 2026-04-28) | ||
| --- |
There was a problem hiding this comment.
P1: The YAML frontmatter here doesn’t match the documented per-row backlog schema in tools/backlog/README.md (e.g., status is documented as open/closed/superseded-by-*/deferred, and last_updated is marked required). Either adjust this row to the documented schema (add last_updated, use a documented status value), or update the schema docs/tooling in the same change-set so the repo has a single source of truth.
| Detector regex (initial): | ||
|
|
||
| ``` | ||
| # Orphan role-ref (no resolvable named source) | ||
| \bcourier-ferry-\d+\b | ||
| \bferry-\d+\b | ||
| \bferry-\d+'s?\b | ||
|
|
||
| # Un-stripped name attribution on code-surface | ||
| \b(Amara|Grok|Gemini|Codex|Cursor|Aaron|Otto)\s+ferry-\d+\b | ||
| \bPer\s+(Amara|Grok|Gemini|Codex|Cursor|Aaron|Otto)\s+2026- | ||
| ``` |
There was a problem hiding this comment.
P1 (shell portability): The proposed detector regexes use \b and \d, which aren’t POSIX ERE and won’t work with common grep -E/awk (notably on macOS). Since this row proposes implementing the lint as a bash script, specify an engine that supports these tokens (e.g., ripgrep PCRE2) or rewrite the patterns in portable ERE form (e.g., [0-9]+ and explicit boundary handling).
| `docs/pr-preservation/**`, `docs/pr-discussions/**`, commit | ||
| messages |
There was a problem hiding this comment.
P1 (xref / rule alignment): This list says docs/pr-discussions/** is a “history surface per Otto-279”, but docs/AGENT-BEST-PRACTICES.md’s Otto-279 history-surface list does not include docs/pr-discussions/** (it lists docs/pr-preservation/**). Either remove docs/pr-discussions/** from the “per Otto-279” claim, or update the cited rule so the surfaces list is consistent.
| `docs/pr-preservation/**`, `docs/pr-discussions/**`, commit | |
| messages | |
| `docs/pr-preservation/**`, commit messages |
| Scope: | ||
|
|
||
| - **Apply to:** `tools/**` (excluding `tools/lean4/.lake/`), | ||
| behavioural docs in `docs/` (excluding history surfaces), | ||
| `.claude/skills/**/SKILL.md` (skill bodies), | ||
| `src/**`, `*.fsproj`, `*.csproj` | ||
| - **Exclude (history surfaces per Otto-279):** `memory/**`, |
There was a problem hiding this comment.
P1: The scan scope includes very broad roots (tools/**, docs/**, src/**) but doesn’t explicitly exclude references/upstreams/**, which the repo’s standing rules require excluding from file-iteration scans due to size/noise (docs/AGENT-BEST-PRACTICES.md “Exclude references/upstreams/ from every file-iteration command”). Please add that exclusion to the planned lint’s scope/implementation notes to avoid a slow, noisy audit.
| Candidate detector regex (for code-surface files only — `tools/`, | ||
| `docs/` excluding history-surfaces, behavioural docs): | ||
|
|
||
| ``` | ||
| \bcourier-ferry-\d+\b | ||
| \bferry-\d+\b | ||
| \bferry-\d+'s?\b | ||
| ``` | ||
|
|
||
| Plus the inverse: `\b<Person>\s+ferry-\d+\b` (Amara/Grok/Gemini etc | ||
| + ferry-N) to catch un-stripped name attribution that should have | ||
| been stripped on code-surface. |
There was a problem hiding this comment.
P1 (shell portability): The “Candidate detector regex” examples here use \b and \d, which are PCRE tokens and can be misleading if the eventual implementation uses grep -E/awk (the repo’s hygiene scripts frequently target macOS portability). Consider either rewriting these patterns in portable ERE form, or explicitly noting the intended engine/tool (e.g., ripgrep PCRE2) so future implementers don’t copy/paste a non-working regex into a bash hygiene script.
| lint shape (write-time scan). Backlog candidate: B-NNNN — extend the | ||
| existing `audit-*` scripts under `tools/hygiene/` to flag these | ||
| patterns with a fix-suggestion: "remove the attribution clause OR |
There was a problem hiding this comment.
P1: This memory still uses the placeholder “Backlog candidate: B-NNNN” even though this PR introduces the concrete backlog row B-0070. Update this reference to B-0070 (and ideally link to docs/backlog/P2/B-0070-orphan-role-ref-detector-lint-aaron-2026-04-28.md) so readers can jump straight to the actionable follow-up.
| lint shape (write-time scan). Backlog candidate: B-NNNN — extend the | |
| existing `audit-*` scripts under `tools/hygiene/` to flag these | |
| patterns with a fix-suggestion: "remove the attribution clause OR | |
| lint shape (write-time scan). Backlog follow-up: `B-0070` | |
| (`docs/backlog/P2/B-0070-orphan-role-ref-detector-lint-aaron-2026-04-28.md`) | |
| — extend the existing `audit-*` scripts under `tools/hygiene/` to flag | |
| these patterns with a fix-suggestion: "remove the attribution clause OR |
Summary
Two artifacts capturing Aaron's 2026-04-28 PR #24 input:
memory/feedback_orphan_role_ref_after_name_stripping_aaron_2026_04_28.md— captures the recurring failure mode: when stripping named attribution from code-surface text per Otto-279, mechanical replacement<Name> ferry-N→courier-ferry-N absorbleaves orphan role-refs that lose semantic weight.B-0070 P2 backlog row —
docs/backlog/P2/B-0070-orphan-role-ref-detector-lint-aaron-2026-04-28.md— backlog the structural fix: lint script undertools/hygiene/wired into CI gate as soft-fail (same pattern asaudit-memory-index-duplicates.sh).The pattern caught
Amara ferry-12courier-ferry-12 absorbGrok ferry-16 invariantcourier-ferry-16 absorb invariantPer Amara ferry-7 evidence-pointer rulePer courier-ferry-7 absorb evidence-pointer ruleAaron's framing
Lint composes with the prompt-protector skill's invisible-Unicode write-time-scan shape; targets BOTH directions:
🤖 Generated with Claude Code