[Post-v0.1/P2] Choose the scrollback capacity control surface #36

Open
opened 2026-09-03 16:26:57 +09:00 by natsukium · 1 comment
Owner

背景

現在 felis-grid::DEFAULT_SCROLLBACK_ROWS = 10_000 が全セッションの上限として compiled-in で固定されている(crates/felis-grid/src/lib.rs:241, docs/explanation/data-model/scrollback.md「Capacity and eviction」, docs/reference/config.md「Not configurable today」)。

  • 10k は Alacritty / Ghostty と同等のデフォルトだが、長時間ビルドやログ用途では不足、多数セッション常駐ユースでは過剰(96 cols で約15 MiB / session, 100k で約150 MiB)。
  • Grid 自体は with_scrollback(rows, cols, cap) で per-session 可変であり、cap=0(alternate / mirror)の経路も既存。問題は設定の置き場が決まっていないこと。

関連:

  • #10 / docs/explanation/architecture/control-surfaces.md「Diagnostic verbs」: daemon は config file を読まず caps は compiled-in、報告のみ(daemon status で観測)。1つ目の tunable は正当だが 2つ目で config 導入を再検討するという Revisit trigger が明記。
  • #4 / #27: config.toml は client-only(felis-client-core が読む)、daemon は読まないという control surface 分離。
  • docs/reference/config.md「Not configurable today」行: scrollback depth は意図的に未公開。

要望

daemon のスクロールバック上限をユーザが変更できること。少なくともグローバルデフォルト、できれば per-session override。

論点 — 設定をどこに持つか

control-surfaces.md の5面(Daemon CLI / Client CLI / config file / keybind / env / wire)のどこに置くかが本 issue の主論点。候補とトレードオフ:

A. クライアント config.toml(例: [scrollback] rows = 20000

  • Pros: 既存の永続 preference 面、live reload / config check / JSON Schema の恩恵をそのまま受けられる。
  • Cons: データは daemon 側なのに所有が client 側になる。--host 越しで client と daemon host が異なる場合、どちらの値が正か曖昧。daemon statuslimit 報告との整合も必要。control-surfaces.md の「daemon は TOML を読まない」原則と衝突はしないが、値を daemon へ伝える経路(SpawnArgs / 新 IPC)が別途必要。

B. daemon 起動時 env var(例: FELIS_SCROLLBACK_ROWS=20000 felis-daemon serve

  • Pros: 既存の FELIS_TERM / FELIS_TERM_PROGRAM と同型で daemon が TOML を読まずに済む。#10 で代替案として挙がった FELIS_DAEMON_* 系と整合。
  • Cons: 永続化は systemd unit / launchd plist / shell profile に分散。per-session の粒度を持てない。

C. daemon 専用 config file(例: daemon.toml

  • Pros: 複数の daemon knobs(将来の MAX_SESSIONS 等)をまとめて tunable にできる。
  • Cons: #10 の Revisit trigger そのもの。「1つの定数なら報告で十分、2つ目で config を検討」を今発火させる判断になる。ファイルの探索パス・リロード・--config との関係を新規に設計する必要。

D. sessions spawn の per-session 引数(例: felis sessions spawn --scrollback-rows 50000 / SpawnArgs.scrollback_rows

  • Pros: 最も粒度が細かく、セッションごとに history / memory をトレードオフできる。グローバルデフォルト(A/B/C)との併用も自然(デフォルト + override)。
  • Cons: 新しい wire フィールド = protocol minor bump。CLI の point/stream 分類や daemon status への反映が必要。

いずれにせよ Gridcap を可変にする配管は既にあるため、実装自体は小さい。決定すべきは control surface の選択と、既存セッションへの適用可否(再起動後のみ / 新規セッションのみ / 既存の ring 縮小・拡大を許すか)。

提案する進め方

  1. 本 issue で A–D の優先度を決める(最小案は B + D の併用: env でグローバルデフォルト、spawn 引数で per-session override。config.toml 案は --host 越しの曖昧さを理由に一旦見送りも選択肢)。
  2. 決まった surface に応じて docs/explanation/architecture/control-surfaces.md / docs/reference/config.md / docs/explanation/data-model/scrollback.md / docs/reference/spec.md(REQ 追加があれば)/ CHANGELOG.md を更新。
  3. 実装時は felis daemon statusscrollback_rows の limit/used 相当を載せるか(#10/#26 の status 報告の流儀に合わせる)も同時に決める。

受け入れ条件(案)

  • 上限の置き場(env / daemon config / client config / spawn arg のいずれか、または併用)が control-surfaces.md に記録され、採用しなかった代替と Revisit 条件が明記されている
  • 選択した surface で上限を変更できることが手動/E2Eで確認できる(例: FELIS_SCROLLBACK_ROWS=1 felis-daemon serve → 新規セッションが1行で eviction する、または spawn --scrollback-rows が反映される)
  • daemon status(または同等の観測面)で有効な上限が確認できる
  • docs/reference/config.md「Not configurable today」の記述が更新されている
  • capacity 変更が既存セッションに与える影響(新規のみ / 縮小時は即時切り捨て / 拡大時は次回 push から)が仕様化されている

備考

  • 現状 DEFAULT_SCROLLBACK_ROWS の変更は cargo testscrollback_tests / table_gc / ref snapshot を更新するだけで済む程度に局所的。
  • 本件は v0.1 ブロッカーではない(#12 の release tracker 外)。Post-v0.1 / P2 想定。

cc @natsukium

## 背景 現在 `felis-grid::DEFAULT_SCROLLBACK_ROWS = 10_000` が全セッションの上限として compiled-in で固定されている(`crates/felis-grid/src/lib.rs:241`, `docs/explanation/data-model/scrollback.md`「Capacity and eviction」, `docs/reference/config.md`「Not configurable today」)。 - 10k は Alacritty / Ghostty と同等のデフォルトだが、長時間ビルドやログ用途では不足、多数セッション常駐ユースでは過剰(96 cols で約15 MiB / session, 100k で約150 MiB)。 - `Grid` 自体は `with_scrollback(rows, cols, cap)` で per-session 可変であり、`cap=0`(alternate / mirror)の経路も既存。問題は**設定の置き場**が決まっていないこと。 関連: - #10 / `docs/explanation/architecture/control-surfaces.md`「Diagnostic verbs」: daemon は config file を読まず caps は compiled-in、報告のみ(`daemon status` で観測)。1つ目の tunable は正当だが 2つ目で config 導入を再検討するという Revisit trigger が明記。 - #4 / #27: `config.toml` は client-only(`felis-client-core` が読む)、daemon は読まないという control surface 分離。 - `docs/reference/config.md`「Not configurable today」行: scrollback depth は意図的に未公開。 ## 要望 daemon のスクロールバック上限をユーザが変更できること。少なくともグローバルデフォルト、できれば per-session override。 ## 論点 — 設定をどこに持つか `control-surfaces.md` の5面(Daemon CLI / Client CLI / config file / keybind / env / wire)のどこに置くかが本 issue の主論点。候補とトレードオフ: ### A. クライアント `config.toml`(例: `[scrollback] rows = 20000`) - **Pros:** 既存の永続 preference 面、live reload / `config check` / JSON Schema の恩恵をそのまま受けられる。 - **Cons:** データは daemon 側なのに所有が client 側になる。`--host` 越しで client と daemon host が異なる場合、どちらの値が正か曖昧。`daemon status` の `limit` 報告との整合も必要。`control-surfaces.md` の「daemon は TOML を読まない」原則と衝突はしないが、値を daemon へ伝える経路(`SpawnArgs` / 新 IPC)が別途必要。 ### B. daemon 起動時 env var(例: `FELIS_SCROLLBACK_ROWS=20000 felis-daemon serve`) - **Pros:** 既存の `FELIS_TERM` / `FELIS_TERM_PROGRAM` と同型で daemon が TOML を読まずに済む。#10 で代替案として挙がった `FELIS_DAEMON_*` 系と整合。 - **Cons:** 永続化は systemd unit / launchd plist / shell profile に分散。per-session の粒度を持てない。 ### C. daemon 専用 config file(例: `daemon.toml`) - **Pros:** 複数の daemon knobs(将来の `MAX_SESSIONS` 等)をまとめて tunable にできる。 - **Cons:** #10 の Revisit trigger そのもの。「1つの定数なら報告で十分、2つ目で config を検討」を今発火させる判断になる。ファイルの探索パス・リロード・`--config` との関係を新規に設計する必要。 ### D. `sessions spawn` の per-session 引数(例: `felis sessions spawn --scrollback-rows 50000` / `SpawnArgs.scrollback_rows`) - **Pros:** 最も粒度が細かく、セッションごとに history / memory をトレードオフできる。グローバルデフォルト(A/B/C)との併用も自然(デフォルト + override)。 - **Cons:** 新しい wire フィールド = protocol minor bump。CLI の point/stream 分類や `daemon status` への反映が必要。 いずれにせよ `Grid` の `cap` を可変にする配管は既にあるため、実装自体は小さい。決定すべきは **control surface の選択**と、既存セッションへの適用可否(再起動後のみ / 新規セッションのみ / 既存の ring 縮小・拡大を許すか)。 ## 提案する進め方 1. 本 issue で A–D の優先度を決める(最小案は B + D の併用: env でグローバルデフォルト、spawn 引数で per-session override。config.toml 案は `--host` 越しの曖昧さを理由に一旦見送りも選択肢)。 2. 決まった surface に応じて `docs/explanation/architecture/control-surfaces.md` / `docs/reference/config.md` / `docs/explanation/data-model/scrollback.md` / `docs/reference/spec.md`(REQ 追加があれば)/ `CHANGELOG.md` を更新。 3. 実装時は `felis daemon status` に `scrollback_rows` の limit/used 相当を載せるか(#10/#26 の status 報告の流儀に合わせる)も同時に決める。 ## 受け入れ条件(案) - [ ] 上限の置き場(env / daemon config / client config / spawn arg のいずれか、または併用)が `control-surfaces.md` に記録され、採用しなかった代替と Revisit 条件が明記されている - [ ] 選択した surface で上限を変更できることが手動/E2Eで確認できる(例: `FELIS_SCROLLBACK_ROWS=1 felis-daemon serve` → 新規セッションが1行で eviction する、または `spawn --scrollback-rows` が反映される) - [ ] `daemon status`(または同等の観測面)で有効な上限が確認できる - [ ] `docs/reference/config.md`「Not configurable today」の記述が更新されている - [ ] `capacity` 変更が既存セッションに与える影響(新規のみ / 縮小時は即時切り捨て / 拡大時は次回 push から)が仕様化されている ## 備考 - 現状 `DEFAULT_SCROLLBACK_ROWS` の変更は `cargo test` の `scrollback_tests` / `table_gc` / `ref` snapshot を更新するだけで済む程度に局所的。 - 本件は v0.1 ブロッカーではない(#12 の release tracker 外)。Post-v0.1 / P2 想定。 cc @natsukium
natsukium changed title from daemonのスクロールバック上限を可変にする / 設定の置き場を決める to [Post-v0.1/P2] Choose the scrollback capacity control surface 2026-09-03 16:58:19 +09:00
Author
Owner

Triage plan (2026-09-03)

Source-grounded triage against main at 69076d42, reviewed through seven rounds of an independent reviewer (pi sol/luna) until it passed with no findings. The dependency order that supersedes the tracker's is posted on #12.

Claim check

Accurate, with one line-number slip and one gap in the option analysis.

  • pub const DEFAULT_SCROLLBACK_ROWS: usize = 10_000; is at crates/felis-grid/src/lib.rs:242 (issue says 241). Grid::newwith_scrollback(rows, cols, DEFAULT_SCROLLBACK_ROWS) at :834-851; scrollback_capacity() at :2861. The daemon's only production construction site is crates/felis-daemon/src/pool.rs:86 (Grid::new(rows, cols)), so the plumbing really is one call, as the issue says. Capacity 0 for mirrors/alternate screen is documented at docs/explanation/data-model/scrollback.md:715-723.
  • docs/reference/config.md:673-678 "Not configurable today" — confirmed. docs/reference/spec.md:156 REQ-605 fixes the default at 10 000 (a user-set capacity does not contradict it). scrollback.md:750-756 records why a larger default is rejected (per-session residency × session count), and scrollback.md:987-990 "Future revisits" already lists "per-session caps with a global memory ceiling across sessions".
  • docs/explanation/architecture/control-surfaces.md:180-190 — confirmed: limits are compiled in, "the daemon reads no configuration file at all", and the Revisit trigger is "if a second knob wants the same treatment: one compiled constant with a report is honest, three would be a config file denied". The first knob is MAX_SESSIONS = 256 (crates/felis-daemon/src/pool.rs:46, reported via DaemonCaps.max_sessions at serve.rs:147,163,971).
  • Precedent for option B: the daemon already reads FELIS_TERM / FELIS_TERM_PROGRAM from its env (crates/felis-daemon/src/lib.rs:246-247; config.md:680-686).
  • Precedent for option D that the issue under-weights: SpawnArgs (crates/felis-protocol/proto/felis.proto:500-515) already carries client-decided, spawn-time, daemon-owned parameters — cwd, env, dims, tags — and the CLI already exposes them (felis sessions spawn --cwd/--env/--rows/--cols/--tag, crates/felis-cli/src/cli_sessions.rs:282-307), including the local-vs-remote resolution the issue worries about for --host (resolve_spawn_cwd :2167). Scrollback rows is the same kind of value as dims.
  • daemon status already has a per-session limit scope: LimitScope::LIMIT_SCOPE_SESSION (felis.proto ~:1435) and a closed ResourceKind enum with reserved slots 6–7 — a scrollback row fits the existing shape without a new taxonomy.

Verdict

defer (keep post-v0.1.0, P2), accept-with-changes on the proposed surface: recommend D + A (wire field + CLI flag, with config.toml supplying the client's default), not the issue's minimal "B + D", and no daemon config file (C).

Reasoning against B/C and for A+D, in the docs' own terms:

  • design.md "Mechanism, not policy": the ring is mechanism (daemon), the depth is a policy choice per session, and the test for "policy" is "would re-attaching with a different client config require restarting the daemon?" — a per-spawn value passed like dims never does. Option B (daemon env) makes depth a daemon-restart-paced setting, which is exactly the boundary crossing principle 3's test names ("If changing a client config requires a daemon restart, the boundary has been crossed"). Option C fires the control-surfaces Revisit trigger for one number.
  • The --host ambiguity the issue raises against A resolves the way --cwd/--env already resolve: the spawner's request wins, and the remote daemon clamps it to its compiled ceiling. Nothing is ambiguous once the value travels in SpawnArgs.
  • The daemon keeps a compiled ceiling (MAX_SCROLLBACK_ROWS, e.g. 1_000_000 per the scrollback.md:987 on-disk-overflow revisit) and reports it as a LIMIT_SCOPE_SESSION row, so the "second knob" stays a report, not a config file — consistent with control-surfaces.md's argument.

Does deferral get more expensive because of the freeze? Slightly, in two known places, both cheap if the v0.1.0 work leaves the door open:

  1. #30 / evolution rules: a new SpawnArgs.scrollback_rows is an additive minor after the 2.0 baseline (docs/reference/ipc.md:202-205). No cost as long as #20's move of spawn to correlated Ops keeps SpawnArgs a message that can grow.
  2. #26 / status scopes: the row-taxonomy #26 freezes must allow a per-session limit whose used is a daemon-wide sum or max — LIMIT_SCOPE_SESSION already says exactly that, so #26 should not remove it.
  3. The default (10 000, REQ-605) freezes as a documented default; changing the default later is a CHANGELOG item, not a contract break. A config key added later is an unknown key to v0.1.0 builds (the add-config-key skill's "older builds reject unknown keys" gotcha) — the normal forward-incompatibility of any new key, and the reason to keep it out of v0.1.0 rather than rush it in.

So: settle the decision (A+D) in the docs whenever convenient (it is a paragraph in control-surfaces.md), implement after the tag.

Approach

  1. Grid: nothing new; with_scrollback exists. Daemon: pool.rs:86 takes the requested capacity, clamped to MAX_SCROLLBACK_ROWS (new const beside MAX_SESSIONS, pool.rs:46) — clamp, not refuse, and report the clamp in the create reply or log (decide at implementation; refuse-with-GeometryOutOfRange-style failure is the other option, matching how dims out of REQ-605a range refuses at felis.proto:511-512; refusing is more explicit and matches the dims precedent, so prefer refuse).
  2. Wire (extend-ipc skill): SpawnArgs.scrollback_rows: optional uint32 (0/absent → daemon default), a ResourceKind::SCROLLBACK_ROWS status row (used = max over sessions or sum, limit = ceiling, scope = SESSION), minor bump, seeds for fuzz/seeds/ipc_body/.
  3. Client-core: spawn.rs/connector.rs SpawnArgs gains the field; config.rs gains [scrollback] rows (add-config-key skill: struct, just schema, home-manager module, live-reload table noting it applies to new sessions only).
  4. CLI: felis sessions spawn --scrollback-rows N (cli_sessions.rs beside --rows/--cols), sessions info --format json reports the session's capacity, daemon status shows the new row. Bridge sessions.spawn params mirror the flag. Completions/man regenerate.
  5. Semantics (acceptance bullet 5): spawn-time only; existing sessions are unaffected; resizing a live ring is not offered (Revisit if a consumer asks). Record in scrollback.md "Capacity and eviction".
  6. Docs: control-surfaces.md (decision + rejected B/C + Revisit: "if a second daemon-side tunable that is not per-session appears, reconsider a daemon config"), config.md (new key; delete "Not configurable today"), scrollback.md, spec.md (REQ-605 gains "default; per-session override via SpawnArgs, ceiling reported by status"), cli.md, ipc.md reference, CHANGELOG.md, skills/felis (the flag and the status row).
  7. Tests: daemon test spawning with scrollback_rows = 1 and asserting eviction after one row (pattern at crates/felis-daemon/src/serve/tests.rs:1086); a refuse/clamp test above the ceiling; CLI parse tests; config schema snapshot; status golden fixture (per #26's fixture set).

Dependencies

  • #26 (status scopes) and #30 (2.0 baseline) first — both v0.1.0. #20 (spawn via correlated Ops) fixes the request shape the field joins. #27 (--config) settles the config surface the key joins. All are v0.1.0, so this lands after the tag as planned.

Risk/effort

M. Grid plumbing S; wire + CLI + config + status row + docs M. Main risk: memory — a user-set 1M rows at 96 cols is ≈1.5 GiB per session (scrollback.md:726-729 gives 15 MiB per 10k), so the compiled ceiling and the status row are not optional, and the value belongs beside the admission limits #14/#15 introduce.

Labels

Keep priority/P2, post-v0.1.0. Recommend recording the A+D decision in the issue now so #20/#26/#30 implementers know what to leave room for.

## Triage plan (2026-09-03) Source-grounded triage against `main` at `69076d42`, reviewed through seven rounds of an independent reviewer (`pi` sol/luna) until it passed with no findings. The dependency order that supersedes the tracker's is posted on #12. ## Claim check Accurate, with one line-number slip and one gap in the option analysis. - `pub const DEFAULT_SCROLLBACK_ROWS: usize = 10_000;` is at `crates/felis-grid/src/lib.rs:242` (issue says 241). `Grid::new` → `with_scrollback(rows, cols, DEFAULT_SCROLLBACK_ROWS)` at `:834-851`; `scrollback_capacity()` at `:2861`. The daemon's only production construction site is `crates/felis-daemon/src/pool.rs:86` (`Grid::new(rows, cols)`), so the plumbing really is one call, as the issue says. Capacity 0 for mirrors/alternate screen is documented at `docs/explanation/data-model/scrollback.md:715-723`. - `docs/reference/config.md:673-678` "Not configurable today" — confirmed. `docs/reference/spec.md:156` REQ-605 fixes the *default* at 10 000 (a user-set capacity does not contradict it). `scrollback.md:750-756` records why a *larger default* is rejected (per-session residency × session count), and `scrollback.md:987-990` "Future revisits" already lists "per-session caps with a global memory ceiling across sessions". - `docs/explanation/architecture/control-surfaces.md:180-190` — confirmed: limits are compiled in, "the daemon reads no configuration file at all", and the Revisit trigger is "if a second knob wants the same treatment: one compiled constant with a report is honest, three would be a config file denied". The first knob is `MAX_SESSIONS = 256` (`crates/felis-daemon/src/pool.rs:46`, reported via `DaemonCaps.max_sessions` at `serve.rs:147,163,971`). - Precedent for option B: the daemon already reads `FELIS_TERM` / `FELIS_TERM_PROGRAM` from its env (`crates/felis-daemon/src/lib.rs:246-247`; `config.md:680-686`). - Precedent for option D that the issue under-weights: `SpawnArgs` (`crates/felis-protocol/proto/felis.proto:500-515`) already carries **client-decided, spawn-time, daemon-owned** parameters — `cwd`, `env`, `dims`, tags — and the CLI already exposes them (`felis sessions spawn --cwd/--env/--rows/--cols/--tag`, `crates/felis-cli/src/cli_sessions.rs:282-307`), including the local-vs-remote resolution the issue worries about for `--host` (`resolve_spawn_cwd :2167`). Scrollback rows is the same kind of value as `dims`. - `daemon status` already has a per-session limit scope: `LimitScope::LIMIT_SCOPE_SESSION` (`felis.proto` ~`:1435`) and a closed `ResourceKind` enum with reserved slots 6–7 — a scrollback row fits the existing shape without a new taxonomy. ## Verdict **defer** (keep post-v0.1.0, P2), **accept-with-changes** on the proposed surface: recommend **D + A** (wire field + CLI flag, with `config.toml` supplying the client's default), not the issue's minimal "B + D", and no daemon config file (C). Reasoning against B/C and for A+D, in the docs' own terms: - design.md "Mechanism, not policy": the *ring* is mechanism (daemon), the *depth* is a policy choice per session, and the test for "policy" is "would re-attaching with a different client config require restarting the daemon?" — a per-spawn value passed like `dims` never does. Option B (daemon env) makes depth a daemon-restart-paced setting, which is exactly the boundary crossing principle 3's test names ("If changing a client config requires a daemon restart, the boundary has been crossed"). Option C fires the control-surfaces Revisit trigger for one number. - The `--host` ambiguity the issue raises against A resolves the way `--cwd`/`--env` already resolve: the spawner's request wins, and the remote daemon clamps it to its compiled ceiling. Nothing is ambiguous once the value travels in `SpawnArgs`. - The daemon keeps a compiled **ceiling** (`MAX_SCROLLBACK_ROWS`, e.g. 1_000_000 per the `scrollback.md:987` on-disk-overflow revisit) and reports it as a `LIMIT_SCOPE_SESSION` row, so the "second knob" stays a report, not a config file — consistent with control-surfaces.md's argument. Does deferral get more expensive because of the freeze? Slightly, in two known places, both cheap if the v0.1.0 work leaves the door open: 1. **#30 / evolution rules**: a new `SpawnArgs.scrollback_rows` is an additive minor after the 2.0 baseline (`docs/reference/ipc.md:202-205`). No cost as long as #20's move of spawn to correlated `Ops` keeps `SpawnArgs` a message that can grow. 2. **#26 / status scopes**: the row-taxonomy #26 freezes must allow a per-session limit whose `used` is a daemon-wide sum or max — `LIMIT_SCOPE_SESSION` already says exactly that, so #26 should not remove it. 3. The **default** (10 000, REQ-605) freezes as a documented default; changing the default later is a `CHANGELOG` item, not a contract break. A config key added later is an unknown key to v0.1.0 builds (the `add-config-key` skill's "older builds reject unknown keys" gotcha) — the normal forward-incompatibility of any new key, and the reason to keep it out of v0.1.0 rather than rush it in. So: settle the *decision* (A+D) in the docs whenever convenient (it is a paragraph in `control-surfaces.md`), implement after the tag. ## Approach 1. **Grid**: nothing new; `with_scrollback` exists. Daemon: `pool.rs:86` takes the requested capacity, clamped to `MAX_SCROLLBACK_ROWS` (new const beside `MAX_SESSIONS`, `pool.rs:46`) — clamp, not refuse, and report the clamp in the create reply or log (decide at implementation; refuse-with-`GeometryOutOfRange`-style failure is the other option, matching how `dims` out of REQ-605a range refuses at `felis.proto:511-512`; refusing is more explicit and matches the `dims` precedent, so prefer refuse). 2. **Wire** (`extend-ipc` skill): `SpawnArgs.scrollback_rows: optional uint32` (0/absent → daemon default), a `ResourceKind::SCROLLBACK_ROWS` status row (`used` = max over sessions or sum, `limit` = ceiling, `scope` = SESSION), minor bump, seeds for `fuzz/seeds/ipc_body/`. 3. **Client-core**: `spawn.rs`/`connector.rs` `SpawnArgs` gains the field; `config.rs` gains `[scrollback] rows` (`add-config-key` skill: struct, `just schema`, home-manager module, live-reload table noting it applies to *new sessions only*). 4. **CLI**: `felis sessions spawn --scrollback-rows N` (cli_sessions.rs beside `--rows/--cols`), `sessions info --format json` reports the session's capacity, `daemon status` shows the new row. Bridge `sessions.spawn` params mirror the flag. Completions/man regenerate. 5. **Semantics** (acceptance bullet 5): spawn-time only; existing sessions are unaffected; resizing a live ring is *not* offered (Revisit if a consumer asks). Record in `scrollback.md` "Capacity and eviction". 6. **Docs**: `control-surfaces.md` (decision + rejected B/C + Revisit: "if a second daemon-side tunable that is not per-session appears, reconsider a daemon config"), `config.md` (new key; delete "Not configurable today"), `scrollback.md`, `spec.md` (REQ-605 gains "default; per-session override via SpawnArgs, ceiling reported by status"), `cli.md`, `ipc.md` reference, `CHANGELOG.md`, `skills/felis` (the flag and the status row). 7. **Tests**: daemon test spawning with `scrollback_rows = 1` and asserting eviction after one row (pattern at `crates/felis-daemon/src/serve/tests.rs:1086`); a refuse/clamp test above the ceiling; CLI parse tests; config schema snapshot; status golden fixture (per #26's fixture set). ## Dependencies - **#26** (status scopes) and **#30** (2.0 baseline) first — both v0.1.0. **#20** (spawn via correlated Ops) fixes the request shape the field joins. **#27** (`--config`) settles the config surface the key joins. All are v0.1.0, so this lands after the tag as planned. ## Risk/effort **M.** Grid plumbing S; wire + CLI + config + status row + docs M. Main risk: memory — a user-set 1M rows at 96 cols is ≈1.5 GiB per session (`scrollback.md:726-729` gives 15 MiB per 10k), so the compiled ceiling and the status row are not optional, and the value belongs beside the admission limits #14/#15 introduce. ## Labels Keep `priority/P2`, post-v0.1.0. Recommend recording the A+D decision in the issue now so #20/#26/#30 implementers know what to leave room for.
Sign in to join this conversation.
No description provided.