ticket: use base32 project record ids

This commit is contained in:
2026-06-09 22:10:47 +09:00
parent 0803bc3725
commit 4203988d74
798 changed files with 477 additions and 105 deletions
+60
View File
@@ -0,0 +1,60 @@
---
title: "TUI: persist composer input recall history per workspace"
state: "closed"
created_at: "2026-06-01T02:11:04Z"
updated_at: "2026-06-09T00:05:13Z"
queued_by: "workspace-panel"
queued_at: "2026-06-08T13:19:06Z"
---
## Issue
TUI composer では上下キーで過去に送信・queue した入力を recall できるが、現在の履歴は TUI-local な揮発状態に留まっている。新しく TUI を起動し直した後も、同じ workspace で使った composer input history を呼び出せるようにしたい。
既存決定として、composer input history recall は Pod protocol / transcript / session history を変更しない TUI-local editing affordance である。この意味論は維持したまま、保存先だけを user data として永続化する。
## Storage decision
永続化先は workspace 配下の `./.yoi/` ではなく、ユーザー data dir(既定では `~/.yoi`、実装上は既存の data-dir 解決に従う)を使う方針とする。
保存 layout は、canonical workspace path / pwd から作る path-safe key を使って workspace ごとに分ける。デフォルト表示としては次のような形にする。
```text
~/.yoi/<path-to-pwd>/composer-history.json
```
実際の `<path-to-pwd>` は path separator や衝突を安全に扱える encoded key / stable key にしてよいが、metadata には元の workspace path / display name を持たせる。
理由:
- composer input history は個人の操作履歴であり、project-authored asset ではない。
- 入力には secret / private context が混ざり得るため、workspace に書くと git 追跡・共有・公開監査のリスクが上がる。
- `./.yoi/` は workflow / knowledge / Ticket records / manifest assets など project/workspace 側の明示的な資産に寄せ、生成された個人履歴は user data 側に置く方が境界が明確。
- 「どの workspace の履歴か」は、user data 側で workspace identitycanonical workspace root / git root などから作る stable key)と display metadata を持てば表現できる。
## Requirements
- 上下キーで呼び出す composer input history を、TUI 再起動後も利用できるよう永続化すること。
- 履歴は workspace ごとに分離すること。別 workspace の入力履歴が通常操作で混ざらないこと。
- 保存先は既存の user data dir 配下にすること。デフォルト表示としては `~/.yoi/<path-to-pwd>/composer-history.json` 相当だが、実装は data-dir override / path resolution に従うこと。
- `./.yoi/` には composer history を作成しないこと。
- 保存 record は、どの workspace の履歴か判別できる metadata / key を持つこと。
- 既存の TUI-local / non-destructive recall semantics を維持すること。
- Pod protocol を変えない。
- transcript / session history を mutate しない。
- recalled input は、ユーザーが再送信するまでは conversation state に影響しない。
- 入力は typed `Segment` vector として保存し、structured input の recall を壊さないこと。
- non-blank input のみ保存し、連続重複を抑止し、履歴件数は workspace ごとに最大 30 件程度に bound すること。
- secret 値が混ざり得る前提で、保存内容を diagnostics / logs / tickets / tests snapshot / model context に不用意に出さないこと。
- 破損した履歴ファイルがあっても TUI startup を致命的に壊さず、必要なら warning と空履歴 fallback にすること。
- 既存の multiline cursor navigation、Up/Down browse、draft restore、edit-on-recall の挙動を regression させないこと。
## Acceptance criteria
- 同じ workspace で TUI を再起動しても、以前送信した composer input を上下キーで recall できる。
- 別 workspace では履歴が分離される。
- workspace 配下に新しい composer history file が作られない。
- user data dir 配下、既定では `~/.yoi/<path-to-pwd>/composer-history.json` 相当の workspace-scoped path に composer history が保存される。
- 保存件数は workspace ごとに最大 30 件程度に bound される。
- Pod session log / Worker history / transcript には、recall 操作だけでは何も追加されない。
- focused test または明確な手動確認手順で、永続化・workspace 分離・既存 recall semantics を検証できる。
+21
View File
@@ -0,0 +1,21 @@
Implemented, reviewed, merged, and validated.
Summary:
- Added persistent TUI composer recall history per workspace.
- Stores history under the user data dir at `composer-history/workspaces/<workspace-label>-<fnv64-key>/history.json`, not under workspace `.yoi/`.
- Stores workspace metadata and typed `Segment` vectors, not flattened strings.
- Persists only non-blank submissions, suppresses consecutive duplicates, and bounds history to 30 entries per workspace.
- Preserves TUI-local/non-destructive recall semantics: recall does not mutate Pod protocol, worker history, session transcript, model context, or conversation state until explicit submit.
- Corrupt history files fall back to empty history with a bounded generic warning.
Implementation:
- Coder commit: `64b7ff7 tui: persist composer history`
- Reviewer approved with no blocking findings.
- Merge commit: `b616420 merge: persist tui composer history`
Validation after merge:
- `cargo fmt --check`
- `git diff --check`
- `cargo run -q -p yoi -- ticket doctor`
- `cargo check --workspace`
- `nix build .#yoi`
+301
View File
@@ -0,0 +1,301 @@
<!-- event: create author: tickets.sh at: 2026-06-01T02:11:04Z -->
## Created
Created by tickets.sh create.
---
<!-- event: decision author: hare at: 2026-06-05T23:01:38Z -->
## Decision
Updated based on user direction:
- keep this as the existing `tui-composer-history-persistence` ticket rather than creating a duplicate;
- default user-data shape should be like `~/.yoi/<path-to-pwd>/composer-history.json` using a path-safe/stable workspace key;
- do not create composer history under workspace `./.yoi/`;
- bound persisted recall history to about 30 entries per workspace instead of the older 100-entry note;
- keep typed `Segment` storage, non-destructive recall semantics, and no Pod/session transcript mutation.
---
<!-- event: intake_summary author: intake at: 2026-06-08T13:14:53Z -->
## Intake summary
既存 Ticket を確認し、同目的の open Ticket は他にないことを確認した。要件は、TUI composer の Up/Down recall 履歴を user data dir 配下に workspace-scoped で永続化し、workspace `./.yoi/`、Pod protocol、transcript、Worker/session history、model context には影響させないこと。保存対象は typed `Segment` vector、non-blank、連続重複抑止、workspace ごと最大 30 件程度。破損ファイルは startup を致命的に壊さず fallback する。受け入れ基準と validation は Ticket 本文に十分記録済みで、Orchestrator が routing 可能なため ready とする。
---
<!-- event: state_changed author: intake at: 2026-06-08T13:14:53Z from: planning to: ready reason: intake_ready field: workflow_state -->
## State changed
Intake 確認により、既存 Ticket は実装 routing 可能な状態です。未解決の blocking open question はありません。主な reviewer focus は user-data persistence 境界、private/secret 混入前提の非露出、workspace 分離、既存 TUI recall semantics の回帰防止です。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-08T13:19:06Z from: ready to: queued reason: queued field: workflow_state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: orchestrator at: 2026-06-08T13:19:31Z -->
## Decision
Routing decision: defer_parallel_tui_work
This Ticket is queued and implementation-ready, but I am intentionally not accepting it to `inprogress` yet.
Reason:
- There is already an active queued-route TUI implementation in progress: `tui-chat-markdown-table-rendering`, with Coder Pod `coder-tui-chat-markdown-table-rendering` running in `.worktree/tui-chat-markdown-table-rendering`.
- `tui-composer-history-persistence` also touches TUI composer/input behavior and likely adjacent tests/helpers.
- Running both TUI changes concurrently would raise conflict/review risk without a clear need; this Ticket can follow immediately after the table-rendering Ticket reaches merge-ready or lands.
State decision:
- Leave this Ticket `queued`.
- Do not create a worktree or spawn a coder for it yet.
Next action:
- Re-read this Ticket after `tui-chat-markdown-table-rendering` finishes review/merge routing, then accept it from queued if still unblocked.
---
<!-- event: state_changed author: orchestrator at: 2026-06-08T23:38:02Z from: queued to: inprogress reason: orchestrator_acceptance field: workflow_state -->
## State changed
Accepted queued implementation after re-reading the Ticket and current workspace state. The previously active TUI table-rendering work has been reviewed, merged, closed, and cleaned up, so the earlier parallel-TUI-work deferral no longer applies.
---
<!-- event: decision author: orchestrator at: 2026-06-08T23:38:02Z -->
## Decision
Routing decision: implementation_ready
Reason:
- This Ticket has clear storage, privacy, workspace-separation, and recall-semantics requirements.
- The earlier deferral behind `tui-chat-markdown-table-rendering` is resolved: that Ticket has been merged, closed, and cleaned up.
- Main workspace is clean and there are no active implementation worktrees, so implementation side effects can proceed safely.
IntentPacket:
Intent:
- Persist TUI composer input recall history per workspace in user data, while preserving the existing TUI-local/non-destructive recall semantics.
Binding decisions / invariants:
- Store composer history under the existing user data dir, not under workspace `./.yoi/`.
- Workspace histories must be separated by a stable/path-safe workspace key and include metadata sufficient to identify the source workspace/display name.
- Store typed `Segment` vectors, not lossy flattened strings, so structured input recall remains possible.
- Persist only non-blank entries, suppress consecutive duplicates, and bound stored history to about 30 entries per workspace.
- Recalled input must not affect conversation state until the user explicitly submits it.
- Do not mutate Pod protocol, worker history, transcript/session logs, model context, or stored message history for recall operations.
- Treat history content as potentially private/secret: avoid diagnostics/logs/snapshots/tickets/model context exposure of saved entries.
- Corrupt history files must not make TUI startup fatal; fall back to empty history with a bounded warning if needed.
- Preserve existing multiline cursor navigation, Up/Down browse, draft restore, and edit-on-recall behavior.
Implementation latitude:
- Coder may choose the exact on-disk user-data path/key encoding if it is stable, path-safe, data-dir aware, and workspace-scoped.
- Coder may add a small persistence module near existing TUI composer history code or shared user-data helpers if present.
- Coder should prefer focused unit tests with temporary data dirs/workspaces for persistence, separation, bounding, duplicate suppression, corrupt-file fallback, and no workspace-file creation.
- If interactive confirmation is still useful, include exact manual steps in the implementation report, but do not rely on manual-only validation if focused tests are practical.
Escalate if:
- The implementation requires changing Pod protocol/history/session serialization.
- The implementation would store history under workspace `.yoi/`.
- Existing composer history representation cannot preserve typed `Segment` vectors without a larger input model redesign.
- Secret/private content would be emitted into logs/diagnostics/tests/tickets/model context.
Validation:
- Focused TUI composer history persistence tests for same-workspace recall after reload, workspace separation, max-size bound, consecutive duplicate suppression, corrupt-file fallback, and no workspace `.yoi` output.
- Existing TUI composer history/navigation tests if present.
- `cargo fmt --check`.
- `git diff --check`.
- `cargo check --workspace`.
- `nix build .#yoi` before final completion because TUI behavior/packaging changes.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-08T23:38:48Z -->
## Implementation report
Implementation routing started after the previously deferred TUI table-rendering work was merged and cleaned up.
Worktree/branch:
- Worktree: `.worktree/tui-composer-history-persistence`
- Branch: `tui-composer-history-persistence`
- Base/routing commit: `ff5f985 ticket: route composer history persistence`
Spawned sibling Coder Pod:
- `coder-tui-composer-history-persistence`
- Scope: non-recursive read on parent workspace root plus recursive write limited to the child worktree.
Routing context:
- The earlier `defer_parallel_tui_work` decision is resolved because `tui-chat-markdown-table-rendering` has been merged, closed, and cleaned up.
- This Ticket is now the active TUI implementation work.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-08T23:55:25Z -->
## Implementation report
Coder implementation completed and is ready for sibling review.
Coder Pod:
- `coder-tui-composer-history-persistence`
- Commit: `64b7ff7c7c6f93c85e0c091ed5526e1e382ea023 tui: persist composer history`
- Worktree status before review: clean branch `tui-composer-history-persistence`
- Stopped after collecting output to reclaim delegated worktree scope.
Implementation summary:
- Adds user-data-backed TUI composer recall history persistence under `<data_dir>/composer-history/workspaces/<workspace-label>-<fnv64-key>/history.json`.
- Stores workspace metadata plus typed `Segment` vectors; does not flatten input to strings.
- Bounds history to 30 entries, skips blank inputs, and suppresses consecutive duplicates.
- Loads history on single-Pod TUI startup and saves on submit while keeping recall non-destructive/TUI-local.
- Corrupt history files fall back to empty history with a bounded actionbar warning that does not include saved entry contents.
Changed files:
- `crates/tui/src/composer_history.rs`
- `crates/tui/src/app.rs`
- `crates/tui/src/lib.rs`
- `crates/tui/src/single_pod.rs`
Coder validation reported passed:
- `cargo test -p tui composer_history`
- `cargo test -p tui input_history`
- `cargo test -p tui completion_flow_tests`
- `cargo fmt --check`
- `git diff --check`
- `cargo check --workspace`
- `nix build .#yoi`
Coder note:
- Full `cargo test -p tui` still fails at pre-existing `multi_composer_target_switch_preserves_typed_text`; `multi_pod.rs` was not modified.
---
<!-- event: review author: reviewer at: 2026-06-08T23:59:44Z status: approve -->
## Review: approve
Approved.
Review evidence:
- Inspected commit `64b7ff7c7c6f93c85e0c091ed5526e1e382ea023` on branch `tui-composer-history-persistence`; changed files are limited to TUI app/persistence wiring (`crates/tui/src/app.rs`, `crates/tui/src/composer_history.rs`, `crates/tui/src/lib.rs`, `crates/tui/src/single_pod.rs`).
- `ComposerHistoryStore` stores under `manifest::paths::data_dir()/composer-history/workspaces/<label>-<fnv64-key>/history.json`, includes `version`, `workspace.root`, `workspace.label`, `workspace.key`, and preserves `entries: Vec<Vec<Segment>>`.
- History normalization and submit path keep only non-blank entries, suppress consecutive duplicates, and bound per-workspace history to `COMPOSER_INPUT_HISTORY_LIMIT = 30`.
- Recall paths remain local `App`/`InputBuffer` edits: Up/Down browse only replaces composer segments and returns no Pod method; `Method::Run` is still produced only through explicit submit.
- Load/save warnings are generic actionbar notices and do not include stored entry contents; corrupt JSON falls back to empty in-memory history without startup failure.
Validation run from worktree:
- `cargo test -p tui composer_history`
- `cargo test -p tui input_history`
- `cargo test -p tui completion_flow_tests`
- `cargo fmt --check`
- `git diff --check`
- `cargo check --workspace`
- `nix build .#yoi`
No blocking issues found.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-09T00:00:35Z -->
## Implementation report
Merge-ready dossier for human/orchestrator approval.
Status:
- Implementation branch: `tui-composer-history-persistence`
- Worktree: `.worktree/tui-composer-history-persistence`
- Commit under review: `64b7ff7c7c6f93c85e0c091ed5526e1e382ea023 tui: persist composer history`
- Reviewer: `reviewer-tui-composer-history-persistence`
- Review result: approved; no blocking findings.
Intent / invariant check:
- Persists TUI composer input recall history per workspace.
- Uses user data dir storage, not workspace `./.yoi/`.
- Stores typed `Segment` vectors with workspace metadata, not flattened strings.
- Preserves recall as TUI-local/non-destructive; no Pod protocol, worker history, session transcript, or model-context changes.
- Keeps saved entry contents out of warnings/logging/tickets/model context; corrupt-file fallback warning is generic.
Implementation summary:
- Adds `crates/tui/src/composer_history.rs` for user-data-backed storage.
- Stores history at `composer-history/workspaces/<workspace-label>-<fnv64-key>/history.json` under `manifest::paths::data_dir()`.
- Stores `version`, `workspace.root`, `workspace.label`, `workspace.key`, and `entries: Vec<Vec<Segment>>`.
- Loads history for single-Pod TUI startup and persists on explicit submit.
- Skips blank entries, suppresses consecutive duplicates, and bounds stored history to `COMPOSER_INPUT_HISTORY_LIMIT = 30`.
Validation evidence:
- Coder reported pass:
- `cargo test -p tui composer_history`
- `cargo test -p tui input_history`
- `cargo test -p tui completion_flow_tests`
- `cargo fmt --check`
- `git diff --check`
- `cargo check --workspace`
- `nix build .#yoi`
- Reviewer independently ran and passed the same validation set:
- `cargo test -p tui composer_history`
- `cargo test -p tui input_history`
- `cargo test -p tui completion_flow_tests`
- `cargo fmt --check`
- `git diff --check`
- `cargo check --workspace`
- `nix build .#yoi`
Residual risks / notes:
- Broader `cargo test -p tui` still has a pre-existing unrelated failure in `multi_composer_target_switch_preserves_typed_text`; this implementation did not modify `multi_pod.rs`.
- Final merge/close/cleanup is intentionally not performed here without explicit merge approval.
---
<!-- event: state_changed author: hare at: 2026-06-09T00:05:13Z from: inprogress to: done reason: closed field: workflow_state -->
## State changed
Ticket closed; workflow_state を done に設定しました。
---
<!-- event: close author: hare at: 2026-06-09T00:05:13Z status: closed -->
## 完了
Implemented, reviewed, merged, and validated.
Summary:
- Added persistent TUI composer recall history per workspace.
- Stores history under the user data dir at `composer-history/workspaces/<workspace-label>-<fnv64-key>/history.json`, not under workspace `.yoi/`.
- Stores workspace metadata and typed `Segment` vectors, not flattened strings.
- Persists only non-blank submissions, suppresses consecutive duplicates, and bounds history to 30 entries per workspace.
- Preserves TUI-local/non-destructive recall semantics: recall does not mutate Pod protocol, worker history, session transcript, model context, or conversation state until explicit submit.
- Corrupt history files fall back to empty history with a bounded generic warning.
Implementation:
- Coder commit: `64b7ff7 tui: persist composer history`
- Reviewer approved with no blocking findings.
- Merge commit: `b616420 merge: persist tui composer history`
Validation after merge:
- `cargo fmt --check`
- `git diff --check`
- `cargo run -q -p yoi -- ticket doctor`
- `cargo check --workspace`
- `nix build .#yoi`
---