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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions