os-sdlc project-config --help treats --help as a project name and writes .sdlc/project.yaml #860
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#860
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
Evidence: running it inside ~/dev/cc-os/plugins/os-sdlc wrote that file (reverted). Reproduced again on main
b80613ec.os-sdlc project-config --help(and-h) treats--helpas the project name and writes.sdlc/project.yamlwithname: "--help".The cause is the design, not the call order.
bin/os-sdlcis a Thor CLI (ADR-0123), butproject-configdeclares no Thor options. It takes a*argssplat, so Thor passes every token through unchecked. Then three hand parsers share the argv:ArgvOption.take!removes--target,callsniffs@args.first == "--show",validated_nameshifts the first token, and a privateOptionParser(OptionParserBuilder) parses the rest. No layer rejects an unknown switch, so--helpbecomes a name.A second symptom of the same design:
os-sdlc help project-configprints onlyos-sdlc project-config NAME. It lists none of the six flags, because Thor does not know them.ADR-0123 chose Thor for
bin/os-sdlcand rejected a hand-rolledOptionParserbecause it re-implements flag parsing and help. ADR-0232 keepsbin/os-sdlcon Thor because humans read its help.Approach
Declare the command's interface in Thor and delete the hand parsers. This is the shape of the sibling Thor controllers
Evidence::CollectionandWorktree::CLI:check_unknown_options!plus onemethod_optionper flag.Onboardingcallscheck_unknown_options!. An unknown switch such as--bogusis refused before any command runs. The refusal fails throughProcessIO#guardedwith exit 3 and writes no file (ADR-0246: every failure on this path exits 3).project_configdeclares--help(alias-h) as a boolean option. When it is set, the command prints Thor's help forproject-config(the same text asos-sdlc help project-config) and writes no file. ADR-0232 kept Thor for this CLI because humans read its--help; a refusal would break that.project_config(name = nil)declares--path,--test-path,--test-command,--lint-config,--test-framework,--target(strings) and--show(boolean).ConfigCommandreceivesname:,target:,show:and the option hash. It no longer reads argv. A missing name keeps the existingLoudFailuremessage.OptionParserBuilder(one caller).ArgvOptionstays for the non-Thor scripts (Boot::Inputs,LintWorklist); only theOnboardingcall goes.os-sdlc help project-configandproject-config --helpprint the same help. Thor lists every declared option.Required work:
Onboardingrefuses unknown switches. check: presentcheck_unknown_options!inplugins/os-sdlc/lib/os_sdlc/controller/project/onboarding.rbproject_configdeclares its flags as Thor options. check: presentmethod_option :test_commandinplugins/os-sdlc/lib/os_sdlc/controller/project/onboarding.rbproject_configtakes a declared name, not a splat. check: absentdef project_config(*args)inplugins/os-sdlc/lib/os_sdlc/controller/project/onboarding.rb--targetcomes from Thor options, notArgvOption. check: absentArgvOptioninplugins/os-sdlc/lib/os_sdlc/controller/project/onboarding.rbConfigCommandno longer parses argv. check: absent@argsinplugins/os-sdlc/lib/os_sdlc/command/project/config_command.rbOptionParserBuilder. check: absentOptionParserBuilderinplugins/os-sdlc/lib/**/*.rb--help,-h, andhelp project-config. Updatetests/model/project_test_path_default_test.rb:50, which buildsConfigCommandwith an argv array.Sketch:
Acceptance criteria
.sdlc/project.yaml, whenos-sdlc project-config --helpruns, then it exits 0, its output names--pathand--test-command, and no.sdlc/project.yamlexists afterward.os-sdlc project-config -hruns, then the result is the same as criterion 1.2a. Given the same directory, when
os-sdlc project-config --bogusruns, then it exits 3, stderr names--bogusas an unknown switch, and no.sdlc/project.yamlexists afterward.os-sdlc help project-configruns, then it exits 0 and its output names--path,--test-path,--test-command,--lint-config,--test-framework,--targetand--show.os-sdlc project-config widgets --path app, when it runs, then it writes.sdlc/project.yamlforwidgetsas it does today.os-sdlc project-configwith no name, when it runs, then it fails with the existing missing-name message and exit 3.project-config --show --target aandproject-config --show --target=arun, then both select targetaas--target=adoes today.Owner sketch
Changes since filing (verified 2026-10-02 on main
b80613ec)b80613ec.858349ec) and #830 (e6961519) moved the files. The paths and lines in this ticket are still valid.ConfigCommand#upsertto Thor-declared options. A swap leaves three hand parsers next to Thor and keeps unknown switches silent (ADR-0123).project-config --helpafter the subcommand; withcheck_unknown_options!it raisesUnknown switches "--help". Verified in a scratch Thor class on 2026-10-02.Blast radius
Project::Onboarding#project_config,Project::ConfigCommand,Project::OptionParserBuilder(deleted, one caller).check_unknown_options!is class-level, solint-initalso refuses unknown switches;InitCommandtakes only a positional directory.tests/controller/project/cli_project_config_test.rb,tests/controller/project/cli_project_config_target_path_test.rb,tests/model/project_test_path_default_test.rb:50,tests/command/project/config_command_missing_message_test.rb:12,tests/hardening_verdict_lint_project_test.rb:31,tests/adapter/gate/evaluator_project_shell_test.rb:40.tests/controller/argv_option_test.rbis unaffected.skills/setup-project/SKILL.mdusesproject-config <name>only.bin/os-sdlc; this change conforms), 0246 (exit 3), 0177/0178. None conflicts.Out of scope
--targetfiltering of--showoutput (#861).project-config --show --target NAMEignores --target and prints all targets #861Body revised 2026-10-02 after blast-radius re-check on main
b80613ec: bug reproduced; parse options first, then name, then test-command check; pinning tests and --help test listed.project-config --show --target NAMEignores --target and prints all targets #861PREDICTED RULING: REVISE
a. No.
b. ADR-0123 picked Thor for bin/os-sdlc and rejected a hand-rolled OptionParser. ADR-0232 keeps project-config on Thor because humans read its help. feedback-lens-request-is-a-design-symptom and feedback-adr-conflict-is-a-symptom say: fix the design that let the defect exist, not the symptom.
c. The line swap leaves three hand parsers next to Thor (ArgvOption, the
--showsniff, OptionParserBuilder). Unknown switches stay silent, andos-sdlc help project-configlists no flags. Research: the sibling Thor controllers Evidence::Collection and Worktree::CLI usecheck_unknown_options!plusmethod_option. A scratch probe on Thor 1.5.0 showed that declared options refuse--helpand accept--target aand--target=a.d. Declare the flags in Thor, add
check_unknown_options!, remove the ArgvOption call and the--showsniff from Onboarding, and delete OptionParserBuilder. Unknown switches fail with exit 3 (ADR-0246). The help path isos-sdlc help project-config. This conforms to ADR-0123, so no ADR ruling is needed. #861 space form: this is not a defect. On main,--show --target aselects target a. The failed repro passed"--target a"as one argv token (unsplit in zsh).e. Not read: the ADR-0177/0178 bodies, the os-backlog CLI's help handling, and any user statement that
project-config --helpmust print usage and exit 0. If such a statement exists, add a help alias.Orchestrator correction to the predicted approach, 2026-10-02:
project-config --help/-hmust print the command's help and exit 0, not be refused as an unknown switch. Reason: ADR-0232 kept Thor for this CLI because 'its --help is read' by humans; a refusal breaks that.check_unknown_options!stays for other unknown switches (criterion 2a:--bogusexits 3). The rest of the predicted approach is unchanged.Work started 2026-10-02 on branch ticket-860 (os-sdlc pipeline, map poodr-ticket-implementation, target os-sdlc).
Resolution
Done: project-config declares its flags as Thor method_options with check_unknown_options!. --help/-h print the command help and exit 0 with no file written; an unknown switch (--bogus) exits 3 with no file written; both --target forms are parsed by Thor. ConfigCommand takes name:/options: and reads no argv; OptionParserBuilder deleted. Approach revised before implementation (predicted ruling REVISE: ADR-0123/0232) and corrected so --help prints help (ADR-0232: its --help is read).
Evidence: Commits
5d0a1cd6(feat, implementation 25: 8 dispatches, 0 retries, suite green, contract-auditor pass),62f28820(History row),afab5688(merge of main, History-table conflict with #890 resolved keeping both rows). Live check on the worktree bin in an empty dir: --help exit 0 usage lists all flags; -h same; --bogus exit 3 'os-sdlc-Unknown switches "--bogus"'; no .sdlc written in any case.Follow-ups: none filed. Observed, left as is: the unknown-switch refusal reads 'os-sdlc-Unknown switches' without the command name (LoudFailure#stderr_line prefix); it names the switch and exits 3, so it is not a defect.
project-config --show --target NAMEignores --target and prints all targets #861Correction to the PREDICTED RULING comment, recorded 2026-10-03. The comment says that declared options refuse
--helpand that the help path isos-sdlc help project-config. The shipped code (5d0a1cd6) declares--help/-has an option and prints the help with exit 0. Live check on main, 2026-10-03, in an empty directory:project-config --helpexit 0,-hexit 0,project-config widgets --bogusexit 3, no file written. How much does this matter: not materially. The shipped behavior matches the ticket's acceptance criteria and ADR-0232. No derivative ticket.Ticket-skeptic DROP for the unknown-switch error line (
os-sdlc-Unknown switches "--bogus", no command name): the line comes from Onboarding.dispatch_refusing_bad_switches, which #860 added, and shares its root with #920. Record it as a finding under #920 instead of a separate ticket.