You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let a user create a missing root or nested OmniFocus tag at the moment it is
assigned to tasks or projects.
In UAT, the user asked to classify inbox items with tags such as Reference, Ideas, and Contact. FocusRelay could only attach existing tag IDs, forcing
the user to leave the workflow, create tags manually, look them up, and retry.
OmniFocus itself supports creating and assigning a tag from the tag picker in one
user action.
A supplied parent must already exist. Recursively creating a missing parent
hierarchy is outside v1.
Existing ID-based add, remove, set, and clear behavior remains
unchanged.
addOrCreate may be combined with ID-based add.
Reject addOrCreate combined with set or clear, because replacement
semantics would otherwise be ambiguous.
For CLI parity, add a repeatable --tag-add-or-create-json option whose value
is one {"name":"...","parentID":"..."} object. The parent is optional for a
root tag.
Parent-scoped resolution
For each requested {name,parentID?} placement:
Trim the name and reject an empty result.
Resolve only among direct children of the specified parent, or only among
root tags when no parent is supplied.
Compare names case-insensitively:
one match: reuse it;
no match: create it at the end of that parent;
multiple matches: fail and return candidate IDs and full paths.
Identical names under different parents are valid and are not ambiguous.
Resolve or create each unique placement once per request, then reuse its
stable ID for every target.
Reject a missing or dropped parent before mutation.
Permit an on-hold parent but preview that its hierarchy may affect task
availability.
Use the documented Tag constructor with the selected parent's insertion
location. Do not reconstruct hierarchy from names when a stable parent ID is
available.
Mutually exclusive tag groups
If the selected parent reports childrenAreMutuallyExclusive == true:
inspect each target's currently assigned siblings;
preview the sibling tag that native OmniFocus assignment will remove;
use native assignment behavior rather than emulating replacement;
verify and return the complete final tag set;
do not claim unrelated tags were preserved when native mutually exclusive
behavior correctly removed a sibling.
Preview, verification, and results
Preview performs no mutation and returns, for each requested placement:
normalized name;
parent ID or root;
full path;
reuse or create;
mutually exclusive replacement warnings.
The write result returns:
created/reused tag ID;
parent ID;
full path;
created/reused status;
per-target mutation and verification results.
Verification checks both tag existence at the expected parent and assignment to
every successful target.
Failure, compensation, and retry behavior
Validate every target, parent, ambiguity, and payload rule before creating a
tag.
If a tag is created but no target assignment succeeds, remove that new unused
tag. Report both the original failure and any compensation failure.
If some targets succeed, keep the tag and report each target independently.
A retry resolves and reuses the already-created parent-scoped tag rather than
creating a duplicate.
Never report success when creation, assignment, save, or verification fails.
Preserve unrelated existing tags except for documented mutually exclusive
replacement.
Out of scope
Standalone tag taxonomy administration.
Recursive creation of multiple missing ancestor tags.
Renaming, moving, dropping, or deleting existing tags.
Use Swift Testing and direct MCP wire coverage for:
create and assign a root tag to tasks and projects;
create a child under an existing parent;
reuse an existing root or nested tag;
at least three levels of hierarchy;
the same child name under different parents;
duplicate siblings under one parent failing without mutation;
missing and dropped parent rejection;
on-hold parent preview warning;
mutually exclusive sibling replacement in preview and verification;
preservation of unrelated tags;
request-level de-duplication of repeated placements;
preview-only behavior;
partial target failure and unused-tag compensation;
retry without duplicate creation;
CLI/MCP parity;
reversible live create, assign, verify, restore, and remove.
Add controlled Kimi K2.7 Code and comparison-model journeys. The model must query #70 when the parent is ambiguous, supply a stable parent ID for nested creation,
and avoid extra tool calls when the root location is explicit.
Record first tool/operation choice, schema errors, retries, total calls,
end-to-end latency, final correctness, serialized catalog bytes, and token
estimates. Catalog size is diagnostic evidence, not a reason to reject a more
reliable user experience.
Acceptance criteria
A user can create and assign a missing root or nested tag in one approved
workflow.
Parent-scoped duplicate handling is deterministic and never guesses.
Mutually exclusive groups have truthful preview and verification.
Retrying cannot create another tag for the same placement.
Preview, compensation, per-target results, and failure reporting are explicit.
The feature reuses existing add/edit commands and does not add a public tool.
Direct MCP, Swift, model-routing, and reversible live tests pass.
User outcome
Let a user create a missing root or nested OmniFocus tag at the moment it is
assigned to tasks or projects.
In UAT, the user asked to classify inbox items with tags such as
Reference,Ideas, andContact. FocusRelay could only attach existing tag IDs, forcingthe user to leave the workflow, create tags manually, look them up, and retry.
OmniFocus itself supports creating and assigning a tag from the tag picker in one
user action.
Validation impact and dependencies
mutationcreate_tagscommand or a generic "new object" tool.User-facing acceptance journey
existing parent tag.
any mutually exclusive sibling that OmniFocus will replace.
targets, and verified without removing unrelated tags.
Public interface
Extend the tag mutation shared by
edit_tasks,edit_projects,add_tasks, andadd_projectswith:{ "addOrCreate": [ { "name": "Reference" }, { "name": "Contact", "parentID": "people-tag-id" } ] }Rules:
parentIDmeans the root tag collection.hierarchy is outside v1.
add,remove,set, andclearbehavior remainsunchanged.
addOrCreatemay be combined with ID-basedadd.addOrCreatecombined withsetorclear, because replacementsemantics would otherwise be ambiguous.
--tag-add-or-create-jsonoption whose valueis one
{"name":"...","parentID":"..."}object. The parent is optional for aroot tag.
Parent-scoped resolution
For each requested
{name,parentID?}placement:root tags when no parent is supplied.
stable ID for every target.
availability.
Use the documented
Tagconstructor with the selected parent's insertionlocation. Do not reconstruct hierarchy from names when a stable parent ID is
available.
Mutually exclusive tag groups
If the selected parent reports
childrenAreMutuallyExclusive == true:behavior correctly removed a sibling.
Preview, verification, and results
Preview performs no mutation and returns, for each requested placement:
reuseorcreate;The write result returns:
Verification checks both tag existence at the expected parent and assignment to
every successful target.
Failure, compensation, and retry behavior
tag.
tag. Report both the original failure and any compensation failure.
creating a duplicate.
replacement.
Out of scope
Test plan
Use Swift Testing and direct MCP wire coverage for:
Add controlled Kimi K2.7 Code and comparison-model journeys. The model must query
#70 when the parent is ambiguous, supply a stable parent ID for nested creation,
and avoid extra tool calls when the root location is explicit.
Record first tool/operation choice, schema errors, retries, total calls,
end-to-end latency, final correctness, serialized catalog bytes, and token
estimates. Catalog size is diagnostic evidence, not a reason to reject a more
reliable user experience.
Acceptance criteria
workflow.