Skip to content

[codex] create sessions from unmatched picker input#1

Merged
uzulla merged 10 commits into
mainfrom
codex/create-session-on-no-match
Jun 3, 2026
Merged

[codex] create sessions from unmatched picker input#1
uzulla merged 10 commits into
mainfrom
codex/create-session-on-no-match

Conversation

@uzulla

@uzulla uzulla commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • TUI picker で絞り込み結果が0件の状態でも Enter で新規セッション名を返すようにしました。
  • cwd 既定候補がある状態で -another のように - から入力した場合は、<cwd-session>-another として作成します。
  • 未ヒット時に作成される候補を (new) として表示し、README / DEV / help の説明も更新しました。

Why

候補に存在しないセッションを TUI から作れず、cwd 派生名にサフィックスを付けた別セッションへすばやく attach できませんでした。

Validation

  • go test ./...
  • go vet ./...

Summary by CodeRabbit

  • New Features

    • TUIで絞り込みが0件のときEnterで入力から新規セッション名を生成して作成可能に(生成は空白含む/空文字は不可、先頭-は既定項目がある場合のみ既定項目+サフィックス化)。
  • Bug Fixes / UX

    • 候補表示を更新:(new)/(invalid session name) を表示、フッター案内を「Enter: attach/create」へ明示。
  • Documentation

    • READMEとヘルプ、プロジェクト規約・運用手順・技術スタック文書を追記・整備。
  • Tests

    • 新規セッション生成、正規化、無効入力、表示挙動などの単体テストを多数追加。
  • Chores

    • メモリドキュメント群を追加し、.gitignoreを更新。

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

TUI セレクターの Enter 処理を拡張し、絞り込み結果が 0 件のとき入力クエリから新規セッション名を生成・確定できるようにした。関連して表示文言、セッション名正規化、テスト、ドキュメント、.serena メモ群と .gitignore を更新した。

Changes

TUI Select No-Match Session Creation

Layer / File(s) Summary
Enter キー確定処理と新規セッション名生成
internal/tui/select.go
Enter 押下時に m.currentSelection() で確定値を統一。filtered が有効なときは該当項目、0 件または範囲外のときは query から newSessionName() を生成。- 接頭は defaultItem がある場合に限り defaultItem + name として許容。Unicode 空白判定を導入。
View 表示と Footer 案内テキスト更新
internal/tui/select.go, cmd/shp/main.go
View() で filtered が 0 件のときに newSessionName() 成功なら (new) を表示、失敗で非空クエリは (invalid session name)、空クエリは (no matches) を表示。フッターを Enter: attach/create に更新。usage 文言をヘルプに反映。
Select Enter キーと View テストケース
internal/tui/select_test.go
strings import と asModel ヘルパーを追加。Enter による確定/拒否条件と View 表示(new 候補、invalid 表示、defaultItem サフィックス、空白扱い、正規化等)を検証する複数のテストを追加。
セッション名生成と Sanitize の責務整理
internal/session/name.go
FromPath が Sanitize の出力を基に名前を構築し、ハッシュサフィックス付与は needsHashSuffix の判定で FromPath が行うよう移管。Sanitize は許可文字以外を _ に置換する正規化に限定。
README・DEV の追記
README.md, DEV.md
絞り込み 0 件で Enter を押したときの新規セッション作成ルール(空白禁止、先頭 - 入力時の defaultItem 連結ルール、許可文字以外の _ 置換)を追記。

Serena memories and gitignore

Layer / File(s) Summary
.serena/.gitignore へ除外ルール追加
.serena/.gitignore
/cache/project.local.yml を ignore に追加。
Serena memories ドキュメント群の追加/更新
.serena/memories/*
プロジェクト規約(conventions)、Core 要点、メモリ保守手順、推奨コマンド、タスク完了手順、技術スタックに関するメモを追加・更新。
ルート .gitignore 更新
.gitignore
/.claude/ を追加。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Pull request title '[codex] create sessions from unmatched picker input' accurately describes the main change: enabling session creation from TUI picker input when no matches are found.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/create-session-on-no-match

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/select_test.go`:
- Around line 83-86: The test uses unchecked type assertions on updated.(model)
which triggers the lint rule; change both assertions to use the "value, ok :=
updated.(model)" form and if !ok call t.Fatalf (or t.Fatalf with context) so the
test fails instead of panicking; specifically update the two places where
updated, _ = m.Update(...) and m = updated.(model) and where got :=
updated.(model).selected to perform ok-checked assertions against the model type
and handle failures with t.Fatalf including helpful context (e.g., the message
type or updated value).

In `@internal/tui/select.go`:
- Around line 191-194: The code currently returns inputs beginning with "-" when
defaultItem is empty, which can be misinterpreted as CLI flags downstream (e.g.,
in internal/shpool/attach.go); in newSessionName() add a guard: if defaultItem
== "" and strings.HasPrefix(name, "-") then treat it as invalid by returning an
empty string (or another explicit error/indicator used by callers) instead of
returning the raw name, ensuring callers cannot accidentally pass option-looking
session names to shpool attach.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce6094c8-34fe-44a6-955b-cfafcda0828e

📥 Commits

Reviewing files that changed from the base of the PR and between ef41690 and 5b7c55e.

📒 Files selected for processing (5)
  • DEV.md
  • README.md
  • cmd/shp/main.go
  • internal/tui/select.go
  • internal/tui/select_test.go

Comment thread internal/tui/select_test.go Outdated
Comment thread internal/tui/select.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/select.go`:
- Around line 200-205: The current early return in the block checking
defaultItem and strings.HasPrefix(name, "-") bypasses the containsSpace check
and allows names like "-another name"; to fix, ensure you validate
containsSpace(name) before accepting and returning defaultItem+name (or reorder
logic so the combined check is performed): update the conditional around
defaultItem and strings.HasPrefix(name, "-") in the function that uses
containsSpace to first reject when containsSpace(name) is true (return "",
false) and only then apply the defaultItem concatenation rule, or combine the
conditions so the concatenation only happens when !containsSpace(name).

In `@README.md`:
- Line 45: Update the sentence that explains Enter-creates-new-session behavior
(the line starting "絞り込み結果が0件の状態で Enter すると...") to also mention the behavior
when the input starts with a '-' and there are NO cwd candidates: clarify that
inputs like "-scratch" will be rejected (no new session created) to avoid
confusion, while keeping the existing note about suffixing when cwd candidates
exist (e.g., "work.company-a.api-another").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a5e78913-cfe3-4996-99c8-0bc49d83824e

📥 Commits

Reviewing files that changed from the base of the PR and between 5b7c55e and 62f2bda.

📒 Files selected for processing (4)
  • DEV.md
  • README.md
  • internal/tui/select.go
  • internal/tui/select_test.go

Comment thread internal/tui/select.go
Comment thread README.md Outdated
uzulla added 2 commits June 3, 2026 22:01
…, suggested commands, task completion, and tech stack
- select.go: reject whitespace before applying the default-suffix rule so
  inputs like "-another name" no longer produce a session name
- select_test.go: use ok-checked type assertions via asModel helper
- README.md: document that "-scratch" without cwd candidates is rejected

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.serena/memories/conventions.md:
- Line 6: The file ".serena/memories/conventions.md" is missing a trailing
newline; open the file and ensure the last line ("TUI filtering is
case-insensitive substring AND over whitespace-separated tokens; Backspace
deletes by rune; default cwd item is prepended/deduped and labeled `(cwd)`.") is
terminated with a single newline character so the file ends with exactly one
newline.

In @.serena/memories/core.md:
- Line 6: ファイル末尾に改行がありませんので、.serena/memories/core.md の行 "Read `mem:tech_stack`
for tools/deps, `mem:conventions` for implementation style,
`mem:suggested_commands` for local commands, `mem:task_completion` before
finishing coding tasks." の直後に単一の改行文字を追加してファイルを改行で終わらせてください。

In @.serena/memories/memory_maintenance.md:
- Line 33: The file .serena/memories/memory_maintenance.md is missing a trailing
newline at EOF; update the file so it ends with a single newline character
(i.e., add one blank line after the final line "Checking for stale memories
(e.g. after deletion): Call `serena memories check` for a report.") to conform
to Markdown best practices.

In @.serena/memories/suggested_commands.md:
- Line 7: The file ends without a trailing newline; ensure the markdown file
that contains the line `go run ./cmd/shp --help` is saved with a single newline
character at EOF (add one final '\n' so the file terminates with a single blank
line).

In @.serena/memories/task_completion.md:
- Line 6: task_completion.md currently lacks a trailing newline at EOF; open
task_completion.md and add a single newline character at the end of the file so
the file ends with exactly one trailing newline (no extra whitespace) to satisfy
Markdown best practices.

In @.serena/memories/tech_stack.md:
- Line 5: Add a single trailing newline character to the end of the file so it
ends with a newline; locate the line containing "Build/install/test tasks are
defined in `mise.toml`; plain `go` commands also work." and ensure there is
exactly one newline after that line (i.e., the file terminates with a single
newline).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 52d17516-a7ff-4b6c-9a9e-11b1b5059e7f

📥 Commits

Reviewing files that changed from the base of the PR and between 62f2bda and 365cd92.

📒 Files selected for processing (7)
  • .serena/.gitignore
  • .serena/memories/conventions.md
  • .serena/memories/core.md
  • .serena/memories/memory_maintenance.md
  • .serena/memories/suggested_commands.md
  • .serena/memories/task_completion.md
  • .serena/memories/tech_stack.md

Comment thread .serena/memories/conventions.md Outdated
Comment thread .serena/memories/core.md Outdated
Comment thread .serena/memories/memory_maintenance.md Outdated
Comment thread .serena/memories/suggested_commands.md Outdated
Comment thread .serena/memories/task_completion.md Outdated
Comment thread .serena/memories/tech_stack.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/tui/select.go (1)

195-210: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

新規セッション名の入力は FromPath と同等の文字制約を通っていない

internal/tui/select.gonewSessionName は「空/空白のみ」「空白含み」「先頭 -(defaultItem 無し時)」以外は無検証で返すため、foo@barfoo/barfoo;cmd のような文字でもそのまま確定され得ます。一方で internal/session/name.goFromPath は生成時に許容文字 [a-zA-Z0-9 . - _] 以外を _ に置換するため、セッション名の期待仕様と整合しません。shpool.Attach へ渡るのはシェル経由ではなく argv ですが、セッション名コントラクト上の不整合として入力側でも同様のサニタイズ/拒否を行うのが安全です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/select.go` around lines 195 - 210, newSessionName currently
accepts characters that FromPath would sanitize (internal/session/name.go),
causing a contract mismatch; update newSessionName to enforce the same character
policy as FromPath by either (A) validating the input against the permitted
character set [a-zA-Z0-9 ._-] and returning false for invalid input, or (B)
calling/reusing FromPath’s sanitization logic and returning the sanitized result
and true; ensure you reference newSessionName and FromPath (or the shared
allowed-char regex/validator) so the TUI input behavior matches session name
creation and avoids passing disallowed characters into shpool.Attach.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@internal/tui/select.go`:
- Around line 195-210: newSessionName currently accepts characters that FromPath
would sanitize (internal/session/name.go), causing a contract mismatch; update
newSessionName to enforce the same character policy as FromPath by either (A)
validating the input against the permitted character set [a-zA-Z0-9 ._-] and
returning false for invalid input, or (B) calling/reusing FromPath’s
sanitization logic and returning the sanitized result and true; ensure you
reference newSessionName and FromPath (or the shared allowed-char
regex/validator) so the TUI input behavior matches session name creation and
avoids passing disallowed characters into shpool.Attach.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3a7ca714-4b0a-44dd-9d00-bf230cdad7ca

📥 Commits

Reviewing files that changed from the base of the PR and between 365cd92 and c86cc18.

📒 Files selected for processing (3)
  • README.md
  • internal/tui/select.go
  • internal/tui/select_test.go

uzulla added 6 commits June 3, 2026 22:15
Free-text picker input bypassed the [A-Za-z0-9._-] normalization that
cwd-derived names go through, so inputs like "foo/bar" or "../etc"
became session names verbatim, diverging from the documented invariant.

- Extract the char-mapping into session.Sanitize and share it between
  path-derived names (FromPath) and free-text names (newSessionName)
- Add tests for normalization (foo/bar -> foo_bar) and full-width-space
  (U+3000) rejection, a documented Japanese-input boundary
- Note the normalization in README/DEV
.claude/ holds machine-local runtime state such as scheduled_tasks.lock
and must not be committed.
newSessionName built defaultItem+query for a '-'-prefixed query without
re-checking the combined result, so a cwd-derived default that itself
starts with '-' (e.g. a ~/-repo dir) yielded names like '-repo-another'.
That defeats the function's own option-injection guard: the name is
passed to 'shpool attach --dir . <name>' and misparsed as a flag.

- Reject dash-only input ('-', '--') and combined names that still lead
  with '-' in newSessionName
- Defense-in-depth: emit 'shpool attach ... -- <name>' so any positional
  name (including an existing '-'-named session selected from the list)
  is never treated as an option
- Tests for both paths
After normalization, a query like "foo/bar" can sanitize to an existing
session "foo_bar" that the raw-query Filter never matched, so the picker
advertised "foo_bar (new)" and Enter silently reattached the existing
session (ignoring --dir .). Check the candidate against the session list
and label it (existing) vs (new) so the displayed state matches what
Enter does.

Also assert the Enter quit command in the success-path Update tests, for
symmetry with the rejection tests.
orderWithDefault injects the cwd-derived default into m.all even when it
is not a running session, so the new (existing)/(new) label treated a
synthetic default as existing. Track the real shpool-list sessions
separately and decide the label against that set, so an injected default
that Enter would create is correctly shown as (new).
- README/DEV: state that leading/trailing whitespace is trimmed and only
  inputs with inner whitespace are rejected; document the (existing)/(new)
  label and the dash-leading guard. Split the long rule lines into bullets.
- .serena/memories: add trailing newlines; drop a duplicated "shall".
@uzulla uzulla marked this pull request as ready for review June 3, 2026 14:07
@uzulla uzulla merged commit d829bab into main Jun 3, 2026
2 checks passed
@uzulla uzulla deleted the codex/create-session-on-no-match branch June 3, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant