#[allow(clippy::wildcard_imports)]
use super::*;
#[allow(clippy::too_many_lines)]
pub(super) fn descriptors() -> Vec<ToolDescriptor> {
vec![
ToolDescriptor {
name: "list_initiatives",
description: "List the initiatives in the registry, in declaration order, each with its **id**, its display name, its target date and its status (mirrors `tix initiative list`). The id is a column of its own because selecting by id is the contract and a rename must never look like a new initiative (C-002). Never fails: an empty registry is an empty list. Read-only: no write, no History entry.",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {}
}),
},
ToolDescriptor {
name: "get_initiative",
description: "Show one initiative's record, its metadata and its references, with the references resolved and diagnosed (mirrors `tix initiative show`; the resolution and diagnostics come from the shared roadmap projection). Resolved by its **stable id**; a name resolves to the same initiative. Returns the raw record fields, each reference's derived label and `resolution` (so a missing reference is visible, C-005), the source-attributed `summary`, and the ordered `diagnostics` — never a blended figure (C-004). Read-only: no write, no History entry.",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"initiative": { "type": "string", "description": "Stable initiative id, or a name that resolves to the same initiative." }
},
"required": ["initiative"]
}),
},
ToolDescriptor {
name: "create_initiative",
description: "Create an initiative (mirrors `tix initiative create`). The registry allocates a **stable generated id**, which is returned; the name is a mutable display label and not the identity (C-002). Validates the name (non-blank, unpadded, unique case-folded), the priority spelling and the reference shapes through the service, and writes through the registry's atomic boundary, so a refusal persists nothing (C-008). An unknown-but-well-formed reference is stored and stays diagnosable (C-005).",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"name": { "type": "string", "description": "Display label. Required and unique in the registry (case-folded, trimmed); never the identity." },
"outcome": { "type": "string", "description": "Optional strategic outcome." },
"owner": { "type": "string", "description": "Optional owner identity string (a bare handle or `Name <email>`); not a user account." },
"status": { "type": "string", "description": "Optional free-form initiative status — **not** a board column and not a workflow category." },
"priority": { "type": "string", "description": "Optional priority. A known spelling (`low`/`medium`/`high`) is normalized; an unknown one is stored verbatim, as the record keeps it." },
"labels": { "type": "string", "description": "Comma-separated filterable labels." },
"target_date": { "type": "string", "description": "Target date as `YYYY-MM-DD`." },
"projects": { "type": "string", "description": "Comma-separated project **ids** this initiative concerns. Each is shape-checked, never resolved: a dangling but well-formed id is stored and diagnosed by `tix roadmap`/`tix lint` (C-005)." },
"epics": { "type": "string", "description": "Comma-separated epic **ids** this initiative concerns. Shape-checked only, never resolved." },
"milestones": { "type": "string", "description": "Comma-separated milestone **names** (the existing name-keyed spelling). Stored verbatim." }
},
"required": ["name"]
}),
},
ToolDescriptor {
name: "update_initiative",
description: "Edit an initiative's fields (mirrors `tix initiative edit`). Resolved by its **stable id** (or a name). A `name` change is a **label change only**: the id is untouched, so no reference and no derived value is re-keyed (C-002). A blank optional field (`\"\"`) clears it; a blank reference list (`\"\"`) clears it. At least one field must be provided; a refusal writes nothing (C-008).",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"initiative": { "type": "string", "description": "Stable initiative id, or a name that resolves to the same initiative." },
"name": { "type": "string", "description": "New display label. The id does not change." },
"outcome": { "type": "string", "description": "New strategic outcome; `\"\"` clears it." },
"owner": { "type": "string", "description": "New owner identity string; `\"\"` clears it." },
"status": { "type": "string", "description": "New free-form status; `\"\"` clears it." },
"priority": { "type": "string", "description": "New priority; `\"\"` clears it. An unknown spelling is stored verbatim." },
"labels": { "type": "string", "description": "Replace the whole label list, comma-separated; `\"\"` clears it." },
"target_date": { "type": "string", "description": "New target date (`YYYY-MM-DD`); `\"\"` clears it." },
"projects": { "type": "string", "description": "Replace the whole project-id list, comma-separated; `\"\"` clears it. Shape-checked only, never resolved." },
"epics": { "type": "string", "description": "Replace the whole epic-id list, comma-separated; `\"\"` clears it. Shape-checked only." },
"milestones": { "type": "string", "description": "Replace the whole milestone-name list, comma-separated; `\"\"` clears it." }
},
"required": ["initiative"]
}),
},
ToolDescriptor {
name: "initiative_associate",
description: "Associate an initiative with exactly one project, epic or milestone (mirrors `tix initiative associate`; the association is part of the record, so the kind is explicit rather than guessed). The target is shape-checked and **never** resolved: a well-formed id that names nothing is stored and stays diagnosable (C-005). A repeated association is an idempotent no-op that writes no bytes; `changed` says which happened. Writes through the atomic boundary, so a refusal persists nothing (C-008).",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"initiative": { "type": "string", "description": "Stable initiative id, or a name that resolves to the same initiative." },
"kind": { "type": "string", "enum": ["project", "epic", "milestone"], "description": "The reference kind; part of the record's shape." },
"target": { "type": "string", "description": "The project id, epic id, or milestone name. Shape-checked, never resolved." }
},
"required": ["initiative", "kind", "target"]
}),
},
ToolDescriptor {
name: "initiative_dereference",
description: "Drop an explicit association from an initiative (mirrors `tix initiative dereference`). Drops only the association — never a source entity. Dropping an association that is not recorded is an idempotent no-op that writes no bytes; `changed` says which happened. Writes through the atomic boundary, so a refusal persists nothing (C-008).",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"initiative": { "type": "string", "description": "Stable initiative id, or a name that resolves to the same initiative." },
"kind": { "type": "string", "enum": ["project", "epic", "milestone"], "description": "The reference kind; part of the record's shape." },
"target": { "type": "string", "description": "The project id, epic id, or milestone name to drop." }
},
"required": ["initiative", "kind", "target"]
}),
},
ToolDescriptor {
name: "delete_initiative",
description: "Delete an initiative's **registry entry only** (mirrors `tix initiative delete --yes`). Nothing cascades: no project, epic, milestone or issue is deleted or modified, and the record's own references are returned (and printed) so an agent can see what the entry held — a missing reference is never silently repaired (C-005). The id is never reused. Requires `confirm: true`.",
input_schema: json!({
"type": "object",
"additionalProperties": false,
"properties": {
"initiative": { "type": "string", "description": "Stable initiative id, or a name that resolves to the same initiative." },
"confirm": { "type": "boolean", "description": "Must be true. Acknowledges that only the registry entry is removed and nothing else is deleted." }
},
"required": ["initiative", "confirm"]
}),
},
]
}