Skip to content

Notion Decommission, Phase 1 (bot reads to CreatorTrack)

URL: https://mkdocs.justinsforge.com/memory/handoffs/notion-decommission-2026-07-03/

Date: 2026-07-03. Author: [Claude Code]. Goal (Justin): "finish moving over from Notion; bots and intake go only to CreatorTrack; Notion fully decommissioned." No content preservation (repoint reads, never copy; [[feedback_no_bulk_notion_import_without_asking]]).

What shipped this session (tested, uncommitted, for integrator review)

CreatorTrack read helpers added to scripts/forge_workspace_capture.py (the spine, ctk_ Bearer reads via _get): food_day, food_summary, habits_day, list_tasks, search_notes. All verified live against workspace justin (id 67), base dev :3060.

Bot brain scripts/forge_telegram_inbox_brain.py reads repointed off Notion onto those helpers: - tool_food_today (L1203): Notion food DB -> _spine.food_day. Same kv_block + mono_table shape. - tool_food_summary (L1258): Notion -> _spine.food_summary (per-day macro rollup). - tool_query_notion -> renamed tool_query_lifeos: reads CreatorTrack tasks | knowledge | habits | food. - tool_search_notion -> renamed tool_search_knowledge: searches CreatorTrack Knowledge notes. - Catalog kept coherent: TOOLS schema entries renamed (query_lifeos, search_knowledge), dispatch lambdas updated, prompt reference updated, query_notion+search_notion added to RETIRED_TOOL_NAMES. - list_notes was already on CreatorTrack (commit 4e21ddf).

Bot WRITE intake (create_task, log_food, log_habit, save_to_inbox, save_knowledge) already routes to CreatorTrack via /api/capture when WORKSPACE_WRITE_TARGET=postgres (bots' live setting); the residual n8n("notion-...") write calls in the brain are dormant Notion fallbacks that early-return under postgres (rollback lever = flip the env var).

Tests: py_compile clean on both files; live read of all 5 helpers + all 6 repointed tool paths returned real data.

To ACTIVATE (integrator, not done here): restart bot, no timers changed

  • Restart the capture / coordinator / general-purpose Telegram bots so they load the renamed tools. The LLM catalog changed (query_notion->query_lifeos, search_notion->search_knowledge).
  • No systemd timers were disabled this session (see gaps below for why).

GAPS, still on Notion, need dedicated work (NOT faked)

  1. Interactive habit/task subsystem (coupled read + write-back): tool_habits_checkin, tool_tasks_form/tool_habits_form/tool_today_form (via forge_telegram_checklist.py), and callbacks forge_habits_callbacks.py. These read Notion rows AND their Telegram button callbacks write notion-update-page keyed by Notion page_id. Repointing needs CreatorTrack task/habit toggle endpoints + a callback rewrite. Coupled with the forge-habits-instantiate.timer (04:00 cron creates the day's Notion habit rows the forms read) and forge-habits-alias-backfill.timer / forge-habits-streaks.timer. Do NOT disable forge-habits-instantiate until the forms are migrated, or the live habit forms break.
  2. tool_update_task (brain L1429): finds + updates a Notion task. WRITE; no CreatorTrack task-update path wired. Needs a /api/tasks PATCH helper.
  3. forge_orient.py (triage/orient): reads Notion inbox/tasks/goals/areas and writes task fields on execute. Read side is swappable to list_tasks/search_notes; write side needs CreatorTrack task update. Whole file still NotionAPI.
  4. forge_time_blocks_tools.py / forge_time_blocks_provision.py / forge_time_daily_aggregator.py: time blocks have NO CreatorTrack equivalent (CreatorTrack calendar = timed tasks). Product decision needed.
  5. Hevy->Notion mirror: forge_hevy_backfill.py, forge_hevy_notion_setup.py, forge_hevy_poll.py, forge_hevy_read.py (tool_sync_workouts/sync_now). Superseded by forge_wellness_pg_sync feeding CreatorTrack Fitness (read-only). RETIRE candidates; no active systemd timer found for them (already dormant). Left untouched to avoid half-editing; retire in the fitness-migration pass.
  6. forge_morning_report.py, forge_wellness_daily_summary.py, forge_workout_recovery_stamp.py, forge_fitness_weekly_retro.py, forge_wellness_gap_repair.py, forge_heartbeat_random.py, forge_telegram_datepick.py: still reference Notion; not on the bot-intake hot path. Migrate per subsystem.

Notion client NOT deleted (correct per ordered plan)

scripts/forge_notion_api.py (NotionAPI, _notion_api, NOTION_DBS) still has ~13 live importers (orient, checklist, food_log, hevy_, time_blocks_, time_daily_aggregator, workout_recovery_stamp, fitness_weekly_retro, habits_streaks, and the brain's retired page tools + dormant fallbacks). DELETE only after the gaps above are closed and grep -rn -iE notion scripts/ shows zero live code refs.


PHASE 2 COMPLETE (2026-07-03, [Claude Code])

Notion fully decommissioned. Every live bot read/write + cron repointed to CreatorTrack (ctk_ spine forge_workspace_capture) or the lifeos Postgres wellness.* schema; the Notion client scripts/forge_notion_api.py DELETED. All changes uncommitted for the integrator.

What changed (file : new target : verified)

  • B1 habit callbacks: forge_habits_callbacks.py _handle_done/_handle_skip -> POST /api/apps/habits (upsert_log / skip); _handle_defer local-ledger only. Callback payload now habit:<action>:<defId>@<date>. _handle_done live idempotent OK.
  • B1 checklist forms: forge_telegram_checklist.py builders read _spine.habits_day/list_tasks; _apply_one writes habit upsert_log + task PATCH /api/tasks/{id} {done:true}. Item id is now a CreatorTrack id. Live builders return real data; habit apply idempotent OK.
  • B1 brain checkin: forge_telegram_inbox_brain.tool_habits_checkin reads _spine.habits_day, emits habit:done:<defId>@<date> buttons.
  • B2 task update: forge_telegram_inbox_brain.tool_update_task -> _spine.list_tasks + PATCH /api/tasks/{id}. Live idempotent OK.
  • B1 datepick: forge_telegram_datepick._apply_task_due -> PATCH /api/tasks/{id} {due} (checklist now passes CT task id under payload key page_id).
  • B3 orient: forge_orient.py reads list_tasks/search_notes//api/apps/goals, writes PATCH /api/tasks/{id}. areas has no CreatorTrack surface (returns []). Live OK.
  • B4 wellness: forge_workout_recovery_stamp.py + forge_fitness_weekly_retro.py reads -> PG wellness.* (via forge_workspace_db.app_connect). forge_morning_report.fetch_tasks_all_brands + forge_heartbeat_random.fetch_habits_today/fetch_due_tasks -> spine list_tasks/habits_day. forge_wellness_daily_summary Notion upsert REMOVED (kept dead-feed alert + logged summary; PG is canonical). forge_wellness_gap_repair RETIRED (guarded no-op).
  • B5 Hevy->Notion mirror: forge_hevy_backfill.py + forge_hevy_notion_setup.py DELETED; forge_hevy_poll.py + forge_hevy_health.py guarded no-op. Brain tool_sync_workouts/sync_now retired (brain worker).
  • B6 habit crons RETIRED (guarded no-op): forge_habits_instantiate.py, forge_habits_streaks.py, forge_habits_alias_backfill.py.
  • B7 time-blocks REPOINTED to CreatorTrack Calendar app (GET/POST /api/apps/calendar): forge_time_blocks_tools.py, forge_time_blocks_provision.py, forge_time_daily_aggregator.py. Live OK.
  • Food: forge_food_log.py + forge_fitness_app._food_block -> spine food_day/food_summary/log_food. Live OK (test meal id 5614 "decommission-test-DELETE" left in Meals; no DELETE route on ctk_ token, remove via Meals UI).
  • Tasks web app: forge_tasks_checklist_app.py (tasks.justinsforge.com, forge-tasks-checklist.service :8097) -> spine list_tasks + PATCH. Live OK.
  • Brain bulk cleanup: default WORKSPACE_WRITE_TARGET=postgres; all capture tools spine-only (no Notion fallback); tool_create_habit_definition -> POST /api/apps/habits {op:"create_habit"}; tool_wellness_history -> PG wellness.wellness_facts; brand task tools (briefing/followup_unscheduled_tasks/weekly_review) -> _spine.list_tasks; Notion page-op tools (subpage/archive/icon/favorite/comment/move_block/linked_view/configure_view) + create_project/create_video_project + sync_workouts REMOVED and added to RETIRED_TOOL_NAMES; NOTION_DBS/_notion_api deleted; n8n() kept (non-notion webhooks only). forge_telegram_brain.py prompt + allowed-tools + fail-patterns scrubbed. Brain compiles + imports post-deletion; only notion hits are the 2 inert RETIRED_TOOL_NAMES literals "query_notion"/"search_notion".
  • Deleted obsolete migration one-offs: forge_notion_to_creatortrack_habits.py, forge_notion_to_creatortrack_notes.py. Scrubbed forge_n8n.py docstring (n8n now Alexa-bridge only).
  • DELETED scripts/forge_notion_api.py.

INTEGRATOR ACTIONS (not done here)

  • systemctl disable --now (system-scoped /etc/systemd/system/): forge-habits-instantiate.{timer,service}, forge-habits-streaks.{timer,service}, forge-habits-alias-backfill.{timer,service} (+ their .service.d/ drop-ins + timers.target.wants/ symlinks).
  • KEEP: forge-wellness-pg-sync.timer, forge-morning-report-snooze-check.timer.
  • Restart to load repointed code: forge-inbox-capture.service, forge-lifeos-coordinator.service, forge-general-purpose.service, forge-notify-bot.service (bots: renamed tools + new habit callback wire format), forge-tasks-checklist.service, forge-fitness-app.service.
  • Delete two reversible smoke-test rows: CreatorTrack Meals entry "decommission-test-DELETE" (id 5614; Meals API has no ctk_ DELETE route) and Knowledge/Inbox note "ZZTEST notion-decommission smoke".
  • Review + commit (all changes left uncommitted).

Gate result

grep -rniE 'notion' scripts/ = ZERO live code refs. Remaining mentions are all non-executable: # Why retired: rationale comments, docstrings/history, one HTML font comment (forge_workspace_ui_base.py:444), the 2 inert RETIRED_TOOL_NAMES literals, and two unrelated brand-name data literals (forge_finances_ui_icons.py favicon map "notion"->"notion.so", forge_books_import.py expense-vendor regex). scripts/forge_notion_api.py DELETED; no importers remain; brain + all coupled modules compile and import clean.

Known gaps (reported, not faked)

  • orient areas, and brands jwvr/nova/fishing/bass: no CreatorTrack workspace yet (degrade to empty, not error).
  • Wellness daily Sonnet note + fitness weekly retro no longer land in Notion; daily note is logged only (no CreatorTrack sink), retro writes local md + notify. Add a CreatorTrack sink later if wanted.
  • Food entries: rating/tags folded into notes; drink/supplement collapse to Snack; write granularity date-only.

Workspace app decommission (2026-07-04, executed by Claude Code)

Justin: "fully shut down workspace, and clean up" (finances he handles later). The old workspace.justinsforge.com Flask surface was an orphaned read-view over the shared core/lifeos Postgres, rendering stale legacy app.meal_entries rows (new food logs go to CreatorTrack app.nodes, never this table). Actions: - systemctl --user disable --now forge-workspace.service (was active/enabled, PID 1282, :8101), then rm ~/.config/systemd/user/forge-workspace.service + daemon-reload. - forge_cloudflare_cf.py rm workspace justinsforge.com --tunnel "VR Alliance" -> DNS record + ingress rule deleted. - Removed stale disabled habit system units + drop-ins (forge-habits-instantiate/streaks/alias-backfill .service/.timer/.service.d) + daemon-reload. - KEPT: DB spine (CT109), RLS core, and forge-workspace-backup.timer (pg_dump->restic->gdrive; despite the name it backs up the lifeos spine CreatorTrack depends on, NOT the retired app). - Docs corrected: reference_forge_data_lifeos_spine.md, reference_intake_tracking.md, system-map/fleet.md:39.

Still open (Justin owns): Finances NOT decommissioned. forge-finances.service (user unit, :8096) is still live and still canonical for writes; finance.db is source of truth; CreatorTrack rebuilt only the read layer and bridges writes back via lib/finance-bridge.ts. Full retire needs the write/ingest/icon path rebuilt native in CreatorTrack first. See [[reference_finances_app]].