Skip to content

feat(section): add description to create and update#396

Merged
lmjabreu merged 4 commits into
mainfrom
lmjabreu/section-descriptions-cli
Jun 11, 2026
Merged

feat(section): add description to create and update#396
lmjabreu merged 4 commits into
mainfrom
lmjabreu/section-descriptions-cli

Conversation

@lmjabreu

Copy link
Copy Markdown
Contributor

What

Surfaces section descriptions (26Q2 Project Essentials) in the CLI, mirroring the project/task description surface.

  • td section create and td section update accept --description <text> and --stdin
  • td section update no longer requires --name — description-only updates work, guarded by NO_CHANGES
  • Curated --json output now includes description

Same contract across descriptions

Identical to projects and tasks: the --description / --stdin flags, the CONFLICTING_OPTIONS guard, and the JSON essential field. Clearing follows the task pattern (pipe empty input via --stdin). The typed-args pattern matches the project PR — only the escape-hatch fields sit outside the SDK types (see below), keeping the rest of the payload compile-checked.

⚠️ SDK dependency (blocks full read-side behaviour)

@doist/todoist-sdk (pinned 10.3.2) does not yet model section descriptions, even though the backend shipped them on 2026-06-10:

  • SectionSchema is a stripping z.object with no description, so the SDK drops it from section reads. JSON output will not surface description until the SDK adds it.
  • UpdateSectionArgs requires name and omits description, so description-only updates and the description field need a localized escape hatch (documented inline).

The write path works at runtime today (the REST client forwards the field). The SDK gap is called out with comments in create.ts / update.ts. This PR needs an SDK release (add description: z.string().nullable() to SectionSchema; add description + optional name to UpdateSectionArgs) before the read side fully lands. Opening as a draft for that reason.

Scope

  • In scope: section descriptions in create / update / JSON.
  • Non-goals: a section view text block (no such command exists; sections expose detail via --json), and the MCP (separate PR).

Backend reference (asymmetry vs projects)

Section update clears with null (NULL_CLEARS), where project clears with "" (NULL_KEEPS_UNCHANGED). The CLI sends what --stdin yields; the exact section clear wire value is a follow-up to confirm once the SDK exposes the field.

Testing

  • New unit tests: create (--description, --stdin, conflict), update (description-only, clear via empty --stdin, NO_CHANGES, conflict), and JSON regression guards asserting description survives the curated projection.
  • Full suite green (1701 tests), type-check, lint/format, build all pass. Dry-run smoke-tested.

🤖 Generated with Claude Code

@lmjabreu

Copy link
Copy Markdown
Contributor Author

@doistbot /review

@doistbot doistbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This cleanly implements section descriptions by mirroring the established project and task patterns in the CLI.

Few things worth tightening:

  • Agent skill docs: The new --description and --stdin flags need to be added to SKILL_CONTENT in src/lib/skills/content.ts per the repository guidelines.
  • Argument mapping and types: Empty string descriptions are currently dropped by a truthiness check, and the Partial<SectionUpdateArgs> SDK workaround could be narrowed (e.g., using Omit) to preserve type safety for other fields.
  • Network efficiency: The update command fetches the existing section unconditionally, which creates a redundant blocking API call for description-only updates.
  • Test precision: A --stdin paired with --dry-run test is needed to ensure previews don't accidentally hang, and the JSON "regression guard" should ideally be adjusted since it currently mocks an SDK response shape that hasn't shipped yet.

Share FeedbackReview Logs

Comment thread src/commands/section/index.ts
Comment thread src/commands/section/create.ts
Comment thread src/commands/section/update.ts Outdated
Comment thread src/commands/section/update.ts
Comment thread src/commands/section/section.test.ts
Comment thread src/commands/section/section.test.ts Outdated
@lmjabreu

Copy link
Copy Markdown
Contributor Author

@doistbot /review

@doistbot doistbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This cleanly introduces section descriptions to the CLI, mirroring the task and project patterns while gracefully handling the temporary SDK limitations.

Few things worth tightening:

  • Map empty --stdin input to null during updates so the description actually clears as advertised.
  • Skip the getSection network roundtrip for name changes when the --quiet flag is active.
  • Add a --dry-run test for the update --stdin path to ensure the API isn't accidentally called and input isn't consumed.
  • Include an update example using --stdin in SKILL_CONTENT to keep the agent command reference in sync.

I also included a few optional follow-up notes in the details below.

Optional follow-up notes (2)
  • [P3] src/commands/section/section.test.ts:231: This regression guard is still living at the command seam even though the pinned SDK/mock layer can't currently return section.description. That makes the test depend on an impossible response shape instead of the behavior this PR actually owns: the curated projection in formatJson/SECTION_ESSENTIAL_FIELDS. Please move this assertion to src/lib/output.test.ts (same for the update case below) and keep the command test focused on wiring.
  • [P3] src/commands/section/section.test.ts:872: This mock for getSection is no longer needed. Since description-only updates now actively skip fetching the existing section, this endpoint is never called in this scenario. The same applies to the empty stdin test on line 895.

Share FeedbackReview Logs

Comment thread src/commands/section/update.ts Outdated
Comment thread src/commands/section/update.ts Outdated
Comment thread src/commands/section/section.test.ts Outdated
Comment thread src/lib/skills/content.ts
lmjabreu and others added 3 commits June 11, 2026 12:01
Surface section descriptions (26Q2 Project Essentials) in the CLI, mirroring
the project and task description surface:

- `section create` / `update` accept `--description <text>` and `--stdin`
- `section update` no longer requires `--name`; description-only updates work,
  guarded by NO_CHANGES
- curated `--json` output now includes `description`

Same contract as projects/tasks: the `--description` / `--stdin` flags, the
CONFLICTING_OPTIONS guard, and the JSON essential field. Clearing follows the
task pattern (pipe empty input via `--stdin`).

SDK dependency: `@doist/todoist-sdk` does not yet model section descriptions.
Its `SectionSchema` strips `description` on reads, and `UpdateSectionArgs`
requires `name` and omits `description`. The write path works at runtime (the
REST client forwards the field), but JSON output will not surface `description`
until the SDK adds it to the section read schema and args. Tracked in the code
with TODO-style comments; needs an SDK release before this fully lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Skip the redundant `getSection` fetch on description-only updates; only fetch
  the existing name when renaming (for the "old → new" message).
- Replace the `Partial<SectionUpdateArgs>` workaround with an explicit
  `{ name?; description? }` arg type plus the call-site SDK cast.
- Document section `--description` / `--stdin` in SKILL_CONTENT (per AGENTS.md)
  and regenerate SKILL.md.
- Add a `--stdin --dry-run` test (reads stdin, previews, no API call) and
  clarify that the JSON regression guard simulates the post-SDK response shape.

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

SDK 10.4.0 (Doist/todoist-sdk-typescript#620) models section descriptions:
`AddSectionArgs` / `UpdateSectionArgs` carry `description`, `UpdateSectionArgs`
makes `name` optional (RequireAtLeastOne), and the section read schema exposes
`description` — so section JSON output now surfaces it for real.

- Drop the create-section description cast (now typed by the SDK).
- Update-section: empty `--stdin` now clears via `null` (backend NULL_CLEARS),
  not an empty string. The remaining cast bridges RequireAtLeastOne, which a
  dynamically-built partial can't satisfy statically (the NO_CHANGES guard
  guarantees at least one field at runtime).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lmjabreu lmjabreu marked this pull request as ready for review June 11, 2026 11:04
@lmjabreu lmjabreu force-pushed the lmjabreu/section-descriptions-cli branch from c21eab4 to 09f4eef Compare June 11, 2026 11:04
@doistbot doistbot requested a review from rfgamaral June 11, 2026 11:05

@doistbot doistbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This cleanly introduces section descriptions to the CLI and aligns nicely with our established project and task patterns.

Few things worth tightening:

  • Skip the blocking getSection network fetch when updating a section name in --quiet mode.
  • Add --stdin usage examples to SKILL_CONTENT for section update and regenerate SKILL.md to keep AI agents in sync.
  • Include a test for the --stdin --dry-run update workflow to ensure the preview output is correct and the API is safely bypassed.

I also included a few optional follow-up notes in the details below.

Optional follow-up notes (3)
  • [P3] src/commands/section/section.test.ts:232: Since package.json shows the SDK was bumped to 10.4.0 in this PR (adding native description support), this comment about simulating the "post-SDK response" because it "strips it today" is likely stale. The same applies for the update test comment on line 276.
  • [P3] src/commands/section/section.test.ts:872: This getSection mock is unused and no longer needed since description-only updates actively bypass fetching the existing section. The same applies to the empty stdin test below on line 895.
  • [P3] src/commands/section/section.test.ts:207: The new tests in this file are hand-building section payloads instead of starting from fixtures.sections.*, which is the repo’s standard for mock entities. Reusing fixtures here would keep these cases aligned with SDK shape changes and make the suite less brittle.

Share FeedbackReview Logs

Comment thread src/commands/section/update.ts Outdated
Comment thread src/lib/skills/content.ts
Comment thread src/commands/section/section.test.ts
- Skip the `getSection` fetch under `--quiet` too (only fetch the old name when
  renaming AND we'll print the result), avoiding a redundant blocking roundtrip.
- Document `section update --stdin` (empty-input clear) in SKILL_CONTENT and
  regenerate SKILL.md (AGENTS.md sync requirement).
- Add a `section update --stdin --dry-run` test asserting stdin is read but the
  API (updateSection/getSection) is not called.

The empty-stdin→null clear (P1) already landed with the 10.4.0 bump; verified
the pushed tip sends `null` and is covered by a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lmjabreu lmjabreu merged commit a2ccb4e into main Jun 11, 2026
5 checks passed
@lmjabreu lmjabreu deleted the lmjabreu/section-descriptions-cli branch June 11, 2026 18:24
doist-release-bot Bot added a commit that referenced this pull request Jun 11, 2026
## [1.74.0](v1.73.4...v1.74.0) (2026-06-11)

### Features

* **section:** add description to create and update ([#396](#396)) ([a2ccb4e](a2ccb4e))
@doist-release-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.74.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants