Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4ac51fe
add agent brief for token diagnostics
peyton-alt Jun 10, 2026
19ca13e
add checkpoint token comparison
peyton-alt Jun 11, 2026
83b9330
add API-only token brief guidance
peyton-alt Jun 13, 2026
79f19d0
fix checkpoint comparison test store refs
peyton-alt Jun 13, 2026
1735b02
fix checkpoint token metadata fallbacks
peyton-alt Jun 18, 2026
0828cf5
clamp checkpoint token delta overflow
peyton-alt Jun 18, 2026
589d5b0
clarify token delta overflow guard
peyton-alt Jun 22, 2026
7fcdff6
avoid checkpoint delta percent overflow
peyton-alt Jun 22, 2026
dd4bc64
Clarify token guidance heuristics
peyton-alt Jun 23, 2026
54766c1
Align agent brief cache replay scope
peyton-alt Jun 23, 2026
1531c23
Check cancellation before token metadata reads
peyton-alt Jun 23, 2026
b11488c
Use checkpoint summary when metadata is partial
peyton-alt Jun 23, 2026
39be421
Avoid singular checkpoint metadata on partial reads
peyton-alt Jun 23, 2026
0d55f55
add token profile diagnostics
peyton-alt Jun 11, 2026
cc33b02
fix token profile review feedback
peyton-alt Jun 13, 2026
9291dac
fix token profile API-call-only usage
peyton-alt Jun 13, 2026
ff1ae90
clarify token profile usage scope
peyton-alt Jun 16, 2026
c34ad59
Add cost-proxy token guidance
peyton-alt Jun 17, 2026
53bff77
Tighten agent token brief stop gate
peyton-alt Jun 17, 2026
9102855
dedupe token plural helper
peyton-alt Jun 18, 2026
956e0fb
reject checkpoint token self-comparison
peyton-alt Jun 18, 2026
8238231
Surface token diagnostics in labs
peyton-alt Jun 17, 2026
9b84620
avoid token profile percentage overflow
peyton-alt Jun 22, 2026
62c5cc2
Align token profile diagnostics
peyton-alt Jun 23, 2026
4492b95
Merge branch 'main' into tokens-profile
peyton-alt Jun 23, 2026
b7a0bf6
Gate checkpoint context on true session count
peyton-alt Jun 23, 2026
20af48c
Align token profile replay denominator
peyton-alt Jun 23, 2026
37c0552
Merge branch 'main' into tokens-agent-brief
peyton-alt Jun 23, 2026
802820e
Merge pull request #1417 from entireio/tokens-profile
peyton-alt Jun 23, 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
4 changes: 4 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ linters:
- empty
- stdlib
- charm.land/bubbletea/v2.Model
- charm.land/bubbletea/v2.Msg
- charm.land/huh/v2.Theme
- grpc.DialOption
- github.com/entireio/cli/cmd/entire/cli/summarize.Generator
- github.com/entireio/cli/cmd/entire/cli/agent\..+
Expand All @@ -122,6 +124,8 @@ linters:
- github.com/entireio/cli/cmd/entire/cli/review/types.AgentReviewer
- github.com/entireio/cli/cmd/entire/cli/review.SynthesisProvider
- github.com/entireio/cli/cmd/entire/cli/checkpoint.CommittedReader
- github.com/entireio/cli/cmd/entire/cli/checkpoint.CommittedStore
- github.com/entireio/cli/cmd/entire/cli/checkpoint.TemporaryStore
- github.com/entireio/cli/cmd/entire/cli/strategy.Strategy
- github.com/entireio/cli/internal/entireclient/tokenstore.store
- github.com/go-git/go-git/v6/x/plugin.Signer
Expand Down
20 changes: 13 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ This repo contains the CLI for Entire.

### Command Layout

The CLI is organized around five noun groups plus a small set of top-level
verbs. The groups are the canonical home for each verb; legacy top-level
shortcuts remain functional but hidden, and emit a deprecation hint pointing
at the canonical group form.

- `session` (alias: `sessions`): `list`, `info`, `stop`, `attach`, `resume`, `current`.
The visible CLI is organized around five noun groups plus a small set of
top-level verbs. The groups are the canonical home for each verb; legacy
top-level shortcuts remain functional but hidden, and emit a deprecation hint
pointing at the canonical group form. Newer experimental command families are
discoverable through `entire labs` and may remain hidden from root help while
their canonical paths are still runnable.

- `session` (alias: `sessions`): `list`, `info`, `tokens`, `stop`, `attach`, `resume`, `current`.
`resume` with a branch arg switches to it and resumes its session; with no arg
it opens an interactive picker of stopped sessions (across all worktrees),
resolving each to its branch and pointing at the owning worktree when the
branch is checked out elsewhere. Resume keeps an existing local session log
as-is by default (`--force` overwrites it from the checkpoint).
- `checkpoint` (aliases: `cp`, `checkpoints`): `list`, `explain`, `search`, plus
- `checkpoint` (aliases: `cp`, `checkpoints`): `list`, `explain`, `tokens`, `search`, plus
the deprecated `rewind` (functional, prints a cobra deprecation message, will
be removed in a future release)
- `agent`: bare opens the interactive agent selector, plus `list`, `add`, `remove`
Expand All @@ -45,6 +47,10 @@ at the canonical group form.
current one) and `--all-contexts` (log out of every saved login)
- `doctor`: bare runs the scan-and-fix flow, plus `trace`, `logs`, `bundle`

Experimental command families advertised through `entire labs`:

- `tokens`: `profile` (hidden from root help while token diagnostics mature)

Top-level lifecycle and standalone commands: `enable`, `disable`, `status`,
`login`, `logout`, `clean`, `version`, `dispatch`, `activity`, `help`,
`configure`.
Expand Down
2 changes: 1 addition & 1 deletion cmd/entire/cli/activity_tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func runActivityTUI(ctx context.Context, client *api.Client) error {
return nil
}

func (m activityModel) fetchData() tea.Msg { //nolint:ireturn // bubbletea Cmd signature requires tea.Msg return
func (m activityModel) fetchData() tea.Msg {
activity, commits, err := fetchActivityData(m.ctx, m.client)
if err != nil {
return activityErrMsg{err: err}
Expand Down
2 changes: 2 additions & 0 deletions cmd/entire/cli/api/trail_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type TrailListResponse struct {
type TrailResource struct {
ID string `json:"id,omitempty"`
Number int `json:"number,omitempty"`
URL string `json:"url,omitempty"`
Branch string `json:"branch"`
Base string `json:"base"`
Title string `json:"title"`
Expand Down Expand Up @@ -58,6 +59,7 @@ func (r *TrailResource) ToMetadata() *trail.Metadata {
m := &trail.Metadata{
Number: r.Number,
TrailID: trail.ID(r.ID),
URL: r.URL,
Branch: r.Branch,
Base: r.Base,
Title: r.Title,
Expand Down
50 changes: 48 additions & 2 deletions cmd/entire/cli/api/trail_types_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
package api

import "testing"
import (
"encoding/json"
"testing"
)

// TestTrailResourceDecodesServerURL covers the wire-compatibility matrix for the
// `url` field the API added:
// - new cli + new api: the field decodes into TrailResource.URL and is used.
// - old cli + new api: a client struct predating the field ignores the extra
// key without error (Go's json.Unmarshal drops unknown fields), so an older
// CLI keeps working against a newer server.
//
// (new cli + old api is exercised by trailDisplayURL's fallback in the cli pkg.)
func TestTrailResourceDecodesServerURL(t *testing.T) {
t.Parallel()

// Shape a newer server would emit: includes `url`.
payload := []byte(`{"id":"t1","number":640,"url":"https://entire.io/gh/o/r/trails/640/slug","branch":"feat/x","title":"T"}`)

// new cli + new api: URL is captured and available to display.
var newClient TrailResource
if err := json.Unmarshal(payload, &newClient); err != nil {
t.Fatalf("new client failed to decode new payload: %v", err)
}
if newClient.URL != "https://entire.io/gh/o/r/trails/640/slug" {
t.Fatalf("URL = %q, want server-provided url", newClient.URL)
}

// old cli + new api: a struct without a URL field must not choke on the
// extra key, and still decodes the fields it knows about.
var oldClient struct {
ID string `json:"id"`
Number int `json:"number"`
Title string `json:"title"`
}
if err := json.Unmarshal(payload, &oldClient); err != nil {
t.Fatalf("old client rejected new payload with extra url field: %v", err)
}
if oldClient.Number != 640 || oldClient.Title != "T" {
t.Fatalf("old client decoded wrong values: %+v", oldClient)
}
}

func TestTrailResourceToMetadataUsesID(t *testing.T) {
t.Parallel()

metadata := (&TrailResource{ID: "trail-db-id", Branch: "feature/x", Phase: "has_code"}).ToMetadata()
metadata := (&TrailResource{ID: "trail-db-id", URL: "https://entire.io/gh/o/r/trails/9", Branch: "feature/x", Phase: "has_code"}).ToMetadata()
if got := metadata.TrailID.String(); got != "trail-db-id" {
t.Fatalf("metadata TrailID = %q, want stable API id", got)
}
if metadata.Phase != "has_code" {
t.Fatalf("metadata Phase = %q, want has_code", metadata.Phase)
}
// The server-provided URL must propagate so callers relying on ToMetadata()
// don't silently drop it.
if metadata.URL != "https://entire.io/gh/o/r/trails/9" {
t.Fatalf("metadata URL = %q, want propagated server url", metadata.URL)
}
}
2 changes: 1 addition & 1 deletion cmd/entire/cli/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (opts attachOptions) committedRefs(ctx context.Context) cpkg.CommittedRefs

// openAttachStore opens the committed store for the resolved topology. refs is
// passed explicitly so attach preserves PrimaryAsRead() pinning.
func openAttachStore(ctx context.Context, repo *git.Repository, refs cpkg.CommittedRefs) (cpkg.CommittedStore, error) { //nolint:ireturn // committed store capability preserves attach's read-ref override
func openAttachStore(ctx context.Context, repo *git.Repository, refs cpkg.CommittedRefs) (cpkg.CommittedStore, error) {
stores, err := cpkg.Open(ctx, repo, cpkg.OpenOptions{Refs: &refs})
if err != nil {
return nil, fmt.Errorf("open checkpoint store: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion cmd/entire/cli/checkpoint/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func resolveOpenRefs(ctx context.Context, opts OpenOptions) CommittedRefs {
}

// Temporary returns the git-backed temporary shadow-branch store.
func (s *Stores) Temporary() TemporaryStore { return s.temporary } //nolint:ireturn // temporary store capability is the abstraction boundary
func (s *Stores) Temporary() TemporaryStore { return s.temporary }

// Refs returns the resolved committed-ref topology.
func (s *Stores) Refs() CommittedRefs { return s.refs }
Loading
Loading