yoi/.yoi/tickets/00001KTK22AN0/thread.md

22 KiB

Created

Created by LocalTicketBackend create.


Decision

Design consideration: Queue gate should account for unresolved dependencies

This relation metadata should be available before Orchestrator planning. That implies a stronger queue-time question:

If a Ticket has a project-level dependency such as depends_on: X, and X is still in planning / not ready / not resolved, should the user be prevented or warned before Queueing the dependent Ticket?

This needs explicit design before implementation.

Considerations:

  • A dependency that is still planning likely means the dependent Ticket is not truly runnable yet.
  • Queue should probably reject or strongly warn when unresolved depends_on / blocking relations remain.
  • The behavior may differ by relation kind:
    • depends_on unresolved: likely hard block or confirmation-required;
    • blocks: informational for the blocked Ticket;
    • related: never blocks;
    • parent / child: depends on workflow semantics;
    • supersedes / duplicate_of: may redirect or discourage Queue.
  • The Panel should be able to show why Queue is unavailable or risky before involving the Orchestrator.
  • CLI Queue/state transitions should enforce the same rule or at least expose the same diagnostics.
  • Orchestrator should still re-check relations at acceptance time, because relations may change between Queue and routing.

The implementation should decide whether unresolved dependencies make Queue invalid, require confirmation, or allow Queue with a visible blocked state. The important requirement is that dependency relation metadata is not only an Orchestrator input; it should also inform the human Queue gate.


Decision

Design consideration: avoid recreating umbrella Tickets through parent/child relations

Umbrella Tickets are being deprecated as long-lived broad progress containers. This affects relation design.

Parent/child relation kinds can easily recreate the umbrella pattern if they imply that one Ticket is a broad container whose close condition depends on manually inspecting child sufficiency. Therefore relation kinds such as parent / child should be reconsidered before implementation.

Design guidance:

  • Keep concrete dependency/blocking relations distinct from broad grouping.
  • Prefer Objective records for medium-term goal/strategy grouping.
  • If decomposition needs to be represented, consider whether a relation such as derived_from, split_from, or related is safer than parent / child.
  • Do not make relation metadata imply that a broad umbrella Ticket should remain open as a progress container.
  • Any relation kind that approximates parent/child must define clear close semantics and avoid ambiguity around whether all child work is sufficient.

This Ticket should explicitly decide whether to include parent/child relations at all in the first version.


Decision

Decision: relation first version excludes hierarchy

The first version of typed Ticket relations must not include hierarchy/container relation kinds. Exclude:

  • parent / child;
  • sub-ticket;
  • umbrella;
  • part_of / contains.

This avoids recreating umbrella Tickets under another schema. The relation feature should focus on non-hierarchical direct relationships: dependency, blocking, related, supersedes, duplicate/replacement. Medium-term grouping belongs to Objective records, not Ticket hierarchy.


Decision

Intake refinement: ready にするための設計決定

この Ticket は新規 Ticket ではなく、既存 Ticket の refinement として扱う。Orchestrator が routing できるよう、未決定だった relation kind / inverse / queue gate の境界を次の通り固定する。

Readiness

  • readiness: implementation_ready
  • risk_flags: [ticket-schema, workflow-state, panel, orchestrator-routing]

Binding decisions / invariants

  • first version の保存対象 relation kind は非階層 relation のみに限定する。
    • depends_on: この Ticket が対象 Ticket の完了/解決を必要とする。
    • blocks: この Ticket が対象 Ticket の実行/完了を妨げる。
    • related: 非 blocking の関連。
    • supersedes: この Ticket が対象 Ticket を置き換える。
    • duplicate_of: この Ticket が対象 Ticket の duplicate である。
  • blocked_by / superseded_by / duplicate 逆一覧などの inverse view は保存済み forward relation から導出する。first version では inverse relation kind を別途保存して整合性を二重管理しない。
  • parent / child / sub-ticket / umbrella / part_of / contains は first version で扱わない。Ticket relation metadata で umbrella Ticket を再作成しない。
  • relation metadata は project-level Ticket record であり、Pod/session claim、worktree、branch ownership、coder/reviewer assignment、capacity、current planned order、do_not_parallelize を保存しない。これらは local role session registry / OrchestrationPlan / Pod metadata の責務に残す。
  • Queue gate は unresolved blocking relation を無視してはならない。
    • 対象 Ticket の unresolved depends_on と incoming unresolved blocks は、Panel/CLI の ready -> queued 操作で visible reason 付きの block/diagnostic にする。
    • related は queue を block しない。
    • supersedes / duplicate_of は replacement/duplicate として visible diagnostic にする。自動的に全 relation を blocking 扱いしない。
    • Orchestrator は queued -> inprogress acceptance 時に relation を再確認する。Queue gate の判定は Orchestrator の再確認を省略する根拠ではない。

Implementation latitude

  • durable storage の具体形は、typed backend が検証でき、git-trackable で、TicketShow / ticket doctor / Panel summary から読める限り実装側で選んでよい。例: item.md frontmatter の typed field、または Ticket artifacts 配下の typed record。
  • CLI の具体的な relation 操作名・オプション名、Panel 上の短い表示文言、cycle 検出の bounded な実装方式は実装側で選んでよい。
  • depends_onblocks は利用者が自然な方向で記録できる relation kind として両方残すが、表示・validation では inverse view を導出して重複/矛盾を診断してよい。

Escalation conditions

  • hierarchy/container semantics を追加したくなった場合。
  • inverse relation を保存しないと実装できない設計にしたくなった場合。
  • queue gate を unresolved dependency でも通常 queue 可能にしたくなった場合。
  • relation metadata に Pod/session/worktree/assignment/capacity/current-batch order を保存したくなった場合。
  • public Ticket schema または role workflow guidance で relation kind 名を上記から変更したくなった場合。

Validation focus

  • ticket doctor が dangling reference、invalid kind、self relation、obvious dependency/blocking cycle を bounded diagnostic として検出すること。
  • TicketShow が forward relation と derived inverse view を理解できる形で表示すること。
  • Panel/CLI が unresolved dependency/blocker を queue 前に visible にすること。
  • Intake/Planning と Orchestrator guidance が project-level relation metadata と OrchestrationPlan runtime decision を混同しないこと。

Intake summary

既存 Ticket を refinement し、typed Ticket relation metadata の first version を非階層 relation に限定して implementation_ready にした。保存 relation kind は depends_on / blocks / related / supersedes / duplicate_of、inverse view は forward relation から導出し、parent / child / sub-ticket / umbrella / part_of / contains は扱わない。unresolved depends_on と incoming unresolved blocks は Panel/CLI queue gate で visible block/diagnostic にし、Orchestrator は acceptance 時に再確認する。runtime claims や OrchestrationPlan execution decisions は relation metadata に保存しない。blocking open questions はない。


State changed

Intake refinement により、relation kind、inverse relation の扱い、queue gate 境界、binding invariants、implementation latitude、escalation conditions が揃ったため ready に遷移する。


State changed

Ticket を workspace-panel が queued にしました。


Decision

Routing decision: defer_pending_ticket_identity_migration

This Ticket is queued and appears implementation-ready, but I am intentionally not accepting it to inprogress yet.

Reason:

  • simplify-ticket-identity-fields is already active, with Coder Pod coder-simplify-ticket-identity-fields running in .worktree/simplify-ticket-identity-fields.
  • This Ticket depends on the same Ticket backend/schema/API/panel/doctor surfaces and explicitly needs canonical Ticket references.
  • Implementing typed relations before the identity simplification lands would risk building relation storage and validation on soon-to-change identity/layout/state semantics.

State decision:

  • Leave this Ticket queued.
  • Do not create a worktree or spawn a coder yet.

