Skip to content

taskwrite add --id mints a malformed 4-segment task ID that start/done can't target and lint can't surface #157

Description

@SUaDtL

Summary

taskwrite.py add --id <value> accepts a --id with more than two dot-separated parts and silently mints a 4-segment task ID (e.g. mvp1.store.0002.0001). That ID is then un-targetable by start/done and invisible to validate_id/lint_board, so the task can never be flipped or surfaced as malformed via the blessed tooling.

Environment

  • codeArbiter ca v2.6.1 (plugin cache), Windows, stock Python.

Repro

taskwrite.py add --id mvp1.store.0002 --boundaries store -- "Fix X"
# -> board entry:  - [ ] mvp1.store.0002.0001 - Fix X
taskwrite.py done -- "mvp1.store.0002.0001"
# -> "no change: 'mvp1.store.0002.0001' not found or already done"
taskwrite.py done -- "mvp1.store.0002"
# -> also "not found"

The task can never be marked done through the tool.

Root cause (two compounding defects)

  1. taskwrite.py (add verb), lines ~87-88 — no validation of --id:

    if args.gid and "." in args.gid:
        group, typ = args.gid.split(".", 1)   # "mvp1.store.0002" -> ("mvp1", "store.0002")

    split(".", 1) on a 3-part value yields typ="store.0002", and add_entry then mints {group}.{typ}.{seq:04d} = mvp1.store.0002.0001. A --id that is not exactly GROUP.TYPE is accepted instead of rejected.

  2. _taskboardlib.py _IDISH_RE matches exactly three segments:

    _IDISH_RE = re.compile(r"^[^\s.]+\.[^\s.]+\.[^\s.]+$")

    So _split_id_title treats a 4-segment leading token as part of the title (id=None). Consequences:

    • set_state -> _find_task_line can't match it (no t.id, and t.title includes the id prefix), so start/done fail by both ID and title.
    • validate_id is never consulted (id is None) and lint_board therefore can't flag it — a malformed ID is silently swallowed rather than surfaced.

Impact

A single mistyped --id permanently strands a task in [ ]/[~] with no tool path to fix or even detect it (the hard rule forbids hand-editing the board). Harvested follow-ups are the common trigger, since callers pass an explicit --id.

Suggested fix

  1. taskwrite.py: validate --id is exactly GROUP.TYPE (one dot, two non-empty parts); error with a clear message otherwise. Use a strict 2-part split, not split(".", 1).
  2. _taskboardlib._IDISH_RE: accept 3+ segments (^[^\s.]+(?:\.[^\s.]+){2,}$) so a malformed ID parses as an id, is rejected by validate_id, and is surfaced by lint_board (defense in depth) and becomes targetable by set_state for repair.
  3. (Optional) a taskwrite verb or lint path to repair/rename an existing malformed ID.

Workaround

Pass --id GROUP.TYPE (e.g. --id mvp1.store) and let the tool mint the seq.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions