This reference covers the public pointbreak command surface provided by the pointbreak crate.
Raw shore.* strings shown in schema examples are frozen persisted protocol identifiers, not a
current command, environment family, or storage namespace.
Command output JSON is the machine-integration surface, under a tiered stability promise. A
narrow hard core is frozen within each document's version:
- the envelope discriminators (
schema,version) on every document; - the field-paths a non-human consumer actually reads —
pointbreak capture'schangeId,revision.{revisionId,objectArtifactContentHash}, andreviewCursor.token,pointbreak input-request list'sinputRequests[].{id,title,mode,reasonCode,trackId}, andpointbreak input-request respond'sinputRequestResponseIdandeventId; - the wire-value vocabularies — the assessment values, the input-request response outcomes, and the
input-request
mode(operative/advisory) andreasonCodevalue sets that ride the consumedinput-request listfield-paths (see theassessmentandinput-requestsections). These vocabularies grow additively within aversion: a new value may be appended (a soft-shell consumer selects the values it knows and tolerates the rest), but removing or renaming an existing value is a coordinated break (ADR-0029, Decision 7 amendment 2026-07-09).
Removing or renaming a hard-core field-path or value is a coordinated break: bump that document's
version and migrate consumers. Everything else in the documents is soft shell — stable but additive-evolvable within
a version: fields may be added, consumers must select by field name and tolerate unknown fields,
and removing, renaming, or reshaping an existing field bumps the version. One documented exception
is a command with multiple authority lanes: it may expose mutually exclusive soft-shell identity
fields within one version when the command documents every alternative and the selected identity is
unambiguous by field presence. Consumers of such a command must accept the documented identity
union rather than requiring one lane's field. eventSetHash (authoritative journal reads) and
projectionStamp (derived reads) are that pair on the history, attention, bounded revision-list, and
review summary documents. Raw event files,
artifact paths, and event filenames are internal storage details unless a
command explicitly returns them.
Document-emitting commands accept --format <fmt>, where <fmt> is json, json-pretty, or
text. Compact json is the default and the machine contract; json-pretty is the same document
indented for manual inspection; text is a disposable human rendering that scripts should not parse.
Capture, association writes (including association land), observation/assessment/validation adds,
input-request open/respond, endorsement, fact port, artifact removal, and store link/migrate results
include an acknowledgement. The Rust ingest result uses the same type. Existing store-profile,
proof, and command-admission checks still apply.
A successful write confirms its durable authoritative outcomes. It does not promise that derived views are current. The four independent fields describe only this invocation:
| Field | Meaning |
|---|---|
authorityOutcome |
created when all attempted authoritative components were new; existing when all were already present; mixed when both occurred; unchanged when none were attempted. Existing IDs, booleans, and counts remain the detailed result. |
derived.availability |
off when the event writer had no derived coordinator; current when that write's catch-up succeeded; catching_up when its truth is durable but catch-up was deferred; unavailable when no usable derived observation could be returned; not_observed when no event write occurred. |
legacyProjectionState |
Always not_attempted. The legacy state.json projection is retired; no write creates, refreshes or reads it. refreshed and refresh_failed remain decodable for receipts produced by earlier versions. |
operationReceipt |
{ "state": "not_recorded" } unless the invocation created or reused an existing durable operation binding. A response is not itself a durable operation receipt. |
current and catching_up include derived.token with generationId, epoch, and headSequence;
the other states omit it. This is a coordinate obtained from the event write, not a promise about a
later read. Compare head sequences only within the same generation and epoch. A composite result
retains the highest compatible head sequence; incompatible generations or epochs yield unavailable
and a diagnostic. For multiple writes, unavailable dominates catching-up, then current, then off.
An empty import/fold reports unchanged authority, not-observed derived state, and no recorded
operation receipt.
Change capture names its existing durable recovery binding using operationReceipt.receiptId, equal
to its operationId: state recorded means this invocation created that binding, and existing
means it reused it. Reuse does not imply the requested Change operation had already completed;
complete remains the completion detail. Other acknowledgement-bearing surfaces report
not_recorded and omit receiptId. These fields create no new durable carrier and authorize no
later action.
Call-specific diagnostics appear once in the existing top-level diagnostics array, never inside
acknowledgement. Multi-event derived diagnostics retain the first occurrence of each code. Store
link/migrate append their existing warnings after workflow diagnostics.
Write results report diagnostics about this invocation only (derived write state, skipped
auto-record, ingest warnings). A write does not replay the event history after recording, so it
does not report duplicates that already existed in the store. Store-wide hygiene diagnostics such as
duplicate_semantic_* are reported by read commands (history, observation list,
input-request list, validation list, assessment show) and the Inspector.
A writer reports derived-generation admission failure on its first attempted publication,
not when its handle is constructed. For example, writing without a usable derived generation
can succeed durably with derived.availability: unavailable and the top-level diagnostic
derived_access_generation_unavailable.
These are additive v1 JSON fields: consumers must tolerate unknown fields. Strict decoders may need updating, and Rust callers constructing public result structs must supply the new fields. Existing text without diagnostics is unchanged. Text renderers that already consume result diagnostics may add advisory lines for derived catch-up or unavailability; land, fact port, link, and migrate keep their existing message/body text. The process-global stderr advisory channel remains unchanged, so a call-specific derived diagnostic can appear in both result text and stderr. Cross-channel suppression is not part of this contract.
Most commands accept optional tracing flags:
--log <filter>
--log-format <compact|pretty|json>
--log-file <path>Tracing writes to stderr by default. When stdout is piped into JSON tools, prefer
--log-file <path> so trace lines do not corrupt the JSON stream.
When --log-file <path> points inside the repository, Pointbreak treats that path as command-helper
plumbing for the current command and excludes it from the reviewed snapshot and fingerprint.
pointbreak version [--format <fmt>]pointbreak version emits the pointbreak.version version 1 compatibility document. Its hard core is
cliVersion, the semantic version of the running CLI; build, the build provenance described below; and
documents, the frozen legacy schema-to-version compatibility map. Change-capable readers negotiate their
larger coherent document set through pointbreak change profile or /api/v2/profile; those documents are
deliberately not added to this legacy map. Inspector API payloads are versioned separately. Clients use the
handshake that owns their reader cohort before decoding other command output.
build.source is git when the crate's manifest root contains checkout metadata (including a linked
worktree .git file). In that mode, build.commit is the full lowercase commit ID,
build.describe is the result of git describe --tags --always --dirty, and build.dirty reports tracked
index or worktree changes at build time. Invalid or partial manifest-root Git metadata fails the build.
When a source package has no manifest-root .git, build.source is package, build.commit is null,
build.describe is package:<cliVersion>, and build.dirty is false. A package directory nested beneath
some other checkout does not inherit that parent's Git identity.
JSON is authoritative for the full identity. A clean exact-tag binary has the exact tag in
build.describe, its peeled full commit in build.commit, and build.dirty=false; semantic version alone
does not establish release identity. Human pointbreak --version and pointbreak version --format text
output append the concise build description in parentheses. Event producer versions remain semantic
cliVersion; build provenance does not enter stored or signed event identity.
The documents map is sorted by schema. New entries are additive soft-shell growth, so consumers
must select the schemas they require and tolerate additional entries. --format text prints a short
human digest; compact JSON remains the default machine contract. The separate pointbreak --version flag
prints the same semantic version and concise build description.
Every write records a writer actorId. By default it derives from the local Git identity
(actor:git-email:<email>, then actor:git-name:<name>, then actor:local). Set
POINTBREAK_ACTOR_ID to write under an explicit identity — agents use actor:agent:<agent-name>:
export POINTBREAK_ACTOR_ID="actor:agent:claude-code"POINTBREAK_ACTOR_ID outranks the Git identity on every CLI write path, including paths without a
per-call override; a malformed value is ignored and falls through rather than corrupting
provenance.
Review read commands (history, the observation / input-request / assessment / validation
list and show commands, revision show, and the inspector) discover a checked-in delegation map at
<repo>/.pointbreak/delegates.json and resolve the human principal an agent wrote on behalf of,
rendering it beside the writer as claude-code (for kevin@swiber.dev). Discovery is presence-based
— absent file, no change. A malformed .pointbreak/delegates.json prints a single warning to stderr and
the read proceeds with no resolution (advisory, never blocking). The file format is documented in
storage-model.md.
The command group also previews the resolved writer and owns the write side of this config —
creating a delegation record or describing an actor's kind/roles. See pointbreak identity whoami,
delegate, and attest below.
Every write may carry an Ed25519 signature. Which key signs (if any) follows this precedence:
--sign-key <name|path>on the write subcommand (a keystore key name or a path to a key file)POINTBREAK_SIGNING_KEY(same shape: a key name or a path)- agent-context auto-keygen — under an
actor:agent:*id, a passphrase-less per-machine key is generated on first write (see agent-authoring.md) - the user-default keystore key named
default - none — the write proceeds unsigned
POINTBREAK_SIGNING=off (case-insensitive) disables signing entirely; POINTBREAK_SIGNING=auto (the default)
resolves a signer where possible. POINTBREAK_HOME overrides the user-level key home (mainly for
tests/CI). Signing never gates a write (with one exception, below): any resolution failure (no key,
an unreadable key home, an unsupported algorithm, a malformed configured key, POINTBREAK_SIGNING=off)
degrades to an unsigned write at exit 0 with a one-line advisory diagnostic on stderr — it never blocks.
The sole exception is pointbreak endorse (below), where unsigned is a hard error because the
signature is the endorsement's content. See
signing-ux.md for the human / agent / CI flows and the
unsigned → untrusted_key → valid ladder.
Every recorded fact — an observation, an assessment, a validation check, an input request, a
commit or ref association — is scoped to a review lane: a caller-chosen free-text label
naming who or what is doing the reviewing, such as agent:codex or a human reviewer's own
identity. There is no fixed vocabulary or required shape; the label is opaque to Pointbreak and
exists so a revision's facts can be filtered and grouped by who recorded them.
- On every write command that records a fact (
pointbreak observation add,pointbreak assessment add,pointbreak validation add,pointbreak association record/land/withdraw,pointbreak fact port,pointbreak input-request open),--track <track-id>is required and stamps the lane that owns the new fact. - On read/list commands (
pointbreak observation list,pointbreak input-request list,pointbreak validation list,pointbreak assessment show,pointbreak history,pointbreak revision show),--track <track-id>is optional and narrows the results to one lane; omitted, all lanes are returned.
pointbreak diff [--repo <path>] [--revision <id>] [--stat] [--color <auto|always|never>] [--theme <theme>]pointbreak diff prints a captured revision's diff — base to target, from the frozen captured
snapshot — as a text unified diff on stdout. It is the terminal reader for the immutable diff a
revision recorded; its subject is always the captured snapshot, never the live working tree
(git diff owns the live tree).
--repo <path>defaults to.and may point at the repository root or a subdirectory inside it.--revision <id>selects the captured revision (a head seed): a current head resolves exactly, a superseded revision resolves its thread's current head. Omit it to diff the current capture; it is required when the store holds more than one candidate.--statprints only the diffstat (a per-file summary and totals), not the diff body.--color <auto|always|never>controls ANSI syntax coloring of the diff body.auto(the default) colorizes only when stdout is a TTY, honoringNO_COLORandCLICOLOR_FORCE(precedence:--colorNO_COLOR>CLICOLOR_FORCE> isatty); piped or redirected output stays plain. Color is pure presentation — stripping the ANSI reproduces the plain diff exactly.--theme <theme>picks the themed palette:auto(the default) detects the terminal background — light or dark — and selects the matching built-in palette;light/darkforce a built-in; any other value names a bundled syntax theme, matched case-insensitively (bat's vocabulary, e.g."Monokai Extended","onehalflight","nord"). Environment fallbacks:POINTBREAK_THEME, then bat'sBAT_THEME(precedence:--theme>POINTBREAK_THEME>BAT_THEME> detection > dark). An unknown name from--theme/POINTBREAK_THEMEis an error listing the valid vocabulary; an unknown inheritedBAT_THEMEwarns on stderr and falls back. The terminal is queried only when colors are on, stdout is a direct truecolor or 256-color TTY, and the preference isauto— piped output never probes and stays deterministic. Themes apply on truecolor terminals (COLORTERM=truecoloror24bit) and, downsampled to the nearest xterm-256 color, on 256-color terminals (TERM=*-256color, whenCOLORTERMdoes not advertise truecolor). Palette-index themes such asansiandbase16keep their terminal palette indices on both lanes. Otherwise the 16-color palette follows the terminal's own theme. Intraline (changed sub-word) emphasis renders as an add/del background tint on truecolor and 256-color terminals (hand-picked 256-color tints per light and dark mode, as delta uses) and as an underline on 16-color terminals.pointbreak diffis a filter, not a pager: it writes plain git-diff to any pipe or redirect and colorizes only when writing directly to a terminal, so it composes with the tools you already use —pointbreak diff | less -Rto page,pointbreak diff | delta(or another diff renderer) to reformat,pointbreak diff > change.diffto save. There is no built-in pager and no--no-pagerflag; use--color alwaysto force color through a pipe (e.g.pointbreak diff --color always | less -R). A reader that closes the pipe early (pointbreak diff | head) is a clean exit.- The command is text-only and non-interactive: it has no
--formatselector and emits no JSON (machine consumers read the review documents, e.g.pointbreak revision show --format json). Its output is disposable — wording, layout, and ordering may change between releases, so nothing should parse it. - File headers carry the captured mode for
/dev/null-sided changes: an added file with a recorded mode gets anew file mode <mode>line and a deleted file adeleted file mode <mode>line, next to the existingold mode/new modepair for mode changes. This lets a savedchange.diffread as a genuine add/delete instead of a/dev/nullrepository path, so ordinary textual changes replay withgit apply. It is a fidelity improvement, not a guaranteed patch-export format: binary payloads, missing-final-newline markers, unusual path quoting, submodules, and object-ID index lines are out of scope, so treatpointbreak diffas human-oriented captured-diff readback. - When a revision's captured content has been removed from the store,
pointbreak diffprints a short "content is unavailable" line (with the removed content's short id) instead of a diff body.
pointbreak change profile [--repo <path>] [--format <fmt>]
pointbreak change list [--order activity_desc|change_id_asc] [--repo <path>] [--format <fmt>]
pointbreak change attention [--order attention_wait|activity_desc|change_id_asc]
[--repo <path>] [--format <fmt>]
pointbreak change show <change-id> [--repo <path>] [--format <fmt>]
pointbreak change select <change-id> [--revision <revision-id>] [--allow-historical]
[--cursor <token>] [--source captured|worktree|commit:<rev>]
[--repo <path>] [--format <fmt>]
pointbreak change revision <change-id> <revision-id> --artifact-hash <sha256>
[--include-body] [--repo <path>] [--format <fmt>]
pointbreak change resource <change-id> <revision-id> --artifact-hash <sha256>
[--include-body] [--repo <path>] [--format <fmt>]
pointbreak change interdiff <change-id> <from-revision-id> <to-revision-id>
--from-artifact-hash <sha256> --to-artifact-hash <sha256>
[--repo <path>] [--format <fmt>]
pointbreak change create --operation-id <id>
(--nonce <64-hex> | --root-revision <revision-id>) [--repo <path>] [--sign-key <name|path>]
pointbreak change join <change-id> <revision-id> --operation-id <id>
[--repo <path>] [--sign-key <name|path>]
pointbreak change withdraw-membership <claim-id> --operation-id <id>
[--repo <path>] [--sign-key <name|path>]
pointbreak change assert-relation <change-id> <successor-id> <predecessor-id>
--successor-artifact-hash <sha256> --predecessor-artifact-hash <sha256>
--operation-id <id> [--repo <path>] [--sign-key <name|path>]
pointbreak change withdraw-relation <claim-id> --operation-id <id>
[--repo <path>] [--sign-key <name|path>]
pointbreak change link <first-change-id> <second-change-id>
--relation same-work|related-work --operation-id <id>
[--repo <path>] [--sign-key <name|path>]
pointbreak change capture --operation-id <id>
(--initial-nonce <64-hex> | --cursor <token> --advance replace|parallel)
[--predecessor <revision-id> --predecessor-artifact-hash <sha256>]...
[--sign-key <name|path>] [capture options]
pointbreak change migrate-dry-run [--root <path>]... [--owner-decisions <file>]
[--repo <path>] [--format <fmt>]
pointbreak change migrate --dry-run <file> --ack-manifest <sha256>
--ack-cohort-manifest <sha256> --ack-minimum-reader review_change_revision_v1
--ack-v0-9-unsupported --backup <external-dir> --operation-id <id>
[--owner-decisions <file>] [--repo <path>] [--sign-key <name|path>] [--format <fmt>]
pointbreak change migrate-restore --backup <external-dir> --target-repo <path>
[--format <fmt>]change list and change attention emit their Changes in one server-owned presentation order and
name it in the document's order member. change list defaults to activity_desc (newest
contributing event first, ties on Change id ascending); change attention defaults to
attention_wait (primary attention tier first, then the longest-waiting unresolved item, ties on
Change id). change_id_asc remains available on both, and attention_wait is accepted only on
change attention. The Inspector Changes and Attention pages use the same values and defaults, so
the two front ends never present a different order for the same store. Each summary carries its
activityAt instant and, when the Change has an anchored attention item, its attentionWaitAt key.
change attention lists Changes by lifecycle, not by item. It does not show advisory asks, or failed
checks on a Change that is already accepted; those are items in pointbreak attention list. Read both
to answer "what is outstanding?".
The Change reader begins with a complete capability profile. An untouched legacy root reports
migration_required; a root with an admitted but incomplete transition reports migration_in_progress.
In either state, semantic Change commands emit only the matching typed status document. A ready root names
the durable minimum reader profile review_change_revision_v1 and advertises the exact document registry
that must be accepted as one cohort before any Change payload is decoded.
The profile is a durable reader-capability contract, not a label unique to this migration. It records the
minimum reader and coherent registry a root actually requires, so a later breaking cohort can require a
successor profile without pretending an older client understands it. Relative to that required target cohort,
migration_required, migration_in_progress, and ready describe root authority;
reader_upgrade_required describes the separate case where a ready root requires a profile the requesting
reader does not support. A partial,
conflicting, or otherwise ambiguous authority record remains unavailable rather than being promoted to
ready. The current bulk-adoption commands are one temporary procedure for the first cohort, not an
implicit general-purpose migration path.
list, attention, and show render the authoritative Change projection. A Change may have multiple
legitimate current Revisions; select therefore requires --revision when there is no unique current
candidate and returns a self-hashed cursor rather than writing state. Supplying a previous --cursor
revalidates the graph before returning a new selection. revision and resource require the exact
Revision id plus its captured object-artifact hash; no current or successor Revision is substituted.
Association comparisons and Revision interdiffs have their own typed identities and availability. The
first reader cohort reports native Revision interdiff material as unavailable instead of substituting a
live Git diff.
The write commands are available only when the store profile is ready; an untouched legacy root fails
with migration_required, and an admitted but incomplete transition fails with
migration_in_progress, before proposal or retry state is written. Every Change mutation takes a stable
--operation-id. Retrying the same operation with the same inputs is idempotent; reusing the id with
different inputs is refused. create, join, and the membership/relation/link commands expose the
low-level append-only claim vocabulary. change capture is the higher-level workflow for initial,
replacement, parallel, and multi-predecessor consolidation captures. Its --summary <text> is the
label shown on Inspector Change cards; when it is omitted, the command prints the same one-line stderr
notice as pointbreak capture and the receipt carries revision.summary: null. Every Change mutation participates
in the same optional signing-key resolution as the review-writing commands.
migrate-dry-run is read-only. It inventories one or more legacy roots, reports anomalies and retained
manifest overlaps, and accepts an explicit owner-decision manifest for deterministic replanning. It does
not activate a store. migrate is the only activation route. It accepts the exact approved dry-run and
both of its acknowledged hashes, requires the new minimum-reader and v0.9 incompatibility acknowledgements,
and creates a byte-verified L0 backup plus a fully signed resume plan in the supplied external directory
before publishing activation. The same command and operation id resume an interrupted M1 transition without
re-signing or recomputing the legacy graph. Completion is appended last; ordinary Change reads and writes
remain unavailable until that L2 record verifies. A repeated completed invocation returns existing.
migrate-restore verifies that retained backup again and copies it only into an empty store with a
different placement identity. The result is a separate L0 recovery fork that requires its own fresh dry
run; it never rolls an M1/L2 store backward in place.
The signed v0.9 reader remains compatible only with untouched legacy roots. It is not a reader for a root once the Change/Revision capability transition begins or completes.
pointbreak inspect [--repo <path>] [--host <loopback-ip>] [--port <n>] [--open] \
[--api-only] [--format <text|json>]pointbreak inspect starts a small local web server that visualizes the worktree's resolved store for
tracing event timelines and outcomes — the kind of inspection that is awkward against the raw JSON
files or per-command output.
--repo <path>defaults to.and may point at the repository root or a subdirectory inside it.--host <loopback-ip>defaults to127.0.0.1. Non-loopback binds are rejected before the server attempts to listen.--port <n>defaults to7878; use--port 0to bind an ephemeral port, which is then printed.--api-onlyomits the static browser shell and assets.--openlaunches the browser shell and is rejected only with--api-only.--format text|jsoncontrols startup output independently of the served surface. Text output is the default: the browser surface prints a fragment capability URL, while--api-onlyprints labeled endpoint and token fields. JSON output is exactly one compactpointbreak.inspect-startupv1 line with the actual loopback host/port and process-local bearer.- Every process generates a distinct bearer. All requests require the exact advertised
Host, and every/api/*request also requires exactly oneAuthorization: Bearer <token>before routing, store, projection, or cache work. Authentication failures return an empty401. The fixed static shell and assets need no bearer and never touch the store; they are the recovery surface when a browser lacks or loses its credential. - The browser moves the fragment token into origin-scoped
sessionStorageand scrubs it before routing. Its connection chrome distinguishes authentication failure, an unreachable server, and an authenticated protocol/data error, with route-preserving Reconnect and Retry actions. The bearer must not be logged, placed in a request target or referrer, or persisted outside the documented startup/session credential carriers. - The server runs until interrupted with Ctrl-C.
The bundled page negotiates /api/v2/profile before any semantic fetch or paint. On a ready root its
default Timeline renders the typed event stream with free-text, event-type, track, Change, and exact
Revision filters; oldest/newest ordering; signed previous/next pages; event details; keyboard navigation;
and explicit follow/park behavior for incoming events. The server owns the filtered chronology and
Change-aware attribution. The browser keeps only a bounded page-local window in the DOM and never infers
one Change or Revision when an event has multiple contexts.
Follow and park are Timeline actions. While an event detail is open, the Timeline follow control stays
visible and reports the retained monitor state (Following, Parked, or Show N new), but it is not operable:
the toggle is aria-disabled there and acts only on the Timeline route. The detail pane reads the loaded
history page and never a parked window, so the monitor observes incoming events only on the Timeline
itself; the count shown with a detail open is the one from the last Timeline observation, not a live
count. Keeping park and resume on the Timeline keeps follow semantics defined in one place instead of
adding an interaction between the monitor and exact-event reading. Return to the Timeline to park or
resume.
The Changes and Attention lenses render Change cards, explicit current-Revision choices, relation-claim provenance, exact captured resources, fact origin/currency, association comparisons, and separately identified Revision interdiffs. Parallel current Revisions remain distinct from a divergent replacement graph; choosing a Revision never turns either topology into acceptance. Validation evidence and reader-relative signature status remain advisory presentation, never a gate or verdict. On a legacy or in-progress root the page renders only the typed migration state.
The inspector is a read-only, single-store, localhost developer tool. It reads through the same
validated projections as pointbreak history and pointbreak revision show rather than parsing raw
storage, and it serves over a synchronous, dependency-free HTTP server with no async runtime. The
Most of the small JSON API remains an internal surface for the bundled page. The Change cohort begins at
/api/v2/profile; /api/v2/changes, /api/v2/attention, and exact Change/Revision member routes are
accepted only against that profile's complete registry and coherent projection stamp. Once a root is ready,
legacy aggregate routes return a typed 426 Upgrade Required before any partial legacy payload. On legacy
roots those aggregate routes remain readable by the signed v0.9 binary; the capable bundled page does not
fall back to them and paints only migration_required. Store activation is a separate explicit operator
transition. Once a transition enters the in-progress state, legacy
aggregate routes return a typed 409 Conflict migration document.
Both surfaces decide legacy admission from one table. The difference between them is intentional: the ordinary command fence keeps every non-Change command away from a pre-migration store, while the Inspector keeps migration-era readers working on untouched legacy roots.
| Store state | Ordinary CLI commands (history, revision list, attention list, review writers) |
Inspector legacy aggregate routes (/api/history, /api/revisions, /api/threads, /api/attention, /api/freshness, member reads) |
|---|---|---|
| Untouched legacy root (no activation record) | refused with migration_required |
served, for the signed v0.9 reader |
| Activation root present, migration still required | refused with migration_required |
409 Conflict, pointbreak.store-migration-required |
| Migration in progress | refused with migration_in_progress |
409 Conflict, pointbreak.store-migration-in-progress |
| Ready Change-aware root | served | 426 Upgrade Required, reader_upgrade_required |
The change family, the store placement commands, key, identity, inspect and version answer their
own typed capability documents instead of taking this table. While the derived view cannot serve, the
Change-first entry routes (/api/v2/profile, /api/v2/changes, /api/v2/history, /api/v2/attention)
accept the same explicit access=authoritative election the legacy routes accept; the derived-access
section below describes it.
Three v1 bundled-pair documents are compatibility-advertised by pointbreak version:
/api/snapshots/{id} returns pointbreak.review-snapshot, /api/freshness returns
pointbreak.inspect-freshness, and JSON startup emits pointbreak.inspect-startup. /api/version mirrors
the exact pointbreak.version v1 document emitted by pointbreak version. The self-described
pointbreak.inspect-event-history document and the remaining Inspector-private payloads are not promoted
contracts.
The legacy v0.9 Inspector-private /api/revisions collection remains only for migration-era readers
on legacy roots. It is snapshot-bound and paged, but it is not a lens in the current bundled page;
ready Change-aware roots refuse the legacy aggregate cohort as described above. The current Changes
and Attention lenses page /api/v2/changes and /api/v2/attention. They open an exact contextual
member through
/api/v2/changes/{changeId}/revisions/{revisionId}?artifactHash={objectArtifactContentHash}, so a
Revision selection always carries its Change membership and exact captured-content identity. Each
page's presentations[].currentRevisions[] entries carry summarySource; a supplied proposal summary
also carries revisionProposalSummary and the finished label, while an absent one carries no label
and the server-owned absentSummaryCue ("No summary supplied"). The card then keeps the exact Revision
id as its headline and shows the cue as a muted state line. Both members are additive, so the page
version stays 1. Each
capture remains distinct, including shared-commit siblings; the CLI's default revision list
presentation may still fold those siblings into a grouped row.
Every worktree of a clone resolves the shared common-dir store (<git-common-dir>/pointbreak), so the inspector
renders snapshots captured in sibling worktrees as well as the current one. The /api/snapshots/{id}
payload is content-only: it carries the immutable diff content and its contentHash only — no
revisionId, source, base, or target. The captured worktree path is therefore simply absent
from the snapshot wire (there is nothing to redact). Endpoint/target display lives on
/api/revisions/{id} and /api/revisions, derived from the revision projection (a path-private
targetDisplay block), not from the snapshot artifact. pointbreak revision list JSON still carries
target.worktreeRoot unchanged for Git-backed worktree captures. A provenance-free revision omits the
complete source / base / target triple and receives targetDisplay.kind: "non_git" with a
non-Git label.
pointbreak capture [--repo <path>] [--base <rev> | --root | --staged | --unstaged] \
[--target <rev>] [--include-untracked] [--allow-empty] \
[--summary <text>] [--path <pathspec>]... [--operation-id <id>] \
[--review-cursor <token> --advance replace|parallel] \
[--also-supersedes <revision-id>@<object-artifact-sha256>]...pointbreak capture records a new exact Revision in a stable Change: the base endpoint, target
endpoint, and captured diff snapshot. Without --review-cursor, it creates a new independent Change.
With --review-cursor --advance, it revalidates that exact Change/Revision selection and records a
replacement or parallel Revision. Repeated --also-supersedes REVISION@ARTIFACT_HASH arguments add
exact current predecessors for a consolidation. The legacy proposal-borne --supersedes spelling is
rejected with an actionable error.
--operation-id supplies the durable retry identity; when omitted, Pointbreak generates one and returns
it in the receipt. The JSON receipt is pointbreak.change-capture-receipt.v1 and includes changeId,
revision.{revisionId,objectArtifactContentHash}, reviewCursor.token, per-event outcomes, and whether
the operation is complete. Retrying the retained operation never silently adopts a different source
snapshot.
By default capture reads the local Git worktree from HEAD (or Git's empty
tree before the first commit) to the working tree (source git_worktree). That default is a
combined "what differs from the baseline" capture: it includes staged and unstaged tracked changes
because both differ from HEAD. Like git diff HEAD, default capture excludes untracked files; add
--include-untracked to synthesize untracked files as added files in the captured snapshot.
In a newly initialized repository with no commits, default worktree capture uses Git's empty tree as
the base endpoint and the working tree as the target. If the only files are still untracked, use
pointbreak capture --include-untracked.
By default, a selected source that produces zero changed files is an error. The error suggests
likely source flags such as --include-untracked, --staged, or --unstaged when they might
explain the empty result. Use --allow-empty to intentionally record an empty revision.
--summary <text> attaches an optional human-readable discovery label to the immutable capture
event. It is the label shown on Inspector Change cards, and it is projected into revision list,
history, the Inspector, and the VS Code extension so people and agents can select the intended
revision without interpreting opaque IDs. The summary is descriptive metadata and does not affect
revision or object identity. An omitted summary stays absent from the event and read documents for
backward compatibility. The capture still succeeds without one, but it prints a one-line stderr
notice (notice: no --summary supplied; Inspector cards and receipts will show only the exact Revision id), the JSON receipt carries revision.summary: null explicitly, and the text receipt reads
summary: none supplied. change capture behaves the same way. Because the
capture event is immutable, rerunning the same content with a different summary is a conflicting
proposal rather than an edit; choose the label on the initial capture.
- With
--base <rev>, capture instead records the committed range from<rev>to--target(defaultHEAD) as agit_commit_rangesource. Both revs are resolved withgit rev-parseto commit OIDs at capture time: annotated tags peel to their commit, and a rev that does not exist or does not name a commit (a blob or tree) is rejected with an error that names the rev. The snapshot is thebase..targettree diff with no working-tree, index, or untracked involvement, so both endpoints serialize asgit_commitand no worktree path appears in the output.--targetdefaults toHEADunder--base. Re-capturing the same range is idempotent and reportseventsExisting, and an equivalent rev spelling (HEAD~1versus the resolved OID) captures the same revision because rev spellings are never stored (and the same summary, when supplied, keeps the proposal byte-identical). Like worktree capture, a range capture lands in the shared common-dir store, so it is immediately visible from sibling worktrees (see below). - With
--root, capture records Git's empty tree to--target(defaultHEAD) as agit_root_commitsource. The base endpoint serializes asgit_tree; the target endpoint serializes asgit_commit. This is the supported way to review a repository's first commit, or any explicit target commit as "all files added", without creating orphan-branch workarounds.--rootcannot be combined with--base,--staged, or--unstaged, and--targetis accepted only with--baseor--root. Like--base, root capture reads only committed trees: the working tree, index, untracked files, and command-helper paths do not affect the captured revision. - With
--staged, capture records staged changes only as agit_stagedsource. IfHEADexists, the base endpoint is the current commit and the target endpoint is the captured Git index tree. If the repository has no commits yet, the base endpoint is Git's empty tree and the target is still the captured index tree. The working tree and untracked files are not read, so unstaged edits do not affect the captured revision. - With
--unstaged, capture records the captured index tree to the working tree as agit_unstagedsource. This mirrorsgit difffrom the index by default: staged changes are in the base endpoint and untracked files are excluded. Add--include-untrackedto synthesize untracked files as added files without staging or mutating them. In a repository with no commits,--unstaged --include-untrackedcaptures untracked working-tree files from the empty index tree to the working tree. --include-untrackedis valid only with default worktree capture or--unstaged. It is rejected with--base,--root, and--stagedbecause those modes are tree/index captures rather than worktree-plus-untracked captures. To capture a new repository's untracked initial files, usepointbreak capture --include-untracked, notpointbreak capture --root --include-untracked.--allow-emptyis valid with every capture source. Without it, Pointbreak refuses to record a revision whose selected source has no changed files. This keeps accidental empty captures from hiding a missed--include-untracked,--staged,--unstaged, or pathspec typo while still allowing an explicit empty revision when that is the intended review object.- Durable state lands in the shared common-dir store at
<git-common-dir>/pointbreakunder the clone's Git common directory (the default for every worktree). Anephemeralworktree instead keeps its own discardable.pointbreak/data/store. A legacy flat.pointbreak/store from before the.pointbreak/data/layout is a retired pre-1.0 format: it is detected and refused, not migrated — distinct frompointbreak store migrate, which folds a pre-flip worktree-local.pointbreak/data/store into the shared store; see storage-model.md. - Opting into ephemeral mode generates a committed
.pointbreak/.gitignore(two lines:data/+*.local.json) when the paths are not already ignored, so the worktree-local store stays out ofgit status; the file is visible, meant to be committed, and survives clone. Writer-initializing commands against the ephemeral store generate it too; a shared-store write generates nothing (the shared store lives inside.git/, which git already ignores) and never mutates the working tree. Nothing writes.git/info/excludeanymore, and no tracked.gitignoreis ever modified. Committed config siblings (.pointbreak/delegates.json,.pointbreak/actor-attributes.json,.pointbreak/allowed-signers.json,.pointbreak/store.json) stay tracked; only.pointbreak/data/and the private.pointbreak/delegates.local.json,.pointbreak/actor-attributes.local.json, and.pointbreak/store.local.jsonoverrides are excluded. - The store subtree (
events/andartifacts/) is the same wherever it resolves: the shared common-dir store at<git-common-dir>/pointbreakby default, or anephemeralworktree's own.pointbreak/data/. events/stores immutable event files.- No
state.jsonprojection is written. A leftover file from an earlier version is inert and may be deleted. - Full captured snapshots are Pointbreak-owned immutable object artifacts under
artifacts/objects/. - The
work_object_proposedevent binds to the object artifact's canonical content hash; the content-only artifact body carries no revision identity or endpoints (those live on the event). - Output is compact
pointbreak.change-capture-receipt.v1JSON and includes the Change, exact Revision and object-artifact hash, a fresh review cursor, the retry operation, and write outcomes. - With
--path <pathspec>(repeatable), the capture is scoped to the given git pathspec(s): both the tracked diff and any enabled untracked-file synthesis include only matching files. This composes with the default worktree capture, with--base/--target, with--root/--target, and with--stagedor--unstaged. The syntax is native git pathspec — including magic such as:(exclude)...— executed by git itself, and pathspecs are interpreted relative to the repository root regardless of the invoking directory. The recorded set is order-independent (sorted, deduped, trailing slashes normalized on plain paths) and is part of the captured revision's identity: the same range captured under a different scope is a different revision, while identical captured content still shares one content object. A scope that matches no changed files is an error unless--allow-emptyis passed; with--allow-empty, the empty revision still records the requested scope. The scope is visible inpointbreak revision show,pointbreak revision list, andpointbreak historyundersource.pathspecs; an unscoped capture carries nopathspecskey and its identity is unchanged from before the option existed. (This is deliberately git pathspec syntax, not the gitignore-style globs of.pointbreak/sensitivity.json— capture scoping is executed by git, while the sensitivity exclude config is matched by Pointbreak at scan time.) git_tree,git_index, andgit_working_treeare endpoint states in the recorded model. The source selector decides which endpoint pair is captured: default worktree (HEADor empty tree to working tree), committed range (committocommit), root (empty treetocommit), staged (commitor empty tree toindex), or unstaged (indextoworking tree).
V1 storage is local and synchronous. The shared common-dir store may take concurrent writes from multiple worktrees of the same clone, kept safe by content-addressed writes and a regenerable projection rather than a lock. V1 does not add a daemon, delivery queue, approval flow, async storage, remote storage, or note mutation.
By default every worktree of a clone resolves the shared common-dir store at <git-common-dir>/pointbreak, so
pointbreak capture lands its capture directly there — no setup step — and the capture is
immediately visible to revision list, revision show, and history from any sibling worktree. An
ephemeral worktree instead captures into its own discardable .pointbreak/data/ store (see
pointbreak store).
The native review write commands — pointbreak observation add, pointbreak input-request open
and respond, pointbreak assessment add, and pointbreak validation add — behave the same
way. They resolve the shared common-dir store, so you can record a
fact against a revision (or related observation, assessment, or request) captured in a sibling
worktree, and the fact lands directly in that shared store, visible to every worktree in place. An
ephemeral worktree writes the fact to its own .pointbreak/data/ store, unchanged.
pointbreak store status [--repo <path>] [--format <fmt>] [--show-paths]
pointbreak store derived status [--repo <path>] [--format <fmt>]
pointbreak store derived build [--repo <path>] [--format <fmt>]
pointbreak store derived rebuild [--repo <path>] [--format <fmt>]
pointbreak store paths [--repo <path>] [--format <fmt>]
pointbreak store mode (shared | ephemeral | show) [--repo <path>] [--format <fmt>]
pointbreak store migrate [--repo <path>] [--include-ephemeral] [--retire-source] [--format <fmt>]
pointbreak store link [<slug>] [--repo <path>] [--include-ephemeral] [--include-sensitive] [--retire-source] [--format <fmt>]
pointbreak store unlink [--repo <path>] [--format <fmt>]
pointbreak store forget <slug> [--yes] [--force] [--format <fmt>]
pointbreak store list [--format <fmt>]
pointbreak store remove [--repo <path>] (--snapshot <id> | --revision <id> | --ref <name> | --range <a>..<b> | --unreachable) [--sign-key <key>] [--format <fmt>]
pointbreak store gc [--repo <path>] [--format <fmt>]
pointbreak store compact [--repo <path>] [--format <fmt>]Transition availability:
store migrateandstore linkretain their command syntax and historical placement contracts, but their transfer writers are inactive in this build. Untouched and partially migrated roots fail at the capability fence; a Change-ready root reportschange_store_transfer_unavailable. This is distinct from the explicitchange migratecommand, which activates one exact owner-approved legacy root in place after retaining a verified external backup. It does not move a store between placements. Do not copy a test capability fixture into an owner store.
pointbreak store commands inspect, configure, and maintain the review store the current Git worktree
resolves. By default every worktree of a clone — the main worktree and every linked worktree alike —
resolves the same shared common-dir store at <git-common-dir>/pointbreak (the path under the repo's Git common
directory), automatically and with no setup step. Because linked worktrees share one Git common
directory, a capture in any worktree is immediately visible from its siblings. By default this is a
per-clone store, not a user-level multi-repository store or remote sync service; a clone can opt into
the machine-wide user-level family store tier once exact Change store transfer is activated (see
the retained placement contract below).
pointbreak store status resolves the store and emits pointbreak.store-status JSON.
pointbreak store derived status|build|rebuild operates on the disposable derived-access generation
for the exact store selected by --repo. The event journal and content store remain authoritative:
these commands do not replace, migrate, or mutate loose truth.
When POINTBREAK_DERIVED_ACCESS is unset, the derived profile is active; set it explicitly to off for
immediate rollback.
The stable derived/ container and its locks, leases, quarantine, and retired artifacts live directly
beneath the exact resolved authoritative store root. Clone-local, ephemeral, and user-level family stores
therefore each keep their own matching disposable generation; Pointbreak does not maintain a second global
derived-path registry.
-
statusis strictly read-only. It reports the selected namespace and lifecycle availability without creating a directory, acquiring a rebuild lease, or starting background work. Itspointbreak.store-derived-statusdocument is path-free. If both the stablederived/namespace and its legacy predecessor are present, text output identifies both local paths so the operator can retain one disposable copy and move the other aside; Pointbreak never guesses, merges, or deletes either. When the cause of an unavailability is typed, the document adds areasonfield. The only reason today isjournal_unavailable: on Windows, the NTFS volume that holds the store has no active USN change journal.availabilityis thenunavailable, nothing retries it, anddetailreads, for a store onD::journal_unavailable: the NTFS change journal is not active on volume D: (os error 1179), so derived access cannot prove authority on it; an administrator can create one with `fsutil usn createjournal m=<size> a=<delta> D:`, or set POINTBREAK_DERIVED_ACCESS=off to use authoritative reads (slower but correct); Pointbreak never creates a journalA background run that stopped on it prefixes the same text with
background recovery stopped:, andbuildandrebuildfail with it. See Windows: the NTFS change journal. -
buildsynchronously creates or repairs a usable generation only when needed. If a validated current generation already exists, it emits a no-oppointbreak.store-derived-buildreceipt. -
rebuildsynchronously constructs and publishes a replacement generation even when the old generation remains readable. It emits apointbreak.store-derived-rebuildreceipt after publication.
If authoritative truth cannot be proven stable during a build or rebuild (for example, a busy NTFS
volume exhausts the change-journal budget), the rebuild runs again, up to three attempts in total, before
it fails.
Who may do what to the disposable derived generation is fixed by the actor's role:
| Role | Commands and routes | May do | Refuses |
|---|---|---|---|
| Observe | store derived status; Inspector status |
Report availability, namespace and progress | Never creates state, takes an exclusive lock, starts work or moves state aside; store derived status is refused on a store that still requires migration, while Inspector routes answer typed documents instead |
| Maintain | Ordinary bounded reads; Inspector data requests | Serve a validated current generation; after activation, ask the existing background maintenance to catch up | Never replace a generation or move invalid state aside; report it and fall back |
| Recover | store derived build; Inspector Retry |
Move invalid disposable state aside and build a usable generation | Derived access set to off; a deferred or conflicting namespace transition; a store that still requires migration |
| Replace | store derived rebuild; Inspector Retry; change migrate |
Publish a replacement while the old generation stays readable until completion | The same refusals as recover |
On an activated store, invalid disposable state stays in place until an explicit recover or replace action; ordinary reads keep reporting it and fall back to authoritative data.
When both the stable derived/ root and its legacy predecessor exist at once, derived access is unavailable,
not off. Ordinary bounded CLI reads fall back to authoritative data with the one-per-process hint. Where
admission permits them (the legacy aggregate routes on an untouched legacy root), Inspector data routes answer
the typed unavailable document and serve only under the explicit access=authoritative election; the
exact-read, search, freshness and bare poll-probe routes keep their existing behaviour. Change-first routes
answer typed migration documents on pre-migration stores and the typed projection_invalid document on ready
stores. Status names the conflict and text output prints both paths; build, rebuild and the Inspector
Retry refuse or do nothing until an operator moves one root aside or selects explicit off. A conflict that
appears while an Inspector is already running is reported through the lifecycle error until that process
restarts.
Build and rebuild may scan the complete event history and can therefore be expensive on a large store.
Progress is written to stderr; stdout contains exactly one completion document, so scripts can consume it
without parsing progress. A cancellation or failure preserves authoritative loose truth and any previously
valid generation. Set POINTBREAK_DERIVED_ACCESS=off to disable all derived reads and writes immediately;
while it is set, build and rebuild refuse to run. This is also the rollback posture for an older binary
that does not understand the stable derived/ namespace. If a live lease defers the namespace transition or
both namespaces conflict, the command still emits its machine-readable receipt to stdout but exits non-zero;
the requested build did not complete, so shell callers must not proceed as though a generation is usable.
A first bounded CLI read with no usable generation falls back to authoritative loose data and emits one
actionable hint for the exact store and process; it does not synchronously rebuild history. A first write
publishes authoritative loose truth once and reports derived degradation, leaving the disposable generation
for a later build or rebuild. Inspector is the interactive exception: it starts one asynchronous first
build while keeping the shell and explicit authoritative fallback available.
When the derived profile is active and current, output-bounded history pages, attention list,
explicitly bounded revision list --limit pages, and summary show use it without enumerating the event
directory. These
commands keep their domain document schemas and expose projectionStamp instead of pretending that the
bounded freshness identity is an eventSetHash. An absent or unusable generation falls back to the
authoritative journal for that invocation and prints one store derived status|build hint. Unbounded,
search, ref-filtered, audit, replay, transfer, repair, migration, removal, and compaction work remains
authoritative.
The rollout and lifecycle are natively qualified on macOS/APFS and Windows/NTFS. Linux remains compile/CI qualified; that support surface does not substitute for retained-scale Linux measurements. Existing retained L100/C262 packages remain the scale authority, and first build or deliberate rebuild remains exceptional, history-proportional maintenance rather than an ordinary read or write path.
pointbreak store paths is the supported path-discovery seam. It emits
pointbreak.store-paths version 1 with the selected tier and exact worktreeStore, commonStore,
binding, home, and keys paths. The binding is
<git-common-dir>/pointbreak.link.json; the common store is
<git-common-dir>/pointbreak. Linked worktrees share both through their Git common directory. Use
this command in scripts instead of reconstructing Pointbreak paths.
modeislocal(the clone-local common-dir store),ephemeral(a worktree pinned to its discardable.pointbreak/data), oruser-level(a clone linked to a family store).storeRefislocalfor the first two and the family slug foruser-level. Auser-levelstatus additionally carriesrepositoryFamilyRef,cloneRef,liveCloneCount,orphaned, andlastWrite; the other two tiers omit them. These family fields sit outside the frozen hard core under this document's tiered stability promise.storeIdentityandcontextIdentityare opaque, machine-local identifiers for the resolved store and current worktree context. Consumers may compare them for equality but must not parse them. Nested paths in one worktree report the same pair; linked worktrees sharing a store have the samestoreIdentityand differentcontextIdentityvalues.inventoryreportseventCount,eventBytes,artifactCount,artifactBytes,totalBytes, optionaluntrackedBytes,largestArtifacts, andrevisionObjects. Artifact entries use opaque artifact refs rather than filesystem paths. EachrevisionObjectsentry carries arevisionIdslist (sourced from thework_object_proposedevents keyed byobjectIdplusobjectArtifactContentHash), because one object artifact may be referenced by several revisions under the shared-store model (#146), while a rebased recapture can store another artifact for the same stable object id.sensitivityreportspolicyOutcomeplus redacted findings. Finding references usefile:sha256:*refs, and the JSON document never prints secret values or source file paths. The local-only--show-pathsflag is the one exception, and only on the text lane — see Sensitivity exclude globs.
Sensitivity findings are reported but do not currently abort a write. A hard-blocking policy and
explicit override controls are a forward-looking note for when movement can target a wider store;
blocking findings still name only safe finding kinds, such as known_token, and command output does
not print the secret text or file path.
Every review read command resolves the shared common-dir store: revision list and revision show,
history, the observation, input-request, and validation lists, the association list, and
assessment show read it from any worktree of the clone, including hydrated bodies and the captured
snapshot. Authoritative documents identify that store state with eventSetHash; eligible bounded reads
served by a current derived generation carry projectionStamp instead. Both identities move when the
visible journal state moves, but a projection stamp is not a full-set hash.
pointbreak store mode reads or sets a per-worktree store mode that controls where the worktree's review
data lands. pointbreak store mode ephemeral pins the worktree to a discardable worktree-local
.pointbreak/data store — the privacy escape hatch for sensitive or throwaway work whose bytes should
disappear when the worktree is removed. pointbreak store mode shared (the default) uses the shared
common-dir store. The mode is written to a committed .pointbreak/store.json, and may be overridden
privately by a git-excluded .pointbreak/store.local.json (the local file wins, the
delegates.json / delegates.local.json precedent). A malformed or unsupported config is a hard
error rather than a silent fallback. pointbreak store mode show reports the resolved mode without changing
it. All three forms emit pointbreak.store-mode JSON with mode (shared | ephemeral) and source
(default | committed | local); the body embeds no storage path.
The worktree sensitivity scan (run by pointbreak store status and pointbreak store migrate's consent
gate) supports a committed .pointbreak/sensitivity.json plus a git-excluded
.pointbreak/sensitivity.local.json (covered by .pointbreak/.gitignore's *.local.json line) listing
path globs the scan skips — the targeted alternative to the blanket --include-ephemeral override
when a repo's own test fixtures carry scanner-triggering strings:
{
"schema": "shore.sensitivity-config",
"version": 1,
"excludeGlobs": ["tests/**", "src/session/store/sensitivity.rs"]
}The two files merge by union (committed order first, then novel local entries) — deliberately
diverging from the local-replaces-committed rule store.json/delegates.json use, because this is
a list: replace would force copying the whole committed list to add one local entry, union grants
nothing replace couldn't, and the audit counts make any widening visible. Default is empty (scan
everything; opt-in only).
Glob semantics are a documented gitignore-style subset matched against the repo-relative path: a
leading / or any interior / makes the pattern rooted (tests/**, src/lib.rs); a slash-free
pattern matches any path component at any depth (*.pem, data); a trailing / marks a directory
pattern matching only paths inside it; ** spans segments (zero or more interior, one or more
trailing); * and ? never cross /. Negation (!), empty patterns, and malformed or
unsupported-version config are hard errors naming the offending file — the config gates a
protection, so a misread never silently changes coverage.
An excluded path is not scanned — an explicit operator opt-out, kept honest by the audit
surfaces: pointbreak store status reports sensitivity.excludedPathCount and
sensitivity.excludeGlobs[{glob, matched}] (zero-count globs included; a dead glob is itself worth
seeing), and pointbreak store migrate reports sensitivityExcludedPathCount whenever its gate scan
ran (absent under --include-ephemeral, which skips the scan). Excluded paths themselves are never
listed — the scan's redacted file:sha256:* posture stands. The gate behavior is unchanged: a
block finding outside the excludes still refuses without --include-ephemeral.
Seeing which files matched (pointbreak store status --show-paths). A finding names only its kind
and a redacted file:sha256:* reference, so on its own it does not tell you which file to exclude.
--show-paths closes that loop: it re-runs the same scan (the same matchers, the same exclude
globs) locally and lists the real matched worktree paths grouped by finding kind, so you can author
a targeted excludeGlobs entry. The link/migrate sensitivity gate errors point at this command.
--show-paths is text-only: it forces the text lane and refuses an explicit --format json /
--format json-pretty. That restriction is deliberately not a security barrier —
the listing prints to your own terminal, the paths are your own local files, and plain text is as
machine-readable as JSON, so nothing is being withheld from a program. It exists only to keep the
versioned pointbreak.store-status JSON document a single, uniformly path-free shape, so a tool that
pipes that document into a log, an index, or a relay never depends on a flag to stay path-free. The
redaction that genuinely matters is on the stored and forwarded data — the events written to
<git-common-dir>/pointbreak and the default pointbreak.store-status document, which can cross machine, family-store,
and relay boundaries and would otherwise leak your local filesystem layout to whoever reads the
store. --show-paths never writes to the store or emits JSON, so it sits outside that contract by
construction: the type that carries the real paths is not serializable, and the paths reach nothing
but stdout.
A pre-flip worktree-local .pointbreak/data store on a non-ephemeral worktree (data written before the
shared common-dir default) is detected on any read or write. The retained transfer contract for
pointbreak store migrate folds that legacy store into the shared common-dir store
non-destructively by default: it copies events and artifacts forward and leaves .pointbreak/data in
place, so you can verify the result and then remove .pointbreak/data yourself to finish the switch. It
is idempotent (re-running reports the already-present facts as existing), and it refuses an ephemeral
or sensitivity-flagged worktree unless you pass --include-ephemeral. That transfer is not executable in
this build; the command fails closed as described above.
--retire-source completes the switch in one command: after the fold, an independent
verification walks every durable file in the source store (events/ and artifacts/, recursively;
only in-flight *.tmp files are excluded — a leftover store-root state.json sits outside
those trees, and a nested file merely named state.json is verified like any other) and requires each to be
present in the shared store — artifacts by content, events by content ignoring the import's own
ingest-provenance stamp. Retirement then deletes exactly the files it verified, plus disposable
rebuildable data, and never deletes recursively. It keeps .pointbreak/data and its authority lock
file, so a leftover directory holding only authority.writer.lock is expected and the very next read
resolves; sourceRetired is true when nothing else remains (see
storage-model.md). On any missing or divergent file —
including an orphan artifact no event references, which the fold deliberately does not carry — the
command errors, names the offending paths, and deletes nothing. It refuses before folding, with an
error whose message begins source_busy;, while another Pointbreak writer holds .pointbreak/data,
and refuses — naming the entry and deleting nothing — when the store holds an entry retirement does
not verify, such as operations/. A record that appears while retirement is checking is kept:
nothing is deleted, sourceRetired is false, and a source_retirement_residue diagnostic asks for
a rerun. A source with no durable files at all (only a leftover store-root state.json, derived-access
data, or the empty directories the writer pre-creates) is retired as a husk without a fold, under the
same rules; a source holding artifact files but no event files is refused outright. Classification
is by file counts, never directory existence.
It emits pointbreak.store-migrate JSON with eventsCreated, eventsExisting, artifactsCreated,
artifactsExisting, sourceEmpty, sourceRetired, verifiedEvents, and verifiedArtifacts.
(This is distinct from the legacy flat .pointbreak/ layout, a retired pre-1.0 format that is detected
and refused rather than migrated; see
storage-model.md.)
The retained pointbreak store link [<slug>] contract promotes a clone into the opt-in user-level family store at
<pointbreak-home-root>/stores/<slug>/, a per-machine store shared across independent clones of the same
repository family so review facts survive removing any one clone. The binding is recorded per
physical clone in the git common dir (pointbreak.link.json under .git/), so it never travels in a
commit and a single pointbreak store link binds the main checkout and every current and future
git worktree of that clone. The per-worktree .pointbreak/store.local.json file is mode-only:
a familyRef or cloneRef there is rejected with guidance to run pointbreak store link <slug>.
A worktree can still opt out locally with pointbreak store mode ephemeral. When a worktree writes
to its clone-local store while a sibling worktree of the same clone is linked, pointbreak store status, every verb that resolves a write store (capture, change writers, association
record/land/withdraw, observation add, validation add, assessment add, input-request
open/respond, endorse, fact port, and store remove/gc/compact), and the Inspector's store
chip surface a one-line advisory pointing at pointbreak store link <slug> — the split is signalled,
never silent. Write verbs print it on stderr after a successful write, from one shared CLI seam; it
never fails the command. Before any family write,
link runs its gates in order: it refuses an ephemeral worktree (override --include-ephemeral) and
a sensitivity-flagged worktree (override --include-sensitive), refuses a slug already stamped for a
different family, and warns (without blocking) on a sync-managed filesystem path or when the clone
shares no git history with an existing family. It then folds the clone-local <git-common-dir>/pointbreak history
forward with independent verification and flips the binding last, so an interrupted link leaves the
clone still resolving its clone-local store. Omitting <slug> fails with a suggestion rather than
picking one silently. --retire-source then retires the clone-local store: it deletes only the
record files an independent re-verification proved present in the family store, plus disposable
rebuildable data, and never deletes recursively. It keeps the store directory and its authority lock
file, so a leftover directory holding only authority.writer.lock is expected; sourceRetired is
true when nothing else remains (see
storage-model.md). It refuses with an error whose message
begins source_busy; while another Pointbreak writer holds the clone-local store, and refuses — naming the
entry, deleting nothing, and leaving the clone unlinked — when the store holds an entry retirement does
not verify, such as operations/. A record that appears while retirement is checking is kept: nothing
is deleted, sourceRetired is false, and a source_retirement_residue diagnostic asks for a rerun.
Do not run family-store maintenance such as pointbreak store forget during a retire. The link writer
is not executable in this build. When the fold carries prior unsigned
pointbreak store remove events, a diagnostic discloses
that they lost possession-based suppression and should be re-issued in the family store. It emits
pointbreak.store-link JSON (familyRef, cloneRef, createdFamily, the folded* counts,
sourceRetired, and any warnings). pointbreak store unlink detaches this clone (clearing the binding
and deregistering it) without moving any data, and survives a family store that was already forgotten.
pointbreak store forget <slug> is the whole-store destructive verb for a family store, deliberately
outside pointbreak store remove's content-targeted removal (no store survives a forget to hold a removal
event). It is dry-run by default: it previews the inventory and live-clone count that would be lost
and deletes nothing. --yes performs the deletion, but only for a family with zero live clones (an
orphaned family store — a different notion from pointbreak store remove --unreachable, which targets
unreachable-commit content); a family with live clones additionally requires --force. pointbreak store list is the one repo-less surface: it takes no --repo flag, never resolves a git repo, and walks
<pointbreak-home-root>/stores/ reporting each family's familyRef, inventory, liveCloneCount,
orphaned flag, and lastWrite. Against an empty home it returns an empty families array.
pointbreak store remove retires content-addressed artifacts from the store. It resolves exactly one
selector to a set of content hashes — --snapshot <id> (a snapshot's bound artifact), --revision <id> (every artifact a revision references), --ref <name> / --range <a>..<b> (artifacts of
revisions anchored on the named commit or commit range), or --unreachable (artifacts of commit-anchored
revisions whose commits are all unreachable from live refs; --orphans is a deprecated alias) — and
records one removal fact per content hash. It emits
pointbreak.store-remove JSON listing each contentHash, whether it was newly created, and
coReferencingUnits (other revisions that still name the same shared artifact, reported before the
removal), plus eventsCreated and eventsExisting. Removal is content-targeted and idempotent:
re-removing a hash reports created: false. Removal is a write, so a signed store stays signed —
--sign-key selects the signing key exactly as pointbreak capture does. There is deliberately no
--idempotency-key; the removal key is derived solely from the content hash. Removal records the
fact; it does not delete bytes — run pointbreak store gc / pointbreak store compact to reclaim them.
pointbreak store gc and pointbreak store compact are the same local sweep: they physically delete the
content-addressed blobs whose content hash has been removed, reclaiming disk. The sweep records no
event and is fully re-derivable from the log — re-capturing the same content re-materializes the blob.
It emits pointbreak.store-compact JSON listing each swept blob's contentHash and outcome
(removed or missing) plus bytesReclaimed. Running it again is a no-op (every removed blob is
already missing).
Removed content renders as an explained state on every read surface, never as an error. For
note-shaped bodies (observation and input-request bodies, response reasons, assessment and
validation summaries, imported note bodies), pointbreak revision show, the leaf list/fetch/show
commands, and pointbreak history omit the body text and carry a bodyContentState /
summaryContentState / reasonContentState field beside the content hash — suppressed_present
while the bytes are still stored (a compact would reclaim them) or physically_removed after the
sweep — plus body_content_suppressed_present / body_content_physically_removed diagnostics.
The field is omitted entirely while content is present, and a body that is missing without a
recorded removal still fails the read with the import referenced artifacts guidance.
Command output is the machine-integration surface, under the tiered stability promise described at
the top of this reference (a frozen hard core; an additive-evolvable soft shell).
Raw store paths, event files, artifact paths, .git paths, and .pointbreak/data paths
remain internal storage details.
# Preview the actor that repository writes will use (pointbreak.identity-whoami).
pointbreak identity whoami [--repo .] [--format <fmt>]
# Stage a delegation record binding an agent to its responsible principal (pointbreak.identity-delegate).
pointbreak identity delegate <agent-actor-id> --principal <principal-actor-id> \
[--from <RFC3339>] [--until <RFC3339>] [--comment <text>] [--local] [--repo .] [--format <fmt>]
# Stage an actor-attributes entry — kind + roles — for any actor (pointbreak.identity-attest).
pointbreak identity attest <actor-id> --kind <kind> [--role <role>]... \
[--comment <text>] [--local] [--repo .] [--format <fmt>]pointbreak identity whoami previews the writer identity that the existing resolver will use. It honors
POINTBREAK_ACTOR_ID, then Git email, Git name, and finally actor:local; it accepts no actor override.
Its v1 JSON is exactly schema, version, and actorId.
The other pointbreak identity commands write the actor/principal config the read side (above) resolves.
Both are possession-style: they stage the working-tree edit only and never invoke git — review and
commit the file to apply it (git log -p is the audit trail), exactly like pointbreak key enroll.
delegatestages a delegation record into.pointbreak/delegates.jsonbinding<agent-actor-id>(anactor:agent:<name>id) to a responsible non-agent--principal(the human/actor that answers for the agent; the depth-0 rule rejects an agent principal).--fromdefaults to now in RFC 3339 UTC;--untildefaults to an open window;--commentis free text for diff readers. Emits apointbreak.identity-delegatedocument and a stderr hint to commit.atteststages an actor-attributes entry into.pointbreak/actor-attributes.jsonfor<actor-id>(any persisted actor id).--kindis required — exactly one kind per actor; the reserved well-known kinds arehuman,agent,service, andreviewer-model, but any lowercase-kebab token is accepted.--roleis repeatable; kind and roles are normalized to lowercase-kebab and roles are deduped + sorted. Re-attesting replaces the actor's entry (kind, roles, and comment) — it is not additive. Emits apointbreak.identity-attestdocument.--localwrites the private.local.jsonsibling instead of the committed file and git-excludes it via the generated, committed.pointbreak/.gitignore(its*.local.jsonline covers every private override). The layers merge git-config style: a local entry fully replaces the committed entry for that key on this machine (never a merge), and the command surfaces that full-replace caveat on stderr.--repo(default.) may be the repository root or a path inside it; the entry always lands at the worktree-root.pointbreak/. Inputs are validated against the same grammar the readers enforce, so a staged file always re-reads and a rejected input writes nothing.
The delegation-map format is documented in storage-model.md; the models and decisions are in ADR-0010 (delegation) and ADR-0012 (actor attributes).
Manage the user-level signing keystore and stage signer enrollment. Keys live in ~/.pointbreak/keys/
(honoring $XDG_DATA_HOME on Unix and %APPDATA%\pointbreak on Windows; POINTBREAK_HOME overrides) — never
in the repo .pointbreak/ or the store. See storage-model.md for the key home and
allowed-signers format.
# Generate a human signing key and print its did:key (pointbreak.key-init).
pointbreak key init --name default
# List local keys with enrollment status and which is the default (pointbreak.key-list).
pointbreak key list --repo .
# Discover local Git/OpenSSH signing evidence (pointbreak.key-discover).
# Discovery only suggests reviewed next steps.
pointbreak key discover --repo .
# Print a key's did:key and/or raw public key (pointbreak.key-show).
pointbreak key show default --did
pointbreak key show default --pubkey
# Adopt an existing SSH Ed25519 key as an agent-backed signer (pointbreak.key-use-ssh).
# Reuses ssh-agent custody — no new key material. Parallel to `init`.
pointbreak key use-ssh ~/.ssh/id_ed25519.pub --name default
pointbreak key use-ssh 'key::ssh-ed25519 AAAA…' # git user.signingKey literal form
# Stage an allow-list entry binding a key's did:key to an actor (pointbreak.key-enroll).
# Possession-style: this stages the working-tree .pointbreak/allowed-signers.json edit only;
# review and commit it to authorize the binding.
pointbreak key enroll default --actor actor:agent:claude-code --repo .
pointbreak key enroll --signer did:key:z6Mk... --actor actor:git-email:alice@example.com --repo .init refuses to overwrite an existing named key. use-ssh adopts an existing SSH public key as an
agent-backed default signer: it accepts a *.pub path or a key::ssh-ed25519 AAAA… literal, emits a
pointbreak.key-use-ssh document with the derived did:key (the same .didKey field pointbreak key show --did prints) plus an enrollment hint, and (like init) refuses to overwrite. Only plain ssh-ed25519
keys are accepted; ed25519-sk/RSA/ECDSA are rejected with a clear error pointing at pointbreak key init.
discover reads local Git/OpenSSH signing evidence and emits a pointbreak.key-discover document:
candidates[] includes source, signerId, keyArgument, suggestedName, actorHints,
matching localKeys, matching enrolledActors, the resolvedActor used for suggestions, and
advisory commands; diagnostics[] reports non-fatal missing or unsupported evidence with source
details. Suggested commands describe unmet setup only: an already adopted signer is not offered a
duplicate use-ssh alias, and an already authorized actor/signer pair is not offered a redundant
enroll command. This discovery does not authorize keys, does not write the key home, and does not
stage .pointbreak/allowed-signers.json. Review a candidate, optionally adopt public key custody with
pointbreak key use-ssh, then stage reviewed trust with pointbreak key enroll --signer <did:key> --actor <actor> --repo ..
list/enroll/discover take --repo (default .) to resolve the committed
.pointbreak/allowed-signers.json or local Git/OpenSSH evidence.
Enrollment never commits — the human's commit is the authorization.
Each write subcommand (capture, observation add, assessment add,
validation add, association record/withdraw, input-request open/respond)
accepts --sign-key <name|path> to
sign that write with a specific key (highest precedence; overrides POINTBREAK_SIGNING_KEY). A key that
cannot be loaded leaves the write unsigned at exit 0 with an advisory diagnostic — signing never
blocks. An agent-backed key resolves through an identities-only ssh-agent pre-flight; if the agent is
unavailable (signing_agent_unavailable), does not hold the key (signing_agent_key_absent), or fails
the real sign (signing_agent_sign_failed), the write is left unsigned at exit 0 — see
signing-ux.md for the full never-gates table. This never-gates behavior covers the
ordinary signed review writes listed above; pointbreak endorse is the exception, where an
unresolved signer is a hard error rather than an unsigned write. Only shipped subcommands are listed;
rotate and revoke are named follow-ons, not yet available.
pointbreak observation add --track <track-id> --title <title> \
[--review-cursor <token> | --revision <revision-id> | --exact-revision <revision-id>] [target options] \
[--body-content-type text/plain|text/markdown] \
[--tag <tag>]... [--confidence low|medium|high] [--supersedes <observation-id>]... \
[--responds-to <observation-id>]...
pointbreak observation list [--revision <revision-id>] [--track <track-id>] \
[--exact-revision <revision-id>] \
[--file <path>] [--tag <tag>] [--include-body] [--format <fmt>]Observations are append-only review notes for a captured revision.
observation addrequires--trackand--title.- Change-capable writers use
--review-cursorso the exact Change/Revision/artifact, graph, and source state are revalidated immediately before append.--exact-revisionis the low-level exact target;--revisionretains legacy proposal-supersession selection and does not follow Change replacement: when it names a Revision that a Change has replaced, the write is refused withrevision_replaced_by_change, which names the current Revision(s); pass--review-cursorto write to the current Revision or--exact-revisionto address the replaced one deliberately. The refusal is decided on the writer-visible store-wide event snapshot loaded before the append; it is not re-checked under the store's authority lock at append time, so a replacement relation another writer appends after that snapshot does not refuse the write (#837). The three options are mutually exclusive. - Tracks are review lanes, not actor or producer provenance.
- Without
--file, the observation targets the whole revision. - With
--file <path>, it targets a captured file. - With
--file <path> --start-line <n> [--end-line <n>], it targets a range on--side <old|new>where the default side isnew. - Bodies may come from
--body,--body-file, or--body-stdin. --body-content-typedefaults totext/plain; usetext/markdownwhen the body should render as Markdown in the inspector.- Large bodies are stored as Pointbreak-owned
shore.note-bodyartifacts while command output keeps artifact paths private. --supersedes <observation-id>(repeatable) records a correction by appending a new observation that names the older observation.--responds-to <observation-id>(repeatable) records that this observation responds to an existing observation — a fact-to-fact relationship (a derivedresponded_byback-pointer is surfaced on the target). It does not supersede or mutate the target.--confidence <low|medium|high>records an optional confidence level on the observation.--tag <tag>(repeatable) attaches free-form tags used by theobservation list--tagfilter.observation listreplays durable events for the revision and may filter by revision, track, file, or tag. It hydrates body text only with--include-body.
Output is compact pointbreak.review-observation-add or pointbreak.review-observation-list JSON by
default.
pointbreak input-request open --track <track-id> --title <title> --reason <reason> \
[--review-cursor <token> | --revision <revision-id> | --exact-revision <revision-id>] \
[--mode operative|advisory] \
[--body-content-type text/plain|text/markdown]
pointbreak input-request list [--revision <revision-id> | --exact-revision <revision-id>] [--track <track-id>] \
[--mode operative|advisory] [--file <path>] [--status open|responded|ambiguous|all] \
[--include-body] [--format <fmt>]
pointbreak input-request show <input-request-id> [--include-body]
pointbreak input-request respond <input-request-id> --outcome <outcome> [reason options] \
[--reason-content-type text/plain|text/markdown]Input requests are durable pause or decision requests for a captured revision.
input-request openrequires--track,--title, and--reason.--reasonclassifies the ask. Values:ambiguous-state,unsafe-action,stale-revision,failed-gate,external-side-effect,conflicting-event,missing-permission,manual-decision-required,insufficient-evidence.insufficient-evidencetypes an ask for more evidence — a debugger or CI run can satisfy it with validation evidence. The set grows additively withinversion:1(a new value is appended, not aversionbump); see the hard-core note above.- Change-capable writers use
--review-cursor;--exact-revisionis the low-level exact target and--revisionretains legacy proposal-supersession selection without following Change replacement: naming a Revision that a Change has replaced is refused withrevision_replaced_by_change, which names the current Revision(s) and the two exact selectors (decided on the pre-append snapshot, as forobservation add). Without a selector, the command defaults to the single captured Revision and errors if several are in scope. --modedefaults tooperative;advisoryrequests are durable and visible but do not imply a cooperative client must pause. Themode(operative/advisory) andreasonCodevalues surface on the consumedinput-request listfield-paths, so — like the response outcomes below — they are part of the frozen hard core: stable withinversion:1, changed only by a coordinatedversionbump.- Targets mirror observations: review-wide by default, captured file, captured range, or an
existing native observation through
--observation <observation-id>. - Request bodies may come from
--body,--body-file, or--body-stdin. --body-content-typedefaults totext/plain; usetext/markdownwhen the request body should render as Markdown in the inspector.- Large request bodies reuse Pointbreak-owned
shore.note-bodyartifacts while command output keeps artifact paths private. input-request listis the V1 polling read surface and defaults to open requests. It may filter by revision, track, mode, file, or status, and hydrates body text only with--include-body.input-request show <id> --include-bodyreturns one request and hydrates the body when requested.input-request respond <id>appends aninput_request_respondedevent.- Response reasons may use
--reason-content-type text/markdown; the default istext/plain. - Response outcomes are
approved,rejected,dismissed,superseded, andabandoned. These wire values are part of the frozen hard core (review-loop drivers branch on them): stable withinversion:1, changed only by a coordinatedversionbump.
Output documents are compact pointbreak.review-input-request-open,
pointbreak.review-input-request-list, pointbreak.review-input-request-show, and
pointbreak.review-input-request-respond JSON by default.
V1 is durable and polling-friendly. It does not add a daemon, filesystem watch mode, TUI prompt, notification transport, or cancellation/escalation event.
pointbreak assessment add --track <track-id> --assessment <assessment> \
[--review-cursor <token> | --revision <revision-id> | --exact-revision <revision-id>] [target options] \
[--summary-content-type text/plain|text/markdown]
pointbreak assessment show [--revision <revision-id> | --exact-revision <revision-id>] \
[--all] [--track <track-id>] \
[--include-summary] [--format <fmt>]Assessments record review calls for a captured revision.
assessment addrequires--trackand--assessment.- Change-capable writers use
--review-cursorso the selected exact state is revalidated before append.--exact-revisionis the low-level exact target;--revisionretains legacy proposal-supersession selection without following Change replacement: naming a Revision that a Change has replaced is refused withrevision_replaced_by_change, which names the current Revision(s) and the two exact selectors (decided on the pre-append snapshot, as forobservation add). The three options are mutually exclusive. - CLI input uses
kebab-caseassessment values:accepted,accepted-with-follow-up,needs-changes, andneeds-clarification. Command JSON output uses the matchingsnake_casevalues:accepted,accepted_with_follow_up,needs_changes, andneeds_clarification. Thesnake_casewire values are part of the frozen hard core (review-loop drivers branch on them): stable withinversion:1, changed only by a coordinatedversionbump. - Targets mirror the revision ledger: review-wide by default, captured file, captured range, native observation, native input request, or another assessment.
- Summaries may come from
--summary,--summary-file, or--summary-stdin. --summary-content-typedefaults totext/plain; usetext/markdownwhen the summary should render as Markdown in the inspector.- Large summaries reuse Pointbreak-owned
shore.note-bodyartifacts while command output keeps artifact paths private. --replaces <assessment-id>is the only V1 relationship that removes an older assessment from the current set.--related-observationand--related-input-requestrecord evidence links; they do not mutate observations or close input requests.assessment showreports current status asunassessed,resolved, orambiguous. It may filter by revision or track, include replaced assessments with--all, and hydrate summaries with--include-summary.
Output documents are compact pointbreak.review-assessment-add and pointbreak.review-assessment-show JSON
by default.
State-change outcomes such as deferred, split-out, overridden, and superseded are ordinary review observations when needed.
This is the item-level attention document: one entry per outstanding fact, anchored to its exact Revision.
pointbreak change attention is its complement, not its summary: the Changes whose lifecycle is not yet
accepted, with current-set topology and exact fact origins. Neither is derivable from the other. A
freshly captured Revision nobody has assessed is no item, yet its Change is awaiting a call; an advisory
ask, or a failed check on an already accepted Change, is an item that puts no Change in
change attention. An empty item list is therefore not an all-clear, and the text digest says so by
closing with a pointer to pointbreak change attention.
Both read replacement from the same authority, at different scope. On a store that holds Change claims a
Revision is superseded when the Changes that hold it replace it, and a proposal-borne supersedes list is
historical input that decides freshness only on a store with no Change claims. Item attention applies that
store-wide (a Revision stays current while any Change holding it still has it current); Change lifecycle
and the attention_wait order follow each Change's own replacement. Replacement retires a replaced
Revision's failed checks and qualifying call inside that Change, not its open requests: those still need a
response, and an operative one keeps the Change in progress.
pointbreak attention list [--repo <path>] [--revision <revision-id>] [--format <fmt>]attention list is a read-only projection of the review record's outstanding, judgment-needing
state — the first product surface of "Pointbreak surfaces the moments that need judgment." It
guides, never gates (ADR-0019): nothing here is a write precondition. The emitted document is
pointbreak.attention-list, version 1.
With a current active derived profile, the command reads the incrementally maintained attention projection
and carries projectionStamp; otherwise it reads authoritative journal data and carries eventSetHash.
The item and filter fields are identical in both cases.
--repodefaults to.;--revisionscopes the read to one revision — its anchored items plus the competing-heads thread that covers it (a short id resolves via the shared id resolver).- Each item carries a kind-qualified
id, atier(primaryorsecondary), the anchoringrevisionId(absent only for thread-scopedcompeting_heads), a replacement-derivedfreshnessblock, anobservedAtstamp, and akind-tagged detail. A Revision replaced in one Change but still current in another stayscurrent: it is still a live candidate somewhere.--revisionscope is exact, so a replaced Revision's items appear under its own id (markedsuperseded), never under its successor's. Items sort by tier, then oldestobservedAtfirst, thenid. - Item kinds:
open_input_request— an open ask (operative →primary, advisory →secondary).ambiguous_assessment— more than one current assessment on a revision, carried as peers; on a superseded revision the item resolves once every successor head has been re-judged.competing_heads— a proposal-borne supersession thread with two or more current heads, on a store with no Change claims.headRevisionIdsis sorted for determinism, not a priority ranking. Once a store holds Change claims this kind no longer occurs: replacement divergence inside a Change reads asconflictedinpointbreak change attention, and two Changes that independently replace a shared Revision do not compete.stale_assessment— a current assessment anchored to a superseded revision, until every current head of the thread has been re-judged.headRevisionIdsnames that complete current head set;freshness.supersededBycontinues to name direct superseders only.failed_validation— the latest failed/errored check per(revision, track, checkName)on a current head; a strictly-later passing rerun clears it (skippednever clears), and so does a later, unanimously accepting judgment on the revision (ADR-0019's judgment-subsumption amendment).follow_up_outstanding— an accepted-with-follow-up assessment whose linked requests are still open.
- This document is entirely soft shell: no field-path here joins the ADR-0029 hard core.
pointbreak summary show [--repo <path>] [--receipt digest|entries] [--format <fmt>]
pointbreak summary check <file> [--repo <path>] [--format <fmt>]summary show describes the recorded review cycles in one store: how many captured Revisions each
Change went through, what the first capture's verdict was, and how much of the captured work carries an
assessment or a commit association. It is a read-only projection: it records nothing, is never recorded
itself, and gates nothing. The figures describe a store, not the people who wrote to it, and are
advisory. The emitted document is pointbreak.review-summary, version 1.
Every figure is a count with its denominator. A measure with nothing to count is
{"state":"unavailable","reasons":[…]}, never 0; the document carries no ratio, percentage, or
score field. (--format text may print a whole percentage next to a nonzero denominator; that is a
rendering only.) No actor id, signer, key, email, or track appears in the document.
Population. A Change is seen when it has at least one membership claim. It is a review Change
when at least one of those claims is not migration backfill. Migration backfill is identified by the
store's signed activation record: the store migration names every record it wrote in the activation's
manifest, by the same key the record's id is derived from, so exactly those records are backfill. A
store without an activation record excludes nothing and says so. Every membership of a review Change
counts, including backfill-written ones. A membership is current until a withdrawal names it; a
review Change with no current membership is excluded as noCurrentMembers rather than dropped. The
remaining Changes are counted, and their current-member Revisions are the captured Revisions.
population reports these counts, the observed capture window, and both exclusions with their sizes
(migrationBackfill names its basis: storeActivationManifest with manifestHash, or
noActivationManifest). Membership and captured-Revision counts range over counted Changes, current and
historical.
reviewRounds. profile is the number of distinct current-member Revisions per counted Change, as
a distribution. A round is one captured cycle, not a judgment of the work. firstCapture gives one
result per counted Change from its earliest-captured Revision (by capture instant, legacy and RFC 3339
timestamps compared as instants, ties by Revision id): unassessed when it has no live verdict (one that
no later assessment replaces), otherwise needsChanges if any live verdict is needs_changes, else
accepted if any is accepting, else otherVerdict.
recordInternalMeasures measure the record against itself, denominated in captured Revisions,
and say nothing about landed work:
assessedCaptureShare— captured Revisions with at least one assessment, replaced or not. A file-, range-, or observation-scoped assessment counts for its Revision.commitAssociatedCaptureShare— captured Revisions with at least one commit association. Withdrawn associations still count here.firstCaptureAcceptance— accepted first captures over first captures carrying a live verdict.actorDistinctAssessmentShare— per captured Revision:actorDistinctwhen some assessment was recorded under a different actor id than the capture,actorSamewhen every one shares it,undeterminedwhen there is no assessment or no capture record. Actor ids are asserted, not verified identity;keyEvidenceis reported separately and isunavailablebecause signing keys are not compared.
landedWorkCoverage always lists six rungs — tipExact, associatedRange, assessedRange,
acceptingVerdictRange, distinctIdentity, provedLanding — denominated in commits on the integration
branch (provedLanding in associations). This read does not walk the integration branch history, so
each rung is unavailable with reason integrationRefNotWalked (and signingKeysNotRead on
distinctIdentity). The two blocks share no field name.
provenance. basis says which read answered. When the derived profile is active and current, the
summary is read from it: basis is projection and projectionStamp names that local index snapshot.
The stamp identifies disposable local state, not the facts counted. Otherwise basis is factSet and
eventSetHash identifies the store's facts; with the derived profile active but its generation absent,
rebuilding, catching up, or moved during the read, the command prints one pointbreak store derived build
hint per store and process and still succeeds. The read never builds or catches up the generation. On
either basis the figures are the same and the receipt below is computed from the counted facts' recorded
bytes, each re-read from its stored record, so it means the same thing on both. eventCount is the number
of facts the read covered; metricDefinitions names the definitions above; computedAt is when the read
ran.
Counted-input receipt. provenance.countedInputs names exactly the facts the measures consumed for
the counted population: the membership claims of counted Changes and the withdrawals naming them, the
captures of captured Revisions, the assessments on captured Revisions and the assessments replacing
them, and the commit associations on captured Revisions. Each entry has four fields:
eventId— commits to the write's idempotency key, not to its content;payloadHash— commits to the payload;eventRecordHash— commits to the record apart from its signatures and transport fields;verificationStatus— how the reader's allowed-signers file verifies the record's signature (valid,untrusted_key,invalid, orunsigned). It depends on the reader's trust set and is outside the digest.
digest is sha256 over the lines eventId SP payloadHash SP eventRecordHash LF, sorted by eventId
then eventRecordHash (algorithm: shore.event-set.canonical-map.v1). By default the receipt carries the
digest, count, per-kind counts, and the verification tally (with allowedSignersConfigured);
--receipt entries also inlines every entry. The receipt proves which facts were counted, never that
the store is complete (completeness: notProven); a receipt minted after a rewrite commits to the
rewritten bytes, so keep a copy outside the store for it to mean anything.
On a store that has not completed its migration, summary show refuses like every other ordinary read.
summary check <file> re-checks the receipt in a saved summary against the store as it is now. Save the
summary with --receipt entries (pointbreak summary show --receipt entries > summary.json); a document
with only the digest has nothing to re-check, and the command says so. The emitted document is
pointbreak.review-summary-check, version 1. Like summary show it is a read-only projection: it records
nothing and gates nothing, and it exits successfully whenever the check ran, so a difference is data for
you to read, not a process failure.
Each listed entry is compared with the event of the same eventId in the store:
matched— the event is present with the recordedpayloadHashand the sameeventRecordHash, recomputed from the stored record now;changed— the event is present but its payload or its record differs. Editing only a field outside the payload (such as the recorded producer version) still changes the record hash, so a rewrite that keeps the payload hash consistent is still caught, with no signing key required;missing— the store holds no event with that id.
differing lists the changed and missing entries with the recorded hashes and, for changed, the
current ones. digestMatchesEntries reports whether the saved file's entries still reproduce its own
digest, which catches an edited receipt file. verificationStatus is not compared: it depends on the
reader's allowed-signers file.
The check proves only the facts the receipt lists (completeness: notProven). Events added to or removed
from the store elsewhere are out of its reach, and a receipt minted after a rewrite commits to the
rewritten bytes.
pointbreak validation add --track <track-id> --check-name <name> --status <status> \
[--review-cursor <token> | --revision <revision-id> | --exact-revision <revision-id>] \
[validation options] \
[--summary-content-type text/plain|text/markdown]
pointbreak validation list [--revision <revision-id>] \
[--exact-revision <revision-id>] \
[--track <track-id>] [--status <status>] [--include-body] [--format <fmt>]Validation checks record local test, lint, build, or other verification evidence for a captured revision. They are advisory review context only: they do not accept, reject, merge, block, or replace a review assessment.
validation addrequires--track,--check-name, and--status.- Change-capable writers use
--review-cursorso the selected exact state is revalidated before append.--exact-revisionis the low-level exact target;--revisionretains legacy proposal-supersession selection without following Change replacement: naming a Revision that a Change has replaced is refused withrevision_replaced_by_change, which names the current Revision(s) and the two exact selectors (decided on the pre-append snapshot, as forobservation add). The three options are mutually exclusive. - Validation targets are revision-only. There are no file or path target flags.
- Status values are
passed,failed,errored, andskipped. --command,--exit-code,--source-fingerprint,--started-at,--completed-at, and repeatable--log-content-hashrecord evidence metadata without exposing artifact paths.--triggerdefaults tomanual; accepted values aremanual,push, andpull-request.- Summaries may come from
--summary,--summary-file, or--summary-stdin. --summary-content-typedefaults totext/plain; usetext/markdownwhen the summary should render as Markdown in the inspector.- Large summaries reuse Pointbreak-owned
shore.note-bodyartifacts while command output keeps artifact paths private. validation listreplays durable events for the revision and may filter by revision, track, or status. It hydrates summaries only with--include-body.
Output documents are compact pointbreak.review-validation-add and
pointbreak.review-validation-list JSON by default.
pointbreak fact port --origin-revision <revision-id>@<object-artifact-sha256>
--origin-fact <observation-id|input-request-id> --review-cursor <token>
--relation context-only|reanchored-as|carried-open-as|resolved-by
[--target-fact <observation-id|input-request-id>] [--rationale-content-hash <sha256>]
--track <track-id> [--repo <path>] [--format <fmt>]fact port records explicit continuity from an observation or input request owned by one exact
Revision to the exact Revision selected by a validated review cursor. reanchored-as and
carried-open-as require a target fact; the other relations forbid one. The origin fact keeps its
original ownership: the port is context, not reassignment. Validation and assessment facts cannot be
ported, so accepting judgments and check results never leak across captured content states.
pointbreak endorse <target-event-id> [--sign-key <name|path>] [--actor <id>] [--repo .] [--format <fmt>]pointbreak endorse records a detached co-signature (an endorsement) over an existing target event —
for example a captured revision's work_object_proposed event. The resolved signer is the attesting
signer and the carrier's envelope writer is the endorser's own actor (--actor, else the resolved
writing identity), never the target's author.
- Unsigned is a hard error. Unlike every other write — where signing never gates — an endorsement
has no unsigned form, because the signature is its content. The signer is resolved first (before the
target); if none resolves (
POINTBREAK_SIGNING=off, no key, an unreadable key), the command exits non-zero and writes nothing. Signer precedence otherwise follows the Signing rules above. - Idempotent: re-endorsing the same target with the same signer is a no-op (
eventsCreated: 0,eventsExisting: 1, same carriereventId). - The emitted
pointbreak.review-endorsedocument reports carrier facts (eventId,targetEventId,targetEventRecordHash,attestingSigner,actorId, and write counts) — not a trust verdict. Whether an endorsement classifies as trusted is reader-relative (resolved against the reader's allow-list at read time), not stamped at write time.
The endorsement record and its read-side classification are decided in ADR-0013.
pointbreak association record --track <track-id> (--commit <rev> | --ref <name> --head <oid>) \
[--revision <revision-id> | --exact-revision <revision-id> | --review-cursor <token>] \
[--sign-key <name|path>] [--repo <path>]
pointbreak association land --review-cursor <token> --track <track-id> --commit <rev> \
[--allow-extension | --provenance-only | --candidate-parent] \
[--dry-run] [--expect-proof <hash>] [--sign-key <name|path>] [--repo <path>]
pointbreak association withdraw <association-id> --track <track-id> \
[--revision <revision-id> | --exact-revision <revision-id> | --review-cursor <token>] \
[--sign-key <name|path>] [--repo <path>]
pointbreak association list [--revision <revision-id>] [--axis commit|ref] [--current] \
[--repo <path>] [--format <fmt>]pointbreak association records and withdraws structural commit-graph associations of an exact
Revision as append-only associate/withdraw events on two axes — commit and ref. A structural record
says only that the named Git object is associated with the Revision; it does not claim byte equality,
containment, or review coverage. Use association land for proof-backed landing language.
After committing an accepted worktree capture, select a commit-bound cursor before landing. The original authoring cursor is worktree-bound and intentionally becomes stale when the commit changes that source state:
landing_cursor=$(pointbreak change select <change-id> \
--revision <revision-id> --source commit:<oid> \
--format json | jq -r '.token')
pointbreak association land --review-cursor "$landing_cursor" \
--track <track-id> --commit <oid>recordtakes exactly one axis.--commit <rev>(resolved to an OID) binds the revision on the commit axis;--ref <name>(a short branch name is normalized to its full ref) at the explicit--head <oid>(never inferred) binds it on the ref axis.--commitand--refare mutually exclusive, and--refrequires--head.landvalidates the exact review cursor, computes and durably records the Revision-to-commit proof first, then records the commit association and final attestation. Exact equality is accepted by default.--allow-extensionadmits a proved extension while reporting unreviewed additions.--provenance-onlyrecords honest attribution without claiming content equivalence. Refuted or indeterminate proof never receives strong landing wording.withdraw <association-id>retracts an earlier association by its id. The id is positional and must carry its prefix —assoc-commit:…orassoc-ref:…— because the prefix selects which axis is withdrawn; a prefixed short form likeassoc-commit:<hex-fragment>resolves against the store. Withdrawal is terminal: a later re-association of the same target does not revive the withdrawn edge.- Both writes are signable —
--sign-key <name|path>selects the signing key exactly aspointbreak capturedoes, and signing never gates the write. --exact-revisionpins the named captured Revision and--review-cursoradditionally revalidates its Change graph before writing. Legacy--revisionretains head-seed behavior. Without a selector, the command defaults to the single captured Revision and errors if multiple candidates exist.listreports both axes unless--axis commit|refnarrows to one, and--currentexcludes withdrawn associations, showing only what currently holds. It emitspointbreak.review-association-listJSON.- The write forms emit
pointbreak.review-association-commit,pointbreak.review-association-commit-withdrawn,pointbreak.review-association-ref, andpointbreak.review-association-ref-withdrawnJSON with the new association id and write counts.
| Situation | Route | Evidence boundary |
|---|---|---|
| Commit materializes the same reviewed state against its original base | Fresh --source commit:<oid> cursor, ordinary association land |
Existing exact-materialization proof |
| One commit replays an identical scoped delta on a descendant base | --source captured, then --candidate-parent --dry-run, then record with --expect-proof |
Verified scoped equivalent rewrite; original review facts stay historical |
| Changed blobs, modes, paths, status, kind, or included scope | Capture and review a replacement Revision in the same Change | Fresh validation and assessment |
| Root/merge candidate, multi-commit source, staged/unstaged/root capture, non-commit base, unrelated or unavailable history | Use an applicable ordinary route or capture/review a replacement Revision | Parent-relative mode refuses |
| Provenance only, without content equivalence | Structural association record or ordinary land --provenance-only |
No content-qualified claim |
--candidate-parent admits only combined worktree captures or a committed range whose source commit
has exactly one parent equal to the captured base A. The candidate C′ must have exactly one actual
commit-object parent B, and A must be an ancestor of B (equality is allowed). It compares the frozen
artifact's canonical entries with B..C′ using the original capture mode and path scope. Full old/new
blob identities, modes, paths, status and content kinds must match, including untracked-add normalization.
An identical text hunk with different before/after blobs fails. Changes outside an explicitly captured
path scope are outside this claim. Advancing the base produces equivalent rewrite, not exact materialization.
This mode cannot combine with --allow-extension or --provenance-only.
Candidate resolution, parent/tree identity, ancestry, candidate diff and structural endpoint recording
ignore Git replacement objects in this mode. Ordinary capture and landing retain their configured
behavior. The policy is local to each read; it does not change process environment or repository settings.
With an existing exact Change/Revision and an eligible committed candidate, run:
candidate=$(git rev-parse --verify 'HEAD^{commit}')
rewrite_cursor=$(pointbreak change select "$change_id" \
--revision "$revision_id" --source captured --format json | jq -r '.token')
pointbreak association land --review-cursor "$rewrite_cursor" --track "$track" \
--commit "$candidate" --candidate-parent --dry-run --format json > rewrite-preview.json
proof_hash=$(jq -er '.proof.evidenceSha256' rewrite-preview.json)
pointbreak association land --review-cursor "$rewrite_cursor" --track "$track" \
--commit "$candidate" --candidate-parent --expect-proof "$proof_hash"--dry-run also works on the ordinary route. It returns pointbreak.association-land-preview.v1 with
exact Revision, commit/tree OIDs and the full canonical proof. It performs no write-store preparation,
signing-key load, artifact/event publication, migration, rebuild or activation.
There is no write acknowledgement or created/landed claim. Preview does not require --expect-proof,
but checks it when supplied: a mismatched hash refuses without writing anything. Recording in parent
mode requires the hash emitted by the current preview. Any supplied expected hash on ordinary
preview or recording is checked too. Preview JSON is evidence for inspection, never trusted input.
Recording recomputes the proof, revalidates graph/artifact and resolves the candidate again immediately
before publication. Drift refuses before publishing a new proof, association or attestation. Git and the
Journal remain separate authorities; there is no transaction excluding arbitrary external mutation.
The writer uses the resolved commit OID and retains ordered, idempotent proof → association → attestation
publication, truthful partial failures, write acknowledgements and advisory post-truth refresh diagnostics.
A captured cursor is safe here because the independent canonical comparison binds the candidate. It does not permit recording candidate tests or assessments against the old Revision. Original Accepted and validation facts still describe the original captured bytes. Retain candidate validation externally: record exact candidate commit, tree, parent, proof hash, environment/tool identities, commands, result, and attempt identity. This slice adds no candidate-validation command or automatic readiness decision. Upstream changes may still require reviewer attention even when the scoped proof succeeds.
Existing associations remain historical; each proof qualifies one association. Multiple live associations can remain ambiguous, and no whole-tree equivalence follows from a scoped proof. No derived rebuild or new stored schema/capability is required. Push, PR creation and merge need their own authorization. Broader multi-commit rewriting, automatic readiness and candidate-validation storage remain outside this #747 slice.
Divergent or dangling associations surface as advisory diagnostics on the read surfaces
(divergent_commit_association when two or more distinct current commit OIDs claim one revision;
retraction_target_missing when a withdrawal names an association that never appeared); they are
render-only and never gate a write.
pointbreak history [--repo <path>] [--revision <id>] [--track <track-id>] \
[--event-type <event-type>]... [--ref <name> [--by label|liveness]] \
[--filter <query>] [--limit <n>] [--cursor <cursor>] [--watch [--poll-ms <ms>]] \
[--include-body] [--format <fmt>]pointbreak history reads the chronological ledger of durable Pointbreak events.
- History emits compact
pointbreak.review-historyv1 JSON by default. A bounded--limitor--tailrequest uses a current active derived generation when--filter,--ref, and--watchare absent; typed revision, track, event-type, and selected-body hydration remain supported on that route. - A derived page carries
projectionStamp; an authoritative page carrieseventSetHash.eventCountdescribes the complete validated event population behind either page. Non-empty search filters, ref filters, watch mode, and unbounded reads deliberately use the authoritative journal. historyCountis the number of returned entries after filters.- Entries are sorted by
occurredAt, theneventId, as display chronology only. Writers may have skewed clocks, and an event received later can therefore backfill an earlier visible position; this order is neither append order nor causal precedence. --revision,--track, and repeated--event-typenarrow the returned entries.--ref <name>filters to events of revisions associated with a ref (a short branch name is normalized to its full ref).--bychooses how--refmatches:label(the recorded label, offline; the default) orliveness(reachability from the ref's live tip).--filter <query>runs the review filter grammar over the same per-event search records the inspector's timeline queries. Event-surface qualifiers:type:(label or wire id; a comma list ORs values, e.g.type:observation,assessment),track:,actor:(theactor:id prefix is optional),revision:,snapshot:,check:(passed|failed|errored|skipped),assessment:,is:(open|answered),tag:(a full tag string or its first-colon key —tag:issue:191ortag:issue), andbefore:/after:(ISO-8601 date/datetime prefixes). Bare terms match free text — including body content even without--include-body— and a leading-negates a clause. The filter applies before--limit/--cursorwindowing and composes with all the typed flags above. A known-but-unsupported qualifier or value (for exampleattention:here) exits non-zero with the diagnostic; the deprecatedstatus:alias forcheck:still runs behind a stderr hint.--limit <n>returns at most N entries as a forward page (from the start, or from--cursor); the response carries anextCursorto continue.--cursor <cursor>continues from a previous response's opaquenextCursor. Omit both for the full history.--watchre-renders whenever the store's liveness changes, polling client-side at--poll-ms(default 3000). It is pull-only — no daemon and no filesystem watch — and is cancelled with Ctrl-C; under--watchthe same--limitpage is re-rendered on each liveness change.- Succession and commit/ref association filters include
revision-captured,revision-commit-associated,revision-commit-withdrawn,revision-ref-associated, andrevision-ref-withdrawn. - Body-like text is omitted by default.
--include-bodyhydrates observation bodies, input request bodies, input request response reasons, assessment summaries, validation summaries, and imported-note bodies. Native Markdown/plain content-type fields are included for those body-like event fields when they are not plain text. - Duplicate semantic events remain visible as separate entries while shared duplicate diagnostics are included in the document.
pointbreak history, pointbreak revision show, and the inspector endpoints render two
reader-relative, advisory facts beside each event. They render only — they never gate a write or
change an exit code, and the temporal require-verified-endorsement tier is out of scope.
verificationStatus∈valid | invalid | untrusted_key | unsigned— the per-event signature ladder, resolved against the reader's.pointbreak/allowed-signers.json. An event signed by a key the reader has not enrolled readsuntrusted_key; an event with no signature readsunsigned.endorsements[]— for an endorsed (co-signed) target event, one entry per endorsement attestation (co-signature member). Because signatures are deterministic, one signer yields one attestation per target, so this is normally one entry per endorsing signer; an actor who endorses the same target with more than one enrolled key surfaces one entry per key (each is a distinct attestation, not collapsed):classification∈endorsement-trusted | unknown_endorser | ambiguous_endorser.endorser— the resolved actor, present only whenendorsement-trusted.endorserAttributes— the endorser's attestedkind/rolesfrom.pointbreak/actor-attributes.json. This is a sibling enrichment rendered beside the classification; it is not an input to how the classification is decided.
Both are reader-relative: the same endorsement carrier may read endorsement-trusted for a
reader who has enrolled the endorser and unknown_endorser for a reader who has not. A field is
omitted when empty — no verification policy configured, no endorsement on the target, or no attested
attributes for the endorser. The classification rules are decided in
ADR-0013.
{
"eventId": "evt:sha256:…",
"eventType": "work_object_proposed",
"verificationStatus": "unsigned",
"endorsements": [
{
"classification": "endorsement-trusted",
"endorser": "actor:git-email:kevin@swiber.dev",
"endorserAttributes": { "kind": "human", "roles": ["reviewer"] }
},
{ "classification": "unknown_endorser" }
]
}History is not the full revision row projection. Use pointbreak revision show for the composite
narrative-first plus snapshot-complete view of one captured revision.
This is the legacy flat Revision directory. It remains useful for exact historical discovery, but its
proposal-supersession classification is not Change current-set authority. Use pointbreak change list and
pointbreak change show for stable work and contextual topology.
pointbreak revision list [--repo <path>] [--object <object-id>] [--ref <name> [--by label|liveness]] \
[--filter <query>] [--integration-ref <name>] [--worktree <path>] [--all | --unreachable] \
[--limit <1..500> [--cursor <cursor>]] [--format <fmt>]pointbreak revision list is the discovery surface for captured revisions. It emits
pointbreak.review-revision-list JSON with eventCount, revisionCount, entries, and the serving
lane's identity (eventSetHash or projectionStamp)
sorted by capture time. Each entry carries the revision id, the content-only object id, the capture
endpoints when Git provenance exists, the optional capture summary, and
objectArtifactContentHash. Provenance-free revisions remain first-class entries and omit
source, base, and target together rather than inventing Git coordinates. Text output places the
summary beside the short revision id and labels provenance-free entries explicitly; Inspector and VS Code
use the summary as the primary selection label.
-
--limit <n>opts into newest-first, one-captured-revision-per-row paging and accepts values from 1 through 500.nextCursoris present when another page remains; pass it back with the same options via--cursor. A cursor binds the serving profile and snapshot. If either changes, the command exits withrevision page changed; retry without --cursorinstead of translating or silently restarting it. Text output reports the displayed rows separately from the total and prints a continuation cue when another page remains. -
A flagless bounded page uses a current active derived generation and carries
projectionStamp. Object, ref, review-filter, reachability, integration-ref, and worktree-scoped pages retain the authoritative implementation and carryeventSetHash. If an active generation is unavailable, a first page falls back authoritatively with one build hint; its returned cursor is therefore authoritative too. -
--object <object-id>lists only the revisions that share one content object. Coincident content may span supersession threads, so this is a listing/grouping lens, never a head selector. -
--ref <name>filters to revisions associated with a ref (a short branch name is normalized to its full ref).--bychooses how--refmatches:label(the recorded label, offline; the default) orliveness(reachability from the ref's live tip). The succession view (the supersession DAG and a thread's competing heads) is reported by this same projection; there is no separate lineage surface. -
--filter <query>runs the same review filter grammar on the revision surface, over per-revision records aggregated from each revision's review facts. Revision-surface qualifiers:track:andactor:(the union across the revision's facts; theactor:id prefix is optional),revision:,snapshot:,assessment:(the resolved current assessment),is:(open|answered|unassessed|stale|follow-up|contested|superseded),tag:(full string or first-colon key),attention:(open-request|unassessed|validation-context|follow-up|stale-fact), andbefore:/after:(ISO-8601 prefixes over the capture time); bare terms match the revision's human text, and a leading-negates a clause.is:supersededandis:contestedread replacement from the same authority asattention list: on a store that holds Change claims a revision is superseded only when every Change that holds it has replaced it, and nothing is contested (divergence inside a Change surfaces throughchange show); proposal-bornesupersedesdecides them only on a store with no Change claims. Only a filtered listing builds the per-revision overviews and supersession classification — a plain listing pays no new cost — and a grouped row filters on its representative revision. A known-but-unsupported qualifier (type:/check:on this surface) exits non-zero with the diagnostic; the deprecatedstatus:alias forassessment:still runs behind a stderr hint. -
--integration-ref <name>sets the reachability target for themergedstatus: a revision ismergedonly when it is an ancestor of this ref (equality counts). It defaults to the repository's detected default branch (origin/HEAD, else localmain/master) — the same narrow defaultpointbreak revision showapplies — so the status answers "did this land on the default branch?". When no default branch is detected it falls back to broad reachability (any live tip). -
--worktree <path>scopes the listing to captures belonging to the worktree at that path. -
Every recorded revision is shown by default, including revisions whose anchored commits are all unreachable.
--allremains an accepted compatibility spelling of that default;--unreachableexplicitly narrows the listing to only those unreachable revisions (--orphansis a deprecated alias). -
Each entry carries
mergeStatus:merged(an ancestor of the integration target),open(still reachable from a live ref without having landed there),unreachable(no live ref reaches any anchored commit — present-but-unreachable and gc'd objects alike; per-commit detail stays onrevision show), orunknown(floating capture, divergent landing claims, or an unavailable repository). The formerorphanedstatus is retired.
This is the legacy composite Revision view. Use
pointbreak change revision <change-id> <revision-id> --artifact-hash <sha256> for an exact Change-capable
resource and pointbreak change show <change-id> for current-set selection.
pointbreak revision show [REVISION] [--repo <path>] [--track <track-id>] \
[--include-body] [--format <fmt>]pointbreak revision show is the composite view for one revision. It emits compact
pointbreak.review-revision v2 JSON by default.
- When exactly one revision has been captured, Pointbreak selects it automatically.
- If multiple revisions exist, pass the
[REVISION]positional. It is a head seed: a current head resolves exactly; a superseded revision resolves its thread's current head; and a thread with competing heads is reported as competing rather than auto-picked. revision showretains legacy proposal-supersession selection and facets and does not follow Change replacement: the[REVISION]head seed,validationChecks[].supersededByRevisions, andstale_by_superseding_revisionread the proposal-bornesupersedeslist only, so a Revision a Change has replaced still resolves to itself. On a store that holds Change authority the document says so with the advisory diagnosticchange_replacement_not_followed, and the text digest ends with the same pointer. Read Change-scoped replacement withpointbreak change show <change-id>(current set) and the exact Revision withpointbreak change revision <change-id> <revision-id> --artifact-hash <sha256>;change revisionshares this projection without the redirect.- The output includes revision identity, event-set freshness metadata, filters, summary counts, current assessment status, native observations, input requests, assessments, validation checks, projection rows, and diagnostics.
- Rows are narrative-first, then snapshot-complete.
commitRange.livenessis the read-time Git enrichment (best-effort; omitted when the repository cannot be read).perCommit[].conditionismerged,live,unreachable(object present, no live ref reaches it), ormissing(object gone) — availability and reachability stay distinguishable, and nothing is calledorphaned. Anunreachablecommit also carriesretention:reflogwhile a reflog entry still retains the object,noneafter expiry.refContinuitydiagnoses each recorded ref association:current,advanced,rewritten(best-effort reflog evidence naming therewriteAction, e.g.commit (amend), plussameTreewhen both objects survive),moved(no rewrite evidence — expired reflog or a reset),deleted, orunknown. Arewrittenref adds aref_rewrittendiagnostic naming the recorded and current OIDs with the suggested explicit follow-up; reflog evidence never mutates the durable record.--track <track-id>filters narrative facts without changing the selected revision, event-set freshness metadata, or captured snapshot completeness.- Body-like text is omitted by default.
--include-bodyhydrates observation bodies, input request bodies and response reasons, assessment summaries, validation summaries, and imported-note bodies. Native Markdown/plain content-type fields are included for those body-like event fields when they are not plain text. - Each narrative member (observations, input requests and their responses, assessments, validation
checks) and the
revisionidentity (the capture event) carry the same reader-relativeverificationStatusandendorsements(withendorserAttributes) readback documented underpointbreak history— advisory, render-only, resolved against the reader's.pointbreak/trust and attributes config.
Revision-scoped selection seeds on the [REVISION] positional and resolves that revision's thread
head; no implicit newest capture globally wins. Unscoped current selection with multiple unrelated captured
revisions still errors at the selection boundary, but routine list, history, and exact-revision reads
have no always-on ambiguous-current warning. A thread-level read may surface
stale_by_superseding_revision for a revision that a newer revision supersedes. This release has no
interdiff or stack DAG beyond the supersession graph.
Capture and succession facts stay signable under ADR-0004's generic EventToBeSigned contract with
the Dead Simple Signing Envelope (DSSE) and pre-authentication encoding rules.
pointbreak revision show is distinct from pointbreak history: history is the chronological raw
event listing, while pointbreak revision show is the composite revision view for agents and future
frontends.