Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
85afb2d
Update agent integration skill to E2E-driven development
alishakawaguchi Feb 26, 2026
c58064c
Fix agent integration skill interface/naming drift
alishakawaguchi Feb 27, 2026
9b48a83
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Feb 27, 2026
3e70f85
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Feb 27, 2026
c38e217
Add Kiro agent integration
alishakawaguchi Feb 27, 2026
19acfef
Restructure agent-integration skill for E2E-first TDD
alishakawaguchi Feb 27, 2026
526070a
revert kiro code
alishakawaguchi Feb 27, 2026
09d3006
Add Kiro agent integration with E2E-first TDD
alishakawaguchi Feb 28, 2026
237ba90
Add commit steps to agent-integration skill phases
alishakawaguchi Feb 28, 2026
bf4dac1
Simplify Kiro agent code: remove dead branch, magic number, and dupli…
alishakawaguchi Feb 28, 2026
df1609d
Audit and fix Kiro agent tests: remove dead test, add missing coverage
alishakawaguchi Mar 3, 2026
846147e
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 3, 2026
ec25180
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 3, 2026
3e19f03
Resolve merge conflicts and strip ENTIRE_TEST_TTY from Kiro E2E runner
alishakawaguchi Mar 3, 2026
d82a915
Add Kiro IDE hook support and SIGV4 auth for E2E
alishakawaguchi Mar 3, 2026
d01bbc6
Fix Kiro IDE hooks hanging on stdin read and missing transcript
alishakawaguchi Mar 3, 2026
834b493
Add Kiro TranscriptAnalyzer and fix stop hook exit code on empty repos
alishakawaguchi Mar 3, 2026
7dd0395
Support Kiro IDE transcript format for session metadata
alishakawaguchi Mar 4, 2026
a56a1ec
Extract helpers to deduplicate Kiro transcript parsing and hook prefi…
alishakawaguchi Mar 4, 2026
390be4f
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 4, 2026
6e4bbf8
kiro hooks
alishakawaguchi Mar 4, 2026
9b9d3fd
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 4, 2026
b7749f2
refactor: replace hardcoded Kiro check with TerminalAgent interface
alishakawaguchi Mar 4, 2026
6b2fd25
fix: clear stale session ID cache on stop and fix test script hook fo…
alishakawaguchi Mar 4, 2026
4b7d6b8
remove claude agent integration files
alishakawaguchi Mar 4, 2026
0ba628c
undo error change
alishakawaguchi Mar 4, 2026
b4d27bb
fix: add debug logging, docs, and map lookup from review feedback
alishakawaguchi Mar 5, 2026
ab89491
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 5, 2026
bbaf6a1
ci: add kiro to e2e workflow agent dispatch options
alishakawaguchi Mar 5, 2026
5e29ca9
fix: use dynamic matrix to filter e2e agents on workflow_dispatch
alishakawaguchi Mar 5, 2026
d7016b9
Merge branch 'main' into alisha/kiro-oneshot
alishakawaguchi Mar 5, 2026
6c49b69
Forward AWS SIGV4 env vars through tmux for Kiro E2E tests
alishakawaguchi Mar 5, 2026
2c6a528
Switch Kiro E2E to --no-interactive mode (no tmux)
alishakawaguchi Mar 5, 2026
3300198
Switch Kiro E2E to kiro-cli-chat binary for SIGV4 auth
alishakawaguchi Mar 5, 2026
6aa475c
Create ~/.local/bin before copying kiro-cli-chat in CI
alishakawaguchi Mar 5, 2026
e6025af
Use setup-kiro-action@v1 with v1.24.0 in e2e-isolated
alishakawaguchi Mar 5, 2026
992bca1
Downgrade kiro-cli version to 1.22.0 in e2e-isolated
alishakawaguchi Mar 5, 2026
87132f9
Switch Kiro CI auth from SIGV4 to device-flow token
alishakawaguchi Mar 5, 2026
40ee0d1
Inject Kiro auth token via SQLite in CI workflows
alishakawaguchi Mar 5, 2026
9677610
Remove Kiro agent from CI E2E workflows
alishakawaguchi Mar 5, 2026
1e56769
clean up
alishakawaguchi Mar 5, 2026
ef9ff9f
Fix stdin timeout and silent empty transcript bugs
alishakawaguchi Mar 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions cmd/entire/cli/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,30 @@ type HookResponseWriter interface {
WriteHookResponse(message string) error
}

// TerminalAgent is implemented by agents that run inside a terminal emulator
// (e.g., Kiro in tmux). These agents have hasTTY()=true even when the agent
// itself is committing, so git hooks cannot distinguish user-initiated commits
// from agent-initiated commits using TTY detection alone.
type TerminalAgent interface {
Agent

// UsesTerminal reports whether this agent runs in a terminal emulator.
UsesTerminal() bool
}

// IsTerminalAgent checks whether the given agent type corresponds to an agent
// that runs inside a terminal emulator. It looks up the agent in the registry
// and checks for the TerminalAgent interface.
func IsTerminalAgent(agentType types.AgentType) bool {
ag, err := GetByAgentType(agentType)
if err != nil {
return false
}
ta, ok := ag.(TerminalAgent)

return ok && ta.UsesTerminal()
}

// TestOnly is implemented by agents that exist solely for testing (e.g., the Vogon canary agent).
// These agents are excluded from the user-facing agent selection in `entire enable`.
type TestOnly interface {
Expand Down
47 changes: 45 additions & 2 deletions cmd/entire/cli/agent/event.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package agent

import (
"bufio"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -128,16 +129,58 @@ type Event struct {
Metadata map[string]string
}

// ErrEmptyHookInput is returned by ReadAndParseHookInput when stdin is empty.
// Agents that support empty stdin (e.g., Kiro IDE mode) can check for this
// with errors.Is and handle it gracefully.
var ErrEmptyHookInput = errors.New("empty hook input")

// stdinReadTimeout is how long ReadAndParseHookInput waits for stdin data
// before treating the input as empty. IDEs like Kiro keep stdin pipes open
// without sending EOF, so io.ReadAll blocks forever. Piped data is available
// immediately, so 500ms is generous.
const stdinReadTimeout = 500 * time.Millisecond

// ReadAndParseHookInput reads all bytes from stdin and unmarshals JSON into the given type.
// This is a shared helper for agent ParseHookEvent implementations.
//
// Uses a two-phase approach to handle agents that keep stdin open without EOF (e.g., Kiro):
// - Phase 1: Peek(1) with a timeout to detect whether any data is available.
// - Phase 2: Once data is confirmed, io.ReadAll without timeout to read the full payload.
//
// Note: on timeout, the Peek goroutine is abandoned (it blocks forever on
// the open stdin pipe). This is an intentional trade-off — hook processes are
// short-lived, so the leaked goroutine is cleaned up when the process exits.
func ReadAndParseHookInput[T any](stdin io.Reader) (*T, error) {
data, err := io.ReadAll(stdin)
br := bufio.NewReader(stdin)

// Phase 1: detect whether any data is available (with timeout for open-pipe cases).
peekCh := make(chan error, 1)
go func() {
_, err := br.Peek(1)
peekCh <- err
}()

select {
case err := <-peekCh:
if err != nil {
if errors.Is(err, io.EOF) {
return nil, ErrEmptyHookInput
}
return nil, fmt.Errorf("failed to read hook input: %w", err)
}
case <-time.After(stdinReadTimeout):
return nil, ErrEmptyHookInput
}

// Phase 2: data available — read the full payload (no timeout, wait for EOF).
data, err := io.ReadAll(br)
if err != nil {
return nil, fmt.Errorf("failed to read hook input: %w", err)
}
if len(data) == 0 {
return nil, errors.New("empty hook input")
return nil, ErrEmptyHookInput
}

var result T
if err := json.Unmarshal(data, &result); err != nil {
return nil, fmt.Errorf("failed to parse hook input: %w", err)
Expand Down
Loading