Skip to content

feat(kanban): promote verb for manual todo->ready recovery (salvage #29464 + bulk --ids)#31334

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-555287da
May 24, 2026
Merged

feat(kanban): promote verb for manual todo->ready recovery (salvage #29464 + bulk --ids)#31334
teknium1 merged 2 commits into
mainfrom
hermes/hermes-555287da

Conversation

@teknium1

@teknium1 teknium1 commented May 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds hermes kanban promote <task_id> [--ids ...] so operators can recover children stuck in todo/blocked after their parent closed outside the auto-promote path — without raw SQL.

Salvages @thedavidmurray's #29464 onto current main (169 commits behind, clean cherry-pick), and extends it with the bulk --ids flag that mirrors the existing block/schedule convention. The marquee #28822 use case is "promote all children of a closed organizational parent in one command," so bulk is the value-add that turns a recovery primitive into an actual one-shot fix.

Closes #28822. Supersedes #29464.

Behavior

hermes kanban [--board <slug>] promote <task_id> [reason...] \
    [--ids <id> [<id> ...]] [--force] [--dry-run] [--json]
  • Refuses promotion unless every parent dep is done/archived (override with --force)
  • Emits promoted_manual audit rows with {actor, reason, forced} — distinct from the auto-fired promoted kind that recompute_ready writes
  • Does NOT mutate assignee — dispatcher picks the card up via normal ready polling
  • --ids adds bulk mode (same convention as block --ids / schedule --ids)
  • Positional task_id + --ids are deduped so the same id can't be promoted twice
  • --dry-run validates without mutating; --json for orchestration (single-id stays a flat object for back-compat, bulk emits a list)

Changes

Validation

Before After
Stuck-todo recovery raw SQL on tasks table hermes kanban promote <id> --force
Bulk recovery (closed parent) shell loop promote a --ids b c d --force
Audit trail none (direct DB write) promoted_manual event with actor/reason/forced
Targeted tests 16 pass (0.4s)

E2E live test (isolated HERMES_HOME):

Authorship

Out of scope

Arbitrary --from/--to transitions. Issue mentioned them but every described use case is todo/blockedready; a general state-machine verb would expand the review surface without solving any reported gap.

Infographic

kanban-promote-cli

thedavidmurray and others added 2 commits May 23, 2026 22:55
Adds `hermes kanban promote <task_id>` for manual lifecycle recovery
when an auto-promote daemon misses the parent-done transition (issue
#28822). Refuses promotion unless every parent dep is done/archived
(override with --force). Emits a `promoted_manual` audit event distinct
from the automatic `promoted` kind, so audit consumers can filter
human-driven from system-driven promotions. Supports --dry-run and
--json for orchestration. Does not mutate assignee/claim state — the
dispatcher picks the card up via its normal ready polling path.

Closes #28822.
Adds an --ids flag to 'hermes kanban promote' mirroring the existing
block/schedule convention, so the marquee use case from issue #28822
(promote all children of a closed organizational parent in one shot)
doesn't require a shell loop. Single-id JSON output stays a flat
object for back-compat; bulk emits a list. Dedupes positional + --ids
so the same id can't be promoted twice in one call. 5 new CLI-level
tests cover bulk happy path, partial-failure exit code, JSON shapes,
and dedup.

Also adds the thedavidmurray noreply-email -> github-login mapping in
scripts/release.py so the salvage cherry-pick passes the AUTHOR_MAP
contributor-credit check.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-555287da vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9061 on HEAD, 9047 on base (🆕 +14)

🆕 New issues (5):

Rule Count
unsupported-operator 2
unresolved-attribute 2
unresolved-import 1
First entries
tests/hermes_cli/test_kanban_promote.py:143: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["'ready'"]` and `str | None`
tests/hermes_cli/test_kanban_promote.py:15: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/hermes_cli/test_kanban_promote.py:143: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["promote only applies"]` and `str | None`
tests/hermes_cli/test_kanban_promote.py:210: [unresolved-attribute] unresolved-attribute: Attribute `status` is not defined on `None` in union `Task | None`
tests/hermes_cli/test_kanban_promote.py:114: [unresolved-attribute] unresolved-attribute: Attribute `assignee` is not defined on `None` in union `Task | None`

✅ Fixed issues: none

Unchanged: 4816 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels May 24, 2026
@teknium1 teknium1 merged commit b207dc2 into main May 24, 2026
26 checks passed
@teknium1 teknium1 deleted the hermes/hermes-555287da branch May 24, 2026 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add first-class Kanban promote / force-claim CLI for todo→ready recovery

3 participants