Next action:

  • After simplify-ticket-identity-fields is merged/closed/cleaned up or explicitly held back, re-read this Ticket against the new identity model and accept it from queued if still unblocked.

State changed

Accepted queued implementation after identity simplification landed, was closed, and the workspace was verified clean on the flat Ticket layout. This Ticket is the lower-level project-level Ticket relation/reference surface, so it should run before Objective records, which may reference Tickets and relation concepts.


Decision

Routing decision: implementation_ready

Evidence checked:

  • Ticket body/thread, including Intake refinement and explicit first-version relation decisions.
  • Current flat Ticket identity state after simplify-ticket-identity-fields landed and closed.
  • Current queued set: typed-ticket-relation-metadata and objective-records-for-medium-term-goals.
  • Orchestration plan records: none existed before this routing; I recorded that typed relations should run before Objective records.
  • Workspace/worktree state: main workspace clean enough to route, no active implementation worktree.

Reason:

  • The Ticket has concrete binding decisions: non-hierarchical relation kinds only, forward stored relations with derived inverse views, queue-gate diagnostics for unresolved dependencies/blockers, and clear separation from OrchestrationPlan/runtime claims.
  • It is lower-level than Objective records because Objective links should target stable canonical Ticket IDs and relation/reference semantics.
  • No concrete missing decision remains that requires returning to planning.

IntentPacket:

Intent:

  • Add typed, durable, non-hierarchical project-level Ticket-to-Ticket relation metadata on top of the flat canonical Ticket ID/state model.

Binding decisions / invariants:

  • Supported stored relation kinds for first version: depends_on, blocks, related, supersedes, duplicate_of.
  • Do not support hierarchy/container kinds: no parent, child, sub-ticket, umbrella, part_of, or contains.
  • Store forward relations only; derive inverse views such as blocked-by / superseded-by / duplicate inverse from forward records.
  • Relations are project-level Ticket metadata and must not store Pod/session claims, worktree paths, branch ownership, coder/reviewer assignments, capacity, current planned order, or do_not_parallelize execution-plan state.
  • Store relations durably under the Ticket backend in a typed, git-trackable, backend-validated form.
  • Use canonical opaque Ticket IDs only. Do not use title/slug words as relation authority.
  • TicketShow must display relation metadata including useful inverse view.
  • ticket doctor must validate dangling references, invalid kinds, self relations, and obvious dependency/blocking cycles with bounded diagnostics.
  • Panel/CLI queue gate should not ignore unresolved blocking relations: unresolved depends_on and incoming unresolved blocks must be visible as block/diagnostic before ready -> queued and rechecked by Orchestrator at acceptance.
  • related does not block queue; supersedes / duplicate_of produce visible replacement/duplicate diagnostics but are not automatically all blocking.
  • Orchestrator routing treats relations as input constraints distinct from OrchestrationPlan runtime decisions.
  • Do not implement Objective records here.
  • Do not implement a full scheduler/dependency graph solver.
  • Do not change Pod protocol/history/session semantics.

Implementation latitude:

  • Coder may choose typed artifact vs current Ticket metadata field if it is validated, git-trackable, queryable, and works with flat IDs.
  • CLI/tool names and exact Panel hint wording are implementation latitude if acceptance criteria are met.
  • Cycle detection may be bounded and documented/test-covered.
  • If the queue gate cannot be fully enforced in Panel/CLI without broad UI redesign, implement visible diagnostics and escalate the exact remaining gap rather than silently skipping it.

Reviewer focus:

  • Verify relation storage is typed/validated and does not rely only on Markdown thread prose.
  • Verify canonical ID references and local record migration/test fixtures use flat IDs.
  • Verify no hierarchy/container relation kind slips in as current behavior.
  • Verify OrchestrationPlan and Ticket relations remain distinct.
  • Verify doctor and queue/panel/list/show surfaces expose unresolved dependency/blocker information before Orchestrator starts work.

