Skip to content

muskan/scratch-fork-trail-check - #13

Closed
MuskanPaliwal wants to merge 822 commits into
mainfrom
muskan/scratch-fork-trail-check
Closed

MuskanPaliwal wants to merge 822 commits into
mainfrom
muskan/scratch-fork-trail-check

Conversation

@MuskanPaliwal

@MuskanPaliwal MuskanPaliwal commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

https://entire.com/gh/muskanpaliwal/-/trails/44/changes/cli/13

This draft pull request was opened by Entire to back the linked trail. Feel free to edit the title or body — the link above is what keeps the trail and PR connected.

khaong and others added 30 commits October 22, 2026 15:23
…d-redaction-counts-per-rule-per-checkpoint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5GY04JGYEMG1NFDEK1SRABP
The shell-stdin step that main added to detectAllLayers had no layer
tag, so its matches were counted as credential_value. It is now the
shell_stdin layer, always on, between custom and credential_value.

Main also added a second rule inside the credential-value step, so one
DB_PASSWORD value was flagged twice at the same span and counted as two
matches. A layer now counts each span it flags once, however many of
its rules match there; the credentialed-URI layer's two rules on one
URL also count once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5GY0WXE8H6CMJ5NWZDBFRRG
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5GT3240VD4JS36380KA2P4R
…s no line

A thinking-only first fragment compacts to empty content and gets no line,
so a call whose later fragments continued it lost its usage entirely. A
fragment now continues a call only when the call's first message is
visible; otherwise it takes over the call's usage state.

The legacy-oracle comparison also covers the claude-code path again,
outside the per-call usage fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5GX56PFSCZZY56YEM5JH6KT
PII redaction covered email, phone and street addresses, so internal
network addresses in transcripts (ssh targets, database hosts, dial
errors) were stored as written.

