14 KiB
Created
Created by tickets.sh create.
Decision
Decision: keep Ticket tool behavior mostly in the ticket crate and use pod only as a thin built-in feature adapter.
Rationale:
ticketshould own the Ticket domain/backend and the behavior of Ticket operations.pod::featureis still owned by thepodcrate, so feature installation/authority wiring cannot be fully crate-contained without extracting a lowerfeature-apicrate.- Extracting
feature-apiis explicitly out of scope for this ticket. - Putting Ticket tools in
crates/toolswould repeat the Task tool responsibility problem.
Dependency shape:
ticket -> llm-worker # Tool/ToolDefinition implementation only
pod -> ticket # built-in feature adapter and backend-root wiring
Forbidden:
ticket -> pod
Implementation direction:
crates/ticketmay add Ticket tool input/output types and Tool implementations.crates/pod/src/feature/builtin/ticket.*should only install/register those tools throughFeatureContributionand resolve host/backend authority.- Ticket tools must operate through typed
TicketBackend/LocalTicketBackend, not throughtickets.shor generic filesystem writes.
Plan
Preflight result: implementation-ready.
Prerequisites are complete:
ticket-local-files-backendadded the typed Ticket backend andLocalTicketBackend.feature-api-authority-separationclarified host-authority naming inpod::feature.
Scope for implementation:
- Add the MVP Ticket tool surface: create/list/show/comment/review/status/close/doctor.
- Keep Ticket tool behavior in
crates/ticketand use a thinpodadapter for built-in feature registration and backend-root/authority wiring. - Do not implement Intake workflow, Orchestrator routing, TUI changes, external trackers, MCP/plugin loading, scheduler/lease behavior, or
work-items/rename.
Detailed delegation intent is recorded in artifacts/delegation-intent.md.
Review: approve
External review: Ticket built-in feature tools
1. Result
approve
2. Summary of implementation
The implementation adds Ticket tool behavior in crates/ticket/src/tool.rs, exposes the eight MVP tools (TicketCreate, TicketList, TicketShow, TicketComment, TicketReview, TicketStatus, TicketClose, TicketDoctor) over LocalTicketBackend, and wires them into pod through a thin built-in feature adapter in crates/pod/src/feature/builtin/ticket.rs.
The Pod side declares HostAuthority::TicketBackend { root }, validates/canonicalizes <workspace>/work-items before registering tools, and contributes the tool definitions through the existing feature contribution path. No Ticket implementation was added to crates/tools, and the implementation does not shell out to tickets.sh.
3. Requirement-by-requirement assessment
- Ticket crate owns tool types and
llm-worker::tool::Toolimplementations: satisfied.crates/ticket/src/tool.rscontains the input/output structs, schemas, tool definitions, and backend calls;ticketdoes not depend onpod. - Pod adapter is thin: satisfied.
crates/pod/src/feature/builtin/ticket.rsresolves the local backend root, declares feature metadata/authority, and registersticket::tool::ticket_tools(...). - No Ticket tools in
crates/tools: satisfied. Focused search found no Ticket tool code undercrates/tools. - Tool names/schemas: satisfied. The implemented names match the requested MVP surface, and schemas are generated from typed serde/schemars input structs.
- Tools use
LocalTicketBackend, nottickets.shor generic filesystem writes: satisfied. Tool execution calls typed backend methods directly. - Backend root resolution: satisfied for this slice. The adapter resolves
<workspace>/work-items, canonicalizes it, requires it to be a directory withopen/,pending/, andclosed/, and registers no tools when unusable. HostAuthority::TicketBackend { root }: satisfied. A Ticket-specific authority is used rather than generic filesystem authority, and each registered tool contribution requires that authority.- Normal PreToolCall/tool permission path: satisfied. Tools are registered through the normal Worker/ToolRegistry path; no bypass was introduced.
- Bounded, model-readable outputs: satisfied. List/doctor/show outputs are JSON with explicit limits and truncation metadata; show truncates item/thread/resolution bodies and bounds returned event/artifact metadata.
tickets.sh doctorcompatibility: satisfied by review and tests present in the implementation. Create/comment/review/status/close paths write the existing work-item layout and thread event format;TicketStatusnow appends a status event while preserving doctor compatibility.- Existing backend behavior: no regression found in the touched backend code. The only backend behavior change in this commit is status-change thread event emission plus
updated_atvia the shared append path. Cargo.lock/package.nix: changes appear necessary and safe for the newticket -> llm-worker/schemars/serde/...andpod -> ticketdependencies;cargoHashwas updated accordingly.- Out-of-scope work: no Intake workflow, Orchestrator routing, TUI changes, scheduler, external tracker, MCP/plugin loading, feature-api extraction, or unrelated refactor was found.
4. Blockers
None.
5. Non-blockers / follow-ups
- The feature install report records the Ticket feature as installed even when the backend root is unusable and no tools are registered. This is fail-closed for tool availability, but surfacing the diagnostic more visibly may be useful later if users expect Ticket tools and the root is missing.
HostAuthority::TicketBackend { root }is declared from the pre-canonical backend path while the actual backend uses the canonicalized root. This is acceptable in the current grant-all built-in host flow, but future explicit grant/config comparisons should use a normalized representation consistently.
6. Validation assessed or rerun
Reran focused read-only validation:
cd /home/hare/Projects/yoi/.worktree/ticket-built-in-feature-tools && git diff --check develop...HEAD && ./tickets.sh doctor
Result:
doctor: ok
Also inspected:
git diff develop...HEAD/ changed file listcrates/ticket/src/lib.rscrates/ticket/src/tool.rscrates/pod/src/feature/builtin/ticket.rscrates/pod/src/controller.rscrates/pod/src/feature.rs- relevant Cargo/package changes
- absence of Ticket tool code in
crates/tools
I did not rerun cargo test, cargo check, or nix build because this external review was constrained to not modify source/worktree state; those commands normally write build artifacts.
7. Residual risk
The remaining risk is mainly operational: full compile/test/Nix validation was not rerun by this reviewer. Based on code inspection and the focused checks above, the implementation matches the agreed architecture and is ready to merge after the normal build/test evidence is accepted.
Implementation report
Implementation report: ticket-built-in-feature-tools
Worktree / branch
- Worktree:
/home/hare/Projects/yoi/.worktree/ticket-built-in-feature-tools - Branch:
work/ticket-built-in-feature-tools
Commit
afd7f04 feat: add built-in ticket tools
Summary
Added the MVP Ticket tool surface as built-in Pod tools while preserving the agreed ownership split:
crates/ticketowns Ticket tool behavior.crates/podowns only the built-in feature adapter and backend-root/host-authority wiring.crates/toolsremains unchanged and does not contain Ticket tools.
The implementation exposes Ticket operations through typed LocalTicketBackend calls rather than shelling out to tickets.sh or granting generic filesystem write access.
Final module layout
crates/ticket/src/tool.rs- Ticket tool input/output types.
- JSON-schema-backed tool definitions.
- Bounded JSON output shaping.
llm_worker::Toolimplementations.ticket_tools(...)factory.
crates/ticket/src/lib.rs- Exports
pub mod tool. - Updates
set_statusto append astatus_changedevent so status moves remain doctor-clean.
- Exports
crates/pod/src/feature/builtin/ticket.rs- Thin built-in Ticket feature adapter.
- Resolves and validates
<workspace>/work-items. - Declares
HostAuthority::TicketBackend { root }. - Registers Ticket tools through
FeatureContribution.
crates/pod/src/feature/builtin.rs- Exports the built-in Ticket feature adapter.
crates/pod/src/controller.rs- Installs the Ticket built-in feature alongside existing built-ins.
crates/pod/src/feature.rs- Adds explicit
HostAuthority::TicketBackend { root }.
- Adds explicit
Tool surface
Implemented tools:
TicketCreateTicketListTicketShowTicketCommentTicketReviewTicketStatusTicketCloseTicketDoctor
Input schemas are generated from typed serde/schemars structs. Outputs are bounded JSON in ToolOutput.content with concise summaries.
Bounds include:
TicketList: default/max100/200.TicketShow: recent events default/max20/100; artifacts default/max50/200; Markdown body bytes default/max16 KiB/64 KiB.TicketDoctor: diagnostics default/max100/500.
TicketStatus intentionally handles open and pending; closed requires TicketClose so resolution.md is written.
Backend root / authority wiring
- Pod adapter resolves the local backend root as
<workspace>/work-items. - The root is canonicalized and validated to contain
open/,pending/, andclosed/. - Missing/unusable roots register no Ticket tools and emit a warning diagnostic; arbitrary directories are not silently created.
- Registered tools require typed
HostAuthority::TicketBackend { root }, not generic filesystem authority. - Tool calls still use the normal feature contribution / ToolRegistry / PreToolCall path.
Changed files
Cargo.lockcrates/pod/Cargo.tomlcrates/pod/src/controller.rscrates/pod/src/feature.rscrates/pod/src/feature/builtin.rscrates/pod/src/feature/builtin/ticket.rscrates/ticket/Cargo.tomlcrates/ticket/src/lib.rscrates/ticket/src/tool.rspackage.nix
Evidence Ticket tools are not in crates/tools
- No files under
crates/toolswere modified. - Ticket tool implementation is in
crates/ticket/src/tool.rs. - Pod only adapts/registers the tools through the feature layer.
Validation
Coder-reported validation passed:
cargo test -p ticketcargo test -p pod ticket --libcargo test -p pod feature --libcargo test -p pod --libcargo test -p tools --libcargo check --workspace --all-targetscargo fmt --checkgit diff --check./tickets.sh doctornix build .#yoi --no-link
Reviewer-rerun validation passed:
git diff --check develop...HEAD./tickets.sh doctor
Review status
External sibling reviewer approved with no blockers.
Non-blocker follow-ups
- Feature install report currently records Ticket as installed even when backend root is unusable and no tools are registered. Fail-closed behavior is correct, but diagnostics may deserve more visible surfacing later.
HostAuthority::TicketBackend { root }is declared from the pre-canonical backend path while the backend uses the canonicalized root. This is acceptable with the current built-in grant flow, but future explicit grant comparisons should normalize consistently.
Ready for merge
Yes.
Closed
Ticket built-in feature tools are complete and merged.
Implementation:
afd7f04 feat: add built-in ticket tools- merge commit:
4486a81 merge: add ticket feature tools
Summary:
- Added the MVP Ticket tool surface:
TicketCreateTicketListTicketShowTicketCommentTicketReviewTicketStatusTicketCloseTicketDoctor
- Kept Ticket tool behavior in
crates/ticket/src/tool.rs. - Kept
podas a thin adapter incrates/pod/src/feature/builtin/ticket.rs. - Added
HostAuthority::TicketBackend { root }to distinguish typed Ticket backend authority from generic filesystem access. - Wired Ticket tools through the existing built-in feature contribution / ToolRegistry path.
- Resolved local backend root as
<workspace>/work-items; unusable roots register no Ticket tools and emit a warning diagnostic. - Did not add Ticket tools to
crates/tools. - Did not shell out to
tickets.sh. - Did not implement Intake workflow, Orchestrator routing, TUI changes, external tracker integration, MCP/plugin loading, scheduler/lease behavior, or feature-api extraction.
Review:
- External sibling reviewer approved with no blockers.
- Non-blocker follow-ups:
- Feature install report currently records Ticket as installed even when backend root is unusable and no tools are registered; diagnostics may deserve more visible surfacing later.
HostAuthority::TicketBackend { root }currently uses the pre-canonical backend path while backend use is canonicalized; future explicit grant comparisons should normalize consistently.
Post-merge validation passed:
cargo test -p ticketcargo test -p pod ticket --libcargo test -p pod feature --libcargo test -p pod --libcargo test -p tools --libcargo fmt --checkgit diff --check./tickets.sh doctorcargo check --workspace --all-targetsnix build .#yoi --no-link
This clears the tool-surface prerequisite for ticket-intake-workflow and ticket-orchestrator-routing.