Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
03ebe34
feat(codex): add authoritative subagent tracking foundation
peyton-alt Sep 1, 2026
e5c44df
feat(codex): reconcile subagents with exact accounting
peyton-alt Sep 1, 2026
32cb75e
test(codex): verify subagent tracking integration
peyton-alt Sep 1, 2026
271b7f5
fix(codex): address subagent tracking review findings
peyton-alt Sep 1, 2026
bc470d8
fix(codex): retain multi-turn child evidence
peyton-alt Sep 1, 2026
366fe69
fix(codex): clear stale session-end evidence
peyton-alt Sep 1, 2026
a5d4e24
fix(codex): guard exact usage completeness
peyton-alt Sep 1, 2026
863faec
fix(codex): skip empty fallback scans
peyton-alt Sep 1, 2026
62ba0a6
fix(codex): harden subagent checkpoint tracking
peyton-alt Sep 3, 2026
068d374
refactor(codex): simplify subagent tracking
peyton-alt Sep 3, 2026
edc1289
fix(codex): preserve concurrent child evidence
peyton-alt Sep 3, 2026
f586632
fix(codex): track current subagent rollout evidence
peyton-alt Sep 3, 2026
db89972
fix(codex): close subagent tracking edge cases
peyton-alt Sep 4, 2026
99268bb
fix(codex): make rollout byte guard overflow-safe
peyton-alt Sep 4, 2026
5c185dd
feat: install missing Graph plugin on demand
ashtom Sep 8, 2026
7b26295
fix: preserve plugin prompt streams and cancellation
ashtom Sep 9, 2026
270d17b
fix: close plugin confirmation input exactly once
ashtom Sep 9, 2026
6cd08c4
fix(status): report disabled checkpoint pushing
peyton-alt Sep 9, 2026
69af387
coreapi: regenerate the client from the current core spec
kramuenke Sep 10, 2026
c0bb11d
repo: add the branch-protection subtree
kramuenke Sep 10, 2026
63a5798
coreapi: loosen the other new read-model fields the client never reads
kramuenke Sep 10, 2026
bbbf523
repo protection: say what an empty list means on a GitHub mirror
kramuenke Sep 10, 2026
1024f14
repo protection: look up the repo only for an empty rule list
Soph Sep 10, 2026
8f76772
coreapi: refuse to empty a security list, and say what the loosenings…
Soph Sep 10, 2026
4227aa4
coreapi: pin the read-model required-field loosenings
Soph Sep 10, 2026
05023e7
repo protection: an empty list needs a positively native provider
Soph Sep 10, 2026
135aac0
fix: address review findings on on-demand plugin installation
Soph Sep 10, 2026
9411294
Update CodeQL workflow to remove unused languages
Soph Sep 10, 2026
e75b832
build: bump Go to 1.27.1 and golangci-lint to 2.13.2
Soph Sep 10, 2026
c11a79f
docs: state the Go 1.27.1 requirement, and be honest about ignore-tests
Soph Sep 10, 2026
1bd2992
Merge remote-tracking branch 'origin/main' into Soph-patch-1
Soph Sep 10, 2026
4ce53ca
fix: report an unrunnable managed plugin, and stop echoing plugin arg…
Soph Sep 10, 2026
d4f783d
ci: read the golangci-lint version from mise.toml
Soph Sep 10, 2026
99eda5c
ci: make the CodeQL advanced setup correct and self-consistent
Soph Sep 10, 2026
190b656
fix: handle Close on the two writable handles that discarded it
Soph Sep 10, 2026
c827855
fix: propagate a signal that reached only the plugin
Soph Sep 10, 2026
7efb51f
fix: name the on-demand prompt's source, and correct the EOF claim
Soph Sep 10, 2026
325483e
fix: prefer Entire's own signal, and bind the install to the prompted…
Soph Sep 10, 2026
a529dc2
fix(status): retain remote diagnostics when pushing is disabled
peyton-alt Sep 10, 2026
14295ee
build(deps): bump the go-dependencies group across 1 directory with 3…
dependabot[bot] Sep 10, 2026
44ce975
fix(codex): preserve child evidence and constrain rollout reads
peyton-alt Sep 10, 2026
9e45f3c
Merge main into feat/codex-subagent-tracking
peyton-alt Sep 10, 2026
ee71bbc
Merge GitHub main into feat/codex-subagent-tracking
peyton-alt Sep 10, 2026
a09a214
fix(status): keep read source and local-only count when pushing is off
peyton-alt Sep 10, 2026
0eedf94
fix(status): do not call push URLs the checkpoint read source
peyton-alt Sep 10, 2026
afd5417
fix(status): scope the unpushed count to the elected destination
peyton-alt Sep 10, 2026
e4cfdae
repo protection: add sends a level only when the flag was given
kramuenke Sep 10, 2026
2e495c2
fix(status): name the read source when the election fails open
peyton-alt Sep 10, 2026
47c7d75
coreapi: make ListReposOutputBody.candidatesIncomplete optional too
kramuenke Sep 11, 2026
bbd6e98
fix(status): treat an unresolvable read source as unknown, not as the…
peyton-alt Sep 11, 2026
e176520
fix(status): report the dedicated read source when the election fails
peyton-alt Sep 11, 2026
eaaf7d0
Only force-close Codex turns for a verified child rollout
peyton-alt Sep 11, 2026
2a6fbef
Count a Codex child's API calls from its usage snapshots
peyton-alt Sep 11, 2026
0be96c7
Merge pull request #2344 from entireio/kai/repo-protection
Soph Sep 11, 2026
86dda01
Merge pull request #2325 from entireio/dependabot/go_modules/go-depen…
Soph Sep 11, 2026
4ff1453
Merge pull request #2356 from entireio/soph/go-1.27
gtrrz-victor Sep 11, 2026
97e2f3c
Remove retired semantic search gate wording
dipree Sep 11, 2026
ca473b9
Merge pull request #2337 from entireio/fix/status-disabled-checkpoint…
Soph Sep 11, 2026
6d85468
deps: bump auth-go for the cross-host redirect and TLS-downgrade guards
Soph Sep 11, 2026
de8555f
coreapi: pin that the cross-juris exchange refuses a redirected POST
Soph Sep 3, 2026
899265d
auth: mint jurisdiction tokens through auth-go's sts client
Soph Sep 3, 2026
1f88676
simplify: fold the one-const httputil package into auth
Soph Sep 3, 2026
875d703
Merge pull request #2366 from entireio/dip/cleanup-retired-feature-flags
Soph Sep 11, 2026
9938a45
Merge pull request #2209 from entireio/feat/codex-subagent-tracking
Soph Sep 11, 2026
175830e
Merge origin/main into feat/graph-plugin-install-on-demand
Soph Sep 11, 2026
2a1656e
Merge pull request #2324 from entireio/feat/graph-plugin-install-on-d…
Soph Sep 11, 2026
af06d13
Merge pull request #2261 from entireio/soph/oauth-redirect-guard-foll…
Soph Sep 11, 2026
21bf9f3
ci: skip the SARIF upload on fork PRs, as the predecessor workflow did
Soph Sep 11, 2026
292b3f5
Merge pull request #2355 from entireio/Soph-patch-1
Soph Sep 11, 2026
8d30069
Merge pull request #2357 from entireio/fix/unhandled-writable-file-close
Soph Sep 11, 2026
170267d
fix(strategy): preserve session token totals on condensation
MuskanPaliwal Sep 11, 2026
5c44abe
test(strategy): cover session token backfill boundaries
MuskanPaliwal Sep 11, 2026
b7f56e4
refactor(strategy): simplify session token backfill
MuskanPaliwal Sep 12, 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
39 changes: 0 additions & 39 deletions .github/workflows/codeql-actions.yml

This file was deleted.

85 changes: 85 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Weekly, so a new query release is picked up even on a quiet week.
- cron: '34 14 * * 0'

# Deny by default; the analyze job declares exactly what it needs.
permissions: {}

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
# Upload the SARIF result to the code-scanning API.
security-events: write
# Fetch the CodeQL query packs.
packages: read
# Read workflow metadata (required for private repositories).
actions: read
contents: read

strategy:
fail-fast: false
matrix:
include:
# The query suite is set per language, not once for the workflow,
# because the two languages have very different cost profiles.
#
# actions: measured at 49s with the extended+quality suites versus
# 50s with the default suite, so the extra 10 queries are free. They
# are also the ones this repo wants: `unpinned-tag`, the
# `*-injection/medium` and `untrusted-checkout/medium` variants (the
# default suite ships only the high/critical precision ones), and
# `if-expression-always-true`.
- language: actions
build-mode: none
queries: security-extended,security-and-quality
# go: autobuild compiles the module, which dominates this leg, so the
# query suite is close to free here too. Measured on this repo:
# 36 queries (default) 192s, 37 (extended) 150s, 59
# (extended+quality) 140s — the spread is runner noise, not suites.
#
# security-and-quality is enabled because its 23 Go additions are
# bug-finding queries, not style: the InconsistentCode family
# (MissingErrorCheck, WrappedErrorAlwaysNil, LengthComparisonOffByOne,
# UnhandledCloseWritableHandle) and the RedundantCode family
# (ImpossibleInterfaceNilCheck, DuplicateSwitchCase, ShiftOutOfRange,
# UnreachableStatement). Run against a local database they add two
# high-precision findings that golangci-lint does not report, so this
# is incremental coverage rather than overlap.
- language: go
build-mode: autobuild
queries: security-extended,security-and-quality

steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Initialize CodeQL
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
queries: ${{ matrix.queries }}

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
category: /language:${{ matrix.language }}
# A fork PR gets a read-only GITHUB_TOKEN, so `security-events: write`
# is not granted and the upload fails the job. Analyze still runs and
# surfaces findings in the log. Note the condition tests the EVENT
# first: the predecessor workflow ran only on pull_request, so it could
# compare head.repo directly, but that expression is null on push and
# schedule — copied here verbatim it would resolve to 'never' and
# silently stop main from ever being uploaded, which is the one thing
# this workflow exists to do.
upload: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && 'always' || 'never' }}
20 changes: 19 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,26 @@ jobs:
# So this golangci-lint uses the same config as `mise run lint:go`, but using special sauce to
# create inline feedback on GitHub's UI. On local dev, the same issues should be surfaced by
# mise-tasks/lint/go
#
# The version is read from mise.toml for the same reason setup-go reads
# go.mod above: the two pins must name the same version, and the hardcoded
# copy that used to live here is what drifted on the Go 1.27 bump. A 2.11
# binary refuses to lint a 1.27 module outright ("the Go language version
# (go1.26) used to build golangci-lint is lower than the targeted Go
# version"), so this step failed after `mise run lint` had already passed
# with the correct version.
- name: Resolve golangci-lint version
id: golangci
run: |
version=$(sed -n "s/^golangci-lint = '\(.*\)'$/\1/p" mise.toml)
if [ -z "$version" ]; then
echo "could not read the golangci-lint version from mise.toml" >&2
exit 1
fi
echo "version=v$version" >> "$GITHUB_OUTPUT"

- name: Run golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
with:
version: 'v2.11.3'
version: ${{ steps.golangci.outputs.version }}
debug: 'clean'
25 changes: 25 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,31 @@ linters:
- whitespace
- wrapcheck
settings:
goconst:
# golangci-lint 2.13's goconst upgrade began scanning composite literals,
# which turned ~2.3k previously-unreported strings into findings. The two
# knobs below are NOT equivalent in what they give up:
#
# ignore-map-keys restores the prior scope exactly: a map-literal key
# was never reported before 2.13, so nothing is lost.
#
# ignore-tests is broader than the 2.13 change and DOES give up
# coverage this repo had. goconst used to lint test logic -- the proof
# is the three //nolint:goconst directives in _test.go files that the
# Go 1.27 bump deleted as unused; they were suppressing real
# comparison/assignment findings under 2.11. Those shapes are no longer
# checked in tests.
#
# It is accepted anyway because no narrower exclusion exists. goconst
# settings are global (there is no per-path variant), the remainder is
# 2016 findings across 62 packages so a path-scoped rule would have to
# name nearly every one, and the field that looks like the right tool --
# exclude-types: [CompositeLit] -- REPLACES the default exclusion set
# rather than adding to it, so it re-enables Call findings and takes the
# count up to 6255. Revisit if goconst gains per-path settings or fixes
# exclude-types.
ignore-tests: true
ignore-map-keys: true
gosec:
excludes:
- G204 # subprocess with variables is expected for git/opencode CLI wrappers
Expand Down
15 changes: 12 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,17 @@ the commands are always runnable in every build.
- `org`: control-plane organization management — `create`, `list`, `get`, `delete`
- `project`: control-plane project management — `create`, `list`, `get`, `delete`
- `repo`: control-plane repository lifecycle — `create`, `list`, `get`, `delete`,
`clone`, plus the `mirror` and `visibility` subtrees. Git content operations
(log, diff, …) are intentionally out of scope. The `mirror` subtree is
`clone`, plus the `mirror`, `visibility` and `protection` subtrees. Git
content operations (log, diff, …) are intentionally out of scope.
`protection` (`list`, `add [--server-side-merge-only]`, `remove`) edits a
native repo's branch-protection rules through core's
`/repos/{repoId}/branch-protection` resource: `add` and `remove` are one
PATCH each (`addRules` upserts by ref), never a read-modify-write of the
list. `add` sends `serverSideMergeOnly` only when the flag was given: the
server keeps an existing rule's level when it is absent, so re-adding a
branch without the flag never lowers it and `--server-side-merge-only=false`
is the explicit way down. A short branch name expands to `refs/heads/`,
`HEAD` and `refs/...` pass through. The `mirror` subtree is
server-side (`create`, `list`, `get`, `remove`, `collaborators`) with one
exception: `mirror use` repoints the *current clone's* git remote at a mirror
(local git config only — it creates nothing server-side). Interactively it
Expand Down Expand Up @@ -234,7 +243,7 @@ named `<noun>_group.go` and `<noun>_<verb>.go` respectively.

## Tech Stack

- Language: Go 1.26.x
- Language: Go 1.27.x (`go.mod` pins the 1.27.1 minimum)
- Build tool: mise, go modules
- Linting: golangci-lint

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Please answer these questions in your bug report:

### Prerequisites

- **Go 1.26.x** - Check with `go version`
- **Go 1.27.1+** - Check with `go version`. `go.mod` pins the minimum, so an older toolchain fails unless it can download the pinned one (`GOTOOLCHAIN=local` cannot).
- **mise** - Task runner and version manager. Install with `curl https://mise.run | sh`

### Clone and Install
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ With Entire, you can:
- Git
- macOS, Linux or Windows
- [Supported agent](#agent-hook-configuration) installed and authenticated
- Go 1.26+ only if you install with `go install` (the packaged installs bundle their own runtime)
- Go 1.27.1+ only if you install with `go install` (the packaged installs bundle their own runtime)

## Quick Start

Expand Down
2 changes: 1 addition & 1 deletion WINDOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- **Windows 10 1809+** (required for ConPTY support in E2E tests)
- **Git for Windows** — provides `git.exe` and bundled bash for git hooks
- **Go 1.26+** — for building from source
- **Go 1.27.1+** — for building from source

## Building

Expand Down
43 changes: 30 additions & 13 deletions cmd/entire/cli/activity_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,40 @@ const (
sessionsOverviewLimit = 50
)

// Canonical agent IDs as /me/activity reports them: the keys of the display
// map, the values knownAgents normalizes onto, and the render order all draw
// from this one set.
const (
activityAgentClaude = "claude"
activityAgentGemini = "gemini"
activityAgentAmp = "amp"
activityAgentCodex = "codex"
activityAgentOpencode = "opencode"
activityAgentCopilot = "copilot"
activityAgentPi = "pi"
activityAgentCursor = "cursor"
activityAgentDroid = "droid"
activityAgentKiro = "kiro"
activityAgentUnknown = "unknown"
)

// knownAgents maps normalized agent strings from the API to display IDs.
// Used for the commit list, where per-checkpoint agent strings are free-form.
// The /me/activity endpoint returns already-normalized canonical IDs.
var knownAgents = map[string]string{
"claude": "claude",
"claudecode": "claude",
"gemini": "gemini",
"geminicli": "gemini",
"amp": "amp",
"codex": "codex",
"opencode": "opencode",
"copilot": "copilot",
"copilotcli": "copilot",
"pi": "pi",
"cursor": "cursor",
"droid": "droid",
"kiro": "kiro",
"claude": activityAgentClaude,
"claudecode": activityAgentClaude,
"gemini": activityAgentGemini,
"geminicli": activityAgentGemini,
"amp": activityAgentAmp,
"codex": activityAgentCodex,
"opencode": activityAgentOpencode,
"copilot": activityAgentCopilot,
"copilotcli": activityAgentCopilot,
"pi": activityAgentPi,
"cursor": activityAgentCursor,
"droid": activityAgentDroid,
"kiro": activityAgentKiro,
}

func newActivityCmd() *cobra.Command {
Expand Down
32 changes: 16 additions & 16 deletions cmd/entire/cli/activity_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ type activityStyles struct {
// used by other commands. Activity benefits from wide output for bar charts.
func getFullTerminalWidth(w io.Writer) int {
if f, ok := w.(*os.File); ok {
if width, _, err := term.GetSize(int(f.Fd())); err == nil && width > 0 { //nolint:gosec // G115: uintptr->int is safe for fd
if width, _, err := term.GetSize(int(f.Fd())); err == nil && width > 0 {
return width
}
}
for _, f := range []*os.File{os.Stdout, os.Stderr} {
if f == nil {
continue
}
if width, _, err := term.GetSize(int(f.Fd())); err == nil && width > 0 { //nolint:gosec // G115: uintptr->int is safe for fd
if width, _, err := term.GetSize(int(f.Fd())); err == nil && width > 0 {
return width
}
}
Expand Down Expand Up @@ -108,22 +108,22 @@ type agentDisplay struct {
// recognizable; lipgloss resolves them to the best representation for the
// terminal's color profile. The non-brand "unknown" fallback uses muted gray.
var agentDisplayMap = map[string]agentDisplay{
"claude": {Label: "Claude Code", Color: "#fb923c", Char: '▓'}, // orange-400
"gemini": {Label: "Gemini", Color: "#60a5fa", Char: '▓'}, // blue-400
"amp": {Label: "Amp", Color: "#f87171", Char: '▓'}, // red-400
"codex": {Label: "Codex", Color: "#818cf8", Char: '▓'}, // indigo-400
"opencode": {Label: "OpenCode", Color: "#22d3ee", Char: '▓'}, // cyan-400
"copilot": {Label: "Copilot", Color: "#a78bfa", Char: '▓'}, // violet-400
"pi": {Label: "Pi", Color: "#fbbf24", Char: '▓'}, // amber-400
"cursor": {Label: "Cursor", Color: "#38bdf8", Char: '▓'}, // sky-400
"droid": {Label: "Droid", Color: "#f472b6", Char: '▓'}, // pink-400
"kiro": {Label: "Kiro", Color: "#c084fc", Char: '▓'}, // purple-400
"unknown": {Label: "Unknown", Color: palette.Muted, Char: '░'},
activityAgentClaude: {Label: "Claude Code", Color: "#fb923c", Char: '▓'}, // orange-400
activityAgentGemini: {Label: "Gemini", Color: "#60a5fa", Char: '▓'}, // blue-400
activityAgentAmp: {Label: "Amp", Color: "#f87171", Char: '▓'}, // red-400
activityAgentCodex: {Label: "Codex", Color: "#818cf8", Char: '▓'}, // indigo-400
activityAgentOpencode: {Label: "OpenCode", Color: "#22d3ee", Char: '▓'}, // cyan-400
activityAgentCopilot: {Label: "Copilot", Color: "#a78bfa", Char: '▓'}, // violet-400
activityAgentPi: {Label: "Pi", Color: "#fbbf24", Char: '▓'}, // amber-400
activityAgentCursor: {Label: "Cursor", Color: "#38bdf8", Char: '▓'}, // sky-400
activityAgentDroid: {Label: "Droid", Color: "#f472b6", Char: '▓'}, // pink-400
activityAgentKiro: {Label: "Kiro", Color: "#c084fc", Char: '▓'}, // purple-400
activityAgentUnknown: {Label: "Unknown", Color: palette.Muted, Char: '░'},
}

var agentOrder = []string{
"claude", "codex", "gemini", "amp", "opencode",
"copilot", "pi", "cursor", "droid", "kiro", "unknown",
activityAgentClaude, activityAgentCodex, activityAgentGemini, activityAgentAmp, activityAgentOpencode,
activityAgentCopilot, activityAgentPi, activityAgentCursor, activityAgentDroid, activityAgentKiro, activityAgentUnknown,
}

// renderActivityHeader renders the stat cards, contribution heatmap, and repo
Expand Down Expand Up @@ -556,7 +556,7 @@ func renderSessionListN(w io.Writer, sty activityStyles, days []sessionDay, maxD

for _, day := range days[:maxDays] {
displayDate := formatCommitDate(day.Date)
sessionWord := "sessions"
sessionWord := nounSessions
if len(day.Sessions) == 1 {
sessionWord = strings.TrimSuffix(sessionWord, "s")
}
Expand Down
Loading
Loading