Skip to content
This repository was archived by the owner on Mar 20, 2026. It is now read-only.

✨ Add status line showing execution environment info#9

Merged
peacock0803sz merged 21 commits into
mainfrom
002-statusline
Feb 26, 2026
Merged

✨ Add status line showing execution environment info#9
peacock0803sz merged 21 commits into
mainfrom
002-statusline

Conversation

@peacock0803sz

@peacock0803sz peacock0803sz commented Feb 26, 2026

Copy link
Copy Markdown
Owner

Summary

Add a status line bar to the chat UI that displays the current execution environment: hostname, repository, branch, agent type, and model name.

  • Proto: Add EnvironmentInfo message and extend StreamEvent.oneof with environment case
  • Backend: Emit EnvironmentInfo as the first stream event (sequence=1) in Execute RPC; add gitinfo.go for repository/branch detection and ModelName() to the AgentAdapter interface
  • Frontend: Add StatusLine component and useStatusLine hook that extracts environment data from the event stream, with fallback ("-") for missing fields and value preservation across events (FR-011)

Other changes included in this branch

  • Fix Vite dev server host binding for CORS compatibility
  • Add DevUser auth bypass option for local development
  • Change submit shortcut to Cmd/Ctrl+Enter for IME compatibility
  • Fix oxlint errors and reformat with oxfmt

Test plan

  • useStatusLine hook: unit tests covering initial state, field extraction, empty-field preservation, and agent label mapping
  • StatusLine component: render tests verifying labels, values, and truncation
  • gitinfo.go: unit tests for ParseRemoteURL (SSH/HTTPS/edge cases) and GetBranch
  • Manual: verify status line renders in chat UI during a live Execute stream

Add `EnvironmentInfo` message (hostname, repository, branch, agent, model_name)
to agent.proto and add it as field 9 in StreamEvent.payload oneof.
This is the schema-first foundation for the status line feature.
Extend the AgentAdapter interface with `ModelName() string` and implement
it in ClaudeAdapter returning "claude-code". Required for EnvironmentInfo emission.
Add gitinfo.go with GetGitInfo(), GetBranch(), ParseRemoteURL() to gather
repository context. Handles detached HEAD (returns short hash), SSH/HTTPS URLs,
and git-not-found gracefully with empty string fallback.
Send EnvironmentInfo (sequence=1) before container start on each Execute RPC call.
Container output events now start at sequence=2. Update existing tests to account
for the additional leading event.
Add useStatusLine hook (ES2022 reverse iteration, FR-011 value preservation),
StatusLine component (5-item display with Tailwind truncation), and integrate
into chat route below header. Lift useAgent() state to route level.
Configure Vitest with jsdom environment and @testing-library/react.
Add 8 hook tests (useStatusLine: fallback, value extraction, FR-011 preservation)
and 5 component tests (StatusLine: labels, values, truncation title attribute).
Enter alone conflicted with Japanese IME composition confirm.
Cmd+Enter (Mac) / Ctrl+Enter (Windows/Linux) now triggers submit,
leaving plain Enter free for newlines and IME input.
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @peacock0803sz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience by providing immediate and dynamic context about the agent's execution environment directly within the chat interface. By streaming detailed environment information from the backend and displaying it in a dedicated status line, users can quickly understand which host, repository, branch, and model an agent is operating with. This change improves transparency and debugging capabilities during agent interactions.

Highlights

  • Agent Environment Information Streaming: Introduced a new EnvironmentInfo message within the StreamEvent protobuf, which is now emitted as the very first event (sequence=1) for each agent execution. This event provides crucial context about the execution environment, including the hostname, Git repository details (owner/repo, branch), agent type, and the specific model name being used.
  • Git Information Extraction: Added new backend utilities to dynamically retrieve Git repository and branch information from the current working directory. This information is then included in the EnvironmentInfo stream event.
  • Dynamic Status Line UI: Implemented a new frontend StatusLine component and a useStatusLine hook to parse and display the streamed EnvironmentInfo in the chat interface. This provides users with real-time context about the agent's operating environment.
  • Agent Adapter Model Naming: Extended the AgentAdapter interface with a ModelName() method, allowing each agent adapter (e.g., Claude) to report its specific model identifier, which is then surfaced in the EnvironmentInfo.
  • Frontend Test Infrastructure: Integrated Vitest for frontend testing, including configuration and a setup file, to enable robust unit and component testing for React components and hooks.
  • Prompt Input Usability Improvement: Modified the prompt input component to change the message submission hotkey from Enter (without Shift) to Ctrl+Enter or Meta+Enter, and updated the placeholder text to reflect this change.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • back/internal/adapter/adapter.go
    • Added ModelName() method to the AgentAdapter interface.
  • back/internal/adapter/claude.go
    • Implemented the ModelName() method for the ClaudeAdapter to return "claude-code".
  • back/internal/server/agent_server.go
    • Imported the os package.
    • Modified the Execute method to emit an EnvironmentInfo event as the first stream event (sequence 1) before container execution.
    • Updated the streamLines function to start its sequence count from 2, reserving 1 for EnvironmentInfo.
  • back/internal/server/execute_test.go
    • Adjusted event count expectations in TestExecute_StreamsEvents to account for the new EnvironmentInfo event.
    • Updated event payload type checks to verify the presence and type of the EnvironmentInfo event.
    • Modified event count expectations in the unparseable JSON test to include the EnvironmentInfo event.
  • back/internal/server/gitinfo.go
    • Added a new file containing GitInfo struct and functions (GetGitInfo, GetBranch, ParseRemoteURL, getRemoteURL) to extract Git repository and branch details.
  • back/internal/server/gitinfo_test.go
    • Added a new file containing unit tests for the ParseRemoteURL, GetBranch_DetachedHead, GetBranch_NormalBranch, and GetBranch_GitNotFound functions.
  • front/app/components/chat/ChatWindow.tsx
    • Modified ChatWindowProps to extend UseAgentResult, allowing agent-related props to be passed directly.
  • front/app/components/chat/PromptInput.tsx
    • Changed the message submission hotkey from Enter (without Shift) to Ctrl+Enter or Meta+Enter.
    • Updated the placeholder text to inform users about the new Ctrl+Enter hotkey.
  • front/app/components/chat/StatusLine.test.tsx
    • Added a new file containing unit tests for the StatusLine component, covering initial state, data display, and truncation behavior.
  • front/app/components/chat/StatusLine.tsx
    • Added a new file containing the StatusLine React component and StatusItem sub-component to display environment information.
  • front/app/lib/hooks/useStatusLine.test.ts
    • Added a new file containing unit tests for the useStatusLine hook, verifying its ability to extract and manage EnvironmentInfo from stream events.
  • front/app/lib/hooks/useStatusLine.ts
    • Added a new file containing the useStatusLine React hook to process StreamEvents and extract the latest EnvironmentInfo for display, including logic to preserve previous non-empty values.
  • front/app/routes/chat.$sessionId.tsx
    • Integrated the useAgent hook to manage agent interactions.
    • Integrated the useStatusLine hook to derive status line data from agent events.
    • Rendered the new StatusLine component above the ChatWindow to display environment details.
  • front/app/test-setup.ts
    • Added a new file to configure Vitest and disable React 19's StrictMode for testing environments.
  • front/package.json
    • Added test and test:watch scripts using Vitest.
  • front/vitest.config.ts
    • Added a new file containing Vitest configuration, including plugin setup and test environment settings.
  • proto/vibra/agent/v1/agent.proto
    • Defined a new EnvironmentInfo message to describe the agent's execution environment.
    • Added EnvironmentInfo as a new oneof field (tag 9) within the StreamEvent message.
Activity
  • The pull request description is empty, indicating no explicit activity or discussion has been documented by the author.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Add EnvironmentInfo message (hostname, repository, branch, agent,
model_name) as a new oneof variant in StreamEvent, emitted at
sequence=1 of each Execute RPC to provide execution context.
buf format enforces single-space before inline comments.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a new status line feature, providing real-time environment information during agent execution. Key changes include extending the AgentAdapter interface, adding backend logic to retrieve Git repository details, emitting EnvironmentInfo as the first event in the agent stream, and integrating a new StatusLine component in the frontend. The changes also include necessary updates to protobuf definitions and comprehensive tests for the new functionalities. The PromptInput component has been updated to change the send shortcut to Ctrl/Cmd+Enter for improved user experience.

I am having trouble creating individual review comments. Click here to see my feedback.

back/internal/server/agent_server.go (74)

medium

The comment (FR-001, FR-007) refers to internal feature requirements. It would be more helpful to describe the functional purpose directly in the comment, explaining why this event is emitted and its significance, rather than referencing internal IDs.

back/internal/server/agent_server.go (112)

medium

This comment is in Japanese. For consistency and maintainability across the codebase, please translate it to English. The purpose of seq.Store(1) is to ensure subsequent events start from sequence 2, as sequence 1 is reserved for EnvironmentInfo.

seq.Store(1) // sequence=1 is reserved for EnvironmentInfo

back/internal/server/gitinfo.go (37)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// detached HEAD: substitute with short commit hash

back/internal/server/gitinfo.go (54)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// SSH format: git@github.com:owner/repo.git

back/internal/server/gitinfo.go (61)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// HTTPS format: https://github.com/owner/repo.git

back/internal/server/gitinfo.go (67)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Remove host part: "github.com/owner/repo.git" -> "owner/repo"

back/internal/server/gitinfo_test.go (62)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Create a git repository in a temporary directory to simulate a detached HEAD

back/internal/server/gitinfo_test.go (67)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Ignore errors in git operations (depends on test environment git config)

back/internal/server/gitinfo_test.go (76)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Get commit hash and transition to detached HEAD

back/internal/server/gitinfo_test.go (81)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Remove newline

back/internal/server/gitinfo_test.go (84)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Switch to detached HEAD

back/internal/server/gitinfo_test.go (90)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Change to the target repository directory and execute

back/internal/server/gitinfo_test.go (97)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// If detached HEAD, a short hash (7 characters) should be returned

back/internal/server/gitinfo_test.go (137)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Verify that GetBranch returns an empty string when git is not found in PATH

back/internal/server/gitinfo_test.go (142)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// If git is not found, it should return an empty string, but

back/internal/server/gitinfo_test.go (143)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// GetBranch uses exec.Command directly, so it doesn't use LookPath internally.

back/internal/server/gitinfo_test.go (144)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Here, we test the fallback via GetGitInfo.

back/internal/server/gitinfo_test.go (147)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// If git is truly unavailable, it should be empty.

back/internal/server/gitinfo_test.go (148)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// If git is found even with an empty PATH (absolute path?), the assertion is skipped.

front/app/components/chat/StatusLine.test.tsx (25)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("all labels are displayed in the initial state", () => {

front/app/components/chat/StatusLine.test.tsx (35)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("each label's value is displayed as '-' in the initial state", () => {

front/app/components/chat/StatusLine.test.tsx (38)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Verify that the value span next to each label element is '-'

front/app/components/chat/StatusLine.test.tsx (45)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("actual values are displayed correctly", () => {

front/app/components/chat/StatusLine.test.tsx (55)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("long values have a title attribute (repo and branch are truncated)", () => {

front/app/components/chat/StatusLine.test.tsx (67)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("hostname and model do not have a title attribute (not truncated)", () => {

front/app/lib/hooks/useStatusLine.test.ts (10)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Factory for test EnvironmentInfo events

front/app/lib/hooks/useStatusLine.test.ts (37)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("returns '-' for all fields in initial state (empty events)", () => {

front/app/lib/hooks/useStatusLine.test.ts (46)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("retrieves all fields from EnvironmentInfo event", () => {

front/app/lib/hooks/useStatusLine.test.ts (64)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("displays empty string fields as '-'", () => {

front/app/lib/hooks/useStatusLine.test.ts (81)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("uses the last EnvironmentInfo if there are multiple events", () => {

front/app/lib/hooks/useStatusLine.test.ts (94)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("returns '-' if there are only non-EnvironmentInfo events", () => {

front/app/lib/hooks/useStatusLine.test.ts (101)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("correctly converts agent types to labels (Codex, Gemini)", () => {

front/app/lib/hooks/useStatusLine.test.ts (113)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("FR-011: maintains previous value if new event field is empty", () => {

front/app/lib/hooks/useStatusLine.test.ts (130)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// If it becomes outside Git management: repository/branch are empty

front/app/lib/hooks/useStatusLine.test.ts (138)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Previous non-empty value is maintained (FR-011)

front/app/lib/hooks/useStatusLine.test.ts (143)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

it("FR-011: displays new value if updated to non-empty", () => {

front/app/lib/hooks/useStatusLine.ts (20)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// ES2022 compatibility: findLast is not available, so iterate in reverse to get the last EnvironmentInfo

front/app/lib/hooks/useStatusLine.ts (46)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// Empty string fields maintain previous values (FR-011)

front/app/test-setup.ts (5)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// React 19's StrictMode mounts components multiple times during development,

front/app/test-setup.ts (6)

medium

This comment is in Japanese. Please translate it to English for better maintainability and consistency with the rest of the codebase.

// causing test queries to find duplicate elements. Disable it in the test environment.

@peacock0803sz peacock0803sz changed the title ✨ Add statuslines (WIP) ✨ Add status line showing execution environment info Feb 26, 2026
@peacock0803sz peacock0803sz marked this pull request as ready for review February 26, 2026 17:39

Copilot AI 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.

Pull request overview

Adds an execution-environment “status line” to the chat UI by introducing a new EnvironmentInfo stream event emitted at the start of each Execute RPC, then consumed by a frontend hook/component.

Changes:

  • Proto: add EnvironmentInfo message and StreamEvent.environment oneof case.
  • Backend: emit EnvironmentInfo as the first streamed event (sequence=1); add git repo/branch detection; extend AgentAdapter with ModelName().
  • Frontend: add useStatusLine + StatusLine and integrate into the chat route; add Vitest setup and unit tests.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
proto/vibra/agent/v1/agent.proto Adds EnvironmentInfo and a new StreamEvent payload case.
back/internal/server/agent_server.go Emits environment event first and reserves sequence=1.
back/internal/server/gitinfo.go Collects repository + branch info from local git.
back/internal/server/gitinfo_test.go Adds tests for remote parsing + branch detection scenarios.
back/internal/server/execute_test.go Updates expectations for the additional first stream event.
back/internal/adapter/adapter.go Extends adapter interface with ModelName().
back/internal/adapter/claude.go Implements ModelName() for Claude adapter.
back/gen/vibra/agent/v1/agent.pb.go Regenerated Go protobuf bindings.
front/app/routes/chat.$sessionId.tsx Renders StatusLine and wires it to agent stream events.
front/app/lib/hooks/useStatusLine.ts Extracts latest environment info from stream events.
front/app/lib/hooks/useStatusLine.test.ts Unit tests for status-line extraction + FR-011 preservation.
front/app/components/chat/StatusLine.tsx UI component for status line display/truncation.
front/app/components/chat/StatusLine.test.tsx Render tests for labels/values and title behavior.
front/app/components/chat/ChatWindow.tsx Refactors ChatWindow to accept useAgent() result via props.
front/vitest.config.ts Adds Vitest config (jsdom + setup file).
front/app/test-setup.ts Testing Library setup (disables React StrictMode in tests).
front/package.json Adds test and test:watch scripts.
front/gen/vibra/agent/v1/agent_pb.js Regenerated JS protobuf bindings.
front/gen/vibra/agent/v1/agent_pb.d.ts Regenerated TS typings for protobuf bindings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread front/app/lib/hooks/useStatusLine.ts Outdated
Comment on lines +30 to +42
export function useStatusLine(events: StreamEvent[]): StatusLineData {
const prevRef = useRef<StatusLineData>({
hostname: FALLBACK,
repository: FALLBACK,
branch: FALLBACK,
agentType: FALLBACK,
modelName: FALLBACK,
});

const latestEvent = findLatestEnvironment(events);
if (!latestEvent || latestEvent.payload.case !== "environment") {
return prevRef.current;
}

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

useStatusLine preserves prevRef even when events is cleared (e.g., useStream.consume() calls setEvents([]) when starting a new Execute). This can cause the status line to show stale hostname/repo/branch/model from a previous run until the new EnvironmentInfo arrives, instead of resetting to the fallback state. Consider resetting prevRef.current back to all "-" when events.length === 0 (or when the latest environment event sequence restarts), and add a test that covers the reset-on-empty case.

Copilot uses AI. Check for mistakes.
Comment thread front/app/lib/hooks/useStatusLine.ts Outdated

// ES2022互換: findLast 不可なため逆順走査で最後のEnvironmentInfoを取得
function findLatestEnvironment(events: StreamEvent[]) {
return [...events].reverse().find((e) => e.payload.case === "environment");

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

findLatestEnvironment allocates and reverses a copy of the full events array ([...events].reverse()) on every render, which can become noticeably expensive as the stream grows. You can scan from the end with a simple for-loop to find the latest environment event without copying.

Suggested change
return [...events].reverse().find((e) => e.payload.case === "environment");
for (let i = events.length - 1; i >= 0; i--) {
const event = events[i];
if (event.payload.case === "environment") {
return event;
}
}
return undefined;

Copilot uses AI. Check for mistakes.
Comment thread back/internal/server/gitinfo_test.go Outdated
Comment on lines +77 to +85
out, err := exec.Command("git", "-C", dir, "rev-parse", "HEAD").Output()
if err != nil {
t.Skip("could not get HEAD commit")
}
commitHash := string(out[:len(out)-1]) // 改行を除去

// detached HEADに切り替え
cmd := exec.Command("git", "checkout", "--detach", commitHash)
cmd.Dir = dir

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

commitHash := string(out[:len(out)-1]) removes only a single trailing byte. On Windows (CRLF) or if the output format changes, this can leave \r behind and break the subsequent git checkout --detach call. Prefer trimming whitespace (e.g., strings.TrimSpace) instead of slicing.

Copilot uses AI. Check for mistakes.
Comment thread back/internal/server/gitinfo_test.go Outdated
Comment on lines +113 to +122
run := func(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = dir
_ = cmd.Run()
}

run("init", "-b", "main")
run("config", "user.email", "test@example.com")
run("config", "user.name", "Test")
run("commit", "--allow-empty", "-m", "initial")

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

In TestGetBranch_NormalBranch, the setup ignores errors and uses git init -b main, which fails on older git versions (and would silently leave the repo uninitialized due to _ = cmd.Run()). This can make the test flaky across CI environments. Consider checking command errors in the run helper and using a more compatible sequence (e.g., git init then rename/create the branch) so the test is deterministic.

Suggested change
run := func(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = dir
_ = cmd.Run()
}
run("init", "-b", "main")
run("config", "user.email", "test@example.com")
run("config", "user.name", "Test")
run("commit", "--allow-empty", "-m", "initial")
run := func(t *testing.T, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd.Dir = dir
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v failed: %v\nOutput: %s", args, err, string(out))
}
}
// Initialize repository in a way compatible with older git versions.
run(t, "init")
run(t, "config", "user.email", "test@example.com")
run(t, "config", "user.name", "Test")
run(t, "checkout", "-b", "main")
run(t, "commit", "--allow-empty", "-m", "initial")

Copilot uses AI. Check for mistakes.
@peacock0803sz

Copy link
Copy Markdown
Owner Author

@claude Can you review this PR?

@peacock0803sz

Copy link
Copy Markdown
Owner Author

@claude once again, cloud you review this?

@claude

claude Bot commented Feb 26, 2026

Copy link
Copy Markdown

Claude finished @peacock0803sz's task in 1m 50s —— View job


PR Review: ✨ Add status line showing execution environment info

  • Read PR context and changed files
  • Review proto changes
  • Review backend changes (gitinfo.go, agent_server.go, adapters)
  • Review frontend changes (StatusLine, useStatusLine, routes)
  • Review tests
  • Post final review

Overall this is a well-scoped feature with good test coverage. There are a few issues worth addressing before merge, ranging from a guideline violation to a functional bug.

Critical: Japanese comments violate project guidelines

CLAUDE.md requires "All documentation must be in English", but there are Japanese comments scattered throughout the new code:

File Location Issue
back/internal/server/gitinfo.go Lines 37, 53, 61, 67 Japanese inline comments
back/internal/server/agent_server.go Line 125 // sequence=1 は EnvironmentInfo 用に予約済み
back/internal/server/gitinfo_test.go Lines 62, 67, 76, 81, 84, 90, 97-98, 137, 142-144, 147-148 Japanese comments throughout
front/app/lib/hooks/useStatusLine.ts Lines 20, 46 Japanese comments
front/app/lib/hooks/useStatusLine.test.ts Virtually all it(...) descriptions Test descriptions in Japanese
front/app/components/chat/StatusLine.test.tsx Lines 25, 35, 38, 45, 55, 67 Japanese test descriptions
front/app/test-setup.ts Lines 4-6 Japanese block comment

This affects readability for international contributors. Gemini Code Assist has already suggested specific English translations for each of these. Fix this →


Bug: GetGitInfo() uses the server's working directory, not the project directory

back/internal/server/gitinfo.go:16 and back/internal/server/agent_server.go:89

// GetGitInfo runs git commands from os.Getwd() — the server's process CWD
gitInfo := GetGitInfo()

But the project the agent is working in is msg.WorkingDirectory. This means:

  • The status line will always show the server's own git repo context (i.e., the vibra repository itself), not the user's project.
  • All concurrent sessions will show identical repository/branch info regardless of their actual working directories.

The fix is to accept a directory parameter:

func GetGitInfo(dir string) GitInfo { ... }
// and pass it down to GetBranch / getRemoteURL via exec.Command("-C", dir, ...)

Then call it as GetGitInfo(msg.WorkingDirectory). Fix this →


Bug: Stale status line between sessions

front/app/lib/hooks/useStatusLine.ts:55

prevRef.current = next;
return next;

When a new execution starts, useAgent likely clears events (sets it to []). In that state, findLatestEnvironment returns undefined and the hook returns prevRef.current — which still holds data from the previous session. The user will see the previous session's repo/branch/model until the new EnvironmentInfo arrives. Consider resetting prevRef when events.length === 0:

if (!latestEvent || latestEvent.payload.case !== "environment") {
  if (events.length === 0) {
    prevRef.current = { hostname: FALLBACK, repository: FALLBACK, branch: FALLBACK, agentType: FALLBACK, modelName: FALLBACK };
  }
  return prevRef.current;
}

Concern: Ref mutation during render

front/app/lib/hooks/useStatusLine.ts:55

prevRef.current = next;  // mutating a ref during render
return next;

React's concurrent mode can invoke the render function multiple times. Mutating a ref during render is unsafe and can produce inconsistent state. The canonical pattern is to return the computed value and let callers use useMemo/useEffect if needed, or to store the previous value in state rather than a ref.


Minor: Unnecessary array copy in findLatestEnvironment

front/app/lib/hooks/useStatusLine.ts:22

return [...events].reverse().find((e) => e.payload.case === "environment");

This copies and reverses the entire array on every render. As the event stream grows this becomes wasteful. A simple reverse-iteration loop avoids the allocation:

for (let i = events.length - 1; i >= 0; i--) {
  if (events[i].payload.case === "environment") return events[i];
}
return undefined;

Minor: Test robustness issues in gitinfo_test.go

Line 81: string(out[:len(out)-1]) strips exactly one byte. On CRLF systems, this leaves \r attached to the hash. Use strings.TrimSpace(string(out)) instead (consistent with how GetBranch itself does it).

Lines 119, 64-68: git init -b main requires git ≥ 2.28 and errors are silently ignored via _ = cmd.Run(). As copilot noted, this makes the test silently pass on older git versions without actually setting up the repo. Consider checking errors in the run helper.


Nit: Internal requirement IDs in comments

back/internal/server/agent_server.go:87

// Emit EnvironmentInfo as sequence=1 before container start (FR-001, FR-007)

FR-001/FR-007 are internal requirement IDs not visible in the repo. A brief functional description would be more useful for future contributors.


Positive notes

  • Proto design is clean — good field-level comments on EnvironmentInfo explaining fallback semantics
  • The sequence=1 reservation pattern is well-implemented and tested
  • StatusLine component is nicely self-contained with appropriate truncation for long repo/branch names
  • FR-011 value preservation is a thoughtful UX detail and well tested
  • Vitest integration is set up cleanly
    | Branch

GetGitInfo/GetBranch/getRemoteURL used the server process CWD, causing
the status line to always show the vibra repo itself rather than the
user's project. Accept a dir parameter and use git -C for all commands.

Also improve test robustness: check git command errors instead of
silently ignoring, use strings.TrimSpace, and remove os.Chdir pattern.
Replace useRef-based state preservation with a forward iteration over
all events, merging EnvironmentInfo fields sequentially. This fixes
stale data on session reset (events cleared to []) and eliminates
unsafe ref mutation during render (React concurrent mode).
CLAUDE.md requires "All documentation must be in English". Replace
Japanese inline comments and test names across backend and frontend.
@peacock0803sz

Copy link
Copy Markdown
Owner Author

@claude fixed, re-review them!

@claude

claude Bot commented Feb 26, 2026

Copy link
Copy Markdown

Claude finished @peacock0803sz's task in 1m 49s —— View job


Re-review: All major issues resolved ✅

All previously raised issues have been addressed across three commits (d158d4c, b76e7be, 0e78fad). Here's the status of each item:


✅ Japanese comments (Critical → Fixed)

All files now have English-only comments and test descriptions. Translation is accurate and natural in every location I checked. No remaining Japanese text found.


GetGitInfo() directory bug (Bug → Fixed)

back/internal/server/gitinfo.go:16 now accepts a dir string parameter and passes it via git -C <dir> to both GetBranch and getRemoteURL. The call site at agent_server.go:89 correctly passes msg.WorkingDirectory. Concurrent sessions will now see their own repo/branch context.


✅ Stale status line + ref mutation (Bug + Concern → Fixed)

front/app/lib/hooks/useStatusLine.ts has been completely rewritten with useMemo — no ref, no mutation during render. The new approach is notably cleaner:

export function useStatusLine(events: StreamEvent[]): StatusLineData {
  return useMemo(() => {
    let result = DEFAULT_DATA;
    for (const event of events) {
      if (event.payload.case === "environment") {
        const env = event.payload.value;
        result = {
          hostname: env.hostname || result.hostname,
          // ...
        };
      }
    }
    return result;
  }, [events]);
}

This elegantly handles two scenarios:

  • FR-011 (preserve across events): because the events array is cumulative, old non-empty values from earlier events naturally win over later empty fields during the forward pass.
  • Session reset: when events resets to [] for a new session, the loop produces no results and DEFAULT_DATA ("-" for all) is returned immediately — no stale data.

✅ Unnecessary array copy (Minor → Fixed)

The [...events].reverse().find(...) pattern is gone. The forward accumulation loop is O(n) and allocation-free, which is better than the originally suggested reverse loop.


gitinfo_test.go robustness (Minor → Fixed)

Both issues corrected:

  • commitHash now uses strings.TrimSpace(string(out)) instead of string(out[:len(out)-1]) — safe on CRLF too.
  • TestGetBranch_NormalBranch now uses a run helper that calls t.Fatalf on error, uses git init + git checkout -b main (compatible with older git), and adds the required user.email/user.name config so --allow-empty commits work without global git config.

⚠️ Nit still remaining: internal requirement IDs in comment

back/internal/server/agent_server.go:87:

// Emit EnvironmentInfo as sequence=1 before container start (FR-001, FR-007)

FR-001/FR-007 are internal requirement IDs not present in the repository. Not a blocker — just worth replacing with a brief functional description for future contributors who won't have access to the requirements doc.


Summary

Every critical and substantive issue from the first review has been cleanly resolved. The useStatusLine rewrite in particular is a significant improvement — simpler, correct under React concurrent mode, and handling both FR-011 and session resets naturally. The only outstanding item is the internal requirement ID nit on line 87 of agent_server.go, which is non-blocking.

This PR is ready to merge pending the minor nit above (or merge as-is, the nit is truly cosmetic).
| Branch

@peacock0803sz peacock0803sz merged commit 9c9f40e into main Feb 26, 2026
6 checks passed
@peacock0803sz peacock0803sz deleted the 002-statusline branch February 26, 2026 19:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants