feat(jtk): INT-693 clear fields with an empty value; none/null clear numbers - #471
Conversation
…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, 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]
monit-reviewer
left a comment
There was a problem hiding this comment.
Automated PR Review
Reviewed commit: 43cf2f65e2f2
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_test.go:950
TestFormatFieldValue_Clearing tests that the option branch keeps a literal "None" value (since a select list may legitimately have an option named "None"), but the priority/resolution/status/issuetype/securitylevel branch — which shares the exact same name-addressed, non-none-clearing contract per the new doc comment — has no equivalent case. This is the one branch in the group where the untested edge is realistic rather than hypothetical: Jira ships a built-in Priority literally named "None" in many instances, so
--field priority=Nonehitting this code path is a real, not speculative, scenario, and it's exactly the case the PR's contract calls out ("a select list or priority scheme may legitimately contain an entry named 'None'"). Add a case mirroring "option keeps the literal string None" for a priority-typed field (e.g.{name: "priority keeps the literal string None", field: priorityField, value: "None", want: map[string]string{"name": "None"}}) to lock in the behavior the doc comment promises.
Reviewer Coverage
go:implementation-tests— complete (broad); skipped: none; constraints: nonepolicies: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.gotools/jtk/api/fields_test.gotools/jtk/internal/cmd/issues/update.go
0 PR discussion threads considered. 0 summarized; 0 resolved.
Completed in 2m 19s | ~$1.79 (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 | 2m 19s wall · 3m 07s compute |
| Cost | ~$1.79 (est.) |
| Tokens | 42 in / 10.8k out |
Per-workstream usage
orchestrator-selection— claude-sonnet-5- In: 6
- Out: 3.3k
- Cache read: 97.7k
- Cache create: 76.8k
- Cost: ~$0.37 (est.)
- Duration: 50s
go:implementation-tests— claude-sonnet-5- In: 10
- Out: 3.4k
- Cache read: 250.9k
- Cache create: 79.3k
- Cost: ~$0.42 (est.)
- Duration: 59s
policies:conventions— claude-sonnet-5- In: 20
- Out: 3.7k
- Cache read: 677.9k
- Cache create: 95.0k
- Cost: ~$0.61 (est.)
- Duration: 1m 04s
orchestrator-rollup— claude-sonnet-5- In: 6
- Out: 438
- Cache read: 103.6k
- Cache create: 93.1k
- Cost: ~$0.39 (est.)
- Duration: 12s
## [INT-693] Fast-follow to #471, addressing its review finding: the name-addressed branch (priority/resolution/status/issuetype/securitylevel) shares the only-empty-clears contract but had no literal-`None` case — and Jira ships a built-in Priority literally named "None" in many instances, so `--field priority=None` hitting that path is a real scenario. One test-table case: `priority=None` → `{"name": "None"}`, mirroring the existing option-field case. GitHub-signed commit (the `main` ruleset requires verified signatures).
[INT-693]
Signed replacement of #470 — that branch's commits were unsigned and the
mainruleset 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 becauseFormatFieldValueonly honored null-intent for user fields; there was no way to unset a custom field from the CLI.The contract
none/nulladditionally clear number fields, matching user-field behaviorNoneas a clear — a select list may contain a literal "None"Validation
TestFormatFieldValue_Clearingcovers every clear branch incl. issuelink; fulltools/jtksuite green; gofmt clean.