Skip to content

checkpoint: committed-ref topology seam#1316

Open
computermode wants to merge 5 commits into
mainfrom
update-v1.1-committed-refs
Open

checkpoint: committed-ref topology seam#1316
computermode wants to merge 5 commits into
mainfrom
update-v1.1-committed-refs

Conversation

@computermode
Copy link
Copy Markdown
Contributor

@computermode computermode commented Jun 1, 2026

https://entire.io/gh/entireio/cli/trails/472

Summary

Addresses @pfleidi's review comment on #1311:

I've been wondering if it would make sense to have a general committedRef
or something similar for rollouts swapping around the write order [...]
defaulting to the v1.1 ref rather than the v1 branch.

The committed-metadata ref topology — "the v1 branch is the source of truth
(written and pushed); the v1.1 custom ref is a local-only mirror that reads use
when checkpoints_version: "1.1" is opted in, and that is never pushed"
— was
re-derived inline from settings.MirrorsToV1CustomRef + the paths constants
at five sites. A future rollout phase that swaps the write order (v1.1 ref as
primary) would have meant editing all five in lockstep.

This PR names that topology once and routes every site through it.

The seam

New checkpoint.CommittedRefs value object + resolver:

Field Meaning
Primary source of truth — written first, pushed/fetched
Read ref committed reads resolve against
Mirror advanced to Primary after writes, kept current before reads; empty when there is no mirror (local-only, never pushed)

Invariant (holds in both rollout phases): Read == Mirror when a mirror
exists, else Read == Primary.

Two entry points: ResolveCommittedRefs(ctx) (disk settings) and
ResolveCommittedRefsFromSettings(s) (an injected EntireSettings, the path
attach uses; nil → v1-branch-only).

Sites routed through the resolver:

  • NewCommittedReadStoreResolveCommittedRefs(ctx).Read
  • read-time sync (syncV1CustomRefForReadsyncMirrorForRead(refs)), gating on HasMirror()
  • strategy.mirrorMetadataToV1CustomRef (hook side, log-only)
  • cli.mirrorToV1CustomRef (error-returning), now taking the resolved refs
  • attach / explain call sites

After the change, MirrorsToV1CustomRef and the two metadata-ref paths
constants are referenced for committed-ref topology only inside
committed_refs.go.

Behavior is unchanged

Behavior-identical refactor: today Primary is always the v1 branch and
Read/Mirror are the v1.1 custom ref only when checkpoints_version: "1.1"
is opted in. Existing read-store, mirror, and sync tests pass unmodified
(beyond a renamed internal helper).

The future write-order flip (making the v1.1 ref Primary) becomes a
one-site change in ResolveCommittedRefs. The flip itself and its push/fetch
semantics are explicitly out of scope.

Design doc

docs/superpowers/specs/2026-06-01-committed-ref-topology-seam-design.md
(local-only; that dir is gitignored in this repo).

Validation

  • mise run check (fmt + lint + unit/integration + Vogon canary) — green
  • New: TestResolveCommittedRefs, TestResolveCommittedRefsFromSettings

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 1, 2026 23:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is described as introducing the v1.1 committed-ref mirror writes and a CommittedRefs topology seam, but the diff also contains substantial unrelated changes: a registrable-domain ("eTLD+1") floor in HostInCluster, removal of cluster→context auto-binding from discovery (a security-relevant behavior change), a new entire auth unbind command + cluster-binding listing in entire auth contexts, and a generated Pi agent extension.

Changes:

  • Introduce checkpoint.CommittedRefs (Primary/Read/Mirror) + ResolveCommittedRefs[FromSettings], route attach, explain, hooks-side mirror, and read-store/sync through it; thread CommittedRefs through mirrorToV1CustomRef.
  • Tighten replica trust: HostInCluster now requires the cluster to extend beyond its public suffix and rejects IP wildcards; clusterdiscovery.ResolveContextForCluster no longer persists a binding after a /.well-known match (re-resolves each call).
  • Add auth.ClusterBindings/UnbindCluster, surface bindings (incl. orphans) in entire auth contexts, and add an entire auth unbind <host> command; add a generated .pi/extensions/entire/index.ts Pi extension.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
