hermes - 💡(How to fix) Fix Feature request: first-class kind field on Kanban cards

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Add a top-level kind field to the Kanban card schema so card classes (standard tasks, CI-fix watchers, integration cards, future kinds) can be discriminated by a structured field rather than a stringly-typed tag convention. Motivation I'm building a protocol layer on top of Hermes Kanban (Phase 9.6 of the Hermes Bootstrap Protocol — a CI auto-fix card kind that watches PRs opened by a pr-author skill and runs bounded auto-fix attempts on classifier-approved failure classes). Different card kinds want different:

Worker rotations (a ci-fix card routes only to the ci-fix-worker profile, never to implementer / reviewer / integrator). Iteration caps (ci-fix uses ci_max_fix_attempts, default 3; standard tasks use kanban_max_iterations, default 10). Lane behavior (ci-fix cards spend most of their life in a watching lane, polling external state). Completion criteria (ci-fix completes on CI green; standard tasks complete on reviewer approval). Audit artifacts (kanban-final-ci-<pr-number>.md vs. kanban-final-<task-id>.md).

The most natural way to express "this card has a different shape" is a kind discriminator. Without one, I've implemented the discriminator as a tag (tags: ["kind:ci-fix"]), and it works, but:

It's stringly-typed. A typo (kind:ci-fixe) silently routes cards into a no-worker-matches limbo where they sit in the watching lane forever. Tag filters are the wrong primitive for this. Tags are meant for cross-cutting metadata (priority, team, area) where a card can have many of them. A card's kind is singular and exclusive — exactly the case where a discriminator field beats tags. Tag-based filtering on hermes kanban list requires verifying AND semantics. The dispatcher cooperation hook I wrote needs cards where kind:ci-fix AND pr:<number> are both present. If --tag is OR-semantics, I have to post-filter with jq everywhere. A --kind filter would always be exact. Card schemas diverge per kind. A ci-fix card has pr_number, parent_card_id, ci_max_fix_attempts fields that mean nothing for a standard task. With a kind discriminator, schemas can be kind-scoped and validated; without, every field has to be either universal or implicit. It blocks introspection. hermes kanban runs <id> shows run history per card but doesn't group by kind. If I want metrics like "what's the success rate of ci-fix cards on this board this quarter," the answer requires post-processing tag strings. A native field would make this a dashboard query.

Proposed shape card: id: <uuid> kind: ci-fix # new field; defaults to "task" for backward compat title: "..." tags: [...] fields: {...} # arbitrary kind-scoped fields (no schema enforcement initially) ... Defaults:

Existing cards without an explicit kind are treated as kind: task. kanban create accepts --kind <name>; omitting it defaults to task. kanban list --kind <name> filters by kind (exact match). The dashboard groups or filters by kind alongside the existing lane view.

Validation:

Initially, kind is a free-form string. The protocol layer is responsible for knowing which kinds exist. Future: an optional kanban.kinds: registry in ~/.hermes/config.yaml could list known kinds with required fields, enabling schema validation.

Migration:

No migration required for existing boards. Cards without kind read as kind: task. Tag-based kind conventions (e.g., kind:ci-fix) continue to work for tools that haven't migrated. A --migrate-tags-to-kind flag on kanban could promote tag-based conventions to native fields.

Backward compatibility

Adding the field is additive on the card schema; readers that don't know about kind ignore it (per the existing tolerant-reader pattern in the dispatcher). Tools that currently use tag-based discrimination (mine included) keep working until they're updated to read the new field. The hermes kanban list --kind <name> filter is a new flag; absent flag = current behavior.

What I'd implement against For my Phase 9.6 work specifically, I need to discriminate ci-fix from task to:

Filter cards in the watching lane to only those of kind: ci-fix (the dispatcher hook scans this set every tick). Route worker assignment by kind (the dispatcher picks ci-fix-worker for ci-fix cards, never for task cards). Render the right audit artifact name when the card completes.

All three are mechanically expressible with tags today; all three are cleaner with a native field. Counterproposals I considered

Keep using tags. Works, but multiplies stringly-typed bugs as more kinds are added. Use the workspace field as a discriminator. Conflates two concerns: where the worker runs (workspace) vs. what kind of work it does (kind). Hard-code kinds in Hermes core. Loses the extensibility that makes the protocol layer work.

A first-class kind field is the design choice with the longest legs. Open question I'd want feedback on Should kind be free-form or registered? Free-form is simpler and lets protocol layers experiment; registered (via a config block) catches typos earlier. I'd start free-form and add registration as a later opt-in. Curious if there's a strong reason to require registration from the start. Out of scope for this issue

Schema validation per kind (separate issue, depends on this one). Per-kind worker rotation config (separate issue, depends on this one). Dashboard UI for kind-based filtering (separate UI issue).

Context This issue is the upstream half of a protocol-layer feature documented in the Hermes Bootstrap Protocol's Phase 9.6 (CI auto-fix card kind). The protocol-layer implementation works today against tags: ["kind:ci-fix"]. A native kind field would let the protocol layer drop the tag convention and the jq post-filtering that comes with it. Happy to discuss design alternatives or contribute the implementation if the direction is welcome.

Root Cause

Add a top-level kind field to the Kanban card schema so card classes (standard tasks, CI-fix watchers, integration cards, future kinds) can be discriminated by a structured field rather than a stringly-typed tag convention. Motivation I'm building a protocol layer on top of Hermes Kanban (Phase 9.6 of the Hermes Bootstrap Protocol — a CI auto-fix card kind that watches PRs opened by a pr-author skill and runs bounded auto-fix attempts on classifier-approved failure classes). Different card kinds want different:

Worker rotations (a ci-fix card routes only to the ci-fix-worker profile, never to implementer / reviewer / integrator). Iteration caps (ci-fix uses ci_max_fix_attempts, default 3; standard tasks use kanban_max_iterations, default 10). Lane behavior (ci-fix cards spend most of their life in a watching lane, polling external state). Completion criteria (ci-fix completes on CI green; standard tasks complete on reviewer approval). Audit artifacts (kanban-final-ci-<pr-number>.md vs. kanban-final-<task-id>.md).

The most natural way to express "this card has a different shape" is a kind discriminator. Without one, I've implemented the discriminator as a tag (tags: ["kind:ci-fix"]), and it works, but:

It's stringly-typed. A typo (kind:ci-fixe) silently routes cards into a no-worker-matches limbo where they sit in the watching lane forever. Tag filters are the wrong primitive for this. Tags are meant for cross-cutting metadata (priority, team, area) where a card can have many of them. A card's kind is singular and exclusive — exactly the case where a discriminator field beats tags. Tag-based filtering on hermes kanban list requires verifying AND semantics. The dispatcher cooperation hook I wrote needs cards where kind:ci-fix AND pr:<number> are both present. If --tag is OR-semantics, I have to post-filter with jq everywhere. A --kind filter would always be exact. Card schemas diverge per kind. A ci-fix card has pr_number, parent_card_id, ci_max_fix_attempts fields that mean nothing for a standard task. With a kind discriminator, schemas can be kind-scoped and validated; without, every field has to be either universal or implicit. It blocks introspection. hermes kanban runs <id> shows run history per card but doesn't group by kind. If I want metrics like "what's the success rate of ci-fix cards on this board this quarter," the answer requires post-processing tag strings. A native field would make this a dashboard query.

Proposed shape card: id: <uuid> kind: ci-fix # new field; defaults to "task" for backward compat title: "..." tags: [...] fields: {...} # arbitrary kind-scoped fields (no schema enforcement initially) ... Defaults:

Existing cards without an explicit kind are treated as kind: task. kanban create accepts --kind <name>; omitting it defaults to task. kanban list --kind <name> filters by kind (exact match). The dashboard groups or filters by kind alongside the existing lane view.

Validation:

Initially, kind is a free-form string. The protocol layer is responsible for knowing which kinds exist. Future: an optional kanban.kinds: registry in ~/.hermes/config.yaml could list known kinds with required fields, enabling schema validation.

Migration:

No migration required for existing boards. Cards without kind read as kind: task. Tag-based kind conventions (e.g., kind:ci-fix) continue to work for tools that haven't migrated. A --migrate-tags-to-kind flag on kanban could promote tag-based conventions to native fields.

Backward compatibility

Adding the field is additive on the card schema; readers that don't know about kind ignore it (per the existing tolerant-reader pattern in the dispatcher). Tools that currently use tag-based discrimination (mine included) keep working until they're updated to read the new field. The hermes kanban list --kind <name> filter is a new flag; absent flag = current behavior.

What I'd implement against For my Phase 9.6 work specifically, I need to discriminate ci-fix from task to:

Filter cards in the watching lane to only those of kind: ci-fix (the dispatcher hook scans this set every tick). Route worker assignment by kind (the dispatcher picks ci-fix-worker for ci-fix cards, never for task cards). Render the right audit artifact name when the card completes.

All three are mechanically expressible with tags today; all three are cleaner with a native field. Counterproposals I considered

Keep using tags. Works, but multiplies stringly-typed bugs as more kinds are added. Use the workspace field as a discriminator. Conflates two concerns: where the worker runs (workspace) vs. what kind of work it does (kind). Hard-code kinds in Hermes core. Loses the extensibility that makes the protocol layer work.

A first-class kind field is the design choice with the longest legs. Open question I'd want feedback on Should kind be free-form or registered? Free-form is simpler and lets protocol layers experiment; registered (via a config block) catches typos earlier. I'd start free-form and add registration as a later opt-in. Curious if there's a strong reason to require registration from the start. Out of scope for this issue

Schema validation per kind (separate issue, depends on this one). Per-kind worker rotation config (separate issue, depends on this one). Dashboard UI for kind-based filtering (separate UI issue).

Context This issue is the upstream half of a protocol-layer feature documented in the Hermes Bootstrap Protocol's Phase 9.6 (CI auto-fix card kind). The protocol-layer implementation works today against tags: ["kind:ci-fix"]. A native kind field would let the protocol layer drop the tag convention and the jq post-filtering that comes with it. Happy to discuss design alternatives or contribute the implementation if the direction is welcome.

Fix Action

Fix / Workaround

It's stringly-typed. A typo (kind:ci-fixe) silently routes cards into a no-worker-matches limbo where they sit in the watching lane forever. Tag filters are the wrong primitive for this. Tags are meant for cross-cutting metadata (priority, team, area) where a card can have many of them. A card's kind is singular and exclusive — exactly the case where a discriminator field beats tags. Tag-based filtering on hermes kanban list requires verifying AND semantics. The dispatcher cooperation hook I wrote needs cards where kind:ci-fix AND pr:<number> are both present. If --tag is OR-semantics, I have to post-filter with jq everywhere. A --kind filter would always be exact. Card schemas diverge per kind. A ci-fix card has pr_number, parent_card_id, ci_max_fix_attempts fields that mean nothing for a standard task. With a kind discriminator, schemas can be kind-scoped and validated; without, every field has to be either universal or implicit. It blocks introspection. hermes kanban runs <id> shows run history per card but doesn't group by kind. If I want metrics like "what's the success rate of ci-fix cards on this board this quarter," the answer requires post-processing tag strings. A native field would make this a dashboard query.

Adding the field is additive on the card schema; readers that don't know about kind ignore it (per the existing tolerant-reader pattern in the dispatcher). Tools that currently use tag-based discrimination (mine included) keep working until they're updated to read the new field. The hermes kanban list --kind <name> filter is a new flag; absent flag = current behavior.

Filter cards in the watching lane to only those of kind: ci-fix (the dispatcher hook scans this set every tick). Route worker assignment by kind (the dispatcher picks ci-fix-worker for ci-fix cards, never for task cards). Render the right audit artifact name when the card completes.

RAW_BUFFERClick to expand / collapse

Summary Add a top-level kind field to the Kanban card schema so card classes (standard tasks, CI-fix watchers, integration cards, future kinds) can be discriminated by a structured field rather than a stringly-typed tag convention. Motivation I'm building a protocol layer on top of Hermes Kanban (Phase 9.6 of the Hermes Bootstrap Protocol — a CI auto-fix card kind that watches PRs opened by a pr-author skill and runs bounded auto-fix attempts on classifier-approved failure classes). Different card kinds want different:

Worker rotations (a ci-fix card routes only to the ci-fix-worker profile, never to implementer / reviewer / integrator). Iteration caps (ci-fix uses ci_max_fix_attempts, default 3; standard tasks use kanban_max_iterations, default 10). Lane behavior (ci-fix cards spend most of their life in a watching lane, polling external state). Completion criteria (ci-fix completes on CI green; standard tasks complete on reviewer approval). Audit artifacts (kanban-final-ci-<pr-number>.md vs. kanban-final-<task-id>.md).

