chore: remove pre-pivot dead code + finish Scribe rebrand (#599 t1-3)
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Successful in 51s
CI & Build / Build & push image (push) Successful in 1m1s

- Header wordmark Fabled -> Scribe; fable:calendar-changed event ->
  scribe:calendar-changed; SettingsView CSS comment.
- Drop dead Project.auto_summary + summary_updated_at columns (migration
  0063) -- the Ollama-era summarizer is gone; model + 2 frontend types +
  projects test updated.
- Remove pivot vestiges: diagnostics _curator_busy()/curator_busy
  heartbeat field, tz BRIEFING_DAY_START_HOUR/user_briefing_date dead
  aliases, the ignored 'model' param on get_embedding (+ its test).

ruff src/ clean; CI is the gate. Part of scribe plan #599.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 16:16:44 -04:00
parent b255a0f90e
commit 70ab3f38c6
12 changed files with 50 additions and 57 deletions
+1 -7
View File
@@ -1,6 +1,5 @@
import enum
from datetime import datetime
from sqlalchemy import DateTime, ForeignKey, Integer, Text
from sqlalchemy import ForeignKey, Integer, Text
from sqlalchemy.orm import Mapped, mapped_column
from scribe.models import Base
from scribe.models.base import TimestampMixin, SoftDeleteMixin
@@ -22,10 +21,6 @@ class Project(Base, TimestampMixin, SoftDeleteMixin):
goal: Mapped[str] = mapped_column(Text, default="")
status: Mapped[str] = mapped_column(Text, default="active")
color: Mapped[str | None] = mapped_column(Text, nullable=True) # hex color
auto_summary: Mapped[str | None] = mapped_column(Text, nullable=True, default=None)
summary_updated_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True, default=None
)
def to_dict(self) -> dict:
return {
@@ -36,7 +31,6 @@ class Project(Base, TimestampMixin, SoftDeleteMixin):
"goal": self.goal,
"status": self.status,
"color": self.color,
"auto_summary": self.auto_summary,
"created_at": self.created_at.isoformat(),
"updated_at": self.updated_at.isoformat(),
}
+6 -13
View File
@@ -5,11 +5,10 @@ clear cause in the logs. This module adds three things designed to make
the crash class identifiable from logs alone:
1. **Heartbeat** — once per minute, log a snapshot of process resources
(RSS memory, asyncio task count, DB pool checked-in/out, curator
busy state). A sudden silence in heartbeats lets you bound the
crash time to within a minute, and the last snapshot before silence
usually rules in or out memory growth / pool exhaustion / hung
curator pass.
(RSS memory, asyncio task count, DB pool checked-in/out). A sudden
silence in heartbeats lets you bound the crash time to within a
minute, and the last snapshot before silence usually rules in or out
memory growth / pool exhaustion.
2. **Signal handler** — catches SIGTERM and SIGINT, logs them with the
sender's intent ("docker stop", "swarm restart", "manual ctrl-C")
@@ -108,11 +107,6 @@ def _asyncio_task_count() -> int | None:
return None
def _curator_busy() -> bool | None:
# Curator was removed in Phase 8 of the MCP-first pivot. Always False.
return False
def _uptime_secs() -> float | None:
if _started_at is None:
return None
@@ -134,7 +128,6 @@ def _snapshot_dict(reason: str = "heartbeat") -> dict[str, Any]:
"rss_mb": _process_rss_mb(),
"asyncio_tasks": _asyncio_task_count(),
"db_pool": _db_pool_stats(),
"curator_busy": _curator_busy(),
"pid": os.getpid(),
}
@@ -284,9 +277,9 @@ async def _heartbeat_loop() -> None:
_persistent_log(
logging.INFO,
"diag heartbeat: uptime=%ss rss=%sMB asyncio_tasks=%s "
"db_pool=%s curator_busy=%s",
"db_pool=%s",
snap["uptime_secs"], snap["rss_mb"], snap["asyncio_tasks"],
snap["db_pool"], snap["curator_busy"],
snap["db_pool"],
)
_write_state_atomic(_CURRENT_STATE_PATH, snap)
except Exception:
+1 -4
View File
@@ -53,12 +53,9 @@ async def _get_model():
return _model
async def get_embedding(text: str, model: str | None = None) -> list[float]:
async def get_embedding(text: str) -> list[float]:
"""Get an embedding vector for the given text.
The ``model`` parameter is preserved for backward compatibility with the
Ollama era but is now ignored — fastembed uses a single fixed model.
Raises if the fastembed model fails to load. Callers should catch and
degrade to keyword search.
"""
+3 -10
View File
@@ -13,14 +13,11 @@ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
from scribe.services.settings import get_setting
# Day-rollover boundary for journal/day-anchored views. The "day" flips at
# Day-rollover boundary for day-anchored "today" logic. The "day" flips at
# this local hour (not midnight) so the 00:0004:00 local window still
# shows yesterday's content until the user "starts" the new day.
DAY_ROLLOVER_HOUR = 4
# Backwards-compat alias for code paths still referencing the old name.
BRIEFING_DAY_START_HOUR = DAY_ROLLOVER_HOUR
async def get_user_tz(user_id: int) -> ZoneInfo:
"""Return the user's IANA ``ZoneInfo``, falling back to UTC."""
@@ -41,12 +38,8 @@ async def user_day_date(user_id: int) -> date:
"""Return the current "day" in the user's local timezone.
The day flips at ``DAY_ROLLOVER_HOUR`` (4am local) rather than midnight,
so the 00:0004:00 local window still returns *yesterday* — the user's
journal stays anchored to yesterday until they cross the rollover.
so the 00:0004:00 local window still returns *yesterday* — a day-anchored
view stays on yesterday until the user crosses the rollover.
"""
tz = await get_user_tz(user_id)
return (datetime.now(tz) - timedelta(hours=DAY_ROLLOVER_HOUR)).date()
# Backwards-compat alias used by briefing-only modules being torn down in Stage B.
user_briefing_date = user_day_date