The new ip category redacts IPv4 and IPv6 addresses as [REDACTED_IP],
on by default when redaction.pii.enabled is true. A dotted quad is
ambiguous in coding transcripts (version numbers, user agents), so a
match is redacted only when it is private/link-local/CGNAT, has network
syntax around it (://, @, :port, /cidr, ->), or a network word nearby.
Loopback, unspecified, 0.0.0.0/8 and broadcast are never redacted, nor
is an address that continues a longer token (v1.2.3.4, u64::from).

Measured on real agent transcripts, about 3% of redactions are false
positives, against 30% for plain shape matching. Byte-scan prefilters
keep the overhead to about 2% on a 1.1 MB transcript.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5GZY2ES7MQ6PPKWM05ZZJ0Q
…w-finding-caps-and-judge-fence

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H0ME1WVKT0JKZ924B31Q5D
The IPv6 candidate regex also took a colon that followed the address
("connect to fe80::1: unreachable"), so validation failed and the
address stayed in the transcript. Drop a single trailing colon and
validate what precedes it; a trailing "::" is part of the address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H0R5NAV59EZCNDW1YM248X
…ack-sessions

# Conflicts:
#	docs/development/checkpoint-implementation.md
…plicitly

Replace the hardcoded agent literal with a package constant, and the
reflect.DeepEqual snapshot comparison with an explicit CallUsage equality
check covered by a field-by-field test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5H1YXHHF2A8PM0R5GD02RE9
…er-call usage

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5GT39W28CXPJTAB81XT4T8C
With usable total_token_usage snapshots, a tool output no longer ends
its call, so interleaved parallel calls and outputs stay one line until
the closing snapshot. A checkpoint slice includes the call still open at
StartLine when the slice adds its outputs or usage. After a counter
decrease the closing snapshot still sets the call's timestamp, and
snapshots missing the input, cached-input or output counter are ignored
instead of read as zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5GXD88QGWECQ91F25NQJDEN
A slice now re-emits the last line before StartLine whenever the slice
adds to it, whether that call is still open or was already closed by
its snapshot, so a tool output that lands just after the boundary stays
in the slice. Earlier lines are still not repeated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Entire-Checkpoint: 01M5GZBQ1NZFTY2CYGDKAM7PS6
The Codex usage tracker now returns the package's CallUsage instead of
a parallel struct with a subset of its fields and the same meaning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnNMsCn1XfR6wwPTAKFmwL
Review found addresses the ip category left visible and one way it broke
a custom rule:

- A custom pattern named "ip" inherited the built-in context checks, so
  the documented full-coverage workaround stopped matching bare
  addresses. The checks now apply to the built-in regexes only.
- Bracketed endpoints ([fd00::5]:8080), an address after a separator
  colon (host:fe80::1), eight-colon compressed forms, and all-letter
  private addresses (fdab::abcd) are redacted; a[1::2] and c::d are not.
- JSONL values are scanned without their key, so {"host":"203.0.113.9"}
  had no context. A key naming an address now counts as context.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H28T7JDMKPK9XJZNMTJKJ9
`entire status` counts the checkpoints not yet on the checkpoint sync
remote, but nothing showed which ones they are or what they contain, so
there was no way to review what a `git push` uploads before it does.

`entire checkpoint list --outgoing` lists the checkpoints the next push
sends, from local state only (no fetch, no ls-remote):

- git-refs: the push queue, split the way pre-push splits it. Refs missing
  locally are counted as stale, not listed. A queued ref that exists but
  names no checkpoint is listed, because the push sends it.
- git-branch: local v1 diffed against its merge base with the elected
  remote's tracking ref. A dedicated checkpoint_remote has no tracking
  ref, so the listing reports complete=false instead of guessing.

Each row shows the ID, age, agent, first prompt (from the stored, already
redacted prompt.txt) or summary, and files touched. "updated" marks a
checkpoint with an earlier version: on git-branch the remote already
holds it, on git-refs the ref was written more than once. The header
names the destination and says when the push sends nothing:
push_sessions=false, a sync misconfiguration, or, on git-branch, a first
push to a remote with no branches. --json prints one object whose
checkpoint_sync_* fields match `entire status --json`.

The integration tests run each case on both backends and compare the
listing with what a real `git push` lands on a bare remote. An ssh trap
proves the command never contacts a remote.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H5RWKPH5ZKCKHX26GMWMRP
ID-based salvage (the background sweep and entire doctor) opens the
session's recorded home worktree. When that folder still exists but its
.git file is malformed, or its repository fails to open, the helper
returned an error, so every salvage attempt failed and the session's
work stayed pending.

Treat an unusable home like a removed one: log a Warn and condense from
the caller's repository, which holds the session's state. The checkpoint
already takes its branch from the session's recorded branch, not HEAD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H7PF475TR3WM0TX9JR8AFD
On git-refs, `checkpoint list --outgoing` marked a checkpoint "updated"
when its ref had more than one commit. Agents usually commit mid-turn
and the stop hook then rewrites that checkpoint, so most refs have two
commits before their first push: 2,737 of this repository's 3,401
checkpoint refs do. The marker flagged checkpoints that were never
pushed.

Nothing local records what a git-refs push delivered, so the marker is
now unknown there: `updated` is null in --json and the text view marks
nothing. git-branch keeps its marker, which it reads from the tracking
ref.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5H8H7HC7X0QB3DP3BH9QXKP
Every successful `entire enable` now names where checkpoints will be
uploaded and follows it with a short notice: checkpoints contain the
agent transcripts, a public destination makes them readable by anyone,
secret redaction is best effort, and how to stop uploads or move them
to a separate private repo. The output is the same with or without a
terminal and adds no prompt. A destination that cannot be resolved or
confirmed keeps its existing report.

Update the README, the security and privacy guide, and the checkpoint
architecture doc to match.

Entire-Checkpoint: 01M5H8HN1ZF4JWQ9JBGDVWJFNG
factoryai-droid: count tokens from the session's settings file
…bility-from-version

Derive experimental visibility from the build version
A checkpoint_push_remote naming a missing remote stops ordinary
checkpoint sync, but pushes still upload to a dedicated
checkpoint_remote. Enable reported that state without the privacy
notice, so print the notice after it as well.

Entire-Checkpoint: 01M5HBQ802CMRDYZKGBD6Z93J3
…ists them

`entire status` said "N checkpoints not yet on origin", but on git-branch
it counted v1 commits ahead of the tracking ref, and one checkpoint
usually has several commits (the commit-time write, the stop-hook
rewrite, summary backfills). On this repository's v1 history, 20 commits
ahead were 14 checkpoints. On git-refs it counted queue entries for refs
deleted locally, which the push drops instead of sending.

CountUnpushedCheckpoints now counts what ListOutgoingCheckpoints lists,
so `status`, the gated-push hint and `checkpoint list --outgoing` give
the same number. The commit-counting code and its helper's test are
removed. The status counter line now ends with
"see 'entire checkpoint list --outgoing'".

Cost: on a queue of 3,401 freshly written refs, `entire status` goes
from 0.48s to 0.85s, because each queued ref is checked locally the way
the push checks it. A typical queue of a few refs shows no measurable
change. On 12,918 v1 commits the git-branch count took 74ms instead of
140ms with 20 commits ahead, and 122ms instead of 70ms with no tracking
ref.

Tests that built v1 from plain commits now write real checkpoint
folders (testutil.CommitV1Checkpoints). The outgoing integration tests
assert that `status --json` agrees on both backends, and the reftable
and SHA-256 tests now cover the listing and the count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5HCA8Z8W7KSGMGQ9EYJWPRM
`entire configure` writes .entire/settings.json when it exists. A
checkpoint_remote there is ignored when its owner differs from
origin's, and a push_sessions there loses to settings.local.json, so
following the notice could leave uploads going to the public remote.
Suggest --local for both commands, in the notice and the docs.

Entire-Checkpoint: 01M5HDZRHA00SHDZ2D88BTJ0PV
…osen

When the user chose a destination, the fan-out, dedicated-store and
alternative-remote details printed after the privacy notice. Print
them before the destination line, so every run ends with the
destination and the notice that refers back to it.

Entire-Checkpoint: 01M5HFRHGC08Y4P9W9241YDZAG
Claude Code writes the result of each parallel tool call in its own user
entry, sometimes after the next assistant message has begun. The JSONL
adapter took results only from the user entry right after the assistant,
so later results were dropped from every stored checkpoint. It now
attaches each result by tool_use_id to the message holding that tool_use,
until the next prompt; a result without an ID still targets the last
assistant message. On 259 local Claude transcripts, tool calls with a
result go from 8831 to 9372 of 9372.

Tool results also gain agent.id, the launched subagent's own session or
thread ID: Claude toolUseResult.agentId (Agent, forked Skill), Codex
SubAgentActivity agent_thread_id, OpenCode task state.metadata.sessionId,
and Copilot subagent.started agentId. All 65 local Claude Agent calls now
carry one (none had a result-borne ID before, and only 34 had a result).

Records fed line by line still fold to Convert's output byte for byte.
The legacy oracle models the new attachment rule as a marked divergence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5HKP2NQQQKXPJH4J068BZQ1
…-redaction-counts-per-rule-per-checkpoint

feat(checkpoint): record redaction counts per checkpoint
OpenCode's task tool stores the subagent's session in
state.metadata.sessionId, but the converter read that field from every
tool call, so another tool's sessionId would have named a wrong agent.

Also state that injected (isMeta) user text ends the window for
attaching tool results, and pin it with a test. Claude Code never writes
such text while a result is outstanding in local transcripts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5HPPXT8MR580RP9THT45QNZ
toothbrush and others added 28 commits October 28, 2026 15:10
test(repo): hold the mirror read until the client cancels
os.UserHomeDir reads only $HOME. Under `sudo -E`, root then reads and
writes the invoking user's ~/.config/entire, leaving root-owned 0600
files that break the user's own CLI. With no $HOME at all (cron,
systemd units), tokens land in a cwd-relative fallback.

