gabriel / muse public
feat patch feat/53-symlog-time-syntax #1 / 1
AI Agent gabriel · 8 hours ago · Oct 22, 2026 · Diff

feat: muse#53 item 6 — relative time syntax for symlog @{...} refs

Extends resolve_symlog_addr() to accept relative-time specs alongside the existing @{N} integer-index form, mirroring muse#54 item 1's reflog equivalent:

- @{N.unit.ago} — unit is second/minute/hour/day/week, singular or plural (e.g. "1.hour.ago", "2.days.ago"). - @{yesterday} — start of today (UTC midnight).

Both forms resolve to the newest entry at or before the computed cutoff. _SYMLOG_REF_RE (duplicated in both muse/core/symlog.py and muse/cli/commands/symlog.py -- the CLI validates the addr@{...} shape before calling into core) was broadened from a digits-only capture to "anything inside the braces" in both places; disambiguation (digit vs time spec) happens in the new _resolve_symlog_index() helper inside resolve_symlog_addr() itself, so none of the three CLI call sites (resolve/show/diff) needed changes beyond the regex. An out-of-range digit index still raises IndexError(index, total); a valid time spec with no qualifying entry raises IndexError(-1, total); an unrecognized @{...} spec raises ValueError.

Covered by tests/test_symlog_time_resolution.py (7 cases: hour-ago cutoff selection, minutes-ago, yesterday, no-entry-old-enough raises IndexError, unrecognized spec raises ValueError, non-regression of the plain @{N} index form, and a `muse symlog resolve` CLI integration test). Confirmed genuine RED by reverting the fix file and re-running (6 of 7 failed; the plain-index non-regression case passed incidentally since it's pre-existing unaffected behavior), then GREEN with the fix restored plus the full symlog regression suite (229 tests, zero regressions). Live-verified via muse-dev against a disposable /tmp sandbox (0.second.ago resolves correctly; 1.week.ago with no qualifying entry produces a clear out-of-range error).

Co-Authored-By: Claude Sonnet 5 <[email protected]>

sha256:9cb57906be1b86b25d7956f3bd72fe735ecde4b0bdde0b005c500d4f7e0f983c sha
+32 ~6 symbols
4 changed · 1234 in snapshot files
sha256:c6a2358801e8ecd48df043319d57a4a1b5b3facf1e7ea8081d2e6e77b5655bd8 snapshot
+32
symbols added
~6
symbols modified
4
files changed
1234
files in snapshot
0
dead code introduced
Semantic Changes 38 symbols
~ tests/test_symlog_time_resolution.py .py 28 symbols added
+ TestSymlogTimeAgoResolutionCore class class TestSymlogTimeAgoResolutionCore L76–157
+ test_hour_ago_finds_entry_before_cutoff method method test_hour_ago_finds_entry_before_cutoff L77–90
+ test_minutes_ago_finds_most_recent method method test_minutes_ago_finds_most_recent L92–105
+ test_no_entry_old_enough_raises_index_error method method test_no_entry_old_enough_raises_index_error L123–132
+ test_plain_index_still_works method method test_plain_index_still_works L145–157
+ test_unrecognized_spec_raises_value_error method method test_unrecognized_spec_raises_value_error L134–143
+ test_yesterday_finds_entry_before_todays_midnight method method test_yesterday_finds_entry_before_todays_midnight L107–121
+ TestSymlogTimeAgoViaCli class class TestSymlogTimeAgoViaCli L160–169
+ test_resolve_accepts_time_spec method method test_resolve_accepts_time_spec L161–169
+ _commit function function _commit L46–56
+ _fake_id function function _fake_id L72–73
+ _init_repo function function _init_repo L35–37
+ _invoke function function _invoke L26–32
+ _make_repo function function _make_repo L59–61
+ _write_file function function _write_file L40–43
+ _write_raw_entry function function _write_raw_entry L64–69
+ CliRunner import import CliRunner L20–20
+ NULL_CONTENT_ID import import NULL_CONTENT_ID L21–21
+ annotations import import annotations L10–10
+ datetime import import datetime L12–12
+ json import import json L13–13
+ os import import os L14–14
+ pathlib import import pathlib L15–15
+ pytest import import pytest L18–18
+ resolve_symlog_addr import import resolve_symlog_addr L21–21
+ symlog_path import import symlog_path L21–21
+ textwrap import import textwrap L16–16
+ runner variable variable runner L23–23
~ muse/cli/commands/symlog.py .py 1 symbol modified
~ muse/core/symlog.py .py 4 symbols added, 2 symbols modified
+ _SYMLOG_TIME_AGO_RE variable variable _SYMLOG_TIME_AGO_RE L969–971
+ _SYMLOG_TIME_UNIT_SECONDS variable variable _SYMLOG_TIME_UNIT_SECONDS L973–975
+ _parse_symlog_time_cutoff function function _parse_symlog_time_cutoff L978–997
+ _resolve_symlog_index function function _resolve_symlog_index L1000–1030
Files Changed
+1 ~3
1234 in snapshot
← Older Oldest on feat/53-symlog-time-syntax
All commits
Newer → Latest on feat/53-symlog-time-syntax

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:9cb57906be1b86b25d7956f3bd72fe735ecde4b0bdde0b005c500d4f7e0f983c --body "your comment"