[codex] Add quick session cards demo and plan#47
Draft
flame4 wants to merge 18 commits into
Draft
Conversation
Add a hoverable quick session hub demo in the top navigation, including local session creation, archive behavior, simulated replies, and drag-to-reference support for channel rows. Add the quick session cards requirements and implementation plan covering storage, runtime state, scoped events, API shape, frontend wiring, and QA phases. Apply rustfmt to the runtime HTTP module so the repository format hook passes. Test: npm --prefix products/gitim/frontend run build Test: cargo fmt --all -- --check Co-authored-by: Codex <codex@openai.com>
- Add cross-node routing contract (git-synced persisted objects, runtime-local execution) - Replace async title generation with title API gate (needs_title → api_set) - Update goals, creation flow, status values, API endpoints, acceptance criteria - Add cross-node daemon dispatch to plan Phase 3 - Replace Phase 5 with Title API Gate And Compression - Add cross-node E2E test to Phase 10 - Add title gate risk and cross-node offline risk to Key Risks
…ef disambiguation) Resolves plan-review High P1 items: - P1-1: poll-based cross-node dispatch via quick-sessions/<id>/ path detection - P1-2b/P1-5c: ULID-based session IDs (qs-<ulid>, 29 chars, Crockford base32) - P1-5a: bare session:<id> ref parser with line ref support; new LinkKind::QuickSession
- Fix: validate_quick_session_id() lives in types/quick_session.rs (not validator.rs) - Add: daemon create checks existence, retries ULID up to 3 times on collision - Add: typed error QUICK_SESSION_ID_COLLISION if all retries exhausted
Phase 1 (gitim-core): - New types/quick_session.rs: QuickSessionMeta, QuickSessionStatus, QuickSessionTitleSource, QuickSessionRuntimeState, request/response types, validate_quick_session_id(), validate_quick_session_title() - LinkKind::QuickSession variant in types/link.rs - SESSION_REF_RE regex and extraction in link.rs for bare 'session:qs-<ulid>' refs with optional :L000001 line refs - Preceding-char boundary check prevents false positives - 10 new tests for quick session ref parsing Phase 2 (gitim-daemon): - New quick_session_handlers.rs: create/list/read/send/archive/title daemon handlers with collision detection (3 retries) - ULID generator (Crockford base32, 26 chars) - Request enum variants: CreateQuickSession, ListQuickSessions, ReadQuickSession, SetQuickSessionTitle, SendQuickSessionMessage, ArchiveQuickSession - Handler dispatch in handlers/mod.rs - LinkKind::QuickSession serialization in handlers/serde.rs Co-authored-by: flame4 <flame0743@gmail.com>
- quick_session_state.rs: read/write/delete .gitim-runtime/quick-sessions/<id>.state.json - quick_session_runner.rs: check_title_gate(), title_gate_prompt_instruction(), run_quick_session_turn() stub with documented integration points - Both modules registered in runtime lib.rs Co-authored-by: flame4 <flame0743@gmail.com>
Phase 4 (runtime): - AgentActivityEvent: added scope (agent_main/quick_session), session_id, ref_ fields with backward-compatible defaults - All construction sites updated across agent_loop, http, workspace, fleet_http, multi_workspace modules/tests Phase cross-cut (daemon poll): - handle_poll: quick-sessions/<id>/ path detection for cross-node dispatch - Emits quick_session_meta when session.meta.yaml changes and agent_id matches a locally-hosted agent - Emits quick_session_thread when discussion.thread changes Co-authored-by: flame4 <flame0743@gmail.com>
- 6 HTTP endpoints added to workspace router:
POST /im/quick-sessions → create_quick_session
GET /im/quick-sessions → list_quick_sessions
GET /im/quick-sessions/{id} → read_quick_session
POST /im/quick-sessions/{id}/messages → send_quick_session_message
POST /im/quick-sessions/{id}/title → set_quick_session_title
POST /im/quick-sessions/{id}/archive → archive_quick_session
- All handlers delegate to daemon via GitimClient::request()
- ListQuickSessionsQuery struct for query params
This completes the backend HTTP surface. The title API gate
is enforced server-side in the daemon handler (Phase 2).
Co-authored-by: flame4 <flame0743@gmail.com>
- New QuickSessionLoop struct that runs alongside AgentLoop as a separate background task, polling for quick sessions assigned to local agents - Per-agent FIFO serialization via shared AgentLockMap to prevent provider profile corruption between concurrent quick session turns - Fresh provider per turn: instantiate from agent config, execute, write assistant response via daemon, then tear down - Title gate enforced in execution path: sessions with status needs_title are skipped until title is set via API - Scoped activity events emitted for quick session turns (thinking, done, error with scope=quick_session and session_id) - build_provider_config made pub(crate) for reuse by QuickSessionLoop - Idempotent workspace-level spawn guarded by quick_session_loop_running flag on WorkspaceContext Known gap: main AgentLoop and QuickSessionLoop do not yet share the AgentLockMap; per-agent serialization between main and quick-session turns requires further plumbing. Co-authored-by: flame4 <flame0743@gmail.com>
- Added agent_locks field to WorkspaceContext (initialized in new()) - AgentLoop now acquires per-agent lock before provider.execute() via set_agent_locks(), preventing concurrent same-agent main + quick-session turns from racing on provider profile state - QuickSessionLoop spawn reuses the shared AgentLockMap instead of creating its own - Lock is held for duration of provider execute + streaming loop This closes the P1 concurrency gap — main AgentLoop and QuickSessionLoop are now serialized per agent. Co-authored-by: flame4 <flame0743@gmail.com>
Phase 7 (data layer): - QuickSessionListItem, QuickSessionDetail, SessionRefDragPayload types - Client methods: list/create/read/send/setTitle/archive - Zustand store (use-quick-session-store.ts) with polling, detail loading, message sending, archiving - SESSION_REF_RE regex for session:<id>(:L<line>)? parsing Phase 8 (hub UI): - ConversationHub component replaces ConversationHubDemo with real API-backed quick session hub - Popover + pinned panel modes, session list, thread display, create/send/archive flow, live 8s polling - Status rendering (needs_title/running/active/error/archived) Phase 9 (refs/drag): - session-ref-dnd.ts with SessionRefDragPayload and drop helpers - Sidebar updated to use SessionRefDragPayload - parseSessionRef() for session:<id>(:L<line>)? format Phase 10 (cleanup): - Removed conversation-hub-demo.tsx and session-demo-dnd.ts - Updated app-shell.tsx import to ConversationHub - AgentActivityEvent: added scope/session_id/ref_ fields and quick_session_blocked event type Verification: - npm run build: successful - vitest: 68 files / 562 tests pass - cargo check: clean Co-authored-by: flame4 <flame0743@gmail.com>
… frontend contract bugs P0 fixes: - Include needs_title sessions in QuickSessionLoop dispatch (were filtered out) - Implement agent-side title generation via dedicated provider call when session is needs_title: generate title from thread, call set_quick_session_title via daemon IPC, then proceed to normal turn - Add QUICK_SESSION_TITLE_REQUIRED gate in handle_send_quick_session_message (blocks non-creator write when status=needs_title) - Add validate_quick_session_id to all daemon handlers (path traversal fix) P1 fixes: - Fix archived query param: include_archived -> archived (client.ts) - Fix create response shape: return QuickSessionListItem instead of CreateQuickSessionResponse (drops nested meta, matches store expectation) - Refresh open session detail on poll (loadDetail after list refresh) - Replace DnD phantom sent message with CustomEvent-driven composer text insert (session ref text goes to input, not chat) - Add inline editable title UI in ConversationHub (click to edit, Enter/blur to save, Escape to cancel) Co-authored-by: flame4 <flame0743@gmail.com>
…ration tests - Pass showArchived state to refresh() so toggling the filter refetches archived sessions from the API (use-quick-session-store.ts + ConversationHub) - Use showArchivedRef to keep poll interval in sync with current toggle state - Add 6 integration tests in quick_session_gate_test.rs: - create sets needs_title status - agent write blocked at needs_title (QUICK_SESSION_TITLE_REQUIRED) - creator (human) exempt from title gate - set_title transitions to active, allows agent write - archived sessions reject writes - invalid/path-traversal session_id rejected Co-authored-by: flame4 <flame0743@gmail.com>
…ety, meta freshness, commit locking flame4 owner-review fixes: P0 — .thread protocol compliance: - Use format_message() from gitim-core (produces [L...][P...][@handler][timestamp] body) - Use parse_thread() for reading existing threads (line numbering, author parsing) - Remove custom format_line_number / manual line parse helpers P1 — Activity event isolation: - applyUsageActivityEvent returns early when scope==="quick_session" - New applyQuickSessionActivityEvent routes quick-session events to useQuickSessionStore (thinking → running, done → active, error → error) - useAgentActivity updated to dispatch scoped events to both stores P1 — Chinese title safety: - validate_quick_session_title: chars().count() instead of byte length - generate_and_set_title: chars().take(MAX) instead of byte-indexed [..80] - message_preview(): chars().take(80) for correct grapheme-aware truncation - Added validate_title_counts_chars_not_bytes test P1 — Meta freshness (stale list fix): - send_quick_session_message now writes updated_at + last_message_preview - write_meta() called after each write to keep meta in sync - Handler::new() validation for author on create/send paths - Empty message validation (first_message / body) P1 — DnD cross-channel race fix: - Event detail now carries {text, workspaceKey, scopeKey} - input-area checks scope match before inserting; falls back to localStorage draft - sidebar dispatches event before channel switch P1 — Provider session continuity (architecture debt): - Read QuickSessionRuntimeState before execution, pass resume_token to provider - Write state back after execution with session_token + usage from ExecResult - Session token extracted before match to avoid partial-move P2 — Commit lock + defensive cleanup: - Create/send/archive all wrap write+commit inside state.commit_lock - path.parent().unwrap() replaced with proper error handling - quick_session_runner.rs stub removed; doc trimmed to active helpers only - gate tests expanded: parse_thread compatibility, Chinese char title validation Co-authored-by: flame4 <flame0743@gmail.com>
…reshness, P2 frontend tests) P1 runtime state path: - Thread repo_root through poll_and_process_sessions → execute_quick_session_turn - quick_session_state::read_state/write_state now use repo_root (gitim repo) instead of agent_info.repo_path (agent clone), avoiding untracked .gitim-runtime/ pollution in agent repos - Add .gitim-runtime/ to root .gitignore as defense-in-depth P2 title edit freshness: - useQuickSessionStore.setTitle() now patches both item.title and detail.meta.title in local store state on API success, so UI reflects the new title immediately without waiting for next poll/refresh P2 frontend coverage gap: - use-quick-session-store.test.ts: 6 parseThread tests (single/multi msg, empty input, event line rejection, CJK) + 3 setTitle store update tests - use-agent-activity.test.ts: 7 quick session scope isolation tests (applyUsageActivityEvent ignores qs events, applyQuickSessionActivityEvent routes thinking/error/done to useQuickSessionStore) Verification: - cargo check, cargo fmt, cargo clippy: pass - cargo test -p gitim-core --lib: 343 passed - cargo test -p gitim-daemon --lib: 167 passed - cargo test -p gitim-daemon --test quick_session_gate_test: 7 passed - cargo test -p gitim-runtime --lib -- quick_session: 3 passed - npx vitest run src: 589 passed Co-authored-by: flame4 <flame0743@gmail.com>
Owner L81: state root must be workspace_root, not repo_root and not
agent_info.repo_path. Thread workspace_root through poll_and_process_sessions
and execute_quick_session_turn for quick_session_state::{read,write}_state.
repo_root remains for GitimClient and provider cwd only.
Co-authored-by: flame4 <flame0743@gmail.com>
QuickSessionLoop now uses workspace_root (stable workspace-level path) for its GitimClient instead of the first-started agent's repo_root. This keeps the loop independent of agent startup order — all session operations route through the workspace daemon, not an agent-specific clone. Co-authored-by: flame4 <flame0743@gmail.com>
…ursor P0 QuickSessionLoop now uses human_repo (resolved from WorkspaceContext::human_repo with persistent-human-repo fallback, same logic as http::human_repo_path) for its GitimClient, instead of workspace_root or first-agent repo_root. This matches the HTTP quick-session handler client binding. - human_repo: daemon IPC root (where daemon socket lives) - workspace_root: state root for .gitim-runtime/quick-sessions/ - agent_info.repo_path: provider cwd (unchanged) Code-path evidence: - http.rs spawn: ctx.human_repo with persistent fallback → qs_human_repo - quick_session_loop.rs: GitimClient::new(human_repo) for all daemon IPC - state read/write: continues using workspace_root Co-authored-by: flame4 <flame0743@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
npm --prefix products/gitim/frontend run buildcargo fmt --all -- --checkcargo clippy --workspace --all-targets --no-deps --locked