Skip to content

feat(jtk): INT-693 clear fields with an empty value; none/null clear numbers - #470

Closed
piekstra wants to merge 2 commits into
mainfrom
piekstra/INT-693-field-clear
Closed

feat(jtk): INT-693 clear fields with an empty value; none/null clear numbers#470
piekstra wants to merge 2 commits into
mainfrom
piekstra/INT-693-field-clear

Conversation

@piekstra

@piekstra piekstra commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

[INT-693]

jtk issues update -f 'Story Points=' (or =none) fails with Jira's per-type validation error — Specify a number for the custom field — because FormatFieldValue only honors null-intent for user fields. A number value falls through to ParseFloat, fails, and ships the raw string. There is no way to unset a custom field from the CLI at all, while --assignee none has worked forever.

The contract

  • Empty value clears every structured type — number, option, array, priority-like, issuelink, parent → JSON null. No structured field has a meaningful empty-string value.
  • none/null additionally clear number fields, matching the existing user-field behavior — those strings can never be legitimate numbers.
  • Option-like fields deliberately do NOT treat None as a clear — a select list may legitimately contain an option named "None"; only the empty value clears them.
  • Free-text unchanged — verbatim value; empty string is the idiomatic text clear.

Wire shape confirmed: UpdateIssueRequest.Fields is map[string]any, so a nil value marshals as JSON null — the shape Jira's update API requires for clearing.

Motivating incident

An accidental Story Points + Change type write to the wrong ticket could not be reverted from the CLI — the operator had to fall back to the Jira UI.

Validation

  • New TestFormatFieldValue_Clearing table: clears per type, the literal-None option case, free-text passthrough.
  • Full tools/jtk suite green; gofmt clean.
  • --help examples document the clear syntax.

…numbers

An empty value now clears (JSON null) every structured field type - number,
option, array, priority-like, issuelink, parent - and none/null additionally
clear number fields, matching the existing user-field behavior. Previously
FormatFieldValue only honored null-intent for user fields; a number field
fell through to ParseFloat and sent the raw string, so Jira rejected every
attempt to unset Story Points with 'Specify a number for the custom field',
and there was no way to unset a custom field from the CLI at all.

Option-like fields deliberately do not treat the string None as a clear: a
select list may legitimately contain an option named None. Free-text fields
keep the verbatim value - empty string is the idiomatic text clear.

[INT-693]
@piekstra
piekstra marked this pull request as ready for review August 7, 2026 15:13

@monit-reviewer monit-reviewer left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: 460576c16995
Profile: claude-monit-reviewer - Posting as: monit-reviewer

Summary

Reviewer Findings
go:implementation-tests 1
policies:conventions 0
go:implementation-tests (1 finding)

Minor - tools/jtk/api/fields.go:191

The new issuelink clear-on-empty branch (if trimmed == "" { return nil }) is untested — TestFormatFieldValue_Clearing covers option, array, number, priority, parent, and default string, but has no case with Schema.Type: "issuelink". This is genuinely new behavior added by this diff (the pre-existing issuelink tests only cover the non-empty id/key-wrapping path), so a regression here (e.g. someone reordering the trim/empty check relative to the Atoi branch) would ship silently. Add a case to the table, e.g. {name: "issuelink clears on empty", field: &Field{ID: "customfield_X", Schema: FieldSchema{Type: "issuelink"}}, value: "", want: nil}.

Reviewer Coverage

  • go:implementation-tests — complete (broad); skipped: none; constraints: none
  • policies:conventions — complete (broad); inspected 2 assigned files (3 inspected across reviewers): tools/jtk/api/fields.go, tools/jtk/internal/cmd/issues/update.go; skipped: none; constraints: none
Inspected files (3)
  • tools/jtk/api/fields.go
  • tools/jtk/api/fields_test.go
  • tools/jtk/internal/cmd/issues/update.go

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 3m 01s | ~$1.97 (est.) | claude-sonnet-5 | cr 0.10.282
Field Value
Model claude-sonnet-5
Reviewers go:implementation-tests, policies:conventions
Engine claude_cli · claude-sonnet-5
Reviewed by cr · monit-reviewer
Duration 3m 01s wall · 4m 20s compute
Cost ~$1.97 (est.)
Tokens 56 in / 13.0k out

Per-workstream usage

  • orchestrator-selection — claude-sonnet-5
    • In: 6
    • Out: 2.4k
    • Cache read: 97.9k
    • Cache create: 75.9k
    • Cost: ~$0.35 (est.)
    • Duration: 34s
  • go:implementation-tests — claude-sonnet-5
    • In: 18
    • Out: 5.2k
    • Cache read: 564.5k
    • Cache create: 85.7k
    • Cost: ~$0.57 (est.)
    • Duration: 1m 58s
  • policies:conventions — claude-sonnet-5
    • In: 26
    • Out: 4.9k
    • Cache read: 874.4k
    • Cache create: 88.7k
    • Cost: ~$0.67 (est.)
    • Duration: 1m 30s
  • orchestrator-rollup — claude-sonnet-5
    • In: 6
    • Out: 463
    • Cache read: 102.7k
    • Cache create: 91.4k
    • Cost: ~$0.38 (est.)
    • Duration: 15s

Comment thread tools/jtk/api/fields.go
@piekstra

piekstra commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by the signed replacement PR — identical tree (cd407189), carrying this PR's review: cr APPROVED, issuelink-test finding addressed, all CI green. Closed because these commits are unsigned and the main ruleset requires verified signatures.

@piekstra piekstra closed this Aug 7, 2026
piekstra added a commit that referenced this pull request Aug 7, 2026
…numbers (#471)

## [INT-693]

Signed replacement of #470 — that branch's commits were unsigned and the
`main` ruleset requires verified signatures. This commit was created via
GitHub's API (GitHub-signed, verified) and its tree SHA (`cd407189`) is
identical to #470's reviewed head, so the content is byte-for-byte what
cr APPROVED there with all CI green and its one finding (issuelink
clear-on-empty test) addressed.

`jtk issues update -f 'Story Points='` (or `=none`) previously failed
with Jira's per-type validation error because `FormatFieldValue` only
honored null-intent for user fields; there was no way to unset a custom
field from the CLI.

### The contract
- Empty value clears every structured type (number, option, array,
priority-like, issuelink, parent) → JSON null
- `none`/`null` additionally clear number fields, matching user-field
behavior
- Option-like fields do NOT treat `None` as a clear — a select list may
contain a literal "None"
- Free-text unchanged: verbatim value; empty string is the idiomatic
text clear

### Validation
`TestFormatFieldValue_Clearing` covers every clear branch incl.
issuelink; full `tools/jtk` suite green; gofmt clean.
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.

2 participants