---
schema_version: 1
id: RAC-KV2E57KR1CBS
type: roadmap
---
# RAC v0.13.2 — Git-Derived Recency

## Status

Planned

## Context

Retention depends on the write habit: a corpus that stops growing is a
product that stops being used. To nudge the habit (v0.13.3) and to
measure it, RAC needs to know when artifacts were last written — but
artifacts carry no timestamp. Frontmatter holds only `schema_version`,
`id`, `type`, and `relationships`; adding a date field would mean a
`schema_version` bump, hand-maintained dates that drift from reality,
and a metadata-versus-meaning tension the corpus has avoided.

The repository already records exactly when each file last changed: git
history. ADR-013 makes leveraging existing source control a standing
principle, and the watchkeeper series already established that git access
belongs in one isolated module (ADR-043). This milestone adds a second,
equally narrow git touchpoint: deriving each artifact's last-authored
time from `git log`, with no schema change and no hand-kept dates.
ADR-045 records the decision to source recency from git rather than
frontmatter.

This milestone is foundation only. It computes recency and exposes it as
a reusable service; it adds no user-facing nudge (v0.13.3) and no commit
hook (v0.13.4).

## Outcomes

- RAC can report, for any artifact, when it was last committed, derived
  from git with no schema change and no frontmatter date.
- RAC can report corpus-level recency — when any artifact, or any
  artifact of a given type, was last authored — so a "no decision in two
  weeks" signal (v0.13.3) has data to stand on.
- Recency lives in one small git-aware module with a directory-in,
  data-out contract, keeping every other service git-free (ADR-043's
  isolation principle preserved).
- Outside a git repository, or for an uncommitted file, recency is a
  clean "unknown", never an error — recency is advisory, never required.

## Initiatives

### Initiative 1 — Recency Service

A `recency` service in the services layer computes last-authored times
from git: per-artifact (`git log -1 --format=%cI -- <path>`) and
corpus-level aggregates (most recent overall, and most recent per type).
It returns a typed result with timezone-aware timestamps and explicit
`None` for files git does not know about, mirroring the
`revisions.py` posture: capture subprocess output, never mutate `.git`,
work offline.

### Initiative 2 — Graceful Degradation Contract

The service answers "unknown" rather than raising when git is
unavailable, the directory is not a repository, or a file is untracked
or uncommitted. A corpus with some committed and some new files yields a
mix of known and unknown recency, which is the realistic working state.

## Constraints

- No frontmatter schema change and no `schema_version` bump: recency is
  derived, never stored (ADR-045).
- Git access stays isolated to recency and revision modules; no other
  service imports git helpers (ADR-043's boundary).
- Timestamps are commit times (`%cI`, ISO-8601, timezone-aware), not
  author times or filesystem mtimes, so the value is stable across
  checkouts.

## Non-Goals

- Any user-facing finding, nudge, or output (v0.13.3 consumes this
  service).
- A commit hook (v0.13.4).
- Per-line or per-section history, blame, or churn analysis — only the
  last-authored timestamp per artifact and its aggregates.

## Implementation Contract

The following decisions are pinned for v0.13.2.

### Service API

- `artifact_recency(directory, recursive=True)` returns a result mapping
  each artifact path to a last-committed timestamp or `None`, plus
  aggregates: most recent overall and most recent per artifact type.
- Timestamps come from `git log -1 --format=%cI -- <path>` run at the
  repository root; an empty result means the file is untracked or
  uncommitted (`None`).
- Outside a git repository the whole result is "unknown" (every
  timestamp `None`, aggregates `None`); no exception crosses the service
  boundary.

### Determinism

- The service is read-only and offline; it never writes, fetches, or
  mutates `.git`.
- Tests run against throwaway git repositories created in temporary
  directories, asserting known commit times and the unknown paths.

## Success Measures

- For a corpus committed at a known time in a throwaway repository, the
  service returns that time per artifact and as the corpus aggregate.
- A mix of committed and newly-added files yields known timestamps for
  the former and `None` for the latter.
- Run outside any git repository, the service returns all-unknown
  without raising.

## Risks

- `git log` per file is one subprocess per artifact. Mitigated: corpora
  are small (hundreds of files at most), the call is cheap, and the
  service is invoked only when a consumer asks for recency.
- Shallow clones can lack the history depth to date older files.
  Mitigated: an undated file degrades to "unknown", which the cadence
  nudge treats conservatively rather than as freshly written.

## Assumptions

- Consumers that care about recency run inside the user's git
  repository, where history exists.
- Commit time is an acceptable proxy for "when the knowledge was last
  written"; rebases and amends move it, which is acceptable for a
  cadence signal.

## Related Decisions

- adr-013
- adr-043
- adr-045

## Related Requirements

- rac-growth-adoption

## Related Roadmaps

- v0.13.3-cadence-nudge
