Skip to content

D274 — Per-concept history is a read-only tool, and concept_read takes a commit rev

Decision. concept_history(id, [limit]) lists the commits that touched a concept, following renames, with the Reason: trailer of D272. concept_read gains an optional rev, a 7–40 hex commit SHA, and returns the concept as of that commit. Both are read-only, scoped and hidden exactly like concept_read, and concept_history is in the core agent profile.

Why. Every write is a git commit, but a remote client has no clone and an agent is told not to run git in the KB, so "when and why did this page change" and "what did it say before" were unanswerable over MCP; changes_since only aggregates by time window. The history is git log --follow on the concept's current file (gitx.FileHistory), the same record format as LogNameStatus. rev resolves through that history: the newest entry that is rev or an ancestor (gitx.IsAncestor) is the version in force at rev, which is what makes a read across a rename or an expansion work.

Alternatives rejected. - A server-side diff tool: adds a format to maintain; an agent compares two concept_read results itself. - Accepting any git ref for rev: the value reaches a git argument, so only a hex SHA is allowed (no branch names, HEAD~n, or option-like input). - Advanced profile, like graph_path: reviewing why a page changed is a normal step before editing it.

Consequences. --follow is a heuristic: when git's rename detection misses a rename or an expansion the history starts there, and a new file very similar to an existing one can inherit that file's history. The history walk for rev is capped at 1000 commits. content_hash of a historical read is not an if_match. Without git, or with auto-commit off, concept_history returns an empty list and a note rather than an error.