The most natural way to express "this card has a different shape" is a kind discriminator. Without one, I've implemented the discriminator as a tag (tags: ["kind:ci-fix"]), and it works, but:

It's stringly-typed. A typo (kind:ci-fixe) silently routes cards into a no-worker-matches limbo where they sit in the watching lane forever. Tag filters are the wrong primitive for this. Tags are meant for cross-cutting metadata (priority, team, area) where a card can have many of them. A card's kind is singular and exclusive — exactly the case where a discriminator field beats tags. Tag-based filtering on hermes kanban list requires verifying AND semantics. The dispatcher cooperation hook I wrote needs cards where kind:ci-fix AND pr:<number> are both present. If --tag is OR-semantics, I have to post-filter with jq everywhere. A --kind filter would always be exact. Card schemas diverge per kind. A ci-fix card has pr_number, parent_card_id, ci_max_fix_attempts fields that mean nothing for a standard task. With a kind discriminator, schemas can be kind-scoped and validated; without, every field has to be either universal or implicit. It blocks introspection. hermes kanban runs <id> shows run history per card but doesn't group by kind. If I want metrics like "what's the success rate of ci-fix cards on this board this quarter," the answer requires post-processing tag strings. A native field would make this a dashboard query.

Proposed shape card: id: <uuid> kind: ci-fix # new field; defaults to "task" for backward compat title: "..." tags: [...] fields: {...} # arbitrary kind-scoped fields (no schema enforcement initially) ... Defaults:

Existing cards without an explicit kind are treated as kind: task. kanban create accepts --kind <name>; omitting it defaults to task. kanban list --kind <name> filters by kind (exact match). The dashboard groups or filters by kind alongside the existing lane view.

Validation:

Initially, kind is a free-form string. The protocol layer is responsible for knowing which kinds exist. Future: an optional kanban.kinds: registry in ~/.hermes/config.yaml could list known kinds with required fields, enabling schema validation.

Migration:

No migration required for existing boards. Cards without kind read as kind: task. Tag-based kind conventions (e.g., kind:ci-fix) continue to work for tools that haven't migrated. A --migrate-tags-to-kind flag on kanban could promote tag-based conventions to native fields.

Backward compatibility

Adding the field is additive on the card schema; readers that don't know about kind ignore it (per the existing tolerant-reader pattern in the dispatcher). Tools that currently use tag-based discrimination (mine included) keep working until they're updated to read the new field. The hermes kanban list --kind <name> filter is a new flag; absent flag = current behavior.

What I'd implement against For my Phase 9.6 work specifically, I need to discriminate ci-fix from task to:

Filter cards in the watching lane to only those of kind: ci-fix (the dispatcher hook scans this set every tick). Route worker assignment by kind (the dispatcher picks ci-fix-worker for ci-fix cards, never for task cards). Render the right audit artifact name when the card completes.

All three are mechanically expressible with tags today; all three are cleaner with a native field. Counterproposals I considered

Keep using tags. Works, but multiplies stringly-typed bugs as more kinds are added. Use the workspace field as a discriminator. Conflates two concerns: where the worker runs (workspace) vs. what kind of work it does (kind). Hard-code kinds in Hermes core. Loses the extensibility that makes the protocol layer work.

A first-class kind field is the design choice with the longest legs. Open question I'd want feedback on Should kind be free-form or registered? Free-form is simpler and lets protocol layers experiment; registered (via a config block) catches typos earlier. I'd start free-form and add registration as a later opt-in. Curious if there's a strong reason to require registration from the start. Out of scope for this issue

Schema validation per kind (separate issue, depends on this one). Per-kind worker rotation config (separate issue, depends on this one). Dashboard UI for kind-based filtering (separate UI issue).

Context This issue is the upstream half of a protocol-layer feature documented in the Hermes Bootstrap Protocol's Phase 9.6 (CI auto-fix card kind). The protocol-layer implementation works today against tags: ["kind:ci-fix"]. A native kind field would let the protocol layer drop the tag convention and the jq post-filtering that comes with it. Happy to discuss design alternatives or contribute the implementation if the direction is welcome.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix Feature request: first-class kind field on Kanban cards