Replace the lint_config default sentinel with Project::LintConfig [capture] #573
Labels
No labels
P0
P1
P2
P3
bug
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
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#573
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?
Context
The responsibility audit found that "is a lint config configured?" is
answered two ways. Project#resolved_lint_config compares the value to the
default string .rubocop.yml. LintWorklistRubocopConfig#custom_lint_config?
compares the value to root/.rubocop.yml. The sentinel and a legal user value
are the same string. Callers that would delegate:
Project#resolved_lint_config, AutocorrectPrepass#root_lint_config,
LintWorklistRubocopConfig#custom_lint_config?. This changes ATTR_DEFAULTS;
decide it before Project::Layout (#570) or Project::ArtifactDir move.
Observed
lib/os_sdlc/project.rb:86 return nil if lint_config ==
self.class::DEFAULT_LINT_CONFIG
lib/os_sdlc/project.rb:88 File.expand_path(lint_config,
root)
lib/os_sdlc/lint_worklist_rubocop_config.rb:50 @lint_config &&
@lint_config != target_config_path
lib/os_sdlc/lint_worklist_rubocop_config.rb:54 File.join(@project_root, ".
rubocop.yml")
Project.new(name: "x", root: "/tmp", lint_config:
".rubocop.yml").resolved_lint_config returns nil, while lint_config:
"cfg/.rubocop.yml" returns /tmp/cfg/.rubocop.yml.
Reproduce
cd plugins/os-sdlc && ruby -Ilib -e 'require "os_sdlc/project"; p
OsSdlc::Project.new(name: "x", root: "/tmp", lint_config: ".rubocop.yml").
resolved_lint_config'
Expected
Minitest snippet test_explicit_default_lint_config_is_configured asserting
that an explicit lint_config: ".rubocop.yml" resolves to /tmp/.rubocop.yml,
and that Project::LintConfig.new(nil, root: "/tmp").configured? is false.
Illustration
illustration, not spec
class Project::LintConfig #
lib/os_sdlc/project/lint_config.rb
def initialize(value, root:) = (@value, @root = value, root)
string
def path = configured? ? File.expand_path(@value, @root) : nil
end
Origin
• Trigger: /os-sdlc:responsibility-audit run 13 on plugins/os-
sdlc/lib/os_sdlc/project.rb, 2026-09-14
• Improvised this session: none
• Chain: two readers disagree ← default sentinel equals a legal value ←
DEFAULT_LINT_CONFIG used as an absence marker (DESIGN, lib/os_sdlc/project.
rb:86)
• Root candidate: this ticket
• Where: lib/os_sdlc/project.rb
• Session: 23a382aa-f78e-495f-9cbd-0934e163b37d
• Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/23a382aa-
f78e-495f-9cbd-0934e163b37d.jsonl
Tasks
Project::LintConfigat lib/os_sdlc/project/lint_config.rb withconfigured?andpath.ATTR_DEFAULTS[:lint_config]becomesnil; absence isnil, not.rubocop.yml.Project#resolved_lint_configdelegates toProject::LintConfig#path.LintWorklistRubocopConfig#custom_lint_config?asksProject::LintConfig#configured?.Acceptance criteria
Project.new(name: "x", root: "/tmp", lint_config: ".rubocop.yml").resolved_lint_configreturns/tmp/.rubocop.yml.Project.new(name: "x", root: "/tmp").resolved_lint_configreturnsnil.Project::LintConfig.new(nil, root: "/tmp").configured?is false.lint_configthat does not exist on disk still raisesHarnessError(ADR-0091).Structural follow-through
AutocorrectPrepass#root_lint_configdelegates toProject::LintConfig.rg -n 'DEFAULT_LINT_CONFIG' plugins/os-sdlc/libreturns nothing.ADR case
Amends ADR-0091 (
Project::LintConfigbecomes the sole sentinel-vs-custom resolver) and ADR-0074 (lint_configdefault isnil). Create the amending ADR when this ticket lands.Batch
Map: #570. Position 2 of 4. Follows #571. Followed by #574. Map: maps/poodr-ticket-implementation.yaml.
Work started via /os-sdlc:responsibility-refactor batch 2 (map #570). Branch: ticket-573, worktree .claude/worktrees/ticket-573, map poodr-ticket-implementation.yaml.
Resolution
Done: Project::LintConfig (project/lint_config.rb) is the sole lint-config resolver: configured? is non-nil, path expands against root. Project#resolved_lint_config and LintWorklistRubocopConfig#custom_lint_config? delegate; ATTR_DEFAULTS[:lint_config] is nil; DEFAULT_LINT_CONFIG removed. ADR-0179 amends ADR-0091/0074.
Evidence: Merged to main
058f20d(codebc4f4cf). Suite 1223 runs, 0 failures; rubocop clean on 5 touched files; pre-tool-use hook smoke test still denies. Pipeline: 16 dispatches, 1529 s, implementation_complete after 3 contract-auditor rounds. Deviations: hand-fixed test-side conflict (shared DEFAULT_ATTRS helper asserted the old default; made nil-aware), hand-settled a reused dispatch 91 after the gate went green, moved LintConfig from a nested class in project.rb to its own file per structural follow-through. Position 2 of 4 on map #570.Follow-ups: none. Structural follow-through done: rg DEFAULT_LINT_CONFIG under lib returns nothing; AutocorrectPrepass#root_lint_config already delegates through resolved_lint_config. Observed once: autocorrect_prepass_test is order-dependent in the full suite (passes alone, 6 vs 5 failures across two runs); pre-existing, not ticketed.