Skip to content

Add 'phabfive edit' command with object type auto-detection #132

@holmboe

Description

@holmboe

Description

Add a new top-level edit command that auto-detects object type from monogram (T/K/P) and routes to the appropriate editor. Initial implementation supports Maniphest tasks (T monogram), with passphrase (K) and paste (P) editing reserved for future work.

Features

  • Auto-detect object type: T=task, K=passphrase (future), P=paste (future)
  • Auto-detect piped input: Automatically reads YAML from stdin when piped (no flag needed)
  • Accept piped YAML: Read from maniphest search or show output
  • Batch editing: Process multiple objects with atomic validation
  • Directional navigation:
    • --priority=raise/lower to move priority up/down (skipping Triage)
    • --column=forward/backward to move between workboard columns by sequence
  • Smart board/column handling:
    • Use --tag=BOARD to specify board context
    • Use --column=COLUMN to set target column
    • Auto-detect board if task is on single board
    • Error with partition suggestions if task on multiple boards
  • Field editing: priority, status, columns, assignee
  • Comment support: Add optional comment with --comment flag
  • Change detection: Only apply transactions for fields that actually changed

Example Usage

# Single task edit with CLI argument
phabfive edit T123 --priority=raise --status=resolved

# Pipe search results (auto-detects stdin, no flag needed!)
phabfive maniphest search --tag "Backend" | phabfive edit --column=Done

# Handle tasks on multiple boards
phabfive maniphest search --assigned=@me | \
  phabfive edit --tag="Sprint 42" --column=Done

# Add task to board and set column in one command
phabfive edit T123 --tag="NewBoard" --column="Backlog"

# Navigate columns directionally
phabfive edit T123 --tag="Sprint" --column=forward

# Navigate priority with Triage skip
phabfive edit T123 --priority=raise  # High -> Unbreak (skips Triage)

# Batch with comment
phabfive maniphest search --assigned=@me | \
  phabfive edit --priority=lower --comment="Deprioritizing"

Technical Approach

Architecture

  • New edit.py module with Edit class
  • Monogram detection: Regex extraction from CLI args or YAML Link field
  • Auto-detect piped input: Use sys.stdin.isatty() (same method used for output format detection)
  • Object routing: T → Maniphest editor, K/P → "not yet implemented" error
  • Atomic batch validation: Validate ALL before processing ANY

Key Components

  1. Monogram Detection (edit.py)

    • Parse T/K/P monograms from CLI or YAML
    • Extract object type and ID
    • Route to appropriate editor
  2. Stdin Auto-Detection (edit.py)

    • Use sys.stdin.isatty() to detect piped input
    • If object_id provided → single object mode
    • If stdin piped → batch mode (auto-detect)
    • If neither → error with helpful message
  3. STDIN YAML Parser (edit.py)

    • Read YAML documents from stdin using ruamel.yaml
    • Extract monograms from Link field
    • Group by object type
    • Handle empty input gracefully
  4. Board/Column Validation (edit.py)

    • Validate board context for column operations
    • Auto-detect if task on single board
    • Error with helpful suggestions if on multiple boards
  5. Batch Error Handling (edit.py)

    • Collect all validation errors
    • Generate partition suggestions for multi-board conflicts
    • Atomic failure (no partial updates)
  6. Task Editing (maniphest.py)

    • New edit_task_by_id() method
    • Fetch current state for change detection
    • Build transaction list
    • Call maniphest.edit API
  7. Priority Navigation (maniphest.py)

    • Ladder: Wish(0) → Low(25) → Normal(50) → High(80) → Unbreak(100)
    • Triage(90) excluded from raise/lower
    • raise: Move up one level (High → Unbreak, skipping Triage)
    • lower: Move down one level (Unbreak → High, skipping Triage)
    • Triage only settable via --priority=triage
  8. Column Navigation (maniphest.py)

    • Use column sequence field for ordering
    • forward: Next column in sequence
    • backward: Previous column in sequence
    • Explicit name matching supported
  9. Change Detection (maniphest.py)

    • Fetch current task state via API
    • Compare requested changes to current values
    • Only generate transactions for actual changes
    • Efficient and cleaner audit trail
  10. PHID Resolution (maniphest.py)

    • Board name → board PHID
    • Column name → column PHID (within board context)
    • Username → user PHID
    • Caching within command execution
  11. Transaction Builder (maniphest.py)

    • Map changes to API transaction format
    • Validate using existing validators
    • Support all transaction types (priority, status, column, owner, comment)

