merge: unify project record ids

This commit is contained in:
2026-06-09 22:24:40 +09:00
798 changed files with 477 additions and 105 deletions
@@ -0,0 +1,174 @@
20260527-000001-001 00001KSKBP8Z8
20260527-000002-001 00001KSKBP9YG
20260527-000003-001 00001KSKBPAXR
20260527-000004-001 00001KSKBPBX0
20260527-000005-001 00001KSKBPCW8
20260527-000006-001 00001KSKBPDVG
20260527-000007-001 00001KSKBPETR
20260527-000008-001 00001KSKBPFT0
20260527-000009-001 00001KSKBPGS8
20260527-000010-001 00001KSKBPHRG
20260527-000011-001 00001KSKBPJQR
20260527-000012-001 00001KSKBPKQ0
20260527-000013-001 00001KSKBPMP8
20260527-000014-001 00001KSKBPNNG
20260527-000015-001 00001KSKBPPMR
20260527-000016-001 00001KSKBPQM0
20260527-000017-001 00001KSKBPRK8
20260527-000018-001 00001KSKBPSJG
20260527-000019-001 00001KSKBPTHR
20260527-000020-001 00001KSKBPVH0
20260527-000021-001 00001KSKBPWG8
20260527-000022-001 00001KSKBPXFG
20260527-000023-001 00001KSKBPYER
20260527-194421-001 00001KSNFEVG8
20260527-201313-001 00001KSNH3PX8
20260528-001748-001 00001KSNZ3HZ0
20260528-131317-001 00001KSQBFGE8
20260528-141602-001 00001KSQF2D6G
20260528-152959-001 00001KSQK9T6R
20260528-163238-001 00001KSQPWH3G
20260528-233524-001 00001KSRF2MK0
20260529-001326-001 00001KSRH893G
20260529-010200-001 00001KSRM16T0
20260529-010200-002 00001KSRM16T1
20260529-031832-001 00001KSRVV6T0
20260529-041911-001 00001KSRZA8GR
20260529-145355-001 00001KST3MFXR
20260529-161928-001 00001KST8H4M0
20260529-163047-001 00001KST95VPR
20260529-171326-001 00001KSTBKYQG
20260529-180257-001 00001KSTEEM38
20260529-181528-001 00001KSTF5HG0
20260529-183318-001 00001KSTG66DG
20260529-205540-001 00001KSTRAW70
20260529-205844-001 00001KSTRGFX0
20260529-222850-001 00001KSTXNF6G
20260529-235408-001 00001KSV2HN80
20260530-013904-001 00001KSV8HSP0
20260530-022235-001 00001KSVB1FFR
20260530-053259-001 00001KSVNY3QR
20260530-053721-001 00001KSVP63K8
20260530-054927-001 00001KSVPW8JR
20260530-062852-001 00001KSVS4E50
20260530-204045-001 00001KSX9W968
20260530-215928-001 00001KSXECDG0
20260531-003743-001 00001KSXQE5YR
20260531-005557-001 00001KSXRFJA8
20260531-010005-001 00001KSXRQ4G8
20260531-022821-001 00001KSXXRRC8
20260531-043239-001 00001KSY4WBJR
20260531-045034-001 00001KSY5X5CG
20260531-054728-001 00001KSY95BC0
20260531-064550-001 00001KSYCG79G
20260531-074258-001 00001KSYFRTYG
20260531-074258-002 00001KSYFRTYH
20260531-074258-003 00001KSYFRTYJ
20260531-082646-001 00001KSYJ91BG
20260531-085959-001 00001KSYM5VMR
20260531-085959-002 00001KSYM5VMS
20260531-104614-001 00001KSYT8D7G
20260531-110818-001 00001KSYVGT6G
20260531-111956-001 00001KSYW63V0
20260531-124040-001 00001KSZ0SYA0
20260531-223506-001 00001KT02TCCG
20260601-001616-001 00001KT08KM40
20260601-013132-001 00001KT0CXE90
20260601-020202-001 00001KT0EN9CG
20260601-021104-001 00001KT0F5TP0
20260601-031252-001 00001KT0JPZS0
20260601-064953-001 00001KT0Z4BK8
20260601-080614-001 00001KT13G57G
20260601-110026-001 00001KT1DF48G
20260601-110026-002 00001KT1DF48H
20260601-123641-001 00001KT1JZBX8
20260601-125240-001 00001KT1KWME0
20260601-132955-001 00001KT1P0V1R
20260603-001124-001 00001KT5D44Z0
20260603-122317-001 00001KT6Q08R8
20260603-122317-002 00001KT6Q08R9
20260604-223500-001 00001KTACD2H0
20260604-234844-001 00001KTAGM2V0
20260605-004807-001 00001KTAM0TAR
20260605-004807-002 00001KTAM0TAS
20260605-025100-001 00001KTAV1TH0
20260605-040104-001 00001KTAZ2400
20260605-040104-002 00001KTAZ2401
20260605-040104-003 00001KTAZ2402
20260605-040104-004 00001KTAZ2403
20260605-173322-001 00001KTCDHFPG
20260605-190330-001 00001KTCJPGYG
20260605-190330-002 00001KTCJPGYH
20260605-203006-001 00001KTCQN35G
20260605-203006-002 00001KTCQN35H
20260605-203006-003 00001KTCQN35J
20260605-203006-004 00001KTCQN35K
20260605-203006-005 00001KTCQN35M
20260605-210703-001 00001KTCSRR6R
20260605-210704-001 00001KTCSRS60
20260605-210704-002 00001KTCSRS61
20260605-210704-003 00001KTCSRS62
20260605-210704-004 00001KTCSRS63
20260605-210704-005 00001KTCSRS64
20260606-052903-001 00001KTDPFY8R
20260606-060548-001 00001KTDRK7K0
20260606-210832-001 00001KTFC8640
20260606-215403-001 00001KTFEVH3R
20260606-221301-001 00001KTFFY8E8
20260606-233520-001 00001KTFMMZP0
20260607-001651-001 00001KTFQ109R
20260607-001651-002 00001KTFQ109S
20260607-001651-003 00001KTFQ109T
20260607-001651-004 00001KTFQ109V
20260607-012131-001 00001KTFTQDBR
20260607-020215-001 00001KTFX202R
20260607-022328-001 00001KTFY8V80
20260607-031439-001 00001KTG16J8R
20260607-031439-002 00001KTG16J8S
20260607-033536-001 00001KTG2CXT0
20260607-035143-001 00001KTG3AE4R
20260607-035201-001 00001KTG3AZQ8
20260607-035231-001 00001KTG3BX0R
20260607-035710-001 00001KTG3MDFG
20260607-062902-001 00001KTGCAFXG
20260607-062902-002 00001KTGCAFXH
20260607-072708-001 00001KTGFMW70
20260607-073313-001 00001KTGG00N8
20260607-084344-001 00001KTGM14G0
20260607-095142-001 00001KTGQXJXG
20260607-213808-001 00001KTJ0B3G0
20260607-220225-001 00001KTJ1QJB8
20260607-220606-001 00001KTJ1YA5G
20260607-223233-001 00001KTJ3EQZ8
20260607-224309-001 00001KTJ42528
20260607-225448-001 00001KTJ4QFP0
20260607-230044-001 00001KTJ52BB0
20260607-234530-001 00001KTJ7MACG
20260607-235442-001 00001KTJ855EG
20260607-235505-001 00001KTJ85VX8
20260608-000047-001 00001KTJ8G9WR
20260608-010442-001 00001KTJC5B0G
20260608-011036-001 00001KTJCG4Q0
20260608-014602-001 00001KTJEH0WG
20260608-015630-001 00001KTJF465G
20260608-032200-001 00001KTJM0QY0
20260608-032911-001 00001KTJMDWTR
20260608-054546-001 00001KTJW7ZRG
20260608-061235-001 00001KTJXS31R
20260608-071722-001 00001KTK1FPYG
20260608-072732-001 00001KTK22AN0
20260608-103133-001 00001KTKCK8W8
20260608-103842-001 00001KTKD0BTG
20260608-110940-001 00001KTKES290
20260608-125430-001 00001KTKMS0VG
20260608-132230-001 00001KTKPC9FG
20260609-032533-001 00001KTN6KYY8
20260609-070926-001 00001KTNKDX3G
20260609-073047-001 00001KTNMN02R
20260609-082209-001 00001KTNQK1V8
20260609-084725-001 00001KTNS1AA8
20260609-085148-001 00001KTNS9B50
20260609-085212-001 00001KTNSA2K0
20260609-093050-001 00001KTNVGT8G
20260609-095518-001 00001KTNWXKVG
20260609-101732-001 00001KTNY6AK0
@@ -0,0 +1,13 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KTNMN02R",
"kind": "related",
"target": "00001KTKES290",
"note": "非ブロッキング関連。先行の Ticket identity/frontmatter 簡素化で timestamp/counter 型の opaque canonical ID と flat layout が導入済みで、本 Ticket はその ID 形式を Ticket / Objective 共通の fixed-width base32 epoch-milliseconds 形式へさらに統一する follow-up。",
"author": "intake",
"at": "2026-06-09T10:26:20Z"
}
]
}
+96
View File
@@ -0,0 +1,96 @@
---
title: 'Ticket と Objective の ID を base32 timestamp 形式に統一する'
state: 'inprogress'
created_at: '2026-06-09T07:30:47Z'
updated_at: '2026-06-09T13:24:34Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-09T10:31:17Z'
---
## 背景
Ticket identity simplification と Objective record 導入により、Ticket / Objective の canonical ID を共通の短い不透明 ID に揃えたい。
現状:
- Ticket は過去の timestamp + slug 形式から移行中。
- Objective は `YYYYMMDD-HHMMSS-001` 形式で、秒単位 timestamp + counter を使っている。
望ましい方向:
- ID は title / slug / 内容を含まない。
- lexicographic sort が作成時系列として使える。
- 完全連番は Git branch / workspace 並行作業で衝突しやすいため避ける。
- 秒単位 + `-001` ではなく、millisecond timestamp を短い固定幅 text に圧縮する。
- `created_at` は人間可読な timestamp field として別に持つ。
## ゴール
Ticket と Objective の canonical ID を、共通の fixed-width base32 encoded Unix epoch milliseconds 形式に統一する。
## 要件
- Ticket と Objective の canonical ID 形式を共通化する。
- ID は Unix epoch milliseconds を base32 text にしたものにする。
- alphabet は人間が読み間違えにくいものを使う。
- 例: Crockford base32 系 `0123456789ABCDEFGHJKMNPQRSTVWXYZ`
- `I` / `L` / `O` など紛らわしい文字は避ける。
- ID は fixed width にする。
- 例: 9 chars。
- fixed width により lexicographic sort が chronological sort と一致する。
- ID は title / slug / content words を含まない。
- ID は canonical path component として安全であること。
- `created_at` は引き続き frontmatter field として持つ。
- ID は compact primary key。
- `created_at` は人間可読な作成時刻。
- `updated_at` も existing behavior として維持する。
## Collision handling
- ID 生成時に同じ workspace 内で path collision が起きた場合、timestamp milliseconds を `+1ms` して再 encode する。
- 衝突時に `-001` / suffix / random tail を付けない。
- `+1ms` を繰り返して空き ID を探す。
- 生成に使った adjusted timestamp と `created_at` の関係を明確にする。
- 推奨: `created_at` は実作成時刻を保持し、ID は collision-adjusted primary key として扱う。
- もしくは adjusted timestamp を `created_at` にも反映する場合は、その理由を明記する。
- 過剰衝突時の bounded error を用意する。
## Scope
- 共通 ID allocator/helper を作る。
- Ticket create path と Objective create path で共有する。
- 将来の project records にも使える形が望ましい。
- Ticket create / path layout をこの ID 形式に移行する。
- Objective create / path layout をこの ID 形式に移行する。
- Existing Ticket / Objective records を migration する。
- `TicketList` / `TicketShow` / `Objective list` / `Objective show` / doctor / tests を更新する。
- Relation metadata や Objective linked tickets は、この canonical ID を前提にする。
## 非目標
- ID から作成時刻を人間が直接読めるようにすること。
- 必要なら `created_at` を見る。
- 完全連番 ID。
- title / slug を ID に含めること。
- random UUID を使うこと。
- この Ticket で Ticket relation metadata や Objective の高機能化を実装すること。
## 受け入れ条件
- Ticket と Objective の新規作成で同じ canonical ID format が使われる。
- ID は fixed-width base32 epoch-milliseconds text で、title/slug を含まない。
- ID の lexicographic sort が作成時系列と一致する。
- 同一 millisecond collision は `+1ms` retry で解決される。
- `created_at``updated_at` が frontmatter に残る。
- Existing Ticket / Objective records が新 ID/path に migration される。
- Objective の `YYYYMMDD-HHMMSS-001` 形式は current format ではなくなる。
- Ticket の old timestamp-slug path / slug-derived identity は current format ではなくなる。
- Tests cover:
- encoding/decoding or ordering property;
- collision handling;
- Ticket create;
- Objective create;
- doctor validation;
- migration-relevant lookup behavior.
- `target/debug/yoi ticket doctor`, `target/debug/yoi objective doctor`, focused tests, `cargo fmt --check`, and `git diff --check` pass.
+231
View File
@@ -0,0 +1,231 @@
<!-- event: create author: LocalTicketBackend at: 2026-06-09T07:30:47Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: decision author: intake at: 2026-06-09T10:26:34Z -->
## Decision
Intake refinement / readiness decision。
この Ticket は `implementation_ready` として扱える。目的、対象範囲、受け入れ条件、collision handling、migration 対象、非目標がすでに具体化されており、Orchestrator が実装 routing を判断できる。
Binding decisions / invariants:
- Ticket と Objective の canonical ID は共通の fixed-width base32 encoded Unix epoch milliseconds text に統一する。
- ID は title / slug / content words を含めない opaque path component とする。
- fixed width により lexicographic sort と chronological sort が一致することを維持する。
- 同一 millisecond collision は suffix / random tail ではなく `+1ms` retry で解決する。
- `created_at` / `updated_at` は frontmatter の人間可読 timestamp field として維持する。
- 既存 Ticket / Objective record の migration、lookup、doctor、関連 metadata / linked-ticket 参照の整合性を対象に含める。
Implementation latitude:
- exact width と alphabet は要件を満たす範囲で実装時に確定してよい。現行 epoch milliseconds を十分な期間表現でき、紛らわしい文字を避け、path-safe で、固定長 ordering property を満たすこと。Crockford base32 系と 9 chars は推奨例として扱える。
- 共通 helper の crate / module 配置は、Ticket create path と Objective create path から共有でき、将来の project records に自然に拡張できる範囲で実装判断してよい。
- migration は既存 durable project records を壊さず、canonical ID/path と内部参照を一貫して更新できる方式を選ぶ。
Risk flags / reviewer focus:
- `storage-migration`
- `canonical-id-schema`
- `ticket-objective-cross-reference`
- `backward-compatibility-boundary`
- `cli-doctor-validation`
Escalation conditions:
- fixed-width base32 epoch milliseconds では要件の ordering / collision / path-safety を同時に満たせないと判明した場合。
- 既存 Ticket / Objective migration が reference integrity を安全に保てない場合。
- exact width を 9 chars から大きく外す、Crockford 系ではない alphabet を採る、または random / suffix fallback を追加したくなった場合。
- ID timestamp と `created_at` の関係を推奨と異なる semantics にしたい場合。
Validation expectation:
- Ticket body の既存 validation に加え、コード・パッケージングに関わるため完了前に `nix build .#yoi` も通す。
---
<!-- event: intake_summary author: intake at: 2026-06-09T10:26:42Z -->
## Intake summary
Ticket と Objective の canonical ID を共通の fixed-width base32 epoch-milliseconds 形式へ統一する concrete work item として整理済み。Open questions はなく、binding decisions は opaque/path-safe ID、title/slug/content words 非包含、lexicographic ordering、`+1ms` collision retry、`created_at` / `updated_at` 維持、既存 Ticket / Objective migration と参照整合性。Risk flags は storage-migration / canonical-id-schema / ticket-objective-cross-reference / backward-compatibility-boundary / cli-doctor-validation。関連する先行 Ticket `00001KTKES290` は closed の非ブロッキング前提、`00001KTNSA2K0` は非ブロッキング関連。
---
<!-- event: state_changed author: intake at: 2026-06-09T10:26:42Z from: planning to: ready reason: intake_ready field: state -->
## State changed
Intake refinement により、目的・範囲・受け入れ条件・binding decisions / invariants・implementation latitude・escalation conditions・validation focus が揃ったため、Orchestrator が routing できる ready に移行する。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-09T10:31:17Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: orchestrator at: 2026-06-09T10:35:08Z -->
## Decision
Routing decision: waiting_for_active_record_churn_to_settle
This Ticket remains queued for now, despite the updated parallelism preference.
Reason:
- This Ticket is a broad Ticket/Objective ID migration touching current project-record paths and internal references.
- There are multiple active worktrees currently writing Ticket records and code.
- Running a storage/ID migration in parallel with active Ticket record churn would create high merge/migration risk, not a small conflict.
State decision:
- Leave this Ticket `queued`.
- Re-read when active worktrees are merged/closed or the workspace is otherwise quiescent enough for a record migration.
---
<!-- event: decision author: orchestrator at: 2026-06-09T11:30:25Z -->
## Decision
Routing decision update: still_waiting_record_migration_window
This Ticket remains queued for now despite the increased parallelism preference.
Reason:
- This is a broad Ticket/Objective ID migration that will touch project record paths and many references.
- I am starting two smaller independent workstreams now (`00001KTNQK1V8` and `00001KTNWXKVG`).
- Running another record identity migration in parallel with active Ticket schema/profile work would create high migration/merge risk, not a small mechanical conflict.
State decision:
- Leave this Ticket queued.
- Re-read and route after current active schema/profile work lands or if the workspace is otherwise quiescent enough for a record migration.
---
<!-- event: state_changed author: orchestrator at: 2026-06-09T12:46:44Z from: queued to: inprogress reason: implementation_acceptance field: state -->
## State changed
Accepting queued implementation now that the parallel Profile feature-flag and Ticket schema cleanup branches are landed, validated, closed, and cleaned up. This Ticket is broad record/path migration work, so it is intentionally started only after workspace quiescence.
---
<!-- event: decision author: orchestrator at: 2026-06-09T12:46:44Z -->
## Decision
Routing decision:
Start implementation now. The earlier high-conflict schema/profile work is complete, leaving this broad Ticket/Object ID and path migration as the only queued work.
Implementation boundaries:
- Use a dedicated worktree/branch.
- Keep migration coherent across Ticket and Objective records, lookup paths, relation metadata, CLI/tool outputs, doctor, and tests.
- Preserve `created_at` / `updated_at` as human-readable frontmatter.
- Keep IDs title/slug-free, fixed-width, lexicographically chronological, path-safe, and collision-handled by `+1ms` retry rather than suffixes.
- Do not introduce old-name compatibility aliases unless needed for a bounded migration/lookup bridge and test-covered.
- Treat current `.yoi/tickets` and `.yoi/objectives` records as project data to migrate in the branch.
Review focus should include migration correctness, relation/reference updates, doctor behavior, and whether base32 timestamp IDs remain stable/sortable under collision handling.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-09T12:47:58Z -->
## Implementation report
Implementation routing started.
Worktree/branch:
- Worktree: `.worktree/base32-record-ids`
- Branch: `base32-record-ids`
- Base/routing commit: `0803bc3 ticket: accept base32 id migration`
Spawned sibling implementation Pod:
- `coder-base32-record-ids`
- Scope: non-recursive read on parent workspace root plus recursive write limited to the child worktree.
Runtime note:
- The current orchestrator session is still running the pre-Profile-feature-flags binary, so `project:coder` cannot decode the newly merged `feature` profile field until the process is refreshed.
- The Pod was therefore launched with `builtin:default` as a runtime workaround, with explicit Coder-role instructions in the handoff. This is a session-runtime workaround only, not a project configuration change.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-09T13:12:25Z -->
## Implementation report
Coder implementation completed on branch `base32-record-ids`.
Implementation commit:
- `4203988d747d4e8ae4d30f63a015835566fd4900` / `feat: unify project record ids`
Reported design:
- Alphabet: `0123456789ABCDEFGHJKMNPQRSTVWXYZ`
- Width: 13 chars, fixed-width base32 Unix epoch milliseconds.
- Collision handling: path collision retries by `+1ms`, bounded at 1000 attempts, no suffix/counter/random tail.
- `created_at` remains real human-readable creation time; ID timestamp may diverge on collision-adjusted allocation.
Reported migration:
- 173 Ticket dirs migrated.
- 1 Objective dir migrated.
- 174 total mapping entries.
- Mapping artifact: `.yoi/tickets/00001KTNMN02R/artifacts/id-migration-map.txt`.
Reported validation:
- `cargo test -q -p project-record`
- `cargo test -q -p ticket`
- `cargo test -q -p yoi objective_cli`
- `cargo fmt --check`
- `git diff --check`
- `git diff --cached --check`
- `cargo run -q -p yoi -- ticket doctor`
- `cargo run -q -p yoi -- objective doctor`
- `cargo check --workspace`
- `nix build .#yoi`
Reviewer should verify migration/reference correctness and whether the committed mapping artifact under the migrated current Ticket is the right durable location.
---
<!-- event: review author: reviewer-base32-record-ids at: 2026-06-09T13:24:34Z status: approve -->
## Review: approve
Approved after external review of implementation commit `4203988 feat: unify project record ids`.
Findings:
- Shared `crates/project-record` helper is used by both Ticket and Objective creation paths.
- Fixed-width 13-char base32 Unix epoch millisecond IDs preserve lexicographic chronological order.
- Collision handling uses bounded `+1ms` retry with no suffix/counter/random tail.
- `created_at` / `updated_at` remain human-readable frontmatter and are not silently replaced by collision-adjusted ID timestamps.
- Ticket and Objective current validation/list/show/doctor paths use canonical record IDs.
- Repository migration is coherent across Ticket dirs, Objective dirs, relation artifacts, orchestration-plan artifacts, linked tickets, docs, and tests.
- `id-migration-map.txt` under the migrated Ticket artifact is acceptable audit evidence and does not pollute schema/list/doctor behavior.
Validation run by reviewer and passed:
- `git diff --check HEAD^..HEAD`
- `cargo test -q -p project-record`
- `cargo test -q -p ticket`
- `cargo test -q -p yoi objective_cli`
- `cargo fmt --check`
- `cargo run -q -p yoi -- ticket doctor`
- `cargo run -q -p yoi -- objective doctor`
- `cargo check --workspace`
- `nix build .#yoi`
- `git status --short --untracked-files=all`
Result: approve, merge-ready. Residual risk: migration map intentionally retains old ID strings for audit; not a blocker.
---