Compare commits

...

7 Commits

32 changed files with 3247 additions and 55 deletions

10
Cargo.lock generated
View File

@ -3617,6 +3617,16 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "ticket"
version = "0.1.0"
dependencies = [
"chrono",
"fs4",
"tempfile",
"thiserror 2.0.18",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.47" version = "0.3.47"

View File

@ -19,6 +19,7 @@ members = [
"crates/tools", "crates/tools",
"crates/tui", "crates/tui",
"crates/memory", "crates/memory",
"crates/ticket",
"crates/workflow", "crates/workflow",
] ]
@ -34,6 +35,7 @@ llm-worker-macros = { path = "crates/llm-worker-macros", version = "0.2" }
manifest = { path = "crates/manifest" } manifest = { path = "crates/manifest" }
lint-common = { path = "crates/lint-common" } lint-common = { path = "crates/lint-common" }
memory = { path = "crates/memory" } memory = { path = "crates/memory" }
ticket = { path = "crates/ticket" }
pod = { path = "crates/pod" } pod = { path = "crates/pod" }
yoi = { path = "crates/yoi" } yoi = { path = "crates/yoi" }
pod-registry = { path = "crates/pod-registry" } pod-registry = { path = "crates/pod-registry" }

13
crates/ticket/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "ticket"
version = "0.1.0"
edition.workspace = true
license.workspace = true
[dependencies]
chrono = { version = "0.4", default-features = false, features = ["clock"] }
fs4 = { workspace = true, features = ["sync"] }
thiserror.workspace = true
[dev-dependencies]
tempfile.workspace = true

1728
crates/ticket/src/lib.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ rustPlatform.buildRustPackage rec {
filter = sourceFilter; filter = sourceFilter;
}; };
cargoHash = "sha256-iickLtGGmqc0raCZp7giowKajAMLn5+jwtQ9c5hZmhA="; cargoHash = "sha256-zf8YS4d/ia/nGTH7MbkWO8ipqjc1ZNnUsnKlS5rH2pQ=";
depsExtraArgs = { depsExtraArgs = {
# Older fetchCargoVendor utilities used crates.io's API download endpoint, # Older fetchCargoVendor utilities used crates.io's API download endpoint,

View File

@ -0,0 +1,152 @@
# Delegation intent: Ticket local files backend
## Classification
`implementation-ready` with a constrained design boundary.
The Ticket concept, split, and terminology have been accepted in the parent umbrella. This ticket should implement the first layer only: a typed Rust Ticket domain/backend and a LocalTicketBackend over the current `work-items/` files.
## Intent
Add a code-facing Ticket domain model and local files backend so yoi can read and mutate the current repository Ticket records without shelling out to `tickets.sh` or ad hoc parsing.
The durable orchestration concept is named `Ticket`. The current local storage directory remains `work-items/` for compatibility.
## Worktree / branch
- worktree: `/home/hare/Projects/yoi/.worktree/ticket-local-files-backend`
- branch: `work/ticket-local-files-backend`
## Requirements
- Add a new backend-shaped Rust layer for Tickets.
- Use `Ticket`, not `WorkItem`, as the public/domain concept name.
- Prefer a new lower-level workspace crate such as `crates/ticket` unless current code mapping reveals a better fit.
- Keep this crate independent from `pod` and `tui`.
- Implement `LocalTicketBackend` over current `work-items/` storage.
- Preserve compatibility with `tickets.sh` and existing `work-items/{open,pending,closed}/<id>/` layout.
- Preserve these local files:
- `item.md` with YAML-ish frontmatter and Markdown body;
- `thread.md` append-only event-ish log;
- `artifacts/` directory;
- `resolution.md` for closed tickets.
- Implement typed operations equivalent to:
- list;
- show;
- create;
- add event/comment for roles `comment`, `plan`, `decision`, `implementation_report`;
- review approve/request-changes;
- status transition across open/pending/closed;
- close with resolution;
- doctor/consistency check.
- Provide a thin typed envelope around Markdown/freeform content.
- Include fields useful for later Orchestrator/TUI/tool layers where practical:
- id / slug / title;
- status;
- kind / priority / labels;
- created_at / updated_at;
- readiness / needs_preflight / risk flags / action_required if present, while tolerating old tickets without them;
- event kind / review result.
- Keep unknown/extension values parseable rather than failing unnecessarily.
- Implement safe local mutation:
- path containment under configured root;
- atomic replace for file rewrites where practical;
- basic backend lock/conflict handling for concurrent Pod/tool callers;
- no writes outside the configured local ticket root except controlled temp files.
- Add focused tests using temp directories/fixtures; do not mutate real `work-items/` in tests.
- Keep `tickets.sh` command behavior intact.
## Non-goals
- Pod tools / built-in feature integration.
- Intake workflow/profile implementation.
- Orchestrator routing implementation.
- TUI UI changes.
- Renaming `work-items/` to `tickets/`.
- Removing or replacing `tickets.sh`.
- External tracker backends.
- Scheduler/lease/automatic maintainer behavior.
- Changing the session-local Task tool.
## Current code map
- `tickets.sh`
- Current authoritative mechanical behavior for local ticket creation/list/show/comment/review/status/close/doctor.
- Use it as compatibility reference, not as a runtime dependency for the Rust backend.
- `work-items/{open,pending,closed}/<id>/item.md`
- Ticket frontmatter and Markdown body.
- Required existing fields: `id`, `slug`, `title`, `status`, `kind`, `priority`, `labels`, `created_at`, `updated_at`, `assignee`, `legacy_ticket`.
- `work-items/{open,pending,closed}/<id>/thread.md`
- Current event log format uses HTML comments like `<!-- event: ... author: ... at: ... -->`, heading/body, and `---` separators.
- `work-items/{open,pending,closed}/<id>/artifacts/`
- Controlled artifact directory for a ticket.
- `work-items/closed/<id>/resolution.md`
- Resolution body for closed tickets.
- root `Cargo.toml`
- Add the new crate to workspace members.
- `work-items/open/20260601-031252-builtin-work-item-intake-routing/artifacts/ticket-definition-and-api-shape-20260605.md`
- Current conceptual Ticket definition/API direction.
## Suggested API shape
The exact API may be adjusted, but keep the layer backend-shaped:
```rust
trait TicketBackend {
fn list(&self, filter: TicketFilter) -> Result<Vec<TicketSummary>>;
fn show(&self, id: TicketIdOrSlug) -> Result<Ticket>;
fn create(&self, input: NewTicket) -> Result<TicketRef>;
fn add_event(&self, id: TicketIdOrSlug, event: NewTicketEvent) -> Result<()>;
fn review(&self, id: TicketIdOrSlug, review: TicketReview) -> Result<()>;
fn set_status(&self, id: TicketIdOrSlug, status: TicketStatus) -> Result<()>;
fn close(&self, id: TicketIdOrSlug, resolution: MarkdownText) -> Result<()>;
fn doctor(&self) -> Result<TicketDoctorReport>;
}
```
It is acceptable to expose concrete `LocalTicketBackend` methods first if trait object design becomes premature, but the code should not bake local paths into the Ticket concept types.
## Compatibility details to preserve
- `tickets.sh create` id format is `<YYYYMMDD-HHMMSS>-<slug>`.
- Status directories are `open`, `pending`, `closed`.
- `status` frontmatter must match containing directory.
- `doctor` checks required fields, id/directory match, duplicate ids/slugs, required files/directories, and legacy `tickets/*.md` references.
- `close` moves the ticket to `closed`, writes `resolution.md`, and appends a close event.
- `review` appends a review event with `status: approve` or `request_changes` in the event comment.
## Escalate if
- Preserving compatibility requires changing existing `tickets.sh` behavior.
- A strict typed schema would reject many existing tickets.
- The lock/atomic write approach requires a new dependency with license/packaging implications.
- The new crate needs to depend on `pod`, `tui`, or other high-level crates.
- Implementing all operations in one commit becomes too large; prefer a clean subset and report what remains.
## Validation
Run at least:
- new crate unit tests;
- compatibility tests that create/comment/review/status/close in temp dirs and verify `doctor` behavior;
- `cargo test -p ticket` or the chosen crate package name;
- `cargo check --workspace --all-targets`;
- `cargo fmt --check`;
- `git diff --check`;
- `./tickets.sh doctor`.
If feasible, run `nix build .#yoi` after the workspace check passes.
## Completion report
Report:
- worktree path / branch;
- commit hash;
- chosen crate/module name;
- public API summary;
- changed files;
- compatibility with `tickets.sh`;
- tests/validation run;
- unresolved risks/follow-ups;
- whether ready for external review.

View File

@ -0,0 +1,98 @@
# Implementation report: ticket-local-files-backend
## Worktree / branch
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-local-files-backend`
- Branch: `work/ticket-local-files-backend`
## Commit
- `740b017 feat: add local ticket backend`
## Summary
Added a new low-level `ticket` workspace crate that exposes a typed Ticket domain, `TicketBackend` trait, and `LocalTicketBackend` over the existing `work-items/` local markdown storage.
The implementation preserves the current local file layout and `tickets.sh` compatibility while making Ticket operations available as Rust API for later built-in tools, Intake workflow, and Orchestrator routing work.
## Public API / module summary
- `Ticket`, `TicketSummary`, `TicketMeta`, `TicketEvent`, `TicketReview`, `TicketArtifactRef`
- `TicketStatus`, `TicketEventKind`, `TicketReviewStatus`, `TicketKind`, `TicketPriority`
- `TicketIdOrSlug`, `TicketFilter`, `NewTicket`, `NewTicketEvent`
- `TicketBackend` trait
- `LocalTicketBackend`
- `TicketDoctorReport` / `TicketDoctorDiagnostic`
Implemented backend operations:
- `list`
- `show`
- `create`
- `add_event`
- `review`
- `set_status`
- `close`
- `doctor`
## Changed files
- `Cargo.lock`
- `Cargo.toml`
- `package.nix`
- `crates/ticket/Cargo.toml`
- `crates/ticket/src/lib.rs`
## Compatibility
- Keeps `work-items/{open,pending,closed}/<id>/item.md`, `thread.md`, `artifacts/`, and closed `resolution.md` layout.
- Rust-created tickets pass `tickets.sh doctor` in tempdir tests.
- `tickets.sh`-created tickets are readable by the Rust backend in tempdir tests.
- `tickets.sh` can mutate Rust-created tickets in tempdir tests.
- Real repository `./tickets.sh doctor` passed.
## Safety / scope
- New crate is lower-level and independent of `pod`, `tui`, Intake, Orchestrator routing, and scheduler code.
- No Pod tools or UI were added.
- No storage directory rename was introduced.
- Writes are constrained to configured backend root paths.
- Local backend uses a `.ticket-backend.lock` file for Rust backend caller coordination.
- File rewrites use temp files in the destination directory followed by rename where practical.
## Validation
Coder-reported validation passed:
- `cargo test -p ticket`
- `cargo check --workspace --all-targets`
- `cargo fmt --check`
- `git diff --check`
- `git diff --cached --check`
- `./tickets.sh doctor`
- `nix build .#yoi`
Reviewer-rerun validation passed:
- `cargo test -p ticket --no-run`
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check develop...HEAD`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`
## Review status
External sibling reviewer approved with no blockers.
Non-blocker follow-ups:
- Event references are modeled but not persisted/parsed in `thread.md` yet.
- Extension enum variants should remain read-tolerant, while local write paths should avoid emitting values that `tickets.sh doctor` rejects unless the format is intentionally extended.
- Backend locking coordinates Rust backend callers, not concurrent direct `tickets.sh` writes.
- The inherited `thread.md` `---` separator remains ambiguous for event bodies containing standalone `---` lines.
## Ready for merge
Yes.

View File

@ -0,0 +1,66 @@
# Review: ticket-local-files-backend
## 1. Result
approve
## 2. Summary of implementation
The implementation adds a new low-level `ticket` workspace crate with a typed Ticket domain, `TicketBackend` trait, and a filesystem-backed `LocalTicketBackend` for the existing `work-items/` directory layout. The crate is independent of `pod`, `tui`, scheduler/orchestrator, and intake UI/runtime code. It models tickets, events, reviews, statuses, artifacts, and doctor diagnostics, and provides operations for list/show/create/add_event/review/set_status/close/doctor.
The local backend writes the same file names and status directories used by `tickets.sh`:
- `work-items/{open,pending,closed}/<id>/item.md`
- `thread.md`
- `artifacts/`
- closed `resolution.md`
## 3. Requirement-by-requirement assessment
- Public/domain naming uses `Ticket`, not `WorkItem`: satisfied. Public names are `Ticket`, `TicketBackend`, `LocalTicketBackend`, `TicketStatus`, `TicketEvent`, etc.
- Crate/module placement: satisfied. `crates/ticket` is a low-level workspace crate and does not depend on `pod`, `tui`, or other high-level crates.
- Backend-oriented API shape: satisfied for this ticket. Local path concepts are mostly confined to `LocalTicketBackend`, `TicketArtifactRef`, and filesystem operations; core ticket/status/event metadata remains backend-neutral.
- Current layout compatibility: satisfied. The implementation preserves the status directories and expected markdown files, including `resolution.md` on close.
- Operation coverage: satisfied for this ticket. The backend covers list/show/create/add_event/review/set_status/close/doctor and includes diagnostics rather than hard failures for malformed existing records.
- Existing old/minimal frontmatter readability: satisfied. Parsing tolerates missing optional readiness/action-required/risk fields and unknown/extension metadata values.
- Markdown/freeform bodies: satisfied for `item.md` bodies and normal event/resolution bodies. See residual risk for the inherited `thread.md` delimiter limitation.
- Path containment/id safety/atomic-ish writes/locking: acceptable for a local-files MVP. IDs are validated as path components, writes are staged through temp files in the destination directory then renamed, and backend operations take an exclusive backend lock.
- Tests do not mutate real `work-items/`: satisfied. Tests use temp directories and pass an explicit `WORK_ITEMS_DIR` to `tickets.sh` compatibility checks.
- Tests exercise `tickets.sh` compatibility: satisfied. The tests create and mutate temp work item trees through both the Rust backend and `tickets.sh`, then run/show/doctor against the same layout.
- `Cargo.lock` / `package.nix`: acceptable. The new crate and `fs4` lock dependency require workspace/package metadata updates; `nix build .#yoi --no-link` passed.
- Scope control: satisfied. I did not find Pod tools, intake workflow routing, orchestrator scheduling, TUI UI, storage rename, or unrelated refactors in the implementation.
## 4. Blockers
None.
## 5. Non-blockers / follow-ups
- `NewTicketEvent.references` / event references are modeled but not visibly persisted into or parsed from `thread.md`. That is acceptable for this backend MVP, but follow-up work should either define a compatible markdown representation or keep references as higher-level metadata outside the shell-compatible thread format.
- Extension/unknown enum variants are useful for reading older/future files, but local write paths should remain careful not to emit values that `tickets.sh doctor` would reject unless the file format is intentionally extended.
- The backend lock coordinates Rust backend callers, but it cannot coordinate concurrent direct `tickets.sh` writes. That is acceptable for this compatibility bridge, but users should not assume cross-tool transactional safety yet.
## 6. Validation assessed or rerun
Reviewed:
- Ticket item, delegation intent, parent Ticket definition/API shape, and `tickets.sh` compatibility reference.
- Diff against `develop...HEAD` for the implementation branch.
- New crate placement and workspace/package metadata.
- Local backend read/write, parser, status transition, close, doctor, and tests.
Reran from `/home/hare/Projects/yoi/.worktree/ticket-local-files-backend`:
- `cargo test -p ticket --no-run`
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check develop...HEAD`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`
All commands completed successfully.
## 7. Residual risk
The `thread.md` format still uses plain `---` event separators, so an event body containing a standalone `---` line remains ambiguous. This appears inherited from the current shell-compatible storage format rather than introduced by the new crate, and should be handled deliberately if future typed consumers require lossless arbitrary markdown event bodies.

View File

@ -0,0 +1,105 @@
---
id: 20260605-040104-ticket-local-files-backend
slug: ticket-local-files-backend
title: Ticket local files backend
status: closed
kind: task
priority: P1
labels: [ticket, backend, orchestration]
created_at: 2026-06-05T04:01:04Z
updated_at: 2026-06-05T04:45:46Z
assignee: null
legacy_ticket: null
---
## Background
The first step toward Ticket-driven multi-agent orchestration is to make the current `work-items/` + `tickets.sh` file format accessible through a typed Rust API.
The product/code concept name is **Ticket**. The current directory name `work-items/` remains the LocalTicketBackend storage path for now; do not rename it in this ticket.
This ticket should produce a backend-shaped domain layer that future Pod tools, Intake workflows, Orchestrator routing, TUI views, and external tracker integrations can use without depending on `tickets.sh` shell execution or ad hoc markdown parsing.
## Requirements
- Add a code-facing Ticket domain/backend layer.
- Preferred crate: `crates/ticket` or `crates/tickets`; choose the name that reads best in Rust and avoids collision with `tickets.sh` scripts.
- The public concept/type names should use `Ticket`, not `WorkItem`.
- Implement `LocalTicketBackend` over current `work-items/` storage.
- Preserve the current markdown + frontmatter + `thread.md` + `artifacts/` layout.
- Preserve compatibility with `tickets.sh`; existing script operations should continue to work on files written by the Rust backend.
- Keep git history and repository files authoritative.
- Implement typed operations equivalent to at least:
- list;
- show;
- create;
- comment / plan / decision / implementation_report events;
- review approve/request-changes;
- status transition;
- close with resolution;
- doctor/consistency check.
- Use a thin typed envelope with Markdown/freeform bodies.
- Include machine-readable fields needed by Orchestrator/TUI/policy:
- id / slug / title;
- kind / priority / labels;
- status;
- readiness;
- needs-preflight;
- risk flags;
- action-required state;
- event kind;
- references to files, branches, commits, Pods, artifacts, URLs where practical.
- Keep enums extensible where backend compatibility needs raw values.
- Implement safe local-file mutation:
- atomic writes where files are replaced;
- lock/conflict handling sufficient for multiple Pod/tool users;
- no writes outside the configured local ticket root except controlled temp files.
- Provide bounded errors/diagnostics suitable for later tool output.
## Suggested API shape
The exact API can be adjusted during implementation, but should remain backend-shaped:
```rust
trait TicketBackend {
fn list(&self, filter: TicketFilter) -> Result<Vec<TicketSummary>>;
fn show(&self, id: TicketIdOrSlug) -> Result<Ticket>;
fn create(&self, input: NewTicket) -> Result<TicketRef>;
fn add_event(&self, id: TicketIdOrSlug, event: NewTicketEvent) -> Result<()>;
fn review(&self, id: TicketIdOrSlug, review: TicketReview) -> Result<()>;
fn set_status(&self, id: TicketIdOrSlug, status: TicketStatus) -> Result<()>;
fn close(&self, id: TicketIdOrSlug, resolution: MarkdownText) -> Result<()>;
fn doctor(&self) -> Result<TicketDoctorReport>;
}
```
## Non-goals
- Exposing Pod tools.
- Implementing Intake Pod behavior.
- Implementing Orchestrator routing or scheduling.
- Renaming `work-items/`.
- Removing `tickets.sh`.
- Integrating GitHub Issues, Linear, Jira, MCP, or other external backends.
- Building a scheduler/lease system.
- Changing the session-local Task tool.
## Acceptance criteria
- Rust code can read existing open/pending/closed tickets from `work-items/`.
- Rust code can create a ticket equivalent to `tickets.sh create`.
- Rust code can append typed thread events equivalent to `tickets.sh comment` roles.
- Rust code can record approve/request-changes reviews equivalent to `tickets.sh review`.
- Rust code can close a ticket with a `resolution.md` equivalent to `tickets.sh close`.
- Rust doctor catches the same core consistency failures as `tickets.sh doctor` or clearly documents any remaining gaps.
- Files written by the Rust backend pass `./tickets.sh doctor`.
- Existing `tickets.sh` can still read/mutate tickets written by the Rust backend.
- Unit tests cover parsing, create, event append, review, status transition, close, doctor, lock/conflict handling, and corrupt input diagnostics.
- `cargo test` for the new crate passes.
- `cargo check --workspace --all-targets`, `cargo fmt --check`, `git diff --check`, and `./tickets.sh doctor` pass.
## Follow-up tickets
- `ticket-built-in-feature-tools`
- `ticket-intake-workflow`
- `ticket-orchestrator-routing`

View File

@ -0,0 +1,34 @@
Ticket local files backend is complete and merged.
Implementation:
- `740b017 feat: add local ticket backend`
- merge commit: `1041cdb merge: add local ticket backend`
Summary:
- Added a new low-level `ticket` workspace crate.
- Added typed Ticket domain types and `TicketBackend` trait.
- Added `LocalTicketBackend` over the current `work-items/` storage.
- Implemented list/show/create/add_event/review/set_status/close/doctor operations.
- Preserved current local storage layout and `tickets.sh` compatibility.
- Kept the implementation independent from `pod`, `tui`, Intake, Orchestrator routing, and scheduler code.
- Did not rename `work-items/` or remove `tickets.sh`.
Review:
- External sibling reviewer approved with no blockers.
- Non-blocker follow-ups recorded in the implementation report/review:
- event references are modeled but not persisted/parsed in `thread.md` yet;
- write paths should avoid emitting extension values that `tickets.sh doctor` rejects unless the format is intentionally extended;
- backend lock coordinates Rust callers but not direct concurrent `tickets.sh` writes;
- inherited `thread.md` `---` separator ambiguity remains.
Post-merge validation passed:
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`

View File

@ -0,0 +1,252 @@
<!-- event: create author: tickets.sh at: 2026-06-05T04:01:04Z -->
## Created
Created by tickets.sh create.
---
<!-- event: plan author: hare at: 2026-06-05T04:24:20Z -->
## Plan
Preflight result: `implementation-ready`.
The Ticket naming and umbrella split are accepted. This ticket is scoped to the first implementation layer only: typed Ticket domain/backend code and LocalTicketBackend compatibility with current `work-items/` files.
Key decisions for implementation:
- Use `Ticket` as the public/domain concept name.
- Keep `work-items/` as the current local storage path.
- Add a lower-level Rust crate for the Ticket backend layer; do not put this in `pod` or `tui`.
- Preserve `tickets.sh` compatibility and do not remove or replace the script in this ticket.
- Treat readiness/action-required/risk fields as optional/extensible because existing tickets do not have a fully normalized schema.
- Keep Markdown/freeform bodies; enforce mechanical consistency and safe mutation, not rigid body sections.
- No Pod tools, Intake workflow, Orchestrator routing, TUI UI, external tracker backend, or scheduler in this ticket.
The detailed delegation intent is recorded in `artifacts/delegation-intent.md`.
---
<!-- event: review author: hare at: 2026-06-05T04:44:08Z status: approve -->
## Review: approve
# Review: ticket-local-files-backend
## 1. Result
approve
## 2. Summary of implementation
The implementation adds a new low-level `ticket` workspace crate with a typed Ticket domain, `TicketBackend` trait, and a filesystem-backed `LocalTicketBackend` for the existing `work-items/` directory layout. The crate is independent of `pod`, `tui`, scheduler/orchestrator, and intake UI/runtime code. It models tickets, events, reviews, statuses, artifacts, and doctor diagnostics, and provides operations for list/show/create/add_event/review/set_status/close/doctor.
The local backend writes the same file names and status directories used by `tickets.sh`:
- `work-items/{open,pending,closed}/<id>/item.md`
- `thread.md`
- `artifacts/`
- closed `resolution.md`
## 3. Requirement-by-requirement assessment
- Public/domain naming uses `Ticket`, not `WorkItem`: satisfied. Public names are `Ticket`, `TicketBackend`, `LocalTicketBackend`, `TicketStatus`, `TicketEvent`, etc.
- Crate/module placement: satisfied. `crates/ticket` is a low-level workspace crate and does not depend on `pod`, `tui`, or other high-level crates.
- Backend-oriented API shape: satisfied for this ticket. Local path concepts are mostly confined to `LocalTicketBackend`, `TicketArtifactRef`, and filesystem operations; core ticket/status/event metadata remains backend-neutral.
- Current layout compatibility: satisfied. The implementation preserves the status directories and expected markdown files, including `resolution.md` on close.
- Operation coverage: satisfied for this ticket. The backend covers list/show/create/add_event/review/set_status/close/doctor and includes diagnostics rather than hard failures for malformed existing records.
- Existing old/minimal frontmatter readability: satisfied. Parsing tolerates missing optional readiness/action-required/risk fields and unknown/extension metadata values.
- Markdown/freeform bodies: satisfied for `item.md` bodies and normal event/resolution bodies. See residual risk for the inherited `thread.md` delimiter limitation.
- Path containment/id safety/atomic-ish writes/locking: acceptable for a local-files MVP. IDs are validated as path components, writes are staged through temp files in the destination directory then renamed, and backend operations take an exclusive backend lock.
- Tests do not mutate real `work-items/`: satisfied. Tests use temp directories and pass an explicit `WORK_ITEMS_DIR` to `tickets.sh` compatibility checks.
- Tests exercise `tickets.sh` compatibility: satisfied. The tests create and mutate temp work item trees through both the Rust backend and `tickets.sh`, then run/show/doctor against the same layout.
- `Cargo.lock` / `package.nix`: acceptable. The new crate and `fs4` lock dependency require workspace/package metadata updates; `nix build .#yoi --no-link` passed.
- Scope control: satisfied. I did not find Pod tools, intake workflow routing, orchestrator scheduling, TUI UI, storage rename, or unrelated refactors in the implementation.
## 4. Blockers
None.
## 5. Non-blockers / follow-ups
- `NewTicketEvent.references` / event references are modeled but not visibly persisted into or parsed from `thread.md`. That is acceptable for this backend MVP, but follow-up work should either define a compatible markdown representation or keep references as higher-level metadata outside the shell-compatible thread format.
- Extension/unknown enum variants are useful for reading older/future files, but local write paths should remain careful not to emit values that `tickets.sh doctor` would reject unless the file format is intentionally extended.
- The backend lock coordinates Rust backend callers, but it cannot coordinate concurrent direct `tickets.sh` writes. That is acceptable for this compatibility bridge, but users should not assume cross-tool transactional safety yet.
## 6. Validation assessed or rerun
Reviewed:
- Ticket item, delegation intent, parent Ticket definition/API shape, and `tickets.sh` compatibility reference.
- Diff against `develop...HEAD` for the implementation branch.
- New crate placement and workspace/package metadata.
- Local backend read/write, parser, status transition, close, doctor, and tests.
Reran from `/home/hare/Projects/yoi/.worktree/ticket-local-files-backend`:
- `cargo test -p ticket --no-run`
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check develop...HEAD`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`
All commands completed successfully.
## 7. Residual risk
The `thread.md` format still uses plain `---` event separators, so an event body containing a standalone `---` line remains ambiguous. This appears inherited from the current shell-compatible storage format rather than introduced by the new crate, and should be handled deliberately if future typed consumers require lossless arbitrary markdown event bodies.
---
<!-- event: implementation_report author: hare at: 2026-06-05T04:44:08Z -->
## Implementation report
# Implementation report: ticket-local-files-backend
## Worktree / branch
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-local-files-backend`
- Branch: `work/ticket-local-files-backend`
## Commit
- `740b017 feat: add local ticket backend`
## Summary
Added a new low-level `ticket` workspace crate that exposes a typed Ticket domain, `TicketBackend` trait, and `LocalTicketBackend` over the existing `work-items/` local markdown storage.
The implementation preserves the current local file layout and `tickets.sh` compatibility while making Ticket operations available as Rust API for later built-in tools, Intake workflow, and Orchestrator routing work.
## Public API / module summary
- `Ticket`, `TicketSummary`, `TicketMeta`, `TicketEvent`, `TicketReview`, `TicketArtifactRef`
- `TicketStatus`, `TicketEventKind`, `TicketReviewStatus`, `TicketKind`, `TicketPriority`
- `TicketIdOrSlug`, `TicketFilter`, `NewTicket`, `NewTicketEvent`
- `TicketBackend` trait
- `LocalTicketBackend`
- `TicketDoctorReport` / `TicketDoctorDiagnostic`
Implemented backend operations:
- `list`
- `show`
- `create`
- `add_event`
- `review`
- `set_status`
- `close`
- `doctor`
## Changed files
- `Cargo.lock`
- `Cargo.toml`
- `package.nix`
- `crates/ticket/Cargo.toml`
- `crates/ticket/src/lib.rs`
## Compatibility
- Keeps `work-items/{open,pending,closed}/<id>/item.md`, `thread.md`, `artifacts/`, and closed `resolution.md` layout.
- Rust-created tickets pass `tickets.sh doctor` in tempdir tests.
- `tickets.sh`-created tickets are readable by the Rust backend in tempdir tests.
- `tickets.sh` can mutate Rust-created tickets in tempdir tests.
- Real repository `./tickets.sh doctor` passed.
## Safety / scope
- New crate is lower-level and independent of `pod`, `tui`, Intake, Orchestrator routing, and scheduler code.
- No Pod tools or UI were added.
- No storage directory rename was introduced.
- Writes are constrained to configured backend root paths.
- Local backend uses a `.ticket-backend.lock` file for Rust backend caller coordination.
- File rewrites use temp files in the destination directory followed by rename where practical.
## Validation
Coder-reported validation passed:
- `cargo test -p ticket`
- `cargo check --workspace --all-targets`
- `cargo fmt --check`
- `git diff --check`
- `git diff --cached --check`
- `./tickets.sh doctor`
- `nix build .#yoi`
Reviewer-rerun validation passed:
- `cargo test -p ticket --no-run`
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check develop...HEAD`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`
## Review status
External sibling reviewer approved with no blockers.
Non-blocker follow-ups:
- Event references are modeled but not persisted/parsed in `thread.md` yet.
- Extension enum variants should remain read-tolerant, while local write paths should avoid emitting values that `tickets.sh doctor` rejects unless the format is intentionally extended.
- Backend locking coordinates Rust backend callers, not concurrent direct `tickets.sh` writes.
- The inherited `thread.md` `---` separator remains ambiguous for event bodies containing standalone `---` lines.
## Ready for merge
Yes.
---
<!-- event: close author: hare at: 2026-06-05T04:45:46Z status: closed -->
## Closed
Ticket local files backend is complete and merged.
Implementation:
- `740b017 feat: add local ticket backend`
- merge commit: `1041cdb merge: add local ticket backend`
Summary:
- Added a new low-level `ticket` workspace crate.
- Added typed Ticket domain types and `TicketBackend` trait.
- Added `LocalTicketBackend` over the current `work-items/` storage.
- Implemented list/show/create/add_event/review/set_status/close/doctor operations.
- Preserved current local storage layout and `tickets.sh` compatibility.
- Kept the implementation independent from `pod`, `tui`, Intake, Orchestrator routing, and scheduler code.
- Did not rename `work-items/` or remove `tickets.sh`.
Review:
- External sibling reviewer approved with no blockers.
- Non-blocker follow-ups recorded in the implementation report/review:
- event references are modeled but not persisted/parsed in `thread.md` yet;
- write paths should avoid emitting extension values that `tickets.sh doctor` rejects unless the format is intentionally extended;
- backend lock coordinates Rust callers but not direct concurrent `tickets.sh` writes;
- inherited `thread.md` `---` separator ambiguity remains.
Post-merge validation passed:
- `cargo test -p ticket`
- `cargo fmt --check`
- `git diff --check`
- `./tickets.sh doctor`
- `cargo check --workspace --all-targets`
- `nix build .#yoi --no-link`
---

View File

@ -1,7 +0,0 @@
<!-- event: migration author: tickets.sh-migration at: 2026-05-27T00:00:17Z -->
## Migrated
Migrated from tickets/tui-spawned-pod-panel.md. No legacy review file was present at migration time.
---

View File

@ -0,0 +1,185 @@
# Ticket definition and API shape
## Definition
In yoi, a Ticket is the durable orchestration record shared by humans, Intake Pods, Orchestrator Pods, coder Pods, and reviewer Pods.
Short definition:
> A Ticket is a durable coordination contract that preserves agreed intent, requirements, readiness, decisions, evidence, review results, and resolution history so Pod groups can route, delegate, implement, verify, and complete work without losing the original intent.
A local markdown ticket, GitHub Issue, Linear issue, Jira issue, or another tracker record can be a backend representation of a Ticket, but none of those storage representations define the concept.
The current local backend is the repository's `work-items/` directory managed by `tickets.sh`. That path remains unchanged for now.
## Roles served by a Ticket
A Ticket is simultaneously:
- Intent anchor: preserves what the user and Intake agreed to.
- Requirements contract: states observable requirements, acceptance criteria, non-goals, and escalation conditions.
- Routing unit: lets Orchestrator decide between requirements sync, preflight, spike, implementation, review, blocked/action-required, pending, or close.
- Delegation source: lets Orchestrator derive an `IntentPacket` for a concrete Pod `Assignment`.
- Review contract: gives reviewer Pods an explicit basis for approval or request-changes.
- Evidence ledger: records plans, decisions, implementation reports, validation, review, artifacts, commits, branches, and resolution.
- Backend-neutral record: local files are the first backend, not the product concept.
## Relationship to other terms
- `Task`: session-local progress tracking inside a Pod/session. Smaller and more ephemeral than a Ticket.
- `Ticket`: durable project/orchestration record.
- `Assignment`: concrete delegation from Orchestrator to a coder/reviewer/investigator Pod.
- `IntentPacket`: concise implementation/review contract extracted from a Ticket and passed to an Assignment.
- `TicketBackend`: backend abstraction for Ticket storage/mutation.
- `LocalTicketBackend`: current local file backend over `work-items/`.
## Conceptual shape
The Rust model should use a thin typed envelope around Markdown/freeform body content.
Typed enough for machines:
- id / slug / title;
- kind / priority / labels;
- status;
- readiness;
- needs-preflight;
- risk flags;
- action-required state;
- event kind;
- review result;
- artifact references;
- branch/commit/Pod references where useful.
Flexible enough for humans/LLMs:
- background;
- requirements;
- acceptance criteria;
- rationale;
- design notes;
- plan;
- implementation report;
- review body;
- resolution.
## Candidate types
```rust
struct Ticket {
id: TicketId,
slug: TicketSlug,
title: String,
meta: TicketMeta,
body: TicketDocument,
events: Vec<TicketEvent>,
artifacts: Vec<TicketArtifactRef>,
}
struct TicketSummary {
id: TicketId,
slug: TicketSlug,
title: String,
status: TicketStatus,
kind: TicketKind,
priority: TicketPriority,
readiness: TicketReadiness,
needs_preflight: bool,
action_required: Option<ActionRequired>,
}
enum TicketStatus {
Open,
Pending,
Closed,
Other(String),
}
enum TicketReadiness {
Unspecified,
RequirementsSyncNeeded,
SpikeNeeded,
ImplementationReady,
Blocked,
Other(String),
}
enum TicketEventKind {
Comment,
Plan,
Decision,
ImplementationReport,
Review,
StatusChanged,
Closed,
Other(String),
}
struct TicketEvent {
kind: TicketEventKind,
body: MarkdownText,
refs: Vec<TicketRef>,
}
```
## Candidate backend trait
```rust
trait TicketBackend {
fn list(&self, filter: TicketFilter) -> Result<Vec<TicketSummary>>;
fn show(&self, id: TicketIdOrSlug) -> Result<Ticket>;
fn create(&self, input: NewTicket) -> Result<TicketRef>;
fn add_event(&self, id: TicketIdOrSlug, event: NewTicketEvent) -> Result<()>;
fn review(&self, id: TicketIdOrSlug, review: TicketReview) -> Result<()>;
fn set_status(&self, id: TicketIdOrSlug, status: TicketStatus) -> Result<()>;
fn close(&self, id: TicketIdOrSlug, resolution: MarkdownText) -> Result<()>;
fn doctor(&self) -> Result<TicketDoctorReport>;
}
```
The trait should remain backend-shaped and should not bake local file paths into the concept. Local paths belong in `LocalTicketBackend` configuration and implementation.
## Authority boundary
Ticket authority is separate from ordinary source/worktree filesystem scope.
Filesystem scope protects implementation areas and source edits. Ticket management is shared project coordination state and should be mediated through typed Ticket operations, backend locks/conflict handling, and audit/history records rather than delegated arbitrary write access.
This does not imply unlimited Ticket access. Ticket tools should be granted explicitly and limited to configured Ticket backends and operations.
## Backend layering
```text
Ticket API / TicketBackend
├─ LocalTicketBackend -> current work-items/ directory
├─ GitHubTicketBackend -> possible future backend
├─ LinearTicketBackend -> possible future backend
└─ McpTicketBackend -> possible future bridge
```
Local files are the first backend because they are already the authoritative project record in this repository. External tracker support is not part of the MVP.
## Validation/linting direction
Prefer a Ticket linter/policy layer over strict structural enforcement for all body content.
The code should enforce mechanical consistency and safe mutation:
- required frontmatter fields;
- status directory consistency;
- id/slug uniqueness;
- thread event parseability;
- review/result shape;
- resolution existence for closed tickets;
- artifact path containment;
- lock/conflict behavior;
- bounded diagnostics.
The code should not require every Ticket body to fit a rigid universal schema. Ticket bodies remain Markdown/freeform because design, cleanup, bugs, investigations, and orchestration epics need different prose.
## Current implementation sequence
1. `ticket-local-files-backend`
2. `ticket-built-in-feature-tools`
3. `ticket-intake-workflow`
4. `ticket-orchestrator-routing`

View File

@ -1,5 +1,7 @@
# WorkItem definition and API shape # WorkItem definition and API shape
> Superseded on 2026-06-05: the durable orchestration record concept is now named `Ticket`, not `WorkItem`. See `ticket-definition-and-api-shape-20260605.md` and the ticket thread decision for current terminology. This file is retained as historical design context.
## Definition ## Definition
In Insomnia, a WorkItem is not primarily an issue tracker item. A WorkItem is an agreed execution contract that fixes user intent into a bounded unit that Pods can schedule, delegate, implement, review, and close safely. In Insomnia, a WorkItem is not primarily an issue tracker item. A WorkItem is an agreed execution contract that fixes user intent into a bounded unit that Pods can schedule, delegate, implement, review, and close safely.

View File

@ -1,68 +1,86 @@
--- ---
id: 20260601-031252-builtin-work-item-intake-routing id: 20260601-031252-builtin-work-item-intake-routing
slug: builtin-work-item-intake-routing slug: builtin-work-item-intake-routing
title: Built-in work item management and intake routing title: Built-in Ticket intake and orchestration routing
status: open status: open
kind: task kind: task
priority: P1 priority: P1
labels: [work-item, intake, orchestration, tui] labels: [ticket, intake, orchestration]
created_at: 2026-06-01T03:12:52Z created_at: 2026-06-01T03:12:52Z
updated_at: 2026-06-03T12:25:05Z updated_at: 2026-06-05T04:04:42Z
assignee: null assignee: null
legacy_ticket: null legacy_ticket: null
--- ---
## Issue ## Background
現在の work item / ticket 運用は、Insomnia システムから切り離しても使えるように `tickets.sh` と markdown files で管理している。一方で、チケットは実質的に WorkItem と統合された構造化データとして運用され始めており、Intake Pod / Orchestrator / coder / reviewer の並行開発フローでは、チケット管理自体を Insomnia の feature として扱う必要が出てきている。 Yoi needs a durable project-level coordination record that Intake, Orchestrator, coder Pods, reviewer Pods, and humans can share. The accepted concept name is **Ticket**.
特に、ユーザーが単一 Orchestrator に依頼してから Orchestrator が調査・チケット化・実装委譲する現在の入口では、ユーザー待ち時間が残る。ユーザーの submit から Intake Pod が直接起動し、ユーザーと意図・要件をすり合わせたうえで正式な WorkItem / ticket を作成し、Orchestrator はそのチケット群の順序付け・割り込み・実装 orchestration に集中する構造へ移行したい。 A Ticket is not the same thing as the session-local Task tool. A Task tracks short-lived user-visible progress inside a Pod/session. A Ticket is a durable orchestration contract with requirements, decisions, plans, implementation reports, reviews, artifacts, and resolution history.
## Direction The current repository already stores this information under `work-items/` and manages it through `tickets.sh`. For now, that storage format remains the local backend. The new code-facing concept should be `Ticket`, not `WorkItem`; `work-items/` is a current local storage path, not the product concept name.
- `tickets.sh` 相当の work item 管理を、Insomnia の built-in feature / tool surface として設計・実装する。 The original version of this ticket mixed several layers: local ticket backend, built-in Pod tools, Intake behavior, Orchestrator routing, action-required state, and scheduler-like automation. That is too broad for a single implementation ticket, so this ticket now acts as the umbrella tracking ticket for the split.
- WorkItem は Pod 専用の独自 context injection や特殊 queue ではなく、`plugin-feature-contribution-registry` で定義する feature contribution として既存 Tool / Hook / Notify 経路に載せる。
- Intake Pod はユーザーと直接会話し、必要な調査・重複確認・要件同期を行い、合意済み WorkItem / ticket を作成できるようにする。
- Orchestrator はユーザー意図の一次解釈や ticket draft の再承認者ではなく、登録済み WorkItem の scheduling / prioritization / interruption / implementation delegation を担当する。
- ユーザー向け Inbox 専用 UI は初期スコープにしない。Intake は既存の `--multi` UI の延長として通常の Pod 会話で制御できるようにする。
- Orchestrator が WorkItem を見て不十分と判断し、Intake と Orchestrator 間だけで合意できない場合は、Intake Pod に action-required flag を持たせ、既存の TUI polling / multi-Pod 表示経路でユーザー対応要求として表示する。
## Scope / permission note ## Terminology
Scope は、エージェントが占有して作業する filesystem space を保証するための仕組みである。WorkItem / ticket 管理を built-in tool として提供する場合、その tool は単なる delegated workspace edit と同じ扱いにせず、既存の `tickets.sh` / Bash と同様に work item authority のための専用経路として設計してよい。 - `Ticket`: durable orchestration record shared by Intake, Orchestrator, implementation Pods, reviewer Pods, and humans.
- `Task`: session-local progress tracking tool; intentionally separate from Ticket.
- `Assignment`: a concrete delegation from Orchestrator to a coder/reviewer/investigator Pod.
- `IntentPacket`: short implementation/review contract derived from a Ticket and passed to an Assignment.
- `TicketBackend`: backend abstraction for reading and mutating Tickets.
- `LocalTicketBackend`: backend implementation for the current `work-items/` directory format.
ただし、これは無制限のファイル編集許可を意味しない。WorkItem tool は対象を work item store に限定し、通常の code/worktree scope とは別の authority boundary と auditability を持つべきである。 ## Scope of the umbrella
This umbrella covers the following sequence:
1. `ticket-local-files-backend`
- Add a code-facing Ticket domain model and local backend for current `work-items/` files.
- Keep `tickets.sh` and existing file format compatible.
2. `ticket-built-in-feature-tools`
- Expose Ticket operations as a built-in Pod feature/tool surface.
- Treat Ticket operations as typed backend authority, not arbitrary filesystem writes.
3. `ticket-intake-workflow`
- Define and install an Intake workflow/profile that clarifies user requests and creates Tickets after user agreement.
4. `ticket-orchestrator-routing`
- Let Orchestrator classify Tickets and route them into preflight, implementation, review, spike, blocked/action-required, or close paths.
Later scheduler/lease/automatic maintainer behavior is out of scope for this umbrella until the above pieces are usable.
## Requirements ## Requirements
- `tickets.sh` で行っている主要操作を、Insomnia の built-in work item management surface として扱えるようにすること。 - Use `Ticket` as the product/code concept name.
- create - Keep existing `work-items/` storage as the LocalTicketBackend path for now.
- show/list - Do not rename the storage directory in this umbrella.
- comment / plan / decision / implementation report - Keep git history + ticket files authoritative.
- review approve/request-changes - Preserve compatibility with `tickets.sh` until a replacement is explicitly accepted.
- status transition - Keep Ticket authority separate from delegated filesystem write scope.
- close / resolution - Avoid exposing arbitrary file writes through Ticket tools.
- doctor / consistency check - Keep Intake focused on clarification and Ticket creation/update; it must not schedule implementation itself.
- WorkItem tool surface は `plugin-feature-contribution-registry` の built-in feature contribution として登録できること。 - Keep Orchestrator responsible for routing/scheduling decisions, not Intake.
- WorkItem / ticket の保存形式は、現在の markdown + frontmatter + thread / artifacts 方式との移行可能性を保つこと。 - Do not introduce an unattended scheduler in the MVP.
- 既存の `tickets.sh` 運用を即座に破壊しないこと。built-in 化の途中でも git history / work-items directory を authority として読めること。
- Intake Pod がユーザーと合意済み WorkItem を作成できる導線を設計すること。
- Intake Pod は正式作成前に、必要に応じて既存 ticket / duplicate / related work / relevant files を調査できること。
- Intake Pod が作った WorkItem には、ユーザー合意済みであること、背景、要件、acceptance criteria、non-goals、risk flags、needs-preflight などを構造化して残せること。
- Orchestrator は作成済み WorkItem queue を見て、実装順序・割り込み・preflight 要否・coder/reviewer 起動を判断できること。
- Orchestrator が WorkItem 不十分と判断した場合、必要な質問や修正要求を Intake Pod 経由でユーザーに戻せること。
- 専用 Inbox storage / UI を初期要件にしないこと。action-required state は Pod metadata / current state に近い形で持ち、既存 multi-Pod polling / display で見えるようにすること。
- action-required Pod は、ユーザーが対応するまで見落とされにくい表示・状態を持つこと。
- Intake 結果や WorkItem 操作は audit 可能で、git history / work item thread に経緯が残ること。
- secret / private context を WorkItem 本文・thread・artifact・diagnostics に不用意に書かないこと。
- work item store への並行書き込みが壊れないよう、atomicity / locking / conflict handling を設計すること。
## Acceptance criteria ## Acceptance criteria
- Insomnia 内部から、少なくとも `tickets.sh create/show/list/comment/review/close/doctor` に相当する操作を型付きに実行できる。 - This umbrella records the Ticket terminology decision and split plan.
- Intake Pod がユーザーと合意した内容を正式 WorkItem として作成できる。 - Child tickets exist for:
- Orchestrator は Intake が作成した WorkItem を、再解釈 gate なしに scheduling 対象として扱える。 - local files backend;
- WorkItem が不十分な場合は、Orchestrator が action-required state を通じて Intake / user に差し戻せる。 - built-in feature tools;
- `--multi` 系 UI で、通常の Pod 状態に加えて user action required な Intake Pod を認識できる。 - intake workflow;
- 専用 Inbox storage を導入しなくても、未対応のユーザー確認要求が見落とされない。 - orchestrator routing.
- 既存 `work-items/` と git history に基づく運用・監査が継続できる。 - Child tickets state their dependencies, scope, non-goals, and acceptance criteria clearly enough for preflight/implementation sequencing.
- Historical `WorkItem` wording in this ticket is either removed or explicitly described as old terminology.
- `tickets.sh doctor` passes after the split.
## Non-goals
- Renaming `work-items/` to `tickets/`.
- Replacing `tickets.sh` immediately.
- Building a scheduler/lease system.
- Building a TUI spawned-Pod panel.
- Changing the session-local Task tool.
- Integrating with GitHub Issues, Linear, MCP, or external trackers in this umbrella.

View File

@ -248,4 +248,73 @@ Two implementation-oriented prerequisite tickets are split out:
This preserves the desired detachable shape: feature state remains in the feature/extension module, while Pod interaction happens through existing durable host surfaces. WorkItem management should be implemented as a built-in feature contribution once the registry boundary is in place, rather than as a special Pod context-injection path. This preserves the desired detachable shape: feature state remains in the feature/extension module, while Pod interaction happens through existing durable host surfaces. WorkItem management should be implemented as a built-in feature contribution once the registry boundary is in place, rather than as a special Pod context-injection path.
---
<!-- event: decision author: hare at: 2026-06-05T04:03:37Z -->
## Decision
Decision: use `Ticket` as the durable orchestration record concept.
Rationale:
- `WorkItem` is not a preferred product/code name.
- `Work*` naming feels too enterprise/work-order-like for this system.
- `Issue` overemphasizes problems/bugs and does not fit design, cleanup, investigation, and orchestration records as well.
- `Task` is already used for session-local progress tracking and implies a smaller unit.
- `Ticket` is broad enough for requests, bugs, design work, implementation tasks, reviews, spikes, and orchestration epics while remaining natural in the current repository workflow.
Terminology:
- `Ticket` is the durable orchestration record.
- `Task` remains session-local progress tracking.
- `Assignment` is a concrete delegation from Orchestrator to a coder/reviewer/investigator Pod.
- `IntentPacket` is a short implementation/review contract derived from a Ticket.
- `LocalTicketBackend` is the current `work-items/` markdown/thread/artifact storage backend.
Scope decision:
- Keep `work-items/` as the current storage path for now.
- Do not rename `work-items/` in this phase.
- Treat the old WorkItem wording as historical terminology being replaced by Ticket.
---
<!-- event: plan author: hare at: 2026-06-05T04:03:37Z -->
## Plan
Plan: split the original broad built-in intake/routing ticket into implementation-sized Ticket tickets.
The parent ticket is now an umbrella for the Ticket-driven intake/orchestration path. The implementation sequence is:
1. `ticket-local-files-backend`
- Add the code-facing Ticket domain/backend layer and LocalTicketBackend over current `work-items/` files.
2. `ticket-built-in-feature-tools`
- Expose typed Ticket operations as a built-in Pod feature/tool surface with Ticket backend authority, not arbitrary filesystem write scope.
3. `ticket-intake-workflow`
- Add the Intake workflow/profile that clarifies user intent and creates/updates Tickets after user agreement.
4. `ticket-orchestrator-routing`
- Add explicit Orchestrator routing classification and intent-packet production for Tickets.
`tui-spawned-pod-panel` is not part of this path; it may be useful UI work later, but it is not what is currently needed for the multi-agent system.
---
<!-- event: comment author: hare at: 2026-06-05T04:04:42Z -->
## Comment
Added current terminology/design artifact:
- `artifacts/ticket-definition-and-api-shape-20260605.md`
The earlier `workitem-definition-and-api-shape-20260601.md` is now explicitly marked superseded and retained only as historical context.
--- ---

View File

@ -0,0 +1,108 @@
# Delegation intent: feature API authority separation
## Classification
`implementation-ready` as a bounded API cleanup/refinement.
This ticket is a prerequisite for `ticket-built-in-feature-tools` because Ticket tools must be installed as internal built-in feature contributions while Ticket operation authority remains a host-granted backend capability, not arbitrary filesystem write scope.
## Intent
Clarify the `pod::feature` API boundary so internal built-in feature contributions are not confused with external plugin/sandbox authority grants.
The important distinction:
- Contribution declarations (`tools`, `hooks`, alerts/notices, service/background descriptors) are what a feature contributes to the host registry.
- Host authority grants are capabilities required for privileged host-mediated operations such as filesystem, network, secrets, Pod management, model notification, state store, or service access.
Internal built-in features should be able to register contributions without implying external plugin approval/sandbox semantics. External plugin authority remains a separate future concern.
## Worktree / branch
- worktree: `/home/hare/Projects/yoi/.worktree/feature-api-authority-separation`
- branch: `work/feature-api-authority-separation`
## Requirements
- Keep the change inside the existing `pod::feature` layer; do not create a new crate in this ticket.
- Make naming and type boundaries explicit enough that later built-in Ticket tools can request Ticket backend authority without being framed as an external plugin package grant.
- Prefer concrete rename/clarification over compatibility aliases because this is unreleased internal API.
- Distinguish host authority naming from generic contribution naming. Candidate renames if they fit the code:
- `AuthorityRequest` -> `HostAuthorityRequest`
- `AuthorityGrantSet` -> `HostAuthorityGrantSet`
- `AuthorityDenial` -> `HostAuthorityDenial`
- `FeatureDescriptor::requested_authorities` -> `requested_host_authorities`
- `FeatureDescriptor::with_authority` -> `with_host_authority`
- `ToolContribution::required_authorities` -> `required_host_authorities`
- `FeatureInstallReport::granted_authorities` -> `host_authority_grants`
- `FeatureInstallContext::grants()` -> `host_authority_grants()` or equivalent
- Keep contribution declarations as contribution declarations; do not require host authority grants merely to contribute a tool/hook.
- Keep existing built-in Task feature behavior unchanged.
- Keep descriptor-first validation:
- actual contributed tools/hooks/notifications/etc. must be declared;
- duplicate tool names remain rejected;
- missing required host authority still fails feature installation where applicable.
- Update tests/docs/comments to reflect the new distinction.
## Non-goals
- Implementing Ticket built-in tools.
- Implementing Ticket backend authority grants beyond the generic host authority naming/model needed here.
- External plugin loading/discovery/package approval.
- WASM/sandbox runtime.
- MCP integration.
- Real human approval/resume protocol.
- Moving feature API to a new crate.
- Changing Hook API behavior.
- Changing Task feature behavior.
- Broad refactors outside `pod::feature` and direct callers/tests.
## Current code map
- `crates/pod/src/feature.rs`
- Main feature API, descriptors, contributions, installation, authority request/grant types, tests.
- Current generic names include `AuthorityRequest`, `AuthorityGrantSet`, `AuthorityDenial`, `requested_authorities`, `granted_authorities`, and `required_authorities`.
- `FeatureRuntimeKind` already distinguishes `Builtin`, `LuaProfile`, and `ExternalPlugin`.
- `HostAuthority` already names the host-mediated capability concept.
- `crates/pod/src/feature/builtin/task/mod.rs`
- Built-in Task feature implementation and contribution example.
- Must continue to install Task tools/hooks/reminders unchanged.
- `crates/pod/src/feature/builtin.rs`
- Built-in feature contribution wiring.
- `crates/pod/src/lib.rs`
- Public exports if affected.
## Critical risks
- Leaving generic `Authority*` naming in place makes later Ticket tools read like external plugin/sandbox grants, which is the confusion this ticket is meant to prevent.
- Overcorrecting by making built-in contribution registration depend on host authority grants would make internal features unnecessarily complex.
- Adding compatibility aliases for old names would preserve the ambiguity; avoid unless required by external public API, which should not be the case for this unreleased surface.
- Changing behavior instead of naming/boundary tests could destabilize Task feature installation.
## Validation
Run at least:
- `cargo test -p pod feature --lib`
- `cargo test -p pod task --lib`
- `cargo test -p pod --lib`
- `cargo test -p llm-worker --lib`
- `cargo check --workspace --all-targets`
- `cargo fmt --check`
- `git diff --check`
- `./tickets.sh doctor`
Run `nix build .#yoi --no-link` if feasible.
## Completion report
Report:
- worktree path / branch;
- commit hash;
- exact API/type/field renames;
- behavior preserved/changed;
- changed files;
- validation results;
- unresolved risks/follow-ups;
- whether `ticket-built-in-feature-tools` can proceed afterward.

View File

@ -7,7 +7,7 @@ kind: task
priority: P1 priority: P1
labels: [plugin, feature-registry, permissions, architecture] labels: [plugin, feature-registry, permissions, architecture]
created_at: 2026-06-04T23:48:44Z created_at: 2026-06-04T23:48:44Z
updated_at: 2026-06-05T00:49:53Z updated_at: 2026-06-05T04:54:33Z
assignee: null assignee: null
legacy_ticket: null legacy_ticket: null
--- ---

View File

@ -49,4 +49,26 @@ Implications:
This preserves the clean distinction: contribution declarations are descriptor-locked; dangerous host APIs are represented by host-created handles; normal tool permission remains the per-call execution gate. This preserves the clean distinction: contribution declarations are descriptor-locked; dangerous host APIs are represented by host-created handles; normal tool permission remains the per-call execution gate.
---
<!-- event: plan author: hare at: 2026-06-05T04:54:33Z -->
## Plan
Preflight result: `implementation-ready`.
`ticket-built-in-feature-tools` should not be implemented until this boundary is clarified, because Ticket tools need to be internal built-in feature contributions while Ticket backend operations remain typed host authority, not arbitrary filesystem scope or external plugin package approval.
Implementation intent:
- Clarify `pod::feature` naming around host authority grants.
- Keep contribution declarations and descriptor reconciliation separate from host authority requests/grants.
- Preserve built-in Task feature behavior as the current contribution-only example.
- Avoid external plugin loading, real approval protocol, Ticket tool implementation, Hook behavior changes, or broader crate moves.
Detailed delegation intent is in `artifacts/delegation-intent.md`.
Note: main workspace currently has an unrelated dirty `README.md` change. This feature work must not touch or commit that file.
--- ---

View File

@ -0,0 +1,97 @@
---
id: 20260605-040104-ticket-built-in-feature-tools
slug: ticket-built-in-feature-tools
title: Ticket built-in feature tools
status: open
kind: task
priority: P1
labels: [ticket, feature, tool, orchestration]
created_at: 2026-06-05T04:01:04Z
updated_at: 2026-06-05T04:01:25Z
assignee: null
legacy_ticket: null
---
## Background
After a typed Ticket backend exists, Pods need a controlled way to read and mutate Tickets without receiving arbitrary filesystem write scope over the repository.
Ticket operations are orchestration authority, not ordinary source-file writes. A coder Pod may have write access only to a child worktree and still need to report implementation progress or attach artifacts to a Ticket through a typed operation. Intake and Orchestrator Pods likewise need Ticket operations that are bounded, auditable, and backend-independent.
This ticket depends on `ticket-local-files-backend`. It should also be sequenced after or alongside `feature-api-authority-separation` if that ticket is still open, because Ticket tools should use the built-in contribution path without confusing internal built-ins with external plugin grants.
## Requirements
- Add a built-in Pod feature for Ticket tools.
- Register tools through the existing feature contribution / ToolRegistry path.
- Use the typed Ticket backend from `ticket-local-files-backend`.
- Treat Ticket operations as configured backend authority, not filesystem scope.
- Do not grant arbitrary writes to `work-items/` through generic filesystem tools.
- Keep tool outputs bounded and model-readable.
- Preserve current `tickets.sh` semantics where equivalent operations exist.
- Ensure Ticket operations are recorded durably in the ticket files/thread/resolution/artifacts.
- Keep permission/policy behavior explicit and fail-closed.
- Avoid external plugin loading or MCP integration in this ticket.
## Candidate tool surface
Exact names can be adjusted during preflight, but the surface should be close to:
- `TicketCreate`
- `TicketList`
- `TicketShow`
- `TicketComment`
- `TicketReview`
- `TicketStatus`
- `TicketClose`
- `TicketDoctor`
Optional follow-up if needed rather than MVP:
- `TicketArtifactWrite`
- `TicketArtifactRead`
- `TicketSearch`
## Authority model
- The Pod must receive a Ticket backend/tool grant through manifest/profile/feature configuration.
- The grant points to a configured backend root, initially the local repository `work-items/` root.
- Tool implementations validate paths and identifiers against the backend root.
- Artifact writes are constrained to the selected ticket's `artifacts/` directory.
- Ticket tools do not imply general `Write` permission to the repository.
- Existing PreToolCall policy still applies to the tool call itself.
## Non-goals
- Implementing the local files backend itself.
- Building Intake workflow behavior.
- Building Orchestrator routing/scheduling.
- Renaming `work-items/`.
- Removing `tickets.sh`.
- External tracker integration.
- MCP/plugin loading.
- Scheduler/lease/queue automation.
- TUI changes.
## Acceptance criteria
- Ticket tools are registered only when the built-in Ticket feature is enabled/configured.
- Ticket tools operate through the typed Ticket backend and not shelling out to `tickets.sh`.
- A Pod without filesystem write scope to `work-items/` can perform allowed Ticket operations through the tool grant.
- A Pod without the Ticket tool grant cannot mutate Tickets through these tools.
- Tool schemas and outputs are bounded, deterministic enough for tests, and suitable for LLM use.
- Ticket create/comment/review/status/close operations produce files accepted by `./tickets.sh doctor`.
- Tool calls produce no writes outside the backend root and selected ticket artifact directories.
- Unit/integration tests cover allowed/denied operation paths and path traversal attempts.
- `cargo test` for affected crates passes.
- `cargo check --workspace --all-targets`, `cargo fmt --check`, `git diff --check`, and `./tickets.sh doctor` pass.
## Dependencies
- Requires `ticket-local-files-backend`.
- Prefer after `feature-api-authority-separation` if that ticket remains open.
## Follow-up tickets
- `ticket-intake-workflow`
- `ticket-orchestrator-routing`

View File

@ -0,0 +1,7 @@
<!-- event: create author: tickets.sh at: 2026-06-05T04:01:04Z -->
## Created
Created by tickets.sh create.
---

View File

@ -0,0 +1,94 @@
---
id: 20260605-040104-ticket-intake-workflow
slug: ticket-intake-workflow
title: Ticket intake workflow
status: open
kind: task
priority: P1
labels: [ticket, intake, workflow, orchestration]
created_at: 2026-06-05T04:01:04Z
updated_at: 2026-06-05T04:01:25Z
assignee: null
legacy_ticket: null
---
## Background
The multi-agent system needs an Intake role that turns a user's vague or broad request into an agreed Ticket before Orchestrator starts scheduling implementation work.
The Intake role is not a scheduler and does not spawn coder/reviewer Pods. It clarifies intent, checks for duplicates/related tickets, asks the user for missing requirements, and creates or updates Tickets after agreement.
This ticket depends on typed Ticket tools. Without a built-in Ticket tool surface, Intake would need arbitrary filesystem write scope or ad hoc shell access, which is not the desired authority boundary.
## Requirements
- Define an Intake workflow/profile/prompt for Ticket intake.
- Intake should be able to:
- understand the user's requested change;
- inspect existing Tickets for duplicates or related work;
- inspect relevant repository files when needed and permitted;
- ask clarifying questions;
- propose Ticket title/kind/priority/labels;
- summarize background, requirements, acceptance criteria, non-goals, escalation conditions, risk flags, and readiness;
- create a Ticket after user agreement;
- update an existing Ticket when the user asks to refine known work.
- Intake-created Tickets should be suitable for Orchestrator routing without a second full reinterpretation pass.
- Intake must classify readiness explicitly:
- `implementation_ready`;
- `requirements_sync_needed`;
- `spike_needed`;
- `blocked`;
- or `unspecified` only when unavoidable.
- Intake should mark `needs_preflight` for tickets with design/authority/scope/history/prompt-context risk.
- Intake should avoid persisting private/secret-like material in Ticket bodies, thread entries, artifacts, or diagnostics.
## User agreement rule
Intake must not silently convert an unresolved draft into an official Ticket.
MVP behavior:
- Draft state can live in the conversation while clarifying.
- Intake creates a Ticket only after the user accepts the proposed contents or explicitly asks to create it.
- If the user wants to record unresolved work, Intake may create a Ticket with readiness such as `requirements_sync_needed` or `spike_needed`, but the unresolved state must be explicit in the Ticket.
## Non-goals
- Scheduling implementation.
- Spawning coder/reviewer Pods.
- Creating worktrees.
- Closing Tickets.
- Building a dedicated Inbox UI or storage.
- Building an unattended maintainer/scheduler.
- Replacing `multi-agent-workflow`.
- Implementing Ticket backend/tools.
## Acceptance criteria
- A user-invocable Intake workflow/profile exists and uses Ticket terminology consistently.
- Intake can create a Ticket through Ticket tools after user agreement.
- Intake can update/comment on an existing Ticket through Ticket tools when refining known work.
- Intake checks for duplicate/related Tickets before creating a new one when practical.
- Intake-created Tickets include enough information for Orchestrator to classify next action:
- issue/background;
- requirements;
- acceptance criteria;
- non-goals where relevant;
- readiness;
- needs-preflight;
- risk flags;
- escalation conditions where relevant.
- Intake does not require general repository write scope to create Tickets.
- Intake does not start implementation or spawn coder/reviewer Pods.
- Secret/private-context handling is documented in the workflow/prompt.
- Focused tests or prompt/resource linting cover the installed workflow/profile where applicable.
- `cargo check --workspace --all-targets`, `cargo fmt --check`, `git diff --check`, and `./tickets.sh doctor` pass if code changes are included.
## Dependencies
- Requires `ticket-local-files-backend`.
- Requires `ticket-built-in-feature-tools` for the intended authority boundary.
## Follow-up tickets
- `ticket-orchestrator-routing`

View File

@ -0,0 +1,7 @@
<!-- event: create author: tickets.sh at: 2026-06-05T04:01:04Z -->
## Created
Created by tickets.sh create.
---

View File

@ -0,0 +1,103 @@
---
id: 20260605-040104-ticket-orchestrator-routing
slug: ticket-orchestrator-routing
title: Ticket orchestrator routing
status: open
kind: task
priority: P1
labels: [ticket, orchestrator, routing, orchestration]
created_at: 2026-06-05T04:01:04Z
updated_at: 2026-06-05T04:01:25Z
assignee: null
legacy_ticket: null
---
## Background
Once Tickets can be created by Intake and read/mutated through built-in Ticket tools, Orchestrator needs a routing layer that decides what should happen next for each Ticket.
This is not an unattended scheduler MVP. The goal is to make Orchestrator's next-action classification explicit and tool/workflow-backed, so multi-agent operation can move from ad hoc conversation into repeatable routing decisions.
## Requirements
- Define Orchestrator routing states for Tickets.
- Route Tickets into next actions such as:
- requirements sync / return to Intake or human;
- preflight;
- read-only spike/investigation;
- implementation-ready delegation;
- review loop;
- blocked/action-required;
- close/complete;
- defer/pending.
- Use Ticket fields/events rather than hidden conversation state as routing authority.
- Produce an intent packet for implementation-ready Tickets that can be handed to `multi-agent-workflow`.
- Preserve current manual merge/close authority unless explicitly authorized otherwise.
- Keep final design-boundary decisions, merge, cleanup, and Ticket close under Orchestrator/human control.
- Avoid automatic scheduler/lease behavior in MVP.
## Candidate routing classification
```text
implementation_ready:
- Ticket has requirements, acceptance criteria, non-goals/invariants where needed, and validation guidance.
- Orchestrator may create worktree + coder/reviewer assignment through existing multi-agent workflow.
preflight_needed:
- Ticket touches design/authority/scope/history/prompt-context or has multiple plausible implementation strategies.
- Orchestrator should run ticket-preflight-workflow before implementation.
requirements_sync_needed:
- Ticket purpose is visible but user-facing behavior, terms, scope, or acceptance criteria are unclear.
- Return to Intake/human.
spike_needed:
- Technical feasibility, dependency/licensing/performance/diagnostic behavior, or current-code mapping must be investigated first.
- Spawn read-only investigation if authorized.
review_needed:
- Implementation report/diff exists and external review has not approved.
blocked_action_required:
- Human decision or external event is required.
closed_or_noop:
- No routing action.
```
## Integration points
- Existing `.yoi/workflow/multi-agent-workflow.md` remains the implementation/review delegation workflow.
- Existing `.yoi/workflow/ticket-preflight-workflow.md` remains the preflight workflow.
- Ticket tools provide list/show/comment/update operations.
- Future action-required UI/dashboard state can consume the routing result, but UI work is not required in this ticket.
## Non-goals
- Building an unattended scheduler.
- LeaseStore / queue persistence.
- Automatically spawning Pods without human/orchestrator authorization.
- Implementing Ticket backend/tools.
- Implementing Intake workflow.
- Building TUI spawned-Pod panel.
- Changing merge/close policy.
- Replacing `multi-agent-workflow`.
## Acceptance criteria
- Orchestrator has a documented and testable routing classification over Tickets.
- Routing decisions are based on Ticket fields/events and current repository/Pod state that is explicitly inspected.
- Orchestrator can produce a concise intent packet for implementation-ready Tickets.
- Orchestrator can record routing decisions/comments back to the Ticket.
- Preflight-needed Tickets are not blindly delegated to coder Pods.
- Requirements-sync/spike/blocked classifications produce clear next questions or follow-up actions.
- Existing multi-agent workflow remains the execution path for coder/reviewer delegation.
- No automatic scheduler/lease system is introduced.
- Focused tests/docs/workflow updates cover classification behavior where applicable.
- `cargo check --workspace --all-targets`, `cargo fmt --check`, `git diff --check`, and `./tickets.sh doctor` pass if code changes are included.
## Dependencies
- Requires `ticket-local-files-backend`.
- Requires `ticket-built-in-feature-tools` for tool-backed routing updates.
- Benefits from `ticket-intake-workflow`, but can be preflighted in parallel once Ticket fields are stable.

View File

@ -0,0 +1,7 @@
<!-- event: create author: tickets.sh at: 2026-06-05T04:01:04Z -->
## Created
Created by tickets.sh create.
---

View File

@ -2,12 +2,12 @@
id: 20260527-000017-tui-spawned-pod-panel id: 20260527-000017-tui-spawned-pod-panel
slug: tui-spawned-pod-panel slug: tui-spawned-pod-panel
title: TUI: spawned child Pod の一覧と一時 attach title: TUI: spawned child Pod の一覧と一時 attach
status: open status: pending
kind: task kind: task
priority: P2 priority: P2
labels: [migrated] labels: [migrated]
created_at: 2026-05-27T00:00:17Z created_at: 2026-05-27T00:00:17Z
updated_at: 2026-05-28T14:16:02Z updated_at: 2026-06-05T04:03:38Z
assignee: null assignee: null
legacy_ticket: tickets/tui-spawned-pod-panel.md legacy_ticket: tickets/tui-spawned-pod-panel.md
--- ---

View File

@ -0,0 +1,20 @@
<!-- event: migration author: tickets.sh-migration at: 2026-05-27T00:00:17Z -->
## Migrated
Migrated from tickets/tui-spawned-pod-panel.md. No legacy review file was present at migration time.
---
<!-- event: decision author: hare at: 2026-06-05T04:03:38Z -->
## Decision
Decision: deprioritize this ticket for the current multi-agent system direction.
Current need is not a TUI panel for spawned Pods. The priority is Ticket-driven intake/routing: making Tickets a code-facing durable orchestration record, then exposing Ticket operations to Intake/Orchestrator through a typed backend/tool surface.
This ticket is not closed as technically invalid; it is moved out of the active multi-agent implementation path. Revisit only if direct child Pod visibility/attach UI becomes a concrete UX requirement.
---