Validation:

  • Focused Ticket backend/parser/writer/doctor tests for relations, dangling references, invalid kinds, self relation, cycles, derived inverse views.
  • Focused CLI/tool/schema tests for relation create/show/list/query or equivalent surfaces.
  • Focused panel/queue-gate tests for unresolved dependency/blocker visibility if touched.
  • Workflow/prompt/doc checks for Intake/Planning/Orchestrator relation guidance.
  • cargo fmt --check.
  • git diff --check.
  • cargo run -q -p yoi -- ticket doctor.
  • cargo check --workspace.
  • nix build .#yoi.

Implementation report

Implementation routing started.

Worktree/branch:

  • Worktree: .worktree/typed-ticket-relation-metadata
  • Branch: typed-ticket-relation-metadata
  • Base/routing commit: 41a61d7 ticket: route typed relation metadata

Spawned sibling Coder Pod:

  • coder-typed-ticket-relation-metadata
  • Scope: non-recursive read on parent workspace root plus recursive write limited to the child worktree.

Routing context:

  • simplify-ticket-identity-fields is merged, closed, cleaned up, and the flat Ticket layout is active.
  • objective-records-for-medium-term-goals remains queued behind this work; durable orchestration plan records now encode that ordering.
  • This Ticket is the active lower-level Ticket relation/reference implementation work.

Implementation report

Coder implementation completed and is ready for sibling review.

Coder Pod:

  • coder-typed-ticket-relation-metadata
  • Commit: 4601ad2b41d6c51c9d445ca2291726a658c42ab5 ticket: add typed relation metadata
  • Worktree status before review: clean branch typed-ticket-relation-metadata
  • Stopped after collecting output to reclaim delegated worktree scope.

Selected design:

  • Store forward project-level Ticket relation metadata per Ticket as typed JSON at .yoi/tickets/<ticket-id>/artifacts/relations.json.
  • Stored relation kinds: depends_on, blocks, related, supersedes, duplicate_of.
  • Derived inverse views are computed, not stored: blocked_by, dependency_of, superseded_by, duplicated_by.
  • Relation authority uses canonical opaque Ticket IDs only.
  • Unresolved depends_on and incoming unresolved blocks are treated as queue/acceptance blockers; related does not block; supersedes / duplicate_of are visible diagnostics only.

Implementation summary:

  • Added typed relation structs, artifact read/write, backend relation query/view, and doctor validation in crates/ticket.
  • Added TicketRelationRecord / TicketRelationQuery tools and relation JSON in TicketShow/List-related output.
  • Added CLI relation commands: yoi ticket relation add ... and yoi ticket relation list ....
  • Updated workspace panel to display unresolved relation blockers for ready Tickets.
  • Updated Orchestrator/work-item guidance to distinguish Ticket relations from OrchestrationPlan execution records.

Changed files:

  • .yoi/workflow/ticket-orchestrator-routing.md
  • crates/ticket/src/lib.rs
  • crates/ticket/src/tool.rs
  • crates/tui/src/workspace_panel.rs
  • crates/yoi/src/ticket_cli.rs
  • docs/development/work-items.md

Coder validation reported passed:

  • cargo test -q -p ticket ticket_relations
  • cargo test -q -p ticket queue_gate_rejects
  • cargo test -q -p ticket doctor_validates_ticket_relations
  • cargo test -q -p ticket ticket_relation_tools_record
  • cargo test -q -p ticket ticket_tool_name_partitions_are_explicit
  • cargo test -q -p yoi ticket_cli_records_lists_and_shows_relations
  • cargo test -q -p tui workspace_panel_marks_ready_ticket_with_unresolved_relation_blocked
  • cargo fmt --check
  • git diff --check
  • cargo run -q -p yoi -- ticket doctor
  • cargo check --workspace
  • nix build .#yoi

