#[allow(clippy::wildcard_imports)]
use super::*;
#[allow(clippy::too_many_lines)]
pub(super) fn descriptors() -> Vec<ToolDescriptor> {
vec![
ToolDescriptor {
name: "bulk_preview",
description: "Plan a batch and return it WITHOUT writing. Read-only: no file, no History entry, no relationship. Returns the selected issues in order, the proposed before/after values and path changes, the validation diagnostics, and the per-item status every surface shares. An apply needs the same arguments plus `confirm: true`.",
input_schema: bulk_schema(false),
},
ToolDescriptor {
name: "triage_preview",
description: "Plan one triage decision over one issue or a selection, and return it WITHOUT writing. Read-only: no file, no History entry, no relationship. Accept, decline, and defer each name the resulting status and one `history` event; a duplicate names the typed `duplicates` relation and never merges files. A missing required reason is a refused item naming `missing_reason`, not an error. An apply needs the same arguments plus `confirm: true`.",
input_schema: triage_schema(false),
},
ToolDescriptor {
name: "view_list",
description: "List saved views in declaration order, as `tix view list` prints them (tab-separated id, name, scope, resolution). Read-only. Each entry also carries its normalized plan, preserved extensions, and diagnostics. Scope is metadata: a `user` view stores an owner/shared-with label and grants no permission and creates no account.",
input_schema: view_schema(
&[],
map_of([(
"scope",
json!({
"type": "string",
"enum": ["repository", "project", "user"],
"description": "Only views in this scope family.",
}),
)]),
),
},
ToolDescriptor {
name: "view_show",
description: "Show one saved view: its stable id, name, explicit scope, normalized plan, preserved unknown metadata, and diagnostics. Read-only. Select by stable id, or by display name when that name is unambiguous — a name shared by two scopes of equal precedence is a `scope_conflict` diagnostic, never an implicit pick. A stored plan this build cannot interpret is refused with the field that caused it, before anything could apply it.",
input_schema: view_schema(&["view"], map_of([("view", view_reference_schema())])),
},
ToolDescriptor {
name: "view_create",
description: "Save a new named view from the existing query grammar. The stable id (`v-…`) is generated by the registry, is returned, and is never reused; `name` is only a display label. Writes one `tix.toml` commit and returns an accepted outcome with the audit event, or a rejected outcome with the ordered field diagnostics that refused it. Nothing is written on rejection.",
input_schema: view_schema(
&["name"],
properties([
map_of([("name", view_name_schema())]),
view_scope_properties(),
view_plan_properties(),
]),
),
},
ToolDescriptor {
name: "view_update",
description: "Replace an existing view's definition, keeping its stable id (identity survives a rename). Merge semantics: only the fields named here change, so a rename cannot drop the plan and an unnamed plan field is carried over. Extensions this build does not interpret are preserved. A same-content update is a `no-op`: no commit is issued. Accepted and rejected outcomes are structured the same way as `view_create`.",
input_schema: view_schema(
&["view"],
properties([
map_of([
("view", view_reference_schema()),
("name", view_name_schema()),
]),
view_plan_properties(),
]),
),
},
ToolDescriptor {
name: "view_duplicate",
description: "Copy a view under a **new** stable id. The copy carries the source's scope, plan, and preserved extensions verbatim; `name` overrides the label when given. The source is validated first, so an unloadable plan cannot be duplicated into the registry.",
input_schema: view_schema(
&["view"],
map_of([
("view", view_reference_schema()),
("name", view_name_schema()),
]),
),
},
ToolDescriptor {
name: "view_delete",
description: "Remove a view **definition** only, and only with `confirm: true`. It never deletes an issue, comment, or relationship: the outcome reports whether the in-memory active marker named it. Deleting an unknown reference is rejected. Definition-only deletion is the contract, not a side effect.",
input_schema: view_schema(
&["view", "confirm"],
map_of([
("view", view_reference_schema()),
(
"confirm",
json!({
"type": "boolean",
"description": "Must be true. Acknowledges that only the saved definition is removed.",
}),
),
]),
),
},
ToolDescriptor {
name: "view_share",
description: "Replace a view's explicit scope metadata, keeping its name and plan. Scope is metadata: `repository` (the default), `project` (naming a project id), or `user` (owner/shared-with labels). It is neither authentication nor permission, and no host account is created. An inconsistent scope — share metadata on a non-share scope, a project scope with no project — is rejected with a `scope_conflict` diagnostic.",
input_schema: view_schema(
&["view"],
properties([
map_of([("view", view_reference_schema())]),
view_scope_properties(),
]),
),
},
ToolDescriptor {
name: "view_apply",
description: "Apply a saved view **read-only**: resolve it, build the board once through the existing filter path, and return the normalized plan, the applied issue numbers in board order, the board summary, the active marker, and diagnostics. No issue, comment, relationship, or `tix.toml` byte changes; a refused or unsupported plan produces no board. The active marker is informational and never overwrites live filter state.",
input_schema: view_schema(&["view"], map_of([("view", view_reference_schema())])),
},
ToolDescriptor {
name: "view_status",
description: "Report a saved plan against a live plan assembled from the plan arguments here, field by field, using the existing grammar. Read-only. With `view` the comparison is against that definition; without it the report is the explicit \"no active saved view\" diagnostic — never a silent `in_sync: true`. Divergence is informational: nothing is reconciled and no live filter is changed.",
input_schema: view_schema(
&[],
properties([
map_of([("view", view_reference_schema())]),
view_plan_properties(),
]),
),
},
]
}