Root, and any process without $HOME, now uses the passwd entry.
Everyone else keeps $HOME, so HOME-based isolation still works.
ENTIRE_CONFIG_DIR still overrides both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ENTIRE_TOKEN_STORE=file has to reach every process that reads a
token. For root that includes `sudo` (which resets the environment),
systemd units and cron jobs, so no single place can set it.

"token_store": "file" in the per-user config.json now does the same.
Root gets it once in /root/.config/entire, like /root/.ssh. A set
ENTIRE_TOKEN_STORE still wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both login flows request offline_access (auth/client.go), and a
--device login writes a :refresh entry to the token store. The
comment on LoginTokenForContext said otherwise; what is true is
that this read itself never refreshes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A malformed config.json, an unreadable one, or an unknown
token_store value is now an error that names the file, instead of a
silent fall back to the keyring that surfaced as a keyring timeout.
It is checked before ENTIRE_TOKEN_STORE, so a set variable cannot
hide a broken file. Every token read and write fails with it, and
login's headless hint stays out of the way.

A set ENTIRE_TOKEN_STORE, even an empty one, still decides the
backend over config.json. `entire auth status` now says when
config.json chose the file store.

Validating config.json when no token is read (no saved login, or
ENTIRE_TOKEN set) is left for a separate change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
resolveStatusTarget skipped every token-read error except an
unreachable keyring, so a malformed config.json showed up as
"Not logged in". Treat ErrBadConfig the same way: the error names
the file.

Also drop the config.json provenance on the token row; review
agreed it isn't needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Export userdirs.Home and use it for the managed plugin directory, so
root's plugins live under the same home as its config and cache.

Agent lookups (transcripts, hooks, skills) and the shell rc path keep
os.UserHomeDir on purpose: those files are written by the agent or
shell, which read $HOME, so under `sudo -E` they land in the caller's
home and Entire must look there. Home's doc comment states the rule
and why root ignores $HOME; agent.ResolveHome points to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A relative ENTIRE_CONFIG_DIR made every token call fail as a bad
config.json, which broke keyring users and an explicit
ENTIRE_TOKEN_STORE_PATH. Skip config.json then; the store and
contexts already report the bad override.

Also: a fileBackend const for goconst, tests for a missing config
dir, auth status and the login hint on a bad config.json, and
comments brought in line with the code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
classifySearchError put ErrKeyringUnavailable in the auth class but
not ErrBadConfig, though both leave the saved login unreadable.

Also drop a redundant comment in pluginParentDir: the doc above
already names userdirs.Home.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TestDialLatencies closed a listener and dialed its port, expecting a
refusal. A parallel test could bind the freed port first, so the dial
connected and the "dead" host showed up with a real rtt.

Port 0 never has a listener: Linux refuses the connect and macOS fails
with EADDRNOTAVAIL, both at once and neither a deadline, so the host
stays absent on every run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M60HY4K74XE4WPSWV02N2NR7
…tore

fix: let root use a token file and its own home, like ssh
Line anchors outside the change or over 50 lines post at file granularity, and snippets are always read from the worktree, never taken from the model.

Entire-Checkpoint: 01M60SF9961W20BXNW881S2DCN
…restarting them

User-initiated commands (explain, resume, enable, checkpoint delete) fetch
the whole checkpoint archive from the checkpoint remote under a fixed
2-minute deadline. An archive that takes longer is killed at the deadline,
git discards the partial pack, the ref never lands, and the next command
restarts the same fetch from zero, so it never completes. On entireio/cli
(a 5.1 GB archive) every explain took 120s and returned nothing.

Foreground fetches now have no fixed deadline. They pass --progress and
set git's HTTP low-speed abort (under 1 byte/s for 60s), so a fetch that
is still transferring finishes and a stalled one fails within about a
minute. A user's own GIT_HTTP_LOW_SPEED_* settings take precedence. The
push hot path keeps its 30s budget.

Concurrent foreground fetches in one repository wait on a lock in the git
common dir, so parallel commands transfer the archive once. The lock is
held through promotion of the shared tmp ref, because one caller's cleanup
could otherwise delete it under the next caller's fetch. It is
best-effort: if it cannot be taken, the fetch runs unserialized.

Fetch error details keep only the final text of each progress line.

Fixes entireio#2902

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5YVZSTJEDV9T71AWV4RTZCZ
…ives

Foreground checkpoint fetches have no fixed deadline and rely on git's
HTTP low-speed abort to fail a stalled transfer. That abort does not
cover SSH, so a stalled or half-open SSH connection hung explain,
resume, enable, and checkpoint delete indefinitely, and every later
foreground command in the repository queued behind it on the fetch lock.

These fetches now also pass -o ServerAliveInterval=15
-o ServerAliveCountMax=4 to ssh, which drops a connection whose server
stops answering for about a minute. Keepalives fire only when no data
arrives, so a working transfer is unaffected. The options are added
only for OpenSSH, since clients such as plink reject -o, and not when
the ssh command already sets either one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M5YXC3SHGMR6D1C3NC3A0QEY
…transports

Kill fetches silent for 5m on any transport, make the fetch-lock wait cancellable and capped, quote GIT_SSH paths, and give the push path its own tmp ref.

Entire-Checkpoint: 01M5Z3BSQ0ZDRJWT9CH061SW38
…he stall window

ENTIRE_CHECKPOINT_FETCH_TIMEOUT overrides the budget; lock waiters give up instead of fetching unserialized.

Entire-Checkpoint: 01M60R4M0KZ2T6CH18KD6NA5F0
…e session directory

OpenCode 1 finds .opencode by searching up from the directory it was
started in, so started in a subdirectory it loads both plugin copies while
`${directory}/.opencode/plugins` does not exist, and every hook fired twice.
The stand-down now looks for the old copy relative to the plugin's own file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M60W8F1971BCS597ZEN3CFSP
Deleted paths could still be quoted from ignored local files, and files a reviewer wrote mid-run were in scope. Out-of-scope anchors now post against the whole change.

Entire-Checkpoint: 01M610FX0CVRFF6VZ0TBMAY8A8
…ot fetch

A failed lock wait no longer fails enable, the heal re-checks for data once it holds the lock, and the stall-window comment states when git is silent.

Entire-Checkpoint: 01M610PQR7SVKQYW87H02DQ2J0
Count tokens of subagents launched by subagents (Claude Code)
Entire-Checkpoint: 01M615PF6RC4C8VH0Y3R84N2PR
Subtract uncommitted deletions and rename origins from the trail scope, skip skip-worktree and assume-unchanged files, and quote only files unchanged since the review started; findings on other tracked files post against their file.

Entire-Checkpoint: 01M6168XN29JEJYK7P7YEH1W9E
A waiter on the fetch lock always fetched again, even when the holder had
just stalled, so concurrent commands against a stalled remote each paid
the full stall window in turn, and so did every new process.

After a foreground fetch stalls or exhausts its budget, record it next to
the fetch lock. For two minutes, foreground fetches of the same ref from
the same remote fail fast without contacting it. Fast failures are not
recorded, so a retry after fixing credentials still runs, and a success
clears the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M617EB6QN3075PBBF0CW932W
…-finding-location-trust

Limit review finding snippets to files in the reviewed change
…checkpoint-explain-sidecar-fetch-timeout-repeats-work

fix(checkpoint): let foreground checkpoint fetches finish instead of restarting them
@MuskanPaliwal
MuskanPaliwal deleted the muskan/scratch-fork-trail-check branch October 29, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants