Skip to content

add changes mark command to acknowledge a change entry as reviewed #1

@modularity

Description

@modularity

Problem / Goal

changes pulse shows the same entries on every run with no way to record that a change has been read and acted on. There is no feedback loop between seeing a change and marking it as acknowledged. After triaging an entry, users must remember mentally which items they have handled — re-running pulse resurfaced them in the same positions.

The service's goal is to help users act on important changes, not just view them. Without a way to record "I have seen and handled this," the tool stops at notification — exactly the problem the hypothesis says current tools already have.

Background

ChangeEntry in src/models.py does not include any reviewed/acknowledged field. FileStore in src/store.py has no method to update an existing entry.

Dependencies

None. This issue is self-contained.

Required changes

1. src/models.py

Add one optional field to ChangeEntry:

reviewed_at: Optional[datetime] = None

2. src/store.py

Add a method to FileStore:

def mark_reviewed(self, entry_id: str) -> bool:
    """Set reviewed_at to datetime.now on the ChangeEntry with the given id.

    Returns True if the entry was found and updated, False if entry_id
    does not exist in the store.
    """

The method should:

  • Locate the entry by id in the store's change feed.
  • Set reviewed_at to datetime.now(timezone.utc).
  • Persist the updated store to disk.
  • Return True if found, False if not found.

Also update add_changes() upsert to preserve reviewed_at from the existing record if the incoming entry has reviewed_at = None.

3. src/cli.py

Add a new Typer command changes mark ENTRY_ID:

@app.command()
def mark(
    entry_id: str = typer.Argument(..., help="Change entry ID to mark as reviewed"),
) -> None:
    """Mark a change entry as reviewed."""
  • Call store.mark_reviewed(entry_id).
  • On success: print Marked <entry_id> as reviewed.
  • On failure (not found): print Error: no entry with ID <entry_id>. and exit 1.

4. changes pulse filter (src/cli.py)

Add --include-reviewed flag to pulse():

include_reviewed: bool = typer.Option(
    False, "--include-reviewed", help="Include entries already marked as reviewed"
)

When --include-reviewed is not set (default), filter out entries whose reviewed_at is not None before bucketing.

Design decisions settled

  • reviewed_at is a nullable datetime field — None means unreviewed. Using a datetime (not a bool) preserves when the review happened for future audit or expiry logic.
  • There is no unmark command in this issue. The decision to add one is deferred.
  • Reviews persist across changes sync. A new sync that upserts an existing entry (same id) must preserve reviewed_at. FileStore.add_changes() uses the entry id as the deduplication key — the upsert must merge reviewed_at from the existing record if the incoming entry has reviewed_at = None.
  • changes pulse hides reviewed entries by default. Users who want to see the full feed pass --include-reviewed.
  • There is no bulk mark command in this issue. changes mark operates on one entry at a time.

Success criteria

  • ChangeEntry has reviewed_at: Optional[datetime] = None field.
  • FileStore.mark_reviewed(entry_id: str) -> bool is implemented and persists to disk.
  • changes mark ENTRY_ID marks the entry and prints confirmation; exits 1 with an error message if not found.
  • changes pulse omits reviewed entries by default; --include-reviewed shows them.
  • FileStore.add_changes() upsert preserves reviewed_at when re-adding an entry with the same id.
  • pytest --tb=short passes with tests covering: mark_reviewed returns True on valid id, returns False on unknown id, add_changes upsert preserves reviewed_at, and pulse stdout excludes reviewed entries without --include-reviewed.
  • ruff check src/ tests/ passes with no new errors.

Files to change

  • src/models.py — add reviewed_at field to ChangeEntry
  • src/store.py — add mark_reviewed() method; update add_changes() upsert to preserve reviewed_at
  • src/cli.py — add changes mark command; add --include-reviewed flag to pulse()
  • tests/test_store.py — test mark_reviewed and add_changes upsert preservation
  • tests/test_cli.py — test changes mark command and pulse --include-reviewed filter

Not involved

src/render.py, src/enrich.py, src/priority.py, src/sync.py, src/summarize.py, src/github_client.py, data/, .github/

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-taskTask intended for an AI coding agentenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions