---
name: Create Item
slug: create-item
category: AI Engineering
description: Create Item turns conversation context into a tracked MCP work item. It anchors bugs, features, tech debt, and observations in the right container, infers priority, and can create single items or work trees.
github: "https://github.com/jpicklyk/task-orchestrator/tree/main/claude-plugins/task-orchestrator/skills/create-item"
language: Kotlin
stars: 206
forks: 20
install: "npx degit https://github.com/jpicklyk/task-orchestrator/tree/main/claude-plugins/task-orchestrator/skills/create-item ~/.claude/skills/create-item"
installs_to: ~/.claude/skills/create-item
source_path: claude-plugins/task-orchestrator/skills/create-item/SKILL.md
collection_size: 25
category_size: 3101
collection_url: "https://dirskills.com/collections/jpicklyk/task-orchestrator"
added: 2026-09-05T05:28:57.355Z
last_synced: 2026-09-05T05:28:57.355Z
canonical_url: "https://dirskills.com/skills/create-item"
---

# Create Item

Create Item turns conversation context into a tracked MCP work item. It anchors bugs, features, tech debt, and observations in the right container, infers priority, and can create single items or work trees.

**Install:**

```bash
npx degit https://github.com/jpicklyk/task-orchestrator/tree/main/claude-plugins/task-orchestrator/skills/create-item ~/.claude/skills/create-item
```

## README

# create-item — Container-Anchored Work Item Creation

Create MCP work items intelligently from conversation context. This skill handles container anchoring, tag inference, structure decisions, and note pre-population so you don't have to.

---

## Step 1 — Infer intent from conversation

Determine from context (or from `$ARGUMENTS` if provided):
- **Title** — what is the work item?
- **Type** — bug / feature / tech debt / observation / action item / general task
- **Priority** — high / medium / low (default: medium)
- **Scope** — single item, or feature with 2+ clear distinct subtasks?

If title or type cannot be inferred with confidence, use `AskUserQuestion` with concrete options. Do not ask open-ended questions.

---

## Step 2 — Scan containers

Resolve the project rootId first: check session context for a rootId injected by the SessionStart hook, or read `.taskorchestrator/config.yaml`'s top-level `project.rootId` (a file read, not an MCP call).

**If a rootId is known:**
```
query_items(operation="overview", anchorId="<rootId>", includeChildren=true)
```
Category containers (Bugs, Features, Tech Debt, etc.) are expected as direct children of the project root — anchor new items there. **Exception:** `agent-observation` items always stay at global depth 0, outside any project root, regardless of whether a rootId is known — they're process-global, not project-scoped.

**If no rootId is known**, fall back to an unscoped scan and the classification below (this is also the exact behavior from before project scoping existed):
```
query_items(operation="overview", includeChildren=true)
```

Classify the existing structure:

| Pattern | Classification |
|---------|---------------|
| Depth-0 item with category-named children (Bugs, Features, etc.) | **Hierarchical** — project root exists |
| Category-named items at depth 0, no project root | **Flat** — use category containers directly |
| No items at all | **Empty** — offer to create project root |

---

## Step 3 — Container anchoring

### Category mapping

| Item type | Target category container | Signal keywords |
|-----------|--------------------------|-----------------|
| Bug / error / crash / unexpected behavior | Bugs | bug, error, crash, broken, failure, wrong, exception |
| Feature / enhancement / new capability | Features | feature, add, implement, new, support, capability, enhancement |
| Tech debt / refactor / cleanup / improvement | Tech Debt | refactor, cleanup, simplify, debt, improve, migrate, restructure |
| Observation / friction / optimization / missing capability | Observations | slow, performance, optimize, latency, friction, missing, gap, observe |
| Action item / follow-up / reminder / TODO | Action Items | todo, follow up, remind, action, track, check |
| General / unclear | Best-effort match — ask if uncertain | |

### Anchoring decision tree

```
Hierarchical structure:
  Matching category found under project root → use as parentId
  Category missing under project root → create it, then use as parentId

Flat structure:
  Matching category at depth 0 → use as parentId
  Category missing at depth 0 → create it, then use as parentId

Empty (no project root exists):
  → AskUserQuestion: "No project root container exists yet.
    Would you like to create one for this project?"
  → Yes: create project root → create category under it → create item
  → No: create category container at depth 0 → create item under it
```

**Exception (all branches):** `agent-observation` items never anchor under a project root or category container — they are standalone process-global items (each its own root, not a child of any container) that live at depth 0 alongside (not under) any project root, per Step 2.

---

## Step 4 — Set type via schema discovery

Read `.taskorchestrator/config.yaml` to discover available schemas (this is a file read, not an MCP call). In Docker, the config is mounted at a path controlled by the `AGENT_CONFIG_DIR` env var — read `$AGENT_CONFIG_DIR/.taskorchestrator/config.yaml` if that variable is set, otherwise use `.taskorchestrator/config.yaml` relative to the working directory.

Schemas are defined under `work_item_schemas:` (preferred) or `note_schemas:` (legacy). Each schema key is a **type identifier** that activates gate enforcement when set as the item's `type` field. Tags remain available for categorization but are no longer the primary schema selector.

**Error handling:** If the config file is not found, cannot be read, or contains invalid YAML, skip schema-based type assignment and create the item without a type. Inform the user: "No schema config found — item created without a type." Do not abort item creation due to a missing or malformed config.

**Infer the best schema match from context:**

| Context signal | Schema to apply |
|----------------|-----------------|
| Feature, enhancement, new capability | Match against feature-related schema keys in config (if any exist) |
| Bug, error, crash, unexpected behavior | Match against bug-related schema keys in config (if any exist) |
| Observation, friction, optimization, missing capability | Match against observation-related schema keys in config (if any exist) |

If the inferred schema key exists in the config, set it as the item's `type` value. If the key does not exist in the config (e.g., no `bug-fix` schema defined), leave `type` unset — do not assign a type that has no matching schema.

**When no confident match can be inferred:**
- If a schema named `default` exists in the config, use it as the fallback — this lets users control what happens to unclassified items
- Otherwise, ask the user which schema to apply via `AskUserQuestion`, listing the available schema keys from the config
- Include a "No schema" option for items that should be schema-free

**If no config file exists**, skip type assignment entirely — all items will be schema-free.

> **Tags vs. type:** Set `type` for schema selection. Use `tags` only for additional categorization/filtering that is independent of schema matching.

### Trait discovery

While reading the config, also check for a top-level `traits:` section. Each key under `traits:` is a trait name that can be assigned to items via the `traits` parameter. Traits add additional note requirements on top of the base schema.

**Assess whether any configured traits apply based on conversation context:**

| Context signal | Trait to consider |
|----------------|-------------------|
| Database migration, schema change, ALTER TABLE | `needs-migration-review` (if configured) |
| MCP tool parameter changes, response shape changes | `needs-api-compat-review` (if configured) |
| Plugin skill/hook behavior changes | `needs-plugin-update` (if configured) |
| Auth, input validation, external data handling | `needs-security-review` (if configured) |
| Hot path changes, per-request work, startup impact | `needs-perf-review` (if configured) |

Only assign traits that exist in the config. If no `traits:` section exists, skip trait assignment entirely.

If multiple traits apply, combine them: `traits: "needs-migration-review,needs-api-compat-review"`

**Resource-bearing traits (informational):** if a chosen trait's config entry carries its own `resources:` list, note this to the user — items with that trait will acquire an exclusive lease on the named resource key(s) when they enter work phase, and `advance_item(start)` can transiently fail with `resource_unavailable` if another item currently holds it. No extra action is needed here; this is just so the choice isn't a surprise later.

---

## Step 5 — Create the item(s)

**Single item** (bug, observation, standalone task, action item):
```
manage_items(operation="create", items=[{
  title: "<inferred title>",
  summary: "<1-2 sentence description from context>",
  priority: "<inferred priority>",
  type: "<schema key or omit>",
  tags: "<categorization tags or omit>",
  parentId: "<category container UUID>"
  // Additional fields like `complexity` are optional — omit if not relevant
}])
```

**Work tree** (feature with 2+ distinct subtasks clearly described):
```
create_work_tree(
  root={title, summary, priority, type: "<schema key>"},
  children=[{ref: "t1", title: "..."}, {ref: "t2", title: "..."}, ...],
  parentId="<category container UUID>"
)
```

Default to single item when scope is unclear. Use `create_work_tree` only when the conversation explicitly names multiple distinct subtasks.

---

## Step 6 — Pre-fill required notes

Check `expectedNotes` in the create response. For each note where `required: true` and `role: "queue"`:
- Extract relevant content from the conversation
- Resolve guidance via `query_items(operation="schema", itemId="<uuid>")` (`expectedNotes` itself is keys-only) — use its `guidance` field as the authoring instruction, taking precedence over free-form inference.
- Batch all notes into a single call rather than one call per note:
  ```
  manage_notes(operation="upsert", notes=[
    {itemId: "<bug-uuid>",     key: "diagnosis",       role: "queue", body: "..."},
    {itemId: "<feature-uuid>", key: "feature-summary", role: "queue", body: "..."}
  ])
  ```
  (note keys come from each item's schema `expectedNotes` — `diagnosis` for `bug-fix`, `feature-summary` for `feature-implementation`; a single call may batch notes across multiple items)
- If conversation content is too sparse for a meaningful note body, leave it — do not fabricate content

---

## Step 7 — Report

```
✓ Created: [title] (`short-id`)
  Path: [container path, e.g. "Features" or "Project Root › Features"]
  Tags: [tags, or "none"]
  Notes pre-filled: [key names, or "none"]
```

If a new category container was created, add one line:
```
  ↳ Created new container: [category name] under [parent]
```

---

## Troubleshooting

**No containers found in overview**
- Cause: Fresh workspace with no existing structure
- Solution: The skill handles this automatically — it will offer to create a project root and category containers via `AskUserQuestion`

**Wrong container chosen for the item**
- Cause: Item type was ambiguous or the category mapping didn't match intent
- Solution: Move the item after creation with `manage_items(operation="update", items=[{itemId: "<uuid>", parentId: "<correct-container-uuid>"}])`

**Type not matching a schema — `expectedNotes` is empty**
- Cause: The `type` field doesn't match any key in `.taskorchestrator/config.yaml`, or the config hasn't been loaded
- Solution: Verify the type matches a `work_item_schemas:` (or `note_schemas:`) key exactly. If the config was recently changed, run `/mcp` to reconnect the server

**Expected notes not returned after item creation**
- Cause: MCP server caches schemas on first access — config changes require reconnect
- Solution: Run `/mcp` in Claude Code to reconnect the server, then retry the create operation
