Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file removed .DS_Store
Binary file not shown.
24 changes: 12 additions & 12 deletions .gemini/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
"name": "trace-session-start",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini session-start"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini session-start"
}
]
}
Expand All @@ -21,7 +21,7 @@
{
"name": "trace-session-end-exit",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini session-end"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini session-end"
}
]
},
Expand All @@ -31,7 +31,7 @@
{
"name": "trace-session-end-logout",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini session-end"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini session-end"
}
]
}
Expand All @@ -42,7 +42,7 @@
{
"name": "trace-before-agent",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini before-agent"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini before-agent"
}
]
}
Expand All @@ -53,7 +53,7 @@
{
"name": "trace-after-agent",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini after-agent"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini after-agent"
}
]
}
Expand All @@ -64,7 +64,7 @@
{
"name": "trace-before-model",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini before-model"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini before-model"
}
]
}
Expand All @@ -75,7 +75,7 @@
{
"name": "trace-after-model",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini after-model"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini after-model"
}
]
}
Expand All @@ -86,7 +86,7 @@
{
"name": "trace-before-tool-selection",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini before-tool-selection"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini before-tool-selection"
}
]
}
Expand All @@ -98,7 +98,7 @@
{
"name": "trace-before-tool",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini before-tool"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini before-tool"
}
]
}
Expand All @@ -110,7 +110,7 @@
{
"name": "trace-after-tool",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini after-tool"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini after-tool"
}
]
}
Expand All @@ -121,7 +121,7 @@
{
"name": "trace-pre-compress",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini pre-compress"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini pre-compress"
}
]
}
Expand All @@ -132,7 +132,7 @@
{
"name": "trace-notification",
"type": "command",
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/trace/main.go hooks gemini notification"
"command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/hawk hooks gemini notification"
}
]
}
Expand Down
8 changes: 4 additions & 4 deletions .gemini/test-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ SESSION_START_INPUT=$(cat <<EOF
EOF
)

echo "$SESSION_START_INPUT" | go run ./cmd/trace/main.go hooks gemini session-start && echo " ✓ session-start passed" || echo " ✗ session-start failed"
echo "$SESSION_START_INPUT" | go run ./cmd/hawk hooks gemini session-start && echo " ✓ session-start passed" || echo " ✗ session-start failed"

# Test 2: Before Tool Hook
echo ""
Expand All @@ -46,7 +46,7 @@ BEFORE_TOOL_INPUT=$(cat <<EOF
EOF
)

echo "$BEFORE_TOOL_INPUT" | go run ./cmd/trace/main.go hooks gemini before-tool && echo " ✓ before-tool passed" || echo " ✗ before-tool failed"
echo "$BEFORE_TOOL_INPUT" | go run ./cmd/hawk hooks gemini before-tool && echo " ✓ before-tool passed" || echo " ✗ before-tool failed"

# Test 3: After Tool Hook
echo ""
Expand All @@ -65,7 +65,7 @@ AFTER_TOOL_INPUT=$(cat <<EOF
EOF
)

echo "$AFTER_TOOL_INPUT" | go run ./cmd/trace/main.go hooks gemini after-tool && echo " ✓ after-tool passed" || echo " ✗ after-tool failed"
echo "$AFTER_TOOL_INPUT" | go run ./cmd/hawk hooks gemini after-tool && echo " ✓ after-tool passed" || echo " ✗ after-tool failed"

# Test 4: Session End Hook
echo ""
Expand All @@ -82,7 +82,7 @@ SESSION_END_INPUT=$(cat <<EOF
EOF
)

echo "$SESSION_END_INPUT" | go run ./cmd/trace/main.go hooks gemini session-end && echo " ✓ session-end passed" || echo " ✗ session-end failed"
echo "$SESSION_END_INPUT" | go run ./cmd/hawk hooks gemini session-end && echo " ✓ session-end passed" || echo " ✗ session-end failed"

# Cleanup
rm -rf "$TEMP_DIR"
Expand Down
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

<!--
Trace records developer sessions. Any change that touches `redact/`,
`cmd/trace/cli/checkpoint/`, or transcript serialization can leak PII,
`cli/checkpoint/`, or transcript serialization can leak PII,
secrets, or proprietary code if regressed.

- Did you change `redact/redact.go`, `redact/pii.go`, the secret-pattern
Expand Down Expand Up @@ -73,7 +73,7 @@ $ golangci-lint run ./...
- [ ] `go test -race -count=1 ./...` passes locally
- [ ] e2e impact considered (relevant `e2e/` test added, updated, or
verified) — n/a if change is contained to non-runtime code
- [ ] Public APIs in `cmd/trace/cli/...` have godoc comments
- [ ] Public APIs in `cli/...` have godoc comments
- [ ] `CHANGELOG.md` updated under `## [Unreleased]` if user-visible
- [ ] No regression in `redact/` tests
- [ ] No secrets, tokens, or PII added to the repo (test fixtures use
Expand Down
20 changes: 10 additions & 10 deletions .github/internal/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Deprecated top-level alias (functional, prints cobra deprecation message):
Hidden infrastructure commands: `hooks`, `migrate`, `trail`,
`curl-bash-post-install`, `__send_analytics`.

The `hideAsAlias(cmd, canonical)` helper in `cmd/trace/cli/aliascmd.go`
The `hideAsAlias(cmd, canonical)` helper in `cli/aliascmd.go`
marks a command Hidden and sets cobra's `Deprecated` field so the hint
renders to stderr on every invocation while the command stays functional.
Diagnostic subcommands live alongside `doctor.go` as `doctor_logs.go` and
Expand Down Expand Up @@ -85,7 +85,7 @@ mise run test:integration
mise run test:ci
```

This runs unit tests, integration tests, and the E2E canary (Vogon agent) in sequence. Integration tests use the `//go:build integration` build tag and are located in `cmd/trace/cli/integration_test/`.
This runs unit tests, integration tests, and the E2E canary (Vogon agent) in sequence. Integration tests use the `//go:build integration` build tag and are located in `cli/integration_test/`.

### Running E2E Canary Tests (Vogon Agent)

Expand All @@ -99,7 +99,7 @@ mise run test:e2e:canary TestFoo # Run a specific test
- **Runs as part of `test:ci`** — canary failures block merges
- **No API calls, no cost** — safe to run freely, unlike real agent E2E tests
- **If a canary test fails, the bug is in the CLI or test infrastructure**, not in an agent
- Located in `e2e/vogon/` (binary) and `cmd/trace/cli/agent/vogon/` (Agent interface)
- Located in `e2e/vogon/` (binary) and `cli/agent/vogon/` (Agent interface)
- The binary parses prompts via regex, creates/modifies/deletes files, and fires lifecycle hooks
- **IMPORTANT: When changing E2E test prompt wording**, the Vogon binary (`e2e/vogon/main.go`) parses prompts with hardcoded regexes. New phrasing may not match existing patterns — always run `mise run test:e2e:canary` after changing prompt text and fix Vogon's parsing if tests fail.

Expand Down Expand Up @@ -190,7 +190,7 @@ Tests that spawn the real `trace` or `git` binary need the child to be non-inter
For subprocesses spawning the real `trace` binary (e2e, integration tests, `trace` calling itself from a hook), prefer `execx.NonInteractive` over env-var plumbing:

```go
import "github.com/GrayCodeAI/trace/cmd/trace/cli/execx"
import "github.com/GrayCodeAI/trace/cli/execx"

cmd := execx.NonInteractive(ctx, getTestBinary(), "status")
cmd.Dir = repoDir
Expand Down Expand Up @@ -303,15 +303,15 @@ return fmt.Errorf("unknown strategy: %s", name)

### Settings

All settings access should go through the `settings` package (`cmd/trace/cli/settings/`).
All settings access should go through the `settings` package (`cli/settings/`).

**Why a separate package:**
The `settings` package exists to avoid import cycles. The `cli` package imports `strategy`, so `strategy` cannot import `cli`. The `settings` package provides shared settings loading that both can use.

**Usage:**

```go
import "github.com/GrayCodeAI/trace/cmd/trace/cli/settings"
import "github.com/GrayCodeAI/trace/cli/settings"

// Load full settings object
s, err := settings.Load()
Expand Down Expand Up @@ -341,7 +341,7 @@ if settings.IsSummarizeEnabled() {

### Logging vs User Output

- **Internal/debug logging**: Use `logging.Debug/Info/Warn/Error(ctx, msg, attrs...)` from `cmd/trace/cli/logging/`. Writes to `.trace/logs/`.
- **Internal/debug logging**: Use `logging.Debug/Info/Warn/Error(ctx, msg, attrs...)` from `cli/logging/`. Writes to `.trace/logs/`.
- **Enabling debug/perf logs locally**: Prefer adding `"log_level": "DEBUG"` to `.trace/settings.local.json` when you need detailed hook/perf logs. This file is gitignored, so it is a low-risk local-only change. `TRACE_LOG_LEVEL=debug` also works and takes precedence.
- **User-facing output**: Use `fmt.Fprint*(cmd.OutOrStdout(), ...)` or `cmd.ErrOrStderr()`.

Expand Down Expand Up @@ -410,7 +410,7 @@ relPath := paths.ToRelativePath("/repo/api/file.ts", repoRoot) // returns "api/

Test case in `state_test.go`: `TestFilterAndNormalizePaths_SiblingDirectories` documents this bug pattern.

### Session Strategy (`cmd/trace/cli/strategy/`)
### Session Strategy (`cli/strategy/`)

The CLI uses a manual-commit strategy for managing session data and checkpoints. The strategy implements the `Strategy` interface defined in `strategy.go`.

Expand Down Expand Up @@ -463,14 +463,14 @@ The manual-commit strategy (`manual_commit*.go`) does not modify the active bran
- `session_state.go` - Package-level session state functions (`LoadSessionState`, `SaveSessionState`, `ListSessionStates`, `FindMostRecentSession`)
- `hooks.go` - Git hook installation

#### Checkpoint Package (`cmd/trace/cli/checkpoint/`)
#### Checkpoint Package (`cli/checkpoint/`)

- `checkpoint.go` - Data types (`Checkpoint`, `TemporaryCheckpoint`, `CommittedCheckpoint`)
- `store.go` - `GitStore` struct wrapping git repository
- `temporary.go` - Shadow branch operations (`WriteTemporary`, `ReadTemporary`, `ListTemporary`)
- `committed.go` - Metadata branch operations (`WriteCommitted`, `ReadCommitted`, `ListCommitted`)

#### Session Package (`cmd/trace/cli/session/`)
#### Session Package (`cli/session/`)

- `session.go` - Session data types and interfaces
- `state.go` - `StateStore` for managing `.git/trace-sessions/` files
Expand Down
4 changes: 2 additions & 2 deletions .github/internal/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Write tests that provide real value, not just coverage:
- **Include edge cases and error conditions** - ensure error paths are properly tested
- **When fixing bugs, write a test that surfaces the bug first** - then write the fix
- **Unit tests**: Same directory as source, `*_test.go` files
- **Integration tests**: `cmd/trace/cli/integration_test/`, require `//go:build integration` tag
- **Integration tests**: `cli/integration_test/`, require `//go:build integration` tag

Run `mise run test` for quick validation, `mise run test:ci` for full CI parity.

Expand All @@ -139,7 +139,7 @@ Run `mise run lint:full` to check all code (not just new issues).

## When Adding New Commands

1. Add command in `cmd/trace/cli/` following existing patterns (look at similar commands)
1. Add command in `cli/` following existing patterns (look at similar commands)
2. Register in `root.go`
3. Use `SilentError` for custom error messages
4. Add meaningful tests that verify behavior
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,15 @@ jobs:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: deadcode
# Advisory, not blocking: trace is a library with no main() entrypoint,
# so plain `deadcode ./...` flags the entire public API as unreachable.
# We run with -test (tests count as roots) for a meaningful signal, but a
# hard gate would false-positive on legitimate exported API — review the
# output in the logs instead.
run: |
go install golang.org/x/tools/cmd/deadcode@latest
deadcode ./... 2>&1 | head -50
deadcode -test ./... 2>&1 | tee deadcode.txt
echo "deadcode reported $(grep -c 'unreachable func' deadcode.txt || echo 0) unreachable funcs (advisory)"

# -------------------------------------------------------------------------
# Duplication detection — jscpd.
Expand Down
Loading
Loading