Replace shell Required-work checks with typed present/absent checks that Ruby evaluates #843
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#843
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
A Required-work check is free shell text today.
RequiredWorkCheck#rungives the text toProjectShell.capture2e, and exit 0 means pass. Authors write checks that cannot run, or that pass while the work is not done:/os-adr:find implementation-reportErrno::ENOENT - /os-adr:findCLI::grep -rn "CLI::" plugins/os-sdlcCLI::is still thereexitandwarngrep -rn "exit|warn" …/commandevidencegrep -n evidence …/os_sdlc.rbgrep -c "for_summary" …prints 0Of the checks in #815–#842, 11 were text searches in repo files, 3 ran tests that the suite gate already runs, and 1 was a slash command. No check needed a shell. The ticket rules also do not say which items a pipeline agent can own, so an ADR item (#836 item 6) can reach the gate.
Decision: ADR-0255 (amends ADR-0244 decision 4 and ADR-0209).
Observed
Reproduce
n/a: design change; #836 implementation 4 is the recorded instance.
Approach
A check has exactly two forms. Ruby evaluates them in the process. No shell starts.
DispatchCommands.required_work_checkreceives today.presentpasses when at least one matched file contains the text.absentpasses when no matched file contains the text.check:form is refused at implementation-open (TicketShape#missing). The os-backlogvalidate-templaterefusal is #847. This includes shell text, slash commands, and free text. The refusal names the item:Required work check is not present/absentin: <item>.check:in an item's lines is the item's check.[required-work, suite]does not change. Theos-sdlc-required-work-checkbin, the gate step, and the repair route also do not change.text found in <path>,text not found, orglob matched no file.REQUIRED_WORK_OUTPUT_LIMITand the shell-output cap are deleted.Required work:
plugins/os-sdlc/lib/os_sdlc/parser/ticket_shape/required_work.rbwith the typed present/absent parse, and refuse every other form throughTicketShape#missing.ProjectShell.capture2einplugins/os-sdlc/lib/os_sdlc/adapter/required_work_check.rbwith an in-process evaluation (Dir.glob,File.read,include?).RequiredWorkReport::Resultfrom(item, command, status, output)to item, check, and reason. DeleteREQUIRED_WORK_OUTPUT_LIMITfromdispatch_commands.rb.Orchestrator work (not for pipeline agents):
plugins/os-sdlc/tests/parser/ticket_shape_parity_test.rb.plugins/os-backlog/references/templates/capture.md, change line 25 to the typed form. Change line 61 from "its own check command" to "its own check". Replace the line 68 example with a typed check. Add this rule: "Each Required-work item is a file change inside the target that a pipeline agent can make. ADR, tracker, and skill-driven work goes on a separateOrchestrator work:line, never in Required work. Test and lint runs are not checks; the suite gate runs them."plugins/os-backlog/references/body-style.md.plugins/os-sdlc/agents/change-auditor.md:49, delete the word "command" after the check keyword.Rejected: refuse only slash commands and keep shell checks — this fixes #836 but not the inverted checks or the #841 crash class.
Rejected: regex patterns — no check in #815–#842 needed one.
Rejected: a transition window that accepts both forms — only 7 open tickets use the old form.
Blocks: #847 (os-backlog part, split 2026-09-30 because an implementation takes one target).
Acceptance criteria
absent `CLI::` in `lib/**/*.rb`and no matched file that containsCLI::, when the required-work gate step runs, then the step passes.CLI::, when the step runs, then it fails and reports the item, the check, andtext found in <path>.present `X` in `lib/a.rb`andlib/a.rbdoes not containX, when the step runs, then it fails and reportstext not found.glob matched no file.check: `grep -q X lib/a.rb`, when implementation-open runs under the ticket map, then open refuses and names the item.check: `/os-adr:find foo`, when implementation-open runs, then open refuses and names the item.Owner sketch
Retired tests
plugins/os-sdlc/tests/command/dispatch_commands_required_work_check_test.rb
plugins/os-sdlc/tests/parser/ticket_shape_mid_line_check_test.rb
plugins/os-sdlc/tests/query/gate/commands_required_work_test.rb#test_registry_offers_a_required_work_step_for_a_ticket_with_checks
plugins/os-sdlc/tests/command/implementation/open_ticket_shape_test.rb#test_open_raises_naming_the_item_when_check_has_no_backticked_command
Blast radius (2026-09-30)
parser/ticket_shape/required_work.rb,parser/ticket_shape.rb(required_work_items,required_work_checks,unchecked_required_work),adapter/required_work_check.rb,model/required_work_report/result.rb,command/dispatch_commands.rb:7,112-118, os-backlogrequired_work.rbandheading_content_issues.rb.open.rb,query/gate/commands.rb, the bin, the boot wiring, and the gate map do not change.Gate::Evaluator(adapter/gate/evaluator.rb:20) still starts theos-sdlc-required-work-checkbin through ProjectShell. That is in scope for #845, not this ticket.ticket_shape_parity_test.rbhas nocheck:case (Orchestrator work, after #847)..sdlc/project.yamlfiles have nocheck:keys.Dir.globskips dotfiles by default.Origin
adapter/required_work_check.rb:16) ← check is free shell text ← DESIGN: ADR-0244 decision 4, ADR-0209Define which Required-work items an os-sdlc agent can own; refuse slash-command checksto Replace shell Required-work checks with typed present/absent checks that Ruby evaluatesWork started: /os-sdlc:implement on branch ticket-843 (worktree .claude/worktrees/ticket-843). Design: ADR-0255.
Blocked by #841. Implementation 10 failed at dispatch 61 (test-writer): os-sdlc-gate crashed two times with Sequel::NotNullConstraintViolation correction_rounds.gate_type. The retired-tests gate step failed, StepOutcome#gate_type returns nil for retired-tests (only lint/test types exist), and Gate::ViolationRecorder#record_round inserts a round with a nil gate_type. This is the #841 crash; it hits every failing gate step that is not lint or test (required-work, retired-tests). #843 cannot pass its gates until #841 ships. Earlier: implementation 6 escalated on an under-decomposed ticket (prose items moved to orchestrator work); implementation 7 could not converge because the os-backlog part is outside the os-sdlc target (split to #847). Worktree ticket-843 kept; branch has ADR-0255 (
8595eb61).Resolution
Done: Required-work checks are typed present/absent text checks evaluated in Ruby (ADR-0255). TicketShape::RequiredWork::Check parses the form and decides the reason; RequiredWorkCheck reads matched files in process with no ProjectShell; implementation-open refuses any other check form and names the item; RequiredWorkReport::Result is item/check/reason; REQUIRED_WORK_OUTPUT_LIMIT deleted. capture.md, body-style.md and change-auditor.md updated; os-sdlc History row added.
Evidence: Branch ticket-843:
4c297ef9(Runner commit, implementation 13),ffb44384(retired tests),eb8ecd76(docs),8595eb61(ADR-0255). Implementation 13 implementation_complete: behavior-verifier pass on all 8 criteria, suite-check pass (required-work + suite), contract-auditor pass after one refactor round. os-sdlc suite 1329 runs, 0 failures.Follow-ups: #847 os-backlog validate-template refusal (split by target; then add the typed-check parity case). #845 shell-call audit. The old-form checks in open tickets #842 #812 #806 #777 #773 #748 #741 are rewritten by the orchestrator in this session after merge.
Lens proposal A1 (dispatch 122) not filed: the challenge found a code defect, not a lens edit (Check in parser/ while RequiredWork, RequiredWorkCheck, RequiredWorkReport share a prefix with no owning model), and ticket-skeptic returned DROP (speculative hardening; no observed failure).