Skip to content

feat(temporal_spine): flip defaults ON (#1064) — HOLD: merge after #1090 + operator go - #1092

Closed
robotrocketscience wants to merge 4 commits into
mainfrom
feat/issue-1064-flip-default-on
Closed

robotrocketscience wants to merge 4 commits into
mainfrom
feat/issue-1064-flip-default-on

Conversation

@robotrocketscience

@robotrocketscience robotrocketscience commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Temporal spine → default-ON (the #1064 flip)

⚠️ HOLD — do not merge yet. This is staged at the operator's request. Merge only:

  1. after feat(temporal_spine): G4 migration — auto-once backfill + reversible spine clear (#1064) #1090 (the G4 auto-once backfill) lands on main — otherwise the flip delivers no historical spine for existing stores; and
  2. on the operator's explicit go — flipping a global default is a release decision.

This PR is opened as a draft to enforce (1)+(2). It will need a rebase once #1090 merges (the design-doc Status line reconciles against #1090's G4 edit).

What it does

Every pre-registered evidence gate passed — G1 (+14.6pp LoCoMo), G2 (production-budget trim survival + 1,986/1,986 top-rank invariance), G3 (latency delta in band), G5 (two-build determinism + ablation-green) — and G4 migration is resolved (#1090). So both flags flip default-ON:

  • is_temporal_spine_write_enabled default False → True — ingest chains new beliefs by default.
  • is_temporal_spine_enabled (lane) default False → True — retrieval traverses the spine by default.

Per-flag opt-out is unchanged (AELFRICE_TEMPORAL_SPINE_WRITE=0 / AELFRICE_TEMPORAL_SPINE=0, or the .aelfrice.toml keys). Existing stores get their historical spine via #1090's sentinel-gated auto-backfill on the first aelf setup after upgrade.

Blast radius (measured)

Full suite: 5651 passed after updating the tests that pinned the default-off posture. The lane flip is contained because a store with no TEMPORAL_NEXT edges makes the lane a no-op (empty-lane guard) — every retrieval test on a spineless store is byte-identical. The only fallout was in test_temporal_spine.py: default-flag assertions flipped, the ingest off-path became an explicit opt-out (+ a new default-on ingest test), and the two "unrecognised/malformed value not decisive" tests now prove non-decisiveness against a lower rung rather than the default.

Verification

  • Full pytest: 5651 passed / 69 skipped / 75 xfailed.
  • Discretion grep clean; two atomic signed commits (feat, then docs).

Summary by CodeRabbit

  • New Features
    • Temporal spine now defaults to ON for both ingest and retrieval.
    • New stores automatically use the spine behavior after upgrade, with existing stores backfilled on first setup.
  • Bug Fixes
    • Invalid or malformed settings no longer force the feature off; the system falls back to the default ON behavior.
    • Explicit opt-out remains available for both writing and retrieval.
  • Documentation
    • Updated release notes and design docs to reflect the new default-ON behavior and opt-out settings.

@robotrocketscience robotrocketscience added the author-Kulili PR coordination mutex label Jul 5, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 89 changed lines (limit: 200)
  • 5 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

@robotrocketscience
robotrocketscience marked this pull request as draft July 5, 2026 06:18
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4c52a0a7-acb7-4490-969c-92cce29098cb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR flips two temporal-spine feature flags from default-off to default-on: is_temporal_spine_write_enabled in temporal_spine.py and is_temporal_spine_enabled in retrieval.py. Docstrings, tests, design docs, and the changelog are updated to reflect the new default-on behavior and existing opt-out mechanisms.

Changes

Temporal spine default-on flip

Layer / File(s) Summary
Ingest writer flag default flip
src/aelfrice/temporal_spine.py, tests/test_temporal_spine.py
is_temporal_spine_write_enabled() fallback return changes from False to True; docstring precedence updated; tests updated for default-on, malformed/unrecognized env fallback, and ingest wiring (opt-out vs default chaining).
Retrieval lane default flip
src/aelfrice/retrieval.py, tests/test_temporal_spine.py
is_temporal_spine_enabled() fallback return changes from False to True; docstring updated; test asserts default True with explicit=False override.
Documentation and changelog updates
docs/design/feature-temporal-spine.md, CHANGELOG/v3.md
Design doc status and changelog Unreleased/Changed section updated to describe the default-ON flip, evidence gate, opt-out flags, and backfill/no-op behavior.

Estimated code review effort: 2 (Simple) | ~12 minutes

Possibly related issues

Possibly related PRs

  • robotrocketscience/aelfrice#1069: Directly modifies the same flag-resolution functions (is_temporal_spine_enabled, is_temporal_spine_write_enabled) introduced in that PR by flipping their default.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the default-ON flip for Temporal spine and mentions the merge hold dependency.
Description check ✅ Passed The description covers the change, rationale, impact, and verification, but omits explicit linked issues, type, and test-plan sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-1064-flip-default-on

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/aelfrice/temporal_spine.py (1)

124-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Confusing parenthetical contradicts the preceding sentence.

The docstring states "Default-ON since the #1064 flip" and then immediately adds "(Landed default-off; the flip is that issue's deliverable 5...)" in the same paragraph. Read at a glance this reads as self-contradictory — a future maintainer skimming the docstring could misread the current default as off. Consider rewording to make clear this parenthetical is purely historical (original landing) vs. current state (this release).

✏️ Suggested rewording
     Default-ON since the `#1064` flip: every evidence gate (G1–G5) passed,
     so the ingest writer chains new beliefs by default. Opt out with
     ``AELFRICE_TEMPORAL_SPINE_WRITE=0`` or ``[ingest] write_temporal_spine
-    = false``. (Landed default-off; the flip is that issue's deliverable
-    5, shipped as a release default change plus the auto-once backfill for
-    existing stores.)
+    = false``. (`#1064` originally landed default-off; this default-ON flip
+    is that issue's deliverable 5, shipped as a release default change
+    plus the auto-once backfill for existing stores.)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aelfrice/temporal_spine.py` around lines 124 - 131, The docstring in
temporal_spine is confusing because the “Default-ON since the `#1064` flip”
sentence is immediately followed by a parenthetical that sounds contradictory.
Reword the documentation around the ingest writer default so it clearly
separates the current behavior from the historical landing note, and keep the
explanation near the existing AELFRICE_TEMPORAL_SPINE_WRITE / [ingest]
write_temporal_spine references.
src/aelfrice/retrieval.py (1)

3270-3277: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale "default-OFF" comment after the flip.

This block-comment above the temporal-spine traversal still says (additive, default-OFF), but is_temporal_spine_enabled now defaults to True per the updated docstring/behavior in this same PR. Left as-is, it will mislead future readers about the lane's default state.

📝 Suggested comment fix
-    # `#1064` temporal-spine lane (additive, default-OFF). Traverses
+    # `#1064` temporal-spine lane (additive, default-ON since the flip).
+    # Traverses
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aelfrice/retrieval.py` around lines 3270 - 3277, Update the block comment
above the temporal-spine traversal so it no longer says “default-OFF”; align it
with the current behavior where is_temporal_spine_enabled defaults to True. Keep
the rest of the `#1064` commentary intact, and make the wording in retrieval.py
consistent with the nearby docstring and traversal logic so future readers don’t
get conflicting guidance.
tests/test_temporal_spine.py (1)

487-489: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Missing isolation in test_lane_default_on_flag.

Unlike the sibling flag tests in this file, this test doesn't accept monkeypatch/tmp_path and calls is_temporal_spine_enabled() / is_temporal_spine_enabled(explicit=False) without pinning start= or clearing AELFRICE_TEMPORAL_SPINE. A leaked env var from another test/CI config, or a real .aelfrice.toml found while walking up from cwd, would make this assertion non-deterministic.

🧪 Suggested isolation fix
-def test_lane_default_on_flag() -> None:
-    assert is_temporal_spine_enabled() is True          # default-ON (`#1064` flip)
-    assert is_temporal_spine_enabled(explicit=False) is False
-    assert resolve_temporal_spine_budget() == 32
-    assert resolve_temporal_spine_budget(explicit=7) == 7
+def test_lane_default_on_flag(monkeypatch: pytest.MonkeyPatch, tmp_path) -> None:
+    monkeypatch.delenv(ENV_TEMPORAL_SPINE, raising=False)
+    assert is_temporal_spine_enabled(start=tmp_path) is True  # default-ON (`#1064` flip)
+    assert is_temporal_spine_enabled(explicit=False, start=tmp_path) is False
+    assert resolve_temporal_spine_budget() == 32
+    assert resolve_temporal_spine_budget(explicit=7) == 7
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_temporal_spine.py` around lines 487 - 489,
`test_lane_default_on_flag` is not isolated because it relies on ambient
configuration when calling `is_temporal_spine_enabled()`. Update this test to
accept the same isolation fixtures used by the sibling flag tests, then
explicitly clear `AELFRICE_TEMPORAL_SPINE` and pin the search root/start
directory so the check cannot pick up a leaked env var or an on-disk
`.aelfrice.toml`. Keep the assertions in `test_lane_default_on_flag` but make
them deterministic by controlling the environment and lookup scope.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/aelfrice/temporal_spine.py`:
- Line 141: The stale ingest comment in the `is_temporal_spine_write_enabled()`
flow no longer matches the implementation because the fallback now returns True
instead of Default-OFF. Update the comment in `ingest.py` around the
`is_temporal_spine_write_enabled` call site to reflect the current default
state, keeping the wording aligned with the behavior in `temporal_spine.py`.

---

Nitpick comments:
In `@src/aelfrice/retrieval.py`:
- Around line 3270-3277: Update the block comment above the temporal-spine
traversal so it no longer says “default-OFF”; align it with the current behavior
where is_temporal_spine_enabled defaults to True. Keep the rest of the `#1064`
commentary intact, and make the wording in retrieval.py consistent with the
nearby docstring and traversal logic so future readers don’t get conflicting
guidance.

In `@src/aelfrice/temporal_spine.py`:
- Around line 124-131: The docstring in temporal_spine is confusing because the
“Default-ON since the `#1064` flip” sentence is immediately followed by a
parenthetical that sounds contradictory. Reword the documentation around the
ingest writer default so it clearly separates the current behavior from the
historical landing note, and keep the explanation near the existing
AELFRICE_TEMPORAL_SPINE_WRITE / [ingest] write_temporal_spine references.

In `@tests/test_temporal_spine.py`:
- Around line 487-489: `test_lane_default_on_flag` is not isolated because it
relies on ambient configuration when calling `is_temporal_spine_enabled()`.
Update this test to accept the same isolation fixtures used by the sibling flag
tests, then explicitly clear `AELFRICE_TEMPORAL_SPINE` and pin the search
root/start directory so the check cannot pick up a leaked env var or an on-disk
`.aelfrice.toml`. Keep the assertions in `test_lane_default_on_flag` but make
them deterministic by controlling the environment and lookup scope.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5ab80cbf-020e-4a5e-95fa-7f83c6252d4c

📥 Commits

Reviewing files that changed from the base of the PR and between 40ecfbe and 0918dc5.

📒 Files selected for processing (5)
  • CHANGELOG/v3.md
  • docs/design/feature-temporal-spine.md
  • src/aelfrice/retrieval.py
  • src/aelfrice/temporal_spine.py
  • tests/test_temporal_spine.py

Comment thread src/aelfrice/temporal_spine.py
@robotrocketscience
robotrocketscience force-pushed the feat/issue-1064-flip-default-on branch 2 times, most recently from d36e5c6 to 03c8327 Compare July 6, 2026 20:17
All pre-registered evidence gates passed (G1-G3, G5) and G4 migration is
resolved (#1090 auto-once backfill + spine clear), so both temporal-spine
flags flip default-ON:

- is_temporal_spine_write_enabled default False -> True (ingest chains new
  beliefs by default; opt out AELFRICE_TEMPORAL_SPINE_WRITE=0 / toml).
- is_temporal_spine_enabled (lane) default False -> True (retrieval
  traverses the spine; opt out AELFRICE_TEMPORAL_SPINE=0 / toml).

A store with no TEMPORAL_NEXT edges keeps the lane a no-op, so retrieval
is byte-identical until a spine exists. Tests that pinned the default-off
posture flip to default-on (flag defaults, lane default, ingest off-path
now an explicit opt-out + a new default-on ingest test); the
'unrecognised/malformed value not decisive' tests now prove
non-decisiveness against a lower rung rather than the default. CHANGELOG
Changed entry added.
Status -> default-ON (flipped); flip-gate section retained as the
pre-registration record.
The flip changed is_temporal_spine_write_enabled to default True, so the
sentinel-gated auto-once backfill now fires on the unset/default path.
test_auto_backfill_default_gate_reads_writer_flag still encoded the old
default-off expectation (ran is False / no sentinel); update it to the
flipped default (ran is True / sentinel written), matching the ratified
#1064 G4 behavior — the backfill fires exactly once the write flag is
enabled, which it now is by default. The sibling explicit-kwarg tests
(runs-when-enabled, rearms-after-flip) already cover the gate both ways.
@robotrocketscience
robotrocketscience force-pushed the feat/issue-1064-flip-default-on branch from 03c8327 to 51df323 Compare July 6, 2026 20:48
…-flip (#1064)

The defaults flip left the writer and lane doc-comments describing the
pre-flip posture: ingest call-site, the module docstring, the backfill
short-circuit note, and the two retrieval-lane comments still read
Default-OFF. Update them to the post-flip default-ON wording (opt-out via
env/toml). Comment/docstring-only; no logic change. Resolves the CodeRabbit
staleness thread on this PR.
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

merge-train: blocked

FF push to main failed:\n\n\nremote: error: GH013: Repository rule violations found for refs/heads/main. remote: Review all repository rules at https://github.com/robotrocketscience/aelfrice/rules?ref=refs%2Fheads%2Fmain remote: remote: - Changes must be made through a pull request. remote: To https://github.com/robotrocketscience/aelfrice ! [remote rejected] 46861efaff91262107378245dc990803a3731e5a -> main (push declined due to repository rule violations) error: failed to push some refs to 'https://github.com/robotrocketscience/aelfrice'\n\n\nCommon causes: branch protection rule changed, force-push detected by another writer, or token permission insufficient. Re-add the label after investigating.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Operator-directed split (2026-07-06): the writer half is being carved out into #1111.

Per operator decision, the temporal-spine flip is split so the write-side ships now while the read-side waits for the retrieval cutover:

Rationale in #1111's description. Flagging so this HOLD draft isn't merged as 'both flags' — the writer half is now #1111.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Superseded by PR #1114 — the #1107 Phase-2 cutover delivers the lane-only flip this draft was reduced to (shim exposes use_temporal_spine resolver-driven on the production retrieve() path + resolver default flipped ON). Suggest closing this draft once #1114 merges; operator's disposition.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Closing — superseded by #1114, which delivered the lane-half of the flip as #1107 Phase 2 (resolver-driven use_temporal_spine=None on the production retrieve() path + resolver default flipped ON). The writer-half shipped separately in #1111. Nothing left here to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-Kulili PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant