fix(task): reject malformed multi-part --id; surface over-segmented task ids#158
Merged
Conversation
taskwrite `add --id <value>` accepted a value with more than two
dot-separated parts and minted a 4-segment id (e.g. `mvp1.store.0002`
-> `mvp1.store.0002.0001`) via `split(".", 1)`. That id was then
un-targetable by start/done and invisible to validate_id/lint_board,
because `_IDISH_RE` matched exactly three segments and `_split_id_title`
absorbed the 4-segment token into the title (id=None). A single mistyped
--id permanently stranded a task with no tool path to fix or detect it.
- taskwrite.py: validate --id is exactly GROUP.TYPE (one dot, two
non-empty parts); error with a clear message and write nothing
otherwise, instead of a lossy `split(".", 1)`.
- _taskboardlib.py: widen `_IDISH_RE` to 3+ segments so a malformed id
parses as an id — rejected by validate_id, surfaced by lint_board, and
targetable by set_state for repair (defense in depth).
- Tests: +2 CLI (rejection + well-formed still mints), +5 lib
(parse/validate/lint/target a 4-segment id; 3-segment unaffected).
Suites: 95 + 33 green.
Closes #157
Claude-Session: https://claude.ai/code/session_01Md7D2ufFrX254HkY1GJPZf
14 tasks
SUaDtL
added a commit
that referenced
this pull request
Jul 1, 2026
2.6.1 is a security-hardening release: the five P1 enforcement-bypass fixes (#159-#163) plus the #158 task-id fix and the #151 release-skill/AGPLv3 surface alignment. Version (plugin.json) and README badges were already at 2.6.1; this adds the user-facing CHANGELOG section and is the last surface before tagging. Claude-Session: https://claude.ai/code/session_01JqTxpxEkbDHb6AuADohtMR Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #157.
Problem
taskwrite add --id <value>accepted a value with more than two dot-separated parts and silently minted a 4-segment task id (e.g.--id mvp1.store.0002->mvp1.store.0002.0001) viasplit(".", 1). That id was then un-targetable bystart/doneand invisible tovalidate_id/lint_board—_IDISH_REmatched exactly three segments, so_split_id_titleabsorbed the 4-segment token into the title (id=None). A single mistyped--idpermanently stranded a task with no tool path to flip or even detect it (the board hard-rule forbids hand-editing).Fix
taskwrite.py— validate--idis exactlyGROUP.TYPE(one dot, two non-empty parts); error clearly and write nothing otherwise, replacing the lossysplit(".", 1)._taskboardlib.py— widen_IDISH_REto 3+ segments so a malformed id parses as anid: rejected byvalidate_id, surfaced bylint_board, and targetable byset_statefor repair (defense in depth).Tests
test_taskwriter.py(+2):--id mvp1.store.0002rejected (exit 1, board untouched); well-formed--id mvp1.storestill mintsmvp1.store.0001.test_taskboardlib.py(+5): a 4-segment token parses as id,validate_idrejects it,lint_boardsurfaces it,set_statetargets it; a 3-segment id is unaffected.Notes
Found while dogfooding on a downstream project: a harvested follow-up was filed with
--id mvp1.store.0002and could never be marked done. Backward-compatible — well-formed ids and all existing behavior are unchanged.https://claude.ai/code/session_01Md7D2ufFrX254HkY1GJPZf