yoi/work-items/open/20260605-173322-ticket-config-role-profile-mapping/artifacts/implementation-report.md

4.2 KiB

Implementation report: ticket-config-role-profile-mapping

Worktree / branch

  • Worktree: /home/hare/Projects/yoi/.worktree/ticket-config-role-profile-mapping
  • Branch: work/ticket-config-role-profile-mapping

Commits

  • 767870a ticket: add workspace ticket config
  • 8fab67b ticket: reject nix profile selectors

Summary

Implemented .yoi/ticket.config.toml as workspace-local Ticket orchestration configuration with fixed Ticket role slots and wired the configured backend root into the existing Ticket built-in feature adapter.

The implementation keeps Ticket role configuration narrow:

  • fixed roles only: intake, orchestrator, coder, reviewer, investigator;
  • role fields: profile, optional launch_prompt, optional workflow;
  • no system_instruction role field;
  • durable role/system behavior remains owned by the selected Profile.

Final module/API layout

Added crates/ticket/src/config.rs, exported as ticket::config.

Main public API:

  • TicketConfig
    • load_workspace(workspace_root)
    • default_for_workspace(workspace_root)
    • backend_root()
    • role(role)
    • profile_for(role)
    • launch_prompt_for(role)
    • workflow_for(role)
  • TicketBackendConfig
  • TicketBackendKind
  • TicketRole
  • ProfileSelectorRef
  • PromptRef
  • WorkflowRef
  • TicketConfigError
  • TICKET_CONFIG_RELATIVE_PATH = ".yoi/ticket.config.toml"

The ticket crate keeps lightweight string refs and does not depend on pod or manifest.

Schema/defaults implemented

Config path:

.yoi/ticket.config.toml

Backend:

[backend]
kind = "local"
root = "work-items"

Role example:

[roles.coder]
profile = "project:coder"
launch_prompt = "$workspace/prompts/ticket-coder"
workflow = "multi-agent-workflow"

Defaults when the config file is missing:

  • backend: local <workspace>/work-items;
  • all role profiles: inherit;
  • launch prompts: none;
  • workflows:
    • intake: ticket-intake-workflow;
    • orchestrator: ticket-orchestrator-routing;
    • coder: multi-agent-workflow;
    • reviewer: multi-agent-workflow;
    • investigator: ticket-orchestrator-routing.

Validation rejects unknown top-level fields, unknown backend fields, unknown role fields, unknown roles, unsupported backend kinds, malformed/empty refs, path-like profile selector values, .lua, and .nix profile selector values.

Pod Ticket feature adapter wiring

Updated crates/pod/src/feature/builtin/ticket.rs so TicketFeature::for_workspace(...) loads ticket::config::TicketConfig.

Behavior:

  • missing config uses documented defaults, preserving previous <workspace>/work-items behavior;
  • valid config uses configured [backend].root;
  • malformed config fails closed: Ticket tools are not registered and a feature diagnostic is emitted;
  • missing/unusable backend root preserves existing no-register behavior;
  • tool authority continues to use HostAuthority::TicketBackend { root } for the configured backend root.

Changed files

  • Cargo.lock
  • crates/pod/src/feature/builtin/ticket.rs
  • crates/ticket/Cargo.toml
  • crates/ticket/src/config.rs
  • crates/ticket/src/lib.rs
  • package.nix

Review status

External sibling review initially requested one blocker fix:

  • ProfileSelectorRef accepted *.nix profile selectors while existing SpawnPod.profile validation rejects them.

The blocker was fixed by commit 8fab67b and re-review approved with no blockers.

Remaining non-blocker follow-ups:

  • HostAuthority::TicketBackend { root } is derived from the configured path while the actual backend uses a canonicalized usable root; future explicit grant/audit comparisons should normalize consistently.
  • Pod adapter root usage could be strengthened with an execution-level tool test against the configured root.

Validation

Coder-reported validation for the main implementation passed:

  • cargo test -p ticket
  • cargo test -p pod ticket --lib
  • cargo test -p pod feature --lib
  • cargo check --workspace --all-targets
  • cargo fmt --check
  • git diff --check
  • ./tickets.sh doctor
  • nix build .#yoi --no-link

Coder-reported validation for the blocker fix passed:

  • cargo test -p ticket config
  • cargo test -p ticket
  • cargo fmt --check
  • git diff --check

Ready for merge

Yes.