Skip to content

feat(pm): add --kind to set-field to correct an issue's type label post-filing#407

Merged
aleskalfas merged 1 commit into
mainfrom
feat/404-add-kind-to-set-field
Jun 30, 2026
Merged

feat(pm): add --kind to set-field to correct an issue's type label post-filing#407
aleskalfas merged 1 commit into
mainfrom
feat/404-add-kind-to-set-field

Conversation

@aleskalfas

Copy link
Copy Markdown
Owner

What

Adds --kind to the project-management set-field verb so an issue's type:* classification label can be corrected after filing, in the same validated batch as --priority / --workstream / --parent.

  • On a kind-driven (Task) issue, --kind <value> swaps the type:* label and realigns the title prefix per classification.yaml's title_prefix_by_value (e.g. [Chore] → [Bug]), keeping label and prefix coupled through the same single source of truth create-issue uses (axis_labels.resolve_write + the shared prefix map — no duplicated tables).
  • On epic / feature / umbrella, where the structural type fixes the kind to feature, a non-feature --kind is refused up front, before any mutation, conforming to the structural_restriction hard-reject in classification.yaml / [project-management:DEC-011-title-formats] rather than manufacturing the mismatch. --kind feature on those types is a clean no-op.
  • Unknown values and set-field's existing validate-before-any-mutation / idempotent-on-re-run posture are unchanged; --kind composes with the other fields in one batch.

Why

Correcting a mis-filed type:* previously required a raw gh issue edit --add-label/--remove-label (off the validated path) plus a manual edit-issue --title to fix the prefix. Surfaced live: #402 was filed type:maintenance but a broken shipped verb is a defect; the relabel to type:bug had to go through raw gh.

Design note (critic-reviewed)

The first cut allowed --kind to swap the label on a non-task while leaving the structural prefix — a critic pass found that manufactures exactly the kind/structural mismatch DEC-011 declares a hard-reject, and is a live break: open-pr/validate-pr derive PR conv-type from the closing issue's type:* label, and a non-task owning issue is the closing issue of its integration→main PR (DEC-013), so an EPIC relabelled type:bug would drive its closure PR to fix(...) against an [EPIC] title and the reviewer gate would reject the natural feat. Reworked to refuse-on-mismatch, which conforms to the existing decision (no amendment).

Verification

  • test_pm_set_field.py 33 pass; pm suite 1749 pass; full suite 4137 pass.
  • pkit schemas validate (13 pass); pkit migrations check-diff --include-working-tree --base main clean (pure addition — new optional flag).
  • Dry-run smokes (mutated nothing): Task --kind docstype:bug → type:docs + [Bug] → [Docs]; EPIC --kind bug refused up front naming the rule; EPIC --kind feature accepted as no-op.

Version / migration

Capability surface change (new flag) → package.yaml 0.41.0 → 0.42.0 (minor). No migration (additive optional flag).

Doc impact

  • .pkit/capabilities/project-management/README.md — set-field row, failure-list bullet, and example block state the Task-only scope and the epic/feature/umbrella refusal.

Test plan

  • Task path: label swap + prefix realign; prefix-already-correct no-op; idempotent re-run.
  • Refusal path: non-feature kind on epic/feature/umbrella refused before any mutation.
  • --kind feature on a feature/epic accepted as no-op.
  • Unknown value refused; combined --kind --priority --workstream batch.

Follow-up (out of scope, surfaced by the critic)

DEC-011's structural_restriction hard-reject is currently enforced nowhere in code (create-issue / validate-issue both skip the cross-check), so a mismatched issue still validates clean. This PR makes set-field conform; the broader enforcement gap (and a shared _lib consistency predicate the three callers want, COR-007) is a separate issue.

Closes #404

🤖 Generated with Claude Code

…st-filing

set-field gains --kind to change an issue's type:* classification label
(bug/feature/docs/test/refactor/maintenance) in the same validated batch as
--priority/--workstream/--parent. On a kind change to a kind-driven (Task)
issue it realigns the title prefix via classification.yaml's
title_prefix_by_value (e.g. [Chore] -> [Bug]), keeping label and prefix coupled
through the same single source of truth create-issue uses.

Refuses up front, before any mutation, when the kind is not permitted for the
issue's structural type (epic/feature/umbrella carry kind 'feature' by
definition) — conforming to the structural_restriction hard-reject in
classification.yaml / DEC-011 rather than manufacturing the mismatch. Unknown
values and the existing idempotent re-run posture are unchanged.

Closes #404

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@aleskalfas

Copy link
Copy Markdown
Owner Author

Reviewer agent (local, reviewer): APPROVED

pm-conventions review of PR #407 against the project-management capability's schemas. All criteria pass; no warnings, no audit-bypass findings.

  • Branch shape ([project-management:DEC-013-branch-and-pr-conventions], git-conventions.yaml branch-name): feat/404-add-kind-to-set-field matches <conv-type>/<issue-number>-<slug>.
  • Branch-type / issue-type alignment (git-conventions.yaml branch-name rule 2 + classification.yaml pr_type_mapping): closing issue [Task] Add --kind to set-field to correct an issue's type label post-filing #404 is type:featurefeat; branch segment is feat.
  • PR title Conventional Commits ([COR-008] + DEC-013): feat(pm): add --kind to set-field … parses as <type>(<scope>): <description> with feat in the accepted list.
  • PR title type matches issue type (pr_type_mapping): type:featurefeat; the title uses feat.
  • Issue classification complete ([project-management:DEC-012-classification-axes]): [Task] Add --kind to set-field to correct an issue's type label post-filing #404 carries type:feature, priority:Medium, and workstream:capabilities.
  • Closing-issue link (git-conventions.yaml pr-body): body has Closes #404 and closingIssuesReferences is populated.
  • ## Doc impact section present (git-conventions.yaml pr-body, hard-reject): present, with the README set-field row / failure-list / example update checked.
  • ## Test plan section (DEC-031 placeholder rule): present with authored, checked items — no empty-skeleton hard-reject.
  • Surface-change discipline ([COR-010]): pkit migrations check-diff --base main reports no migration-triggering changes; the package.yaml 0.41.0 → 0.42.0 bump is an additive new-flag minor with no renames/removals or schema_version change — no migration required.
  • No-shared-files invariant ([COR-001]): the diff touches only capability-owned paths under .pkit/capabilities/project-management/ and tests/; no */core/ or otherwise core-owned files edited.

@aleskalfas aleskalfas merged commit 4045cc4 into main Jun 30, 2026
1 check passed
@aleskalfas aleskalfas deleted the feat/404-add-kind-to-set-field branch June 30, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task] Add --kind to set-field to correct an issue's type label post-filing

1 participant