# git-cas v6.3.0 Release Notes

`v6.3.0` closes the lifetime gap between observing a CacheSet hit and consuming
its handle. Applications can now retain a bounded cache hit for exactly one
explicit scope without learning Git refs or recursively validating a large
target graph during lookup.

## Scoped Cache Acquisitions

```javascript
const acquisition = await cache.acquire(materializationKey);
if (acquisition) {
  try {
    await consume(acquisition.hit.handle);
  } finally {
    await acquisition.release();
  }
}
```

`acquire()` reads only the cache index path needed for the requested key. An
atomic Git ref transaction verifies the observed cache generation and creates a
unique acquisition ref that anchors that generation. Replacement, expiry,
capacity eviction, or explicit removal may then publish a newer cache
generation without making the acquired target collectible during use.

The returned `CacheAcquisition` contains:

- the immutable `CacheHit` observation;
- separate pinned `RetentionWitness` evidence for the active acquisition;
- an opaque acquisition ID and canonical acquisition time;
- an idempotent, generation-checked `release()` operation.

An acquisition retains the selected cache generation, not only one target.
Callers must release it in `finally`. The API intentionally supplies no
automatic TTL because age cannot prove that an active consumer is dead.

## Operations And Diagnostics

`cache.inspectAcquisitions({ limit })` reads at most `limit + 1` refs from one
exact cache namespace and reports `truncated` without disclosing original cache
keys. Recovery tooling releases the returned entries with
`cache.releaseAcquisition({ id, expectedGeneration })`, then repeats inspection
when `truncated` is true. Cleanup refuses an unexpected generation or symbolic
ref observed at preflight. Every mutation uses no-dereference mode, so a
post-probe symbolic-ref race can affect only the managed acquisition ref name,
never its referent. Ordinary RootSet, publication, and vault ref updates now use
the same preflight and no-dereference boundary, closing a pre-existing path that
could otherwise follow a managed symbolic ref into an external referent.

`cas.diagnostics.doctor()` now reports active acquisition count, oldest and
newest acquisition timestamps, maximum age, bounded detail coverage, and
malformed acquisition refs. This exposes abandoned anchors before destructive
repository maintenance. A future-dated but structurally valid direct ref remains
healthy with `ageMs: null` and a `CACHE_ACQUISITION_CLOCK_SKEW` issue; clock
order is not treated as retention authority. Git does not enumerate dangling
symbolic refs through `for-each-ref`, so doctor cannot claim exhaustive dangling-symref inventory;
missing ref-type evidence is unhealthy, and direct mutation paths independently
preflight symbolic refs before no-dereference updates. Checked deletion gathers
ref-type evidence after a transaction conflict and then fails closed. Git 2.43
cannot atomically prove that an absent direct ref is not a dangling symbolic ref,
so recovery code must re-inspect the bounded namespace before declaring cleanup
complete.

## Compatibility

This minor release is API-additive. Existing CacheSet `get()`, `put()`, `replace()`,
`remove()`, `sweep()`, `touch()`, doctor, repair, stored generations, and ref
stored formats remain compatible. Acquisition ref namespaces are canonical
encoded path segments, pre-existing symbolic refs are rejected, and concurrent
ref-type races cannot redirect mutations to symbolic referents. Existing custom
Git ref ports remain structurally compatible because acquisition-only
capabilities are optional until invoked. The existing `RetentionRootKind` union
is unchanged, and the new doctor acquisition group is declaration-optional for
structural compatibility. The existing diagnostic limitation `kind` union is
also unchanged; acquisition-detail truncation uses its own open string error
code. `get()` retains its existing complete target
validation semantics; applications that need a lifetime-safe, bounded hot path
should adopt `acquire()`.

## Verification

Focused unit and real-Git integration coverage proves bounded lookup,
generation-race retry, explicit and checked release, doctor inventory, and
survival across `git prune --expire=now`, namespace isolation, symbolic-ref
authority safety, work-bounded inventory, and legacy adapter type compatibility.
The release-candidate verifier passed 14/14 local gates and observed 6,325
tests across Node, Bun, and Deno. Its npm dry run contained 242 files;
the non-packaged verification witness records the exact byte receipt without
making the package describe its own compressed size. CI, self-review, Code
Rabbit, and independent Code Lawyer remain mandatory gates before tagging.

See [Scoped Cache Acquisitions](../API.md#acquire-and-release) for the complete
API contract and
[PERF-0048](https://github.com/git-stunts/git-cas/blob/main/docs/design/0048-scoped-cache-acquisitions/scoped-cache-acquisitions.md)
for the design and proof obligations.
