Skip to content
SHAMPOO

Tool catalogue

upsert_note_by_title_project

Write · Ordinary · Tasks and notes

upsert_note_by_title_project

  • Category: tasks
  • Access: write
  • Audience: ordinary (an ordinary user normally calls this directly)

Purpose

Creates a note or updates the existing note with the same normalized title within the same project. The idempotent write surface for durable research and decision notes: repeated runs converge on one note instead of creating near-duplicates.

Arguments

Required: title.

Optional: description, notes, priority, project, section, update_if_found.

  • title: Note title (required).
  • description: Primary long-form note body. Note: Primary long-form content. notes is only for auxiliary or machine-readable metadata.
  • notes: Optional auxiliary/internal metadata.
  • priority: Priority for new notes; updates only when explicitly set.
  • project: Project tag for matching and grouping. Note: Empty or absent means untagged, which needs an explicit untagged grant.
  • section: Section for new notes; updates only when explicitly set. Note: Defaults to next and priority to medium on creation; on update they change only when explicitly set.
  • update_if_found: When false, return the existing row without mutation. Note: When false, a matched note is returned untouched with action existing.

Result

JSON object with task_id, title, type (always note), action (created, updated, or existing), and matched_on (always normalized_title_project). Creation also returns status not_started; updates return the changed fields list.

Boundaries

Matching and creation stay inside the selected profile boundary and the caller's project grants. Out-of-scope projects deny with a generic scope message; untagged writes fail closed without the untagged grant.

Lifecycle / side effects

Creates the note or applies the supplied fields through the canonical mutation path, recording an audit/history event. Matching is by normalized title plus project. No undo tool exists; later movement uses update_task, which preserves history per the no-delete invariant.

Errors

Blank title is rejected. Unknown arguments are rejected (strict validator). Out-of-scope projects deny generically. If the operation fails, nothing is partially created (atomic).

Example

{
  "description": "Chosen because WAL tolerates concurrent writers.",
  "project": "shared-ops",
  "title": "Bus Timeout Decision"
}

Result shape:

{
  "action": "created",
  "matched_on": "normalized_title_project",
  "status": "not_started",
  "task_id": "<uuid>",
  "title": "Bus Timeout Decision",
  "type": "note"
}

task_id is assigned by the server; the placeholder stands for the returned UUID.

See also

create_task_or_note, update_task, query_tasks, find_by_title.

On this page