Give every lint-fixing skill and agent the lint lessons and a shared offense analysis #989
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#989
Loading…
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?
Problem
Lint lessons reach only one place today: the pipeline gate. Other agents and skills that fix lint offenses never see them. None of them ask the agent to name the smell before it fixes or exempts an offense.
lib/os_sdlc/command/gate/run.rbline 9 loadsLesson::Library.new(dir: .../"lint-lessons"). Lines 72, 80, and 102-103 buildLesson::Relay. The renderer islib/os_sdlc/presenter/lesson/relay.rb.skills/fix-lints,bin/lint-worklist, and the worklist code never read them.agents/refactorer.md:15says "state in one line what design fault it hints at".agents/programmer.mdhas nothing on this.skills/fix-lints/SKILL.md:46-47says to stop and report if a cop looks wrong. The ladderskills/fix-lints/references/lint-exemption-ladder.md:13suggests onlyrubocop --show-cops.All paths are under the plugin root
plugins/os-sdlc.Observed cost (n8n-api, issue jaredswanson/n8n-api#2, commit c51ebb3): a pipeline programmer added a
Naming/PredicateMethodExclude for 13 resource methods that always returnedtrue. It did not ask why a method returns a constant. A human review found the real smell.Survey (AC1)
Five places format rubocop offenses for an agent. One adds a lesson. All paths under
plugins/os-sdlc.lib/os_sdlc/presenter/gate/reply.rblint_outputviaLintFeedbackLesson::Relaywithseen_keys: dispatch.violations_dataset.keys(command/gate/run.rb:103)lib/os_sdlc/model/worklist.rbOffense#detail_lineWorklist::Offense(cop,file,line,message)lib/os_sdlc/model/residual_worklist.rbFileUnit#promptWorklist::Offenselib/os_sdlc/controller/lint_worklist.rbprint_iterative_copWorklist::Offenselint_offense_historylib/os_sdlc/presenter/brief.rbrendered_lint_offense_historyviaLintOffenseLineLintOffenseLine::Entrybuilt fromLintReport::OffenseAgents:
agents/lint-fixer.mdreads an assignment file verbatim.agents/programmer.mdsees offenses only through gate reruns.agents/refactorer.md:15asks for one line on the design fault.skills/fix-lints/SKILL.mdforbidsrubocop:disableand points at the exemption ladder; it asks no smell question.Approach
One presenter owns the block an agent reads about offenses. Every path above calls it.
Required work: none beyond the acceptance criteria.
Owner sketch
LintReport::Offense(cop_name,path,line,message,to_s) is the one offense value.Worklist::OffenseandLintOffenseLine::Entryconvert to it;Worklist::Offense#detail_lineand theFileUnit#promptformat go away.Callers delegate:
The gate keeps its seen-set from the dispatch. The fix-lints paths have no dispatch and pass no seen keys, so a fresh agent always gets the full lesson. The library is
Lesson::Library.new(dir: File.join(PluginRoot::PATH, "lint-lessons"))in every caller.Agent and skill text:
agents/lint-fixer.md,agents/programmer.md,agents/refactorer.md(replace line 15), andskills/fix-lints/SKILL.mdeach get one line: "Answer the two questions in the offense block before you edit." No copy of the questions in prose.AC5 is a prompt rule in this change, carried by
QUESTIONSon every path. A tested gate step that rejects anExcludewithout a named smell is not required work; one incident so far.Acceptance criteria
Origin
Discoverer: /home/jared/dev/ruby-gems/n8n-api, session 44cf3646-a8fe-4f26-8550-e92296c57f86, 2026-10-11. A pipeline programmer exempted a cop instead of finding the smell, because lint lessons and smell questions do not reach it.
Work started on branch ticket-989 (os-sdlc implement pipeline, poodr-ticket-implementation map).
Resolution
Done: One OsSdlc::OffenseAnalysis owns the lint lessons plus the two smell questions (what smell does this cop name; what is the correct way to address it) and every offense path calls it: gate reply, batch assignment file, residual assignment file, iterative stdout, and the brief's lint_offense_history. Survey of the five paths recorded in the ticket Approach. lint-fixer, programmer, refactorer, and fix-lints each gained the one-line rule to answer both questions before editing; an exemption proposal must quote the named smell.
Evidence: main commits
59064bb7,38d979be,5beb1580via os-sdlc implementation 36 (15 dispatches, 13 min 54 s, one escalation rerouted at programmer-repair). Suite 1540 runs, 0 failures. Lens challenge on A10/A11 and A15 found two code defects; both fixed in5beb1580(residual guidance moved to ResidualDispatchReport; OffenseAnalysis moved to lib/os_sdlc/offense_analysis.rb).Follow-ups: #994 captured: lesson for Naming/PredicateMethod, the stock cop whose Exclude started this ticket (ticket-skeptic VERDICT: CREATE). Dropped: unifying the four per-path offense line formats onto LintReport::Offense; the formats are pinned by tests and no longer differ in what the agent learns. AC5 remains a prompt rule; a tested gate step that rejects an Exclude without a named smell is not filed, one incident so far.