Residual risks noted by coder:

  • No relation delete/update operation in this first version.
  • Derived inverse view scans relation artifacts; acceptable for current local scale but may need index/cache if Ticket counts grow.
  • Cycle detection is bounded and intentionally not a scheduler/dependency solver.
  • supersedes / duplicate_of do not automatically close/block/transition Tickets.

Review: approve

Approved review for commit 4601ad2b41d6c51c9d445ca2291726a658c42ab5.

Evidence checked:

  • TicketRelationKind stores only depends_on, blocks, related, supersedes, and duplicate_of; hierarchy/container names are not supported as current relation kinds.
  • Relation storage is a typed artifacts/relations.json artifact with versioned JSON, deny_unknown_fields, owner-ticket validation, self/duplicate validation, and canonical Ticket-id lookup for targets.
  • Inverse relation views are derived through TicketShow/CLI output; only forward records are written.
  • Queue gates reject unresolved outgoing depends_on and incoming unresolved blocks at both ready -> queued and queued -> inprogress; Panel rows use the derived blocker view rather than silently offering Queue.
  • TicketRelationQuery is read-only and TicketRelationRecord is mutating in the ticket tool partitions.
  • Orchestrator guidance explicitly separates project-level relation metadata from OrchestrationPlan runtime ordering/capacity records.

Validation run from the worktree:

  • cargo test -q -p ticket ticket_relations
  • cargo test -q -p ticket queue_gate_rejects
  • cargo test -q -p ticket doctor_validates_ticket_relations
  • cargo test -q -p ticket ticket_relation_tools_record
  • cargo test -q -p ticket ticket_tool_name_partitions_are_explicit
  • cargo test -q -p yoi ticket_cli_records_lists_and_shows_relations
  • cargo test -q -p tui workspace_panel_marks_ready_ticket_with_unresolved_relation_blocked
  • cargo run -q -p yoi -- ticket doctor
  • nix build .#yoi

Residual risk: TicketShow tool description still summarizes the old output shape and does not mention relations, but the returned JSON and CLI display include relation metadata; this is documentation polish rather than a correctness blocker.


State changed

Ticket を closed にしました。


完了

Implemented, reviewed, merged, and validated.

Summary:

  • Added typed, durable, non-hierarchical Ticket relation metadata.
  • Stored forward project-level relations as typed JSON artifacts at .yoi/tickets/<ticket-id>/artifacts/relations.json.
  • Supported first-version relation kinds: depends_on, blocks, related, supersedes, and duplicate_of.
  • Derived inverse views such as blocked_by, dependency_of, superseded_by, and duplicated_by from forward relations rather than storing inverse relation kinds.
  • Added Ticket backend validation and ticket doctor diagnostics for relation artifacts, dangling references, self relations, duplicate relations, and bounded dependency/blocking cycles.
  • Added TicketRelation LLM tools, CLI relation add/list surfaces, TicketShow/List relation metadata, and workspace panel unresolved blocker hints.
  • Kept relation metadata distinct from OrchestrationPlan execution records and from Pod/session/worktree/runtime claims.

Implementation:

  • Coder commit: 4601ad2 ticket: add typed relation metadata
  • Reviewer approved with no blocking findings.
  • Merge commit: 2225311 merge: add typed ticket relation metadata

Validation after merge:

  • cargo test -q -p ticket ticket_relations
  • cargo test -q -p ticket queue_gate_rejects
  • cargo test -q -p ticket doctor_validates_ticket_relations
  • cargo test -q -p ticket ticket_relation_tools_record
  • cargo test -q -p ticket ticket_tool_name_partitions_are_explicit
  • cargo test -q -p yoi ticket_cli_records_lists_and_shows_relations
  • cargo test -q -p tui workspace_panel_marks_ready_ticket_with_unresolved_relation_blocked
  • cargo fmt --check
  • git diff --check
  • cargo run -q -p yoi -- ticket doctor
  • cargo check --workspace
  • nix build .#yoi