CLI Schema

phabfive edit [<object_id>] [options]

Options:
  --priority=PRIORITY       Set priority (unbreak|high|normal|low|wish|raise|lower)
  --status=STATUS           Set status (open|resolved|wontfix|invalid|...)
  --tag=BOARD               Specify board context for --column (also adds task to board)
  --column=COLUMN           Set column on board (or use forward/backward)
  --assign=USER             Set assignee
  --comment=TEXT            Add comment with changes
  --dry-run                 Show changes without applying
  --format=FORMAT           Output format [default: auto-detect]

Input Modes (auto-detected):
  - If <object_id> provided: Edit single object (e.g., T123)
  - If stdin is piped: Edit multiple objects from YAML stream
  - If neither: Error

Input Auto-Detection Logic

if object_id:
    # Single object mode (CLI argument)
    return self._edit_task_single(object_id, ...)
elif not sys.stdin.isatty():
    # Batch mode (piped input auto-detected)
    return self._edit_tasks_batch_from_stdin(...)
else:
    # Error: no input
    sys.stderr.write("ERROR: Object ID required (e.g., T123) or pipe YAML from stdin\n")
    return 1

Board/Column Interaction Rules

  1. --column only, task on single board: Auto-detect board ✓
  2. --column only, task on multiple boards: Error with partition suggestions ✗
  3. --tag + --column, task on specified board: Move to column ✓
  4. --tag + --column, task not on specified board: Add to board + move to column ✓

Error Messages with Partition Suggestions

When tasks in a batch are on different boards:

ERROR: Validation failed for 3 task(s):
  - T123: Task T123 is on multiple boards [Backend Team, Sprint 42]. Use --tag=BOARD to specify which board.
  - T124: Task T124 is on multiple boards [Backend Team, Sprint 42]. Use --tag=BOARD to specify which board.
  - T125: Task T125 is on multiple boards [Backend Team, Frontend Team]. Use --tag=BOARD to specify which board.

Suggested partition commands:

# Tasks on Backend Team + Sprint 42:
echo "T123\nT124" | phabfive edit --tag="Backend Team" --column=Done

# Task on Backend Team + Frontend Team:
echo "T125" | phabfive edit --tag="Backend Team" --column=Done

No tasks were modified (atomic batch failure).

Implementation Checklist

  • Create edit.py module with Edit class
  • Add edit command to CLI schema in cli.py
  • Implement monogram detection
  • Implement stdin auto-detection (using sys.stdin.isatty())
  • Implement STDIN YAML parser
  • Add board/column validation logic
  • Add batch error handling with partition suggestions
  • Add edit_task_by_id() method to maniphest.py
  • Implement priority navigation logic (with Triage skip)
  • Implement column navigation logic
  • Add change detection
  • Add PHID resolution helpers
  • Add transaction builder
  • Write tests for all functionality
  • Update documentation

Benefits

  • Unified interface: Single command for all object editing (extensible to K/P later)
  • Smart defaults: Auto-detection reduces typing and errors
  • No flags needed for piping: Just pipe and it works (consistent with auto-format detection)
  • Batch operations: Process multiple tasks efficiently
  • Safety: Atomic validation prevents partial updates
  • Helpful errors: Partition suggestions make multi-board scenarios easy
  • Pipeline-friendly: Works seamlessly with piped YAML from search/show

Related

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