Allow setting/moving a note's column #4

Closed
opened 2026-08-09 19:52:11 -05:00 by mcp-gateway · 2 comments
Member

Filed from halfst/mpx-engine #120. Blocks person-sync.

What's needed

A way to set a note's column_id on an existing note — either as a parameter on ticktick-update-note or as a dedicated move tool.

column_id is already returned on read by list-notes and get-note. This is the write side.

Why it blocks

Sync Operating Spec §3 makes column placement a required, recurring operation for the People mirror, in both directions:

Each note carries its section in a section: frontmatter key — that key is the SoT (Obsidian-owned) — and the note-task lives in the matching column. On reconcile, place/move the card into the column its section: names; if Ethan re-files a card in TickTick, treat like an office-jot and pull the new section back into section:.

The pull-back half works today — column_id is readable, and mpx-engine #136 resolves it against the Registry's eleven People columns to derive section. The push half has no mechanism at all, so a section: change in the vault can never reach TickTick.

create-note reportedly accepts a column at creation time (§4.2: "create with create_note (title/content/column only)"), so the concept exists on write — it just isn't available after creation.

Acceptance

  • Set column_id on an existing note without touching its body. Critical — update-note's content parameter replaces the whole body, so a move that requires round-tripping the content is a destructive rewrite waiting to happen. That exact hazard is why note write-back was pulled from the sweep in mpx-engine #81 decision 2.
  • A column id belonging to a different project is rejected rather than silently ignored.
  • Works for kind: NOTE objects specifically — the People mirror and Mission Control are both NOTE projects.

Unblocks

halfst/mpx-engine #120 — the person-sync push path, Sync Spec §3 section placement.

Filed from `halfst/mpx-engine` #120. **Blocks person-sync.** ## What's needed A way to set a note's `column_id` on an existing note — either as a parameter on `ticktick-update-note` or as a dedicated move tool. `column_id` is already returned on read by `list-notes` and `get-note`. This is the write side. ## Why it blocks `Sync Operating Spec` §3 makes column placement a required, recurring operation for the People mirror, in both directions: > Each note carries its section in a `section:` frontmatter key — that key is the SoT (Obsidian-owned) — and the note-task lives in the matching column. **On reconcile, place/move the card into the column its `section:` names**; if Ethan re-files a card in TickTick, treat like an office-jot and **pull the new section back into `section:`**. The pull-back half works today — `column_id` is readable, and mpx-engine #136 resolves it against the Registry's eleven People columns to derive `section`. The push half has no mechanism at all, so a `section:` change in the vault can never reach TickTick. `create-note` reportedly accepts a column at creation time (§4.2: *"create with `create_note` (title/content/column only)"*), so the concept exists on write — it just isn't available after creation. ## Acceptance - [ ] Set `column_id` on an existing note without touching its body. **Critical** — `update-note`'s `content` parameter replaces the whole body, so a move that requires round-tripping the content is a destructive rewrite waiting to happen. That exact hazard is why note write-back was pulled from the sweep in mpx-engine #81 decision 2. - [ ] A column id belonging to a different project is rejected rather than silently ignored. - [ ] Works for `kind: NOTE` objects specifically — the People mirror and Mission Control are both NOTE projects. ## Unblocks `halfst/mpx-engine` #120 — the person-sync push path, Sync Spec §3 section placement.
Author
Member

Worth recording before this closes: the headline ask here was already shipped.

ticktick-update-note has accepted column_id since v0.2.0, at all three layers (tool → handler → client), and the deployed gateway exposes it today — I checked the live tool schema, not just the source:

"column_id": {
  "anyOf": [{"type": "string"}, {"type": "null"}],
  "description": "Place the note in this kanban column id (from list_columns)…"
}

It also does not touch the body: update_note re-reads the full raw payload and overrides only the fields you pass, so a column move has never required round-tripping content. The destructive-rewrite hazard this issue (correctly) worried about doesn't apply to that path.

The Sync Spec §3 caveat that motivated the issue — "the push half has no mechanism at all" — was stale rather than wrong-at-the-time. Worth fixing in the spec so it doesn't generate a second copy of this issue later.

What was genuinely missing is the third item on the acceptance list: a column id from a different project was silently ignored, because v2 accepts and drops it. That's now a loud api error, validated against the destination project so a project+column move in one call still works. Fixed in #11.

Filing this was still the right call — it surfaced a real bug and corrected a stale spec. Just noting it so the "blocks person-sync" framing doesn't outlive the fact.

Worth recording before this closes: **the headline ask here was already shipped.** `ticktick-update-note` has accepted `column_id` since v0.2.0, at all three layers (tool → handler → client), and the deployed gateway exposes it today — I checked the live tool schema, not just the source: ```json "column_id": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Place the note in this kanban column id (from list_columns)…" } ``` It also does not touch the body: `update_note` re-reads the full raw payload and overrides only the fields you pass, so a column move has never required round-tripping `content`. The destructive-rewrite hazard this issue (correctly) worried about doesn't apply to that path. The Sync Spec §3 caveat that motivated the issue — "the push half has no mechanism at all" — was stale rather than wrong-at-the-time. Worth fixing in the spec so it doesn't generate a second copy of this issue later. **What was genuinely missing** is the third item on the acceptance list: a column id from a *different* project was silently ignored, because v2 accepts and drops it. That's now a loud `api` error, validated against the destination project so a project+column move in one call still works. Fixed in #11. Filing this was still the right call — it surfaced a real bug and corrected a stale spec. Just noting it so the "blocks person-sync" framing doesn't outlive the fact.
ethan referenced this issue from a commit 2026-08-09 20:37:52 -05:00
Author
Member

Closing — shipped in v0.5.0.

Acceptance list, final state:

  • Set column_id on an existing note without touching its body — already true since v0.2.0. update_note re-reads the full raw payload and overrides only what you pass, so a column move has never round-tripped content.
  • A column id belonging to a different project is rejected rather than silently ignored — the one genuinely missing piece. Now raises an api error, validated against the destination project so a project+column move in a single call still works. Landed in #11.
  • Works for kind: NOTE — covered by unit and live tests.

Related, from #7 in the same release: update_note now takes append/prepend, so the destructive read-modify-write this issue warned about has a safe alternative for body edits too.

Closing — shipped in **v0.5.0**. Acceptance list, final state: - [x] **Set `column_id` on an existing note without touching its body** — already true since v0.2.0. `update_note` re-reads the full raw payload and overrides only what you pass, so a column move has never round-tripped `content`. - [x] **A column id belonging to a different project is rejected rather than silently ignored** — the one genuinely missing piece. Now raises an `api` error, validated against the *destination* project so a project+column move in a single call still works. Landed in #11. - [x] **Works for `kind: NOTE`** — covered by unit and live tests. Related, from #7 in the same release: `update_note` now takes `append`/`prepend`, so the destructive read-modify-write this issue warned about has a safe alternative for body edits too.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
halfst/ticktick-mcp#4
No description provided.