cmd/entire/cli/checkpoint/committed_refs.go New CommittedRefs value object + resolvers from disk/injected settings.
cmd/entire/cli/checkpoint/committed_refs_test.go Unit tests for the resolver across checkpoints_version values.
cmd/entire/cli/checkpoint/committed_read_store.go NewCommittedReadStore + SyncCommittedReadRef that advance the local mirror before reads (no v1 fallback).
cmd/entire/cli/checkpoint/committed_read_store_test.go Tests for sync semantics and v1.1 read selection.
cmd/entire/cli/checkpoint/store.go GitStore gains a per-instance committedReadRef + NewGitStoreWithRef constructor.
cmd/entire/cli/checkpoint/committed.go Sessions-tree/author lookups use the configured read ref; v1-only fallback to origin/entire/checkpoints/v1.
cmd/entire/cli/v1_custom_ref_mirror.go Mirror helper now takes a CommittedRefs and writes to refs.Mirror from refs.Primary.
cmd/entire/cli/v1_custom_ref_mirror_test.go Tests updated to pass a v1.1 CommittedRefs.
cmd/entire/cli/strategy/v1_custom_ref_mirror.go Hook-side mirror routed through ResolveCommittedRefs/HasMirror.
cmd/entire/cli/explain.go explain uses NewCommittedReadStore + SyncCommittedReadRef; post-generate reload re-syncs mirror; mirror error wording uses resolved refs.
cmd/entire/cli/explain_test.go New regression test that v1.1 reload re-syncs the custom ref to the v1 write.
cmd/entire/cli/attach.go attach resolves CommittedRefs (honoring injected settings) and gates the mirror on HasMirror.
cmd/entire/cli/paths/paths.go Doc-only update on MetadataRefName describing v1.1 read-after-sync semantics.
cmd/entire/cli/auth.go Registers the new auth unbind subcommand.
cmd/entire/cli/auth_context.go auth contexts now also lists cluster_contexts bindings; adds auth unbind <host>.
cmd/entire/cli/auth_context_test.go Tests for binding listing, orphaned bindings, and unbind idempotency.
cmd/entire/cli/auth/context_store.go New ClusterBindings() and UnbindCluster() helpers.
internal/entireclient/discovery/parse_replicas.go HostInCluster adds a registrable-domain floor and IP-literal rejection via golang.org/x/net/publicsuffix.
internal/entireclient/discovery/parse_replicas_test.go Tests for bare-suffix and IP-cluster cases.
internal/entireclient/clusterdiscovery/resolve.go Discovery no longer persists a cluster→context binding; doc/log updates.
internal/entireclient/clusterdiscovery/resolve_test.go Tests updated: ephemeral resolution, no persisted binding, second call re-discovers.
go.mod Promotes golang.org/x/net from indirect to direct (needed by publicsuffix).
.pi/extensions/entire/index.ts New auto-generated Pi extension forwarding lifecycle hooks to entire hooks pi.
.entire/settings.json Reorders strategy fields (no behavior change).

computermode and others added 3 commits June 1, 2026 16:34
Introduce a single value object that names the committed-metadata ref
topology for the active checkpoints_version, instead of re-deriving it
inline from settings.MirrorsToV1CustomRef plus the paths constants at
every read/write/mirror site.

CommittedRefs has three named refs:
  - Primary: source of truth, written first and pushed/fetched
  - Read:    ref committed reads resolve against
  - Mirror:  advanced to Primary after writes, kept current before reads;
             empty when there is no mirror (local-only, never pushed)

Invariant (holds in both rollout phases): Read == Mirror when a mirror
exists, else Read == Primary.

Two entry points:
  - ResolveCommittedRefs(ctx): resolves from disk settings.
  - ResolveCommittedRefsFromSettings(s): resolves from an already-loaded
    EntireSettings, honoring an injected object (the path attach uses)
    rather than disk. A nil settings object resolves to v1-branch-only.

Today Primary is always the v1 branch; opting into checkpoints_version
"1.1" sets Read and Mirror to the local-only v1.1 custom ref. Behavior
is unchanged — this is the seam that lets a future rollout phase flip
the write order (v1.1 as Primary) by changing the resolver alone instead
of editing every call site.

Addresses @pfleidi's review comment on PR #1311.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f2ebba6141ef
NewCommittedReadStore now binds reads to ResolveCommittedRefs(ctx).Read
rather than re-checking MirrorsToV1CustomRef and naming the v1.1 custom
ref inline. When no mirror is configured this resolves to the v1 branch,
identical to the previous NewGitStore path.

The read-time sync is generalized from syncV1CustomRefForRead to
syncMirrorForRead(refs): it advances refs.Mirror toward refs.Primary's
tip (local primary ref, or origin's on a fresh clone via resolvePrimaryTip)
using the same seed / advance / equal-noop / diverged-leave rules as
before. SyncCommittedReadRef gates on refs.HasMirror() instead of calling
the settings helper directly. Log messages and ref attributes are sourced
from the resolved topology.

resolvePrimaryTip derives the remote-tracking ref from the primary's
short name (guarded by IsBranch), which for today's v1-branch primary is
exactly refs/remotes/origin/entire/checkpoints/v1 as before.

No behavior change: the existing read-store table tests (ref selection,
read equivalence, remote-only metadata, no-v1-fallback, and the
seed/advance/diverge sync rules) pass unmodified beyond the renamed
internal helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 26f8b37ded44
Both committed-write mirrors now consult the CommittedRefs topology for
which ref is primary (source) and which is the mirror (dest), instead of
hardcoding paths.MetadataBranchName / paths.MetadataRefName and the
MirrorsToV1CustomRef gate:

  - strategy.mirrorMetadataToV1CustomRef (hook side, log-only): returns
    early on !refs.HasMirror(), reads refs.Primary's tip, and advances
    refs.Mirror via SafelyAdvanceLocalRef.
  - cli.mirrorToV1CustomRef (error-returning) now takes the resolved
    CommittedRefs and force-sets refs.Mirror to refs.Primary's tip.

Each mirror keeps its distinct error-handling contract; only the ref-name
policy is centralized.

Call sites:
  - attach gains an attachOptions.committedRefs(ctx) helper that mirrors
    the previous injected-vs-disk settings selection (via
    ResolveCommittedRefsFromSettings for an injected EntireSettings, else
    ResolveCommittedRefs), then guards on HasMirror().
  - explain resolves the topology via ResolveCommittedRefs and guards on
    HasMirror().
  - Both error messages now interpolate refs.Primary / refs.Mirror.

After this change, settings.MirrorsToV1CustomRef and the two metadata-ref
paths constants are referenced for committed-ref topology only inside
committed_refs.go; every other site goes through the resolver. Behavior
is unchanged (v1 primary, v1.1 mirror when opted in); the future
write-order flip becomes a one-site change in ResolveCommittedRefs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 5fb1011ba6d6
@computermode computermode force-pushed the update-v1.1-committed-refs branch from ba595e6 to c7fff56 Compare June 1, 2026 23:37
@computermode computermode changed the title v1.1 committed-ref mirror writes + topology seam checkpoint: committed-ref topology seam Jun 1, 2026
computermode and others added 2 commits June 1, 2026 16:41
Condense the doc comments on CommittedRefs and the read/mirror helpers to
their essentials, and collapse the resolver table tests to compare whole
CommittedRefs values rather than asserting field-by-field.

No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: a6c375b7d174
ResolveCommittedRefs and ResolveCommittedRefsFromSettings only consume a
boolean ("opted into v1.1 mirror?") from settings.MirrorsToV1CustomRef.
The string-vs-numeric strictness of that opt-in is the parsing concern
of isV1CustomRefValue, which already has exhaustive dedicated tests in
settings_test.go. Drop the parsing-shape cases (string 1, numeric 1,
numeric 1.1, garbage) from the resolver tests so each table covers
just the two topologies the resolver can produce.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 6a991b41e02c
@computermode computermode marked this pull request as ready for review June 2, 2026 00:16
@computermode computermode requested a review from a team as a code owner June 2, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants