feat: truncate --fields body uniformly (task 0021) #21

Merged
alexion merged 1 commits from task-0021-body-field-truncation-ruling into main 2026-07-14 14:27:24 -04:00
Owner

Task: .claude/tasks/0021-body-field-truncation-ruling.md

Summary

A single ruling on whether --fields body truncates, applied uniformly everywhere the body extra field is offered.

The ruling: it truncates.
Principle 3 already said body text truncates at 500 chars "in all contexts (list and detail alike)"; the four --fields body extractors were the drift, not the intent.
"Raw" in the Command Surface is resolved to mean uncleaned markdown (short bodies still pass through byte-for-byte), never unbounded — an unbounded body on a list path lets issue list --limit 30 --fields body spill thirty full bodies into an agent's context, the exact cost Principle 3 exists to prevent.

What changed:

  • New truncatedBody() FieldDef in fields.ts routes body through the same truncateBody(value, BODY_TRUNCATE_LIMIT, host) the detail views use, so the hint text and cleanBody-on-overflow are byte-identical to issue view / pr view.
  • ExtractContext gained required host and full fields; every extractRow call site updated (body-less ones pass full: false).
  • ISSUE_LIST, ISSUE_CREATE, PR_LIST, and SEARCH extra-field registries now use truncatedBody("body").
  • A --full flag (suppresses --fields body truncation, matching issue view) was added to issue list, issue create, pr list, and search, so the inline hint's "use --full to see complete body" is keepable on every command that offers the field.
  • Spec (Principle 3, all four Command Surface body entries), ADR 0003, and the four commands' --help text reconciled.

Deviations from the plan:
The ACs named only issue list and issue create, but the task body mandated "any later command exposing body via --fields must behave the same", so pr list and search were included too, each with a parity test.
No new e2e case — the task scoped verification to the fixture/unit tier (deterministic string processing, no live-Gitea semantics to attest to).

Verified: full suite green (387 tests), including truncated-and---full fixture tests on all four commands.

Review

Overall: LOW

  • Blast radius — Low: touches several list/search/dashboard commands, but all go through one shared truncatedBody/ExtractContext change; callers updated uniformly.
  • Reversibility — Low: pure additive --full flag plus a truncation swap; trivial to revert, no migrations or breaking removals.
  • Test coverage — Low: each affected command (issue create/list, pr list, search) gets both truncated and --full fixture tests in the diff.
  • Sensitive domain — Low: no auth, permissions, concurrency, or data migration; only output formatting of body text.
  • Size & complexity — Low: mechanical, repetitive edits threading { host, full } through calls; new helper is a small pure function.
  • Runtime criticality — Low: CLI output shaping; changes are output-only and the default (truncation) matches prior detail-view behavior.

Standards findings left unaddressed

  • Duplicated Code (judgement call) — the four --full parse/plumb sites repeat the same "--full" flag + const full = flags["--full"] === true + { now, host, full } shape. Left as-is: each command already parses its flags independently, so extracting a helper would fight the existing per-command structure. (The one hard finding — a multi-sentence spec/ADR line vs. the one-sentence-per-line rule — was fixed in the diff.)

Spec findings left unaddressed

None — all four acceptance criteria met; no wrong implementations found.

Task: `.claude/tasks/0021-body-field-truncation-ruling.md` ## Summary A single ruling on whether `--fields body` truncates, applied uniformly everywhere the `body` extra field is offered. **The ruling: it truncates.** Principle 3 already said body text truncates at 500 chars "in all contexts (list and detail alike)"; the four `--fields body` extractors were the drift, not the intent. "Raw" in the Command Surface is resolved to mean *uncleaned markdown* (short bodies still pass through byte-for-byte), never *unbounded* — an unbounded body on a list path lets `issue list --limit 30 --fields body` spill thirty full bodies into an agent's context, the exact cost Principle 3 exists to prevent. **What changed:** - New `truncatedBody()` `FieldDef` in `fields.ts` routes `body` through the same `truncateBody(value, BODY_TRUNCATE_LIMIT, host)` the detail views use, so the hint text and `cleanBody`-on-overflow are byte-identical to `issue view` / `pr view`. - `ExtractContext` gained required `host` and `full` fields; every `extractRow` call site updated (body-less ones pass `full: false`). - `ISSUE_LIST`, `ISSUE_CREATE`, `PR_LIST`, and `SEARCH` extra-field registries now use `truncatedBody("body")`. - A `--full` flag (suppresses `--fields body` truncation, matching `issue view`) was added to `issue list`, `issue create`, `pr list`, and `search`, so the inline hint's "use --full to see complete body" is keepable on every command that offers the field. - Spec (Principle 3, all four Command Surface `body` entries), ADR 0003, and the four commands' `--help` text reconciled. **Deviations from the plan:** The ACs named only `issue list` and `issue create`, but the task body mandated "any later command exposing `body` via `--fields` must behave the same", so `pr list` and `search` were included too, each with a parity test. No new e2e case — the task scoped verification to the fixture/unit tier (deterministic string processing, no live-Gitea semantics to attest to). Verified: full suite green (387 tests), including truncated-and-`--full` fixture tests on all four commands. ## Review **Overall: LOW** - Blast radius — Low: touches several list/search/dashboard commands, but all go through one shared `truncatedBody`/`ExtractContext` change; callers updated uniformly. - Reversibility — Low: pure additive `--full` flag plus a truncation swap; trivial to revert, no migrations or breaking removals. - Test coverage — Low: each affected command (issue create/list, pr list, search) gets both truncated and `--full` fixture tests in the diff. - Sensitive domain — Low: no auth, permissions, concurrency, or data migration; only output formatting of body text. - Size & complexity — Low: mechanical, repetitive edits threading `{ host, full }` through calls; new helper is a small pure function. - Runtime criticality — Low: CLI output shaping; changes are output-only and the default (truncation) matches prior detail-view behavior. ### Standards findings left unaddressed - **Duplicated Code (judgement call)** — the four `--full` parse/plumb sites repeat the same `"--full"` flag + `const full = flags["--full"] === true` + `{ now, host, full }` shape. Left as-is: each command already parses its flags independently, so extracting a helper would fight the existing per-command structure. (The one hard finding — a multi-sentence spec/ADR line vs. the one-sentence-per-line rule — was fixed in the diff.) ### Spec findings left unaddressed None — all four acceptance criteria met; no wrong implementations found.
alexion added 1 commit 2026-07-14 12:24:05 -04:00
feat: truncate --fields body uniformly (task 0021)
All checks were successful
CI / test (pull_request) Successful in 49s
CI / test (push) Successful in 49s
b5955cd7b8
Rule that the `body` extra field truncates at 500 chars like `issue view`,
resolving the spec's Principle 3 / Command Surface contradiction. Route the
`body` extractor through a new `truncatedBody()` FieldDef so `issue list`,
`issue create`, `pr list`, and `search` all present it exactly as the detail
views do, and add a `--full` flag to each to suppress truncation, keeping the
inline hint's "use --full" promise honest.
alexion merged commit b5955cd7b8 into main 2026-07-14 14:27:24 -04:00
alexion deleted branch task-0021-body-field-truncation-ruling 2026-07-14 14:27:24 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alexion/gitea-axi#21