Repository navigation
feat(#89): reactive consumer (stage 1) — dependents reader + staleness predicates - #126
Merged
Merged
Conversation
paddymul
force-pushed
the
feat/89-reactive-consumer-staleness
branch
3 times, most recently
from
June 18, 2026 19:43
4f14672 to
7185e2d
Compare
paddymul
marked this pull request as ready for review
June 18, 2026 19:54
Contributor
Author
|
✅ CI green (lint + fast + integration) on TDD trail: |
Failing-first (TDD): tests/test_dependents.py and tests/test_staleness.py exercise the read-only half of the reactive consumer (epic #89), which does not exist yet — both error on import of tallyman_xorq.dependents / tallyman_xorq.staleness. dependents: parents_of / build_dag / dependents_index / descendant_cone over manifest.parents, covered with synthetic manifests (chain, diamond, mixed follow/pin, cycle-raises, leaf). staleness: entry_staleness's two axes (followed-alias-advanced, source-drifted) and scan's direct-vs-transitive tagging, covered with real catalog_create / catalog_revise builds — alias advance marks a follow child stale, a hash pin does not, an in-place source edit marks the entry stale under cas, off mode reports the source axis unknown (not fresh), and a source edit under a chain root tags descendants transitively stale. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the read-only half of the reactive consumer (epic #89), turning tests/test_dependents.py and tests/test_staleness.py green. - tallyman_xorq/dependents.py — parents_of / build_dag / dependents_index / descendant_cone over manifest.parents. Rebuilds the DAG walk #76 deleted with lineage.py (the walk, not the column lineage), enumerating via build.list_entries so an uncheckpointed entry is still seen. descendant_cone is topologically ordered (Kahn) and raises DependencyCycleError rather than looping on a cycle. - tallyman_xorq/staleness.py — entry_staleness over two read-only axes (followed-alias-advanced; source-drifted, forced past digest_for's stat memo) and scan tagging direct vs transitive staleness across the dependency cone. off mode reports the source axis unknown, not fresh. result_digest is not a staleness input — recompute nondeterminism is the #83/#121 path, not this one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
paddymul
force-pushed
the
feat/89-reactive-consumer-staleness
branch
from
June 18, 2026 20:06
67272c6 to
b8eb009
Compare
This was referenced Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First landable increment of the reactive consumer (epic #89) — the read-only
half: walk the recorded
manifest.parentsDAG and flag which entries are stalerelative to their inputs. No recompute yet (that is the next increment), so this
is independent of #115 (cold-read content-faithfulness) and #121 (determinism
attribution) and can land in parallel.
Design:
plans/reactive-staleness-recalc.md(prerequisite item #1 + Stage 1).What lands
tallyman_xorq/dependents.py—parents_of,build_dag,dependents_index(the reverse index recalc needs, which did not existanywhere), and
descendant_cone(topologically ordered, parents-before-children, cycle-detecting). Pure graph logic over
manifest.parents; rebuildsthe DAG-walk caching: expensive-parent from_catalog children pin the parent's untracked compute_cache snapshot by path — child read fails (no recompute) when it's pruned or uncloned #76 deleted with
lineage.pywithout reviving column lineage.tallyman_xorq/staleness.py—entry_stalenessover two read-only axes:a
follow=Trueparent whose alias head advanced, and a recorded source digestthat no longer matches the file on disk (re-digested with the same
source_identityhelper, forced past its stat-memo for a sound check).scanruns it over every live entry and tags direct (own inputs moved) vs
transitive (a directly-stale ancestor in the cone). off-mode reports the
source axis
unknown, neverfresh.TDD
Red→green. This PR's first commit is the failing tests (modules absent); the fix
commit follows once CI shows them red. Watching CI.
Decision defaults exercised (confirm)
unknown(not fresh).follow=False) child → never stale on the alias axis.Not in this PR
The recalc action (rebuild the cone) and the MCP/companion surfaces — they
depend on the cascade-failure and trigger-model decisions and on #115/#118.
🤖 Generated with Claude Code