Skip to content

Make every shell block in the handoff skill parse, and stop calling /rename the only act there is (#78, #79) - #200

Merged
brettheap merged 5 commits into
mainfrom
fix/handoff-skill-78-79
Oct 18, 2026
Merged

brettheap merged 5 commits into
mainfrom
fix/handoff-skill-78-79

Conversation

@brettheap

@brettheap brettheap commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What was wrong

Both defects are in skills/handoff/SKILL.md, and both were found by opensoft/workBenches' devcontainer.test/ when it vendored the file byte for byte.

#78: a block that does not parse. The late-recovery example printed a bare <profile>:

lane-handoff --late --at 2026-09-14T12:02:27Z "late; usage limit hit before the swap"
lclaude <profile>      # and only then; use pclaude --lane <lane> if lclaude is unavailable

Bash reads < and > as redirections whatever stands beside them, so a person who pasted the block got a parse error instead of a command. The command had been renamed from pclaude to lclaude and the bare placeholder carried through untouched, because nothing in this repository parsed a fenced example inside a SKILL.md (tests/test_repo_hygiene.py runs bash -n on the twelve top-level command files only). Measured on main f87fd5a, over every fenced sh/bash block in skills/*/SKILL.md:

skills/handoff/SKILL.md:755: syntax error near unexpected token `newline' -- in `lclaude <profile>      # and only then; ...` (the ```sh block that opens at line 753)

That is the only block of the 19 (12 in handoff, 7 in restart, none in lane-swap) that fails.

#79: a stale claim. Step 5's comment said "wherever a session comes up outside lane-start the operator's /rename <lane> is the only act there is". That was true until Amendment 12. Its name guard now types the rename itself into the session's own tmux pane: the SessionStart hook (lanes-edit.sh session-start, the clause (f) line in docs/README-lanes.md) and the UserPromptSubmit guard (lanes-edit.sh guard, guard_lock_rename and choice 3, via guard_type). The operator's /rename is the fallback.

What changed

Functions and regions edited:

  • skills/handoff/SKILL.md: step 5's WHICH ACT REMOVES THIS LINE comment (about lines 645-652)
  • skills/handoff/SKILL.md: the late-recovery sh block under lane-handoff --late --at <UTC> (about line 759)
  • tests/test_skill_shell_blocks.py: new file: fenced_blocks, parse_problems, shipped_skills, and six tests

Not touched: lines 310-315 of the same SKILL.md and tests/test_handoff_skill_commit_block.py, which #199 edits.

Tests

Added tests/test_skill_shell_blocks.py, six tests:

Fail before, pass after, run as the one file only, not the suite (python3 -m pytest tests/test_skill_shell_blocks.py, scratch TMPDIR, lane seams unset):

  • Before the fix (the test file against main's SKILL.md, commit 2c4b7a6): 2 failed, 4 passed. The two failures were test_every_shell_block_in_every_skill_parses (the :755 report above) and test_the_handoff_skill_does_not_call_rename_the_only_act_there_is.
  • After the fix: 6 passed in 0.08s.
  • Cross-check with a separate awk extractor and plain bash -n: fixed handoff 12 blocks, 0 failing; restart 7 blocks, 0 failing; main f87fd5a handoff 12 blocks, 1 failing (the block opening at line 753).

The full suite was not run locally (CI's tests job is the record).

Closes #78
Closes #79

🤖 Generated with Claude Code

Summary by Sourcery

Ensure shipped skill examples remain copy-pasteable shell and keep handoff rename guidance aligned with the current session name guards.

Bug Fixes:

  • Fix the late-recovery handoff example so its shell command parses correctly when copied.
  • Correct the handoff guidance to describe the session name guard as the usual rename mechanism and operator renaming as the fallback.

Enhancements:

  • Add validation for all fenced shell examples in shipped skill documents, including diagnostics for missing language tags and unterminated fences.

Documentation:

  • Update handoff skill guidance to reflect Amendment 12's SessionStart and UserPromptSubmit rename guards.

Tests:

  • Add tests covering shell-block discovery, Bash parsing, diagnostic locations, fence handling, and the corrected handoff rename guidance.

brettheap and others added 2 commits October 11, 2026 16:56
… the stale claim that /rename is the only act there is (#78, #79)

The regression tests only, committed before the fix so the failing state is on
the branch: skills/handoff/SKILL.md:755's bare `lclaude <profile>` does not
parse under bash -n, and step 5's comment still calls the operator's /rename
"the only act there is". The SKILL.md edits are not made yet.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…rename the only act there is (#78, #79)

#78: the late-recovery example in skills/handoff/SKILL.md printed
`lclaude <profile>`, and bash reads `<` and `>` as redirections, so a person
who pasted the block got a parse error instead of a command. The command was
renamed from `pclaude` to `lclaude` and the bare placeholder carried through
untouched, because nothing here parsed an example block inside a SKILL.md. The
placeholder now sits in the quoted parameter expansion step 5 already uses,
`lclaude "${CLAUDE_PROFILE_NAME:-<profile>}"`, with only the argument quoted:
quoting the whole command, as the issue suggested, would name a program
literally called "lclaude ...".

#79: step 5's comment said the operator's `/rename <lane>` is "the only act
there is". Amendment 12's name guard (the SessionStart hook, `lanes-edit.sh
session-start`, and the UserPromptSubmit guard, `lanes-edit.sh guard`) types
the rename into the session's own pane, so the operator's is the fallback.
"No API renames a running session from inside" stays: a keystroke is not an API.

tests/test_skill_shell_blocks.py walks every skills/*/SKILL.md, runs `bash -n`
on every fenced sh/bash block, and names the file and line of any that does not
parse; it also refuses an untagged or unclosed fence, so a block cannot leave
the check by losing its tag. It fails on main's SKILL.md at :755 and passes here.
The same file asserts the stale #79 sentence is gone and the guard is named.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR fixes the malformed late-recovery shell example, corrects stale rename guidance to reflect Amendment 12’s automatic name guard, and adds focused regression coverage that parses every fenced shell block in shipped skills.

Sequence diagram for automatic session rename with fallback

sequenceDiagram
    participant Session as Claude session
    participant Hook as SessionStart hook
    participant Guard as UserPromptSubmit guard
    participant Tmux as Session tmux pane
    participant Operator

    Hook->>Guard: lanes-edit.sh guard
    Guard->>Tmux: guard_type /rename <lane>
    Tmux->>Session: type rename command
    alt guard cannot run or type
        Operator->>Session: /rename <lane>
    end
Loading

Flow diagram for shell block validation

flowchart TD
    Skills["skills/*/SKILL.md"] --> Extract[fenced_blocks]
    Extract --> Tagged{sh/bash/shell fence?}
    Tagged -->|yes| Parse[parse_problems]
    Tagged -->|no| Skip[skip tagged non-shell block]
    Parse --> Bash[bash -n]
    Bash --> Result{parses?}
    Result -->|yes| Pass[validation passes]
    Result -->|no| Report[report file, line, and block text]
Loading

File-Level Changes

Change Details Files
Fix the handoff skill’s late-recovery command example so every shipped shell block is syntactically valid.
  • Quote the profile expansion while preserving the placeholder fallback.
  • Add coverage that extracts all fenced shell blocks from every skill and validates them with bash -n.
  • Report malformed, untagged, and unterminated fences with source file and line context while ignoring explicitly non-shell fences.
  • Add regression tests covering the original malformed example and fence parsing behavior.
skills/handoff/SKILL.md
tests/test_skill_shell_blocks.py
Update the handoff documentation to describe the name guard as the normal rename mechanism and operator input as fallback behavior.
  • Clarify that SessionStart and UserPromptSubmit guards type /rename into the session pane.
  • Retain the distinction that no API renames a running session from inside.
  • Document fallback cases such as missing hooks, non-Claude panes, or unavailable tmux.
  • Add assertions preventing the stale “only act there is” claim and requiring the relevant guard terminology.
skills/handoff/SKILL.md
tests/test_skill_shell_blocks.py

Assessment against linked issues

Issue Objective Addressed Explanation
#78 Make the late-recovery shell example parse successfully by avoiding a bare placeholder in the command. ✅
#79 Update step 5 of skills/handoff/SKILL.md so it no longer claims the operator's /rename <lane> is the only act, and accurately explains that Amendment 12's SessionStart and UserPromptSubmit guards type the rename while the operator's command is a fallback. ✅

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai

sourcery-ai Bot commented Oct 17, 2026

Copy link
Copy Markdown

Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 3 hours and 15 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@brettheap brettheap added ready landing gate: runs tests-macos once before the squash and removed ready landing gate: runs tests-macos once before the squash labels Oct 17, 2026
…R on today's main

GitHub's refs/pull/200/merge stayed on aaa7bc8 after main moved, so a re-labelled run tested the old base. A head that contains main is tested on it whatever base the run merges with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 18, 2026
…le's (#55) (#201)

Landed on Brett Heap's word "land #200 #201 #203 when green" (2026-10-17), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39079829533) was green on head afe2eb7 with main 2732d59 in its tree. Main has since moved to 83d2690 only through files this PR does not change.

Independent review (lane 5, Opus, of f42b982; the merge of main adds nothing to the PR's diff): LAND, no blocking defect.

Closes #55

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…R on today's main

Main moved through files this PR also changes (#199 or #216, and #201) after the last green run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sourcery assessment

Approved.

…R on today's main

Main moved through the suite's machinery (#229's tests/test_repo_hygiene.py) and the openRepoShape pin (v1.1.0) after the last green run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

brettheap added a commit that referenced this pull request Oct 18, 2026
…olders verifies it, not on kill -0 (#56) (#203)

Landed on Brett Heap's word "land #200 #201 #203 when green" (2026-10-17), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39089234266) was green on head 6952a3a with main f595e44 in its tree.

Independent review (lane 5, Opus, of c855985; the merges of main add nothing to the PR's diff): LAND, no blocking defect.

Closes #56

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap
brettheap merged commit f5c3bcd into main Oct 18, 2026
5 checks passed
brettheap pushed a commit that referenced this pull request Oct 18, 2026
Brings in cb3a2c7 (#203, lane-start's transcript follow counts a holder
only when transcript-holders verifies it) and f5c3bcd (#200, every
shell block in the handoff skill parses) on top of f595e44. Neither
touches a file this branch changes, and git merged with no conflict.
lane-start's seven rung-5 reader lines, which
test_t018_the_legs_reader_is_lane_starts_rung_5_line_for_line holds
equal to lanes-edit.sh's legs reader, are byte-identical at f595e44 and
f5c3bcd. bash -n passes on lane-start and tests/test_lane_helpers.sh,
the two shell files the merge touches.

Lane: openRepoTools-3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready landing gate: runs tests-macos once before the squash

Projects

None yet

1 participant