resmon Update 3 — April 27, 2026
Update 3 — Calendar Bug Cluster, AI-Key Deep-Link, and the New About resmon Page (Tutorials, Issues, Blog, About App)
Metadata
- Update number: 3
- Update type: mixed (bugfix + feature)
- Date: 2026-04-27
- Author: Ryan Kamp
- Commit hash: 0570bc5ac416b42b774b3e1609e1602d6c8adc27
- Commit timestamp: 2026-04-30T17:35:25-04:00
- GitHub push timestamp: 2026-04-30T21:35:39Z
- App version: 1.1.0 → 1.2.0
Summary
This update lands two Calendar bugs, one small deep-link feature, and one large feature — a brand-new top-level About resmon page — together with eleven out-of-band additions that emerged mid-flight and were folded into the same change set per the T-UPD-ADD rule. The Calendar’s scheduled-routine times no longer drift by ~4 hours and Custom-cadence first-fire / interval anomalies (every-N-months, every-5-hours, every-5-days, every-3-weeks, every-1-year) all expand correctly; the 30-minute “orange-bar” cosmetic bug is fixed; and the expansion window now extends to a full 12 months with a user-facing notice when the FullCalendar viewport is navigated past the horizon. The Repositories & API Keys page gains a “Looking for AI API key settings?” deep-link button to Settings → AI. A new top-level About resmon page hosts four tabs — Tutorials (eighteen embedded YouTube walk-throughs covering the full app, every page, and every Settings sub-tab), Issues (a credentials-free mailto: + GitHub-issue-deep-link form), Blog (an in-app reader fed by the new GitHub Pages site at https://ryanjosephkamp.github.io/resmon/), and About App (relocated out of Settings); a shared TutorialLinkButton is rendered next to every page header and every Settings sub-panel header so any user can deep-link straight into the matching tutorial section. App version bumps 1.1.0 → 1.2.0.
Motivation
All items in this update originated in the user’s third-after-release feedback session and map back to the change inventory in .ai/updates/update_4_27_26/update_4_27_26_workflow.md.
- Bug 1 — Calendar scheduled-routine times incorrect (workflow item #1, batch 1). Daily / weekday / weekly / monthly cron expansions on the Calendar page rendered 4 hours earlier than they actually fired (UTC vs. local-time mismatch), and several Custom cadences exhibited first-fire / interval anomalies. The Calendar’s 90-day expansion window also silently truncated upcoming fires for high-frequency cadences with no user-facing notice.
- Bug 2 — Cosmetic 30-minute routines render as multi-day orange bars (workflow item #2, batch 1). Same Calendar subsystem; FullCalendar event mapping was treating short-duration routine fires as all-day events.
- Feature 3 — “Looking for AI API key settings?” deep-link button (workflow item #3, batch 2). Users repeatedly looked for AI provider keys (OpenAI, Anthropic, etc.) on the Repositories & API Keys page even though those keys live on
Settings → AI. A small inline button between the page intro paragraph and the scope selector now routes them directly to/settings/ai. - Feature 4 — New About resmon top-level page (workflow item #4, batch 3). Users had no in-app place to learn how each page worked, no credentials-free way to file a bug or request a feature, and no surfaced channel for per-update release notes. The About App tab was also crowding the Settings page. Update 3 introduces the new top-level page with Tutorials, Issues, Blog, and the relocated About App tab, plus a shared
TutorialLinkButtonnext to every page and every Settings sub-panel header. - Out-of-band additions (T-UPD-ADD). Eleven user-requested additions emerged after T-UPD-1 was scaffolded and during T-UPD-2 execution; they were folded into the active batches per the workflow’s T-UPD-ADD rule. They are listed under Changes below and motivated individually in
update_4_27_26_workflow.md(OOB-1 … OOB-11).
Changes
Batch 1 — Calendar bug cluster (Bug 1 + Bug 2 + window extension + horizon notice)
resmon_scripts/resmon.py—/api/calendar/eventscron expansion now resolves trigger fire times in the local timezone rather than UTC (fixes the ~4-hour shift); Custom-cadence first-fire arithmetic is reworked to honorIntervalTriggerstart-date semantics for every-N-hours / every-N-days / every-N-weeks / every-N-months / every-N-years schedules so first-fires and intervals are correct; the expansion window is extended from 90 days to a full 12 months andMAX_PER_ROUTINEis raised proportionally so high-frequency cadences (every 5 hours) are not truncated; the response now carries ahorizon_endtimestamp the frontend can compare against the FullCalendar viewport.resmon_scripts/frontend/src/pages/CalendarPage.tsx— FullCalendar event mapping now setsallDay: falseand a realendderived from the routine duration so 30-minute routines render as a tight bar rather than a full-width orange band; renders a user-facing notice when the FullCalendar viewport is navigated past the 12-month horizon explaining that the calendar only projects scheduled fires up to 12 months ahead.
Batch 2 — Repositories & API Keys deep-link button
resmon_scripts/frontend/src/pages/RepositoriesPage.tsx— adds a “Looking for AI API key settings?” inline button between the page intro paragraph and the scope selector that routes to/settings/ai.
Batch 3 — About resmon page + tutorial deep-link buttons + Settings → About App relocation
- New top-level page and routes.
resmon_scripts/frontend/src/pages/AboutResmonPage.tsx(new) — top-level page with the tab strip and nested router; final tab order Tutorials → Issues → Blog → About App (Issues and Blog were added under OOB-5 / OOB-6).resmon_scripts/frontend/src/components/AboutResmon/TutorialsTab.tsx(new) — eighteen tutorial sections (one full-app overview + ten page sections + seven Settings sub-tab sections), each with an embeddedyoutube-nocookie.com/embed/<id>iframe, a TOC, and prev / next navigation; deep-link hash drives smooth-scroll into view.resmon_scripts/frontend/src/components/AboutResmon/AboutAppTab.tsx(new — relocated content) — the previous Settings → About App panel content, now mounted under/about-resmon/about-app.resmon_scripts/frontend/src/App.tsx— adds the/about-resmon/*route and the sidebar nav entry appended after Settings.
- Shared
TutorialLinkButtonnext to every page header and every Settings sub-panel header.resmon_scripts/frontend/src/components/AboutResmon/TutorialLinkButton.tsx(new) — single shared component navigating to/about-resmon/tutorials#<anchor>.- All ten page components (
DashboardPage,DeepDivePage,DeepSweepPage,RoutinesPage,CalendarPage,ResultsPage,ConfigurationsPage,MonitorPage,RepositoriesPage,SettingsPage) plus all seven Settings sub-panels (EmailSettings,CloudAccountSettings,CloudSettings,AISettings,StorageSettings,NotificationSettings,AdvancedSettings) renderTutorialLinkButtonnext to their<h1>/<h2>headers.
- Settings → About App removal.
resmon_scripts/frontend/src/pages/SettingsPage.tsx— removes theAbout AppNavLinkand nested<Route>; removes theAboutAppSettingsimport; tab count goes 8 → 7. TheSettingsindex redirect to/settings/emailis unchanged.resmon_scripts/frontend/src/components/Settings/AboutAppSettings.tsx— deleted (content relocated toAboutResmon/AboutAppTab.tsx).
Out-of-band additions (T-UPD-ADD)
- OOB-1 — Calendar
Routines: x of ydropdown filters to active-only.resmon_scripts/frontend/src/pages/CalendarPage.tsx—fetchDataseedsvisibleRoutinesfrom the active subset and a derivedactiveRoutinesconstant drives theSelect allaction and the rendered checkbox list. - OOB-2 — Calendar event popover shows
Name:andCron Schedule:info lines.resmon_scripts/frontend/src/pages/CalendarPage.tsx— popover renders two newevent-popover-metalines for the matching active routine. - OOB-3 —
Edit Routinebutton on Calendar popover + sharedRoutineEditModal+ cross-page sync.resmon_scripts/frontend/src/lib/routinesBus.ts(new) — pub/sub bus mirroringconfigurationsBus.tswithnotifyRoutinesChanged()+useRoutinesVersion().resmon_scripts/frontend/src/components/Routines/RoutineEditModal.tsx(new) — extracted reusable create/edit modal that broadcasts on bothroutinesBusandconfigurationsBuson save.resmon_scripts/frontend/src/pages/RoutinesPage.tsx— refactored to consume the shared modal; subscribes touseRoutinesVersion().resmon_scripts/frontend/src/pages/CalendarPage.tsx— adds theEdit Routinepopover button; subscribes touseRoutinesVersion()and re-runsfetchData()on save without closing the popover.
- OOB-4 —
.modal-overlayz-index above the Calendar event popover.resmon_scripts/frontend/src/styles/global.css— bumps.modal-overlayfromz-index: 1000→1100. - OOB-5 —
About resmon → Issuestab + GitHub issue templates.resmon_scripts/frontend/src/components/AboutResmon/IssuesTab.tsx(new) — credentials-free form with two read-only submit paths (mailto:link + GitHub-issue deep link); both routed throughwindow.resmonAPI.openPath(falls back towindow.location.href/window.openwhen the preload bridge is unavailable)..github/ISSUE_TEMPLATE/bug.yml,feature.yml,question.yml,config.yml(new) — typed GitHub issue forms whose IDs match the slugs the Issues tab generates.resmon_scripts/frontend/src/pages/AboutResmonPage.tsx— mounts the new tab between Tutorials and About App.
- OOB-6 —
About resmon → Blogtab + GitHub Pages publishing infrastructure.resmon_scripts/frontend/src/components/AboutResmon/BlogTab.tsx(new) — fetches the Atom feed athttps://ryanjosephkamp.github.io/resmon/feed.xml, parses client-side viaDOMParser, renders a two-pane layout with an origin-locked Electron<webview>; off-origin links open in the user’s default browser.resmon_scripts/frontend/electron/main.ts— enableswebPreferences.webviewTag: trueand adds awill-attach-webviewhardening hook that scrubsnodeIntegration,preload, and any non-httpssrc.resmon_scripts/frontend/src/index.html— widens the CSP<meta>to permithttps://ryanjosephkamp.github.ioforframe-src/child-src/connect-src, plushttps://www.youtube-nocookie.comandhttps://www.youtube.comfor the Tutorials embeds.docs/_config.yml,docs/Gemfile,docs/index.md,docs/README.md,docs/_posts/2026-04-23-welcome-to-the-resmon-blog.md(new — Jekyll site scaffolding). The two republished update posts (docs/_posts/2026-04-24-resmon-update-1.md,docs/_posts/2026-04-25-resmon-update-2.md) shipped in a separate7f1ea24commit on 2026-04-29 ahead of T-UPD-4 and are noted here for the record; they are not staged as part of the Update 3 commit.resmon_scripts/frontend/src/pages/AboutResmonPage.tsx— mounts the new tab between Issues and About App.
- OOB-7 — New T-UPD-5 prompt template in
update_prompts.md..ai/updates/update_prompts.md— adds a T-UPD-5 — Publish Update as Blog Post prompt template formalizing the seven-step per-post procedure, bumps the document to version 1.3, extends the usage / TOC / hard rules to reflect the new five-prompt sequence, and adds a “Push before publish” hard rule. - OOB-8 —
saved_configuration_idlinkage on theexecutionstable.resmon_scripts/implementation_scripts/database.py— adds a nullablesaved_configuration_id INTEGER REFERENCES saved_configurations(id) ON DELETE SET NULLcolumn to theexecutionstable via an idempotentALTER TABLE … ADD COLUMNmigration.resmon_scripts/resmon.py—_enrich_execution_rowLEFT JOINssaved_configurationsand projectssaved_configuration_id+saved_configuration_nameonto every execution-returning endpoint; extendsDiveRequestandSweepRequestwith an optionalsaved_configuration_id; addsPATCH /api/executions/{id}accepting{ saved_configuration_id: int }.resmon_scripts/frontend/src/pages/DeepDivePage.tsx,resmon_scripts/frontend/src/pages/DeepSweepPage.tsx— track the loaded id in aloadedConfigIdRefpopulated byConfigLoader.applyConfig; user edits clear the ref via adirtyRefguard.resmon_scripts/frontend/src/components/Save/SaveConfigButton.tsx,resmon_scripts/frontend/src/pages/CalendarPage.tsx—PATCHthe originating execution row with the new id after a successful Save Config.
- OOB-9 —
Saved as <name>badge +Namecolumn wiring.resmon_scripts/frontend/src/pages/DashboardPage.tsx,resmon_scripts/frontend/src/components/Results/ResultsList.tsx,resmon_scripts/frontend/src/pages/CalendarPage.tsx,resmon_scripts/frontend/src/components/Save/SaveConfigButton.tsx— adds aNamecolumn (withsaved_configuration_name → routine_name → Execution #{id}fallback chain) and aSaved as <name>badge that reconciles in place after a save broadcast. - OOB-10 — Configurations page
View JSONper-row read-only modal.resmon_scripts/frontend/src/pages/ConfigurationsPage.tsx— adds a per-rowView JSONbutton next toEditthat opens a read-only modal with a Copy-to-clipboard button. - OOB-11 — Settings → Advanced **Danger Zone (16 destructive actions, two-tier confirmation).**
resmon_scripts/frontend/src/components/Settings/ConfirmDangerModal.tsx(new) — typed-CONFIRMconfirmation gate for the six destructive data/settings actions.resmon_scripts/frontend/src/components/Settings/AdvancedSettings.tsx— appends a Danger Zone section with two columns (Local / Cloud) of 8 buttons each; broadcasts onconfigurationsBus,routinesBus, and theresmon:execution-completedwindow event on success; the cloud column is rendered disabled with aComing soonmuted note.resmon_scripts/resmon.py— adds 8 admin route handlers underPOST /api/admin/...; the two API-key wipes accept an empty body, the six data/settings destructions require{ "confirm": "CONFIRM" }.resmon_scripts/implementation_scripts/database.py— helpers for whole-table truncates with FK cascade.resmon_scripts/implementation_scripts/credential_manager.py— bulk-wipe helpers for the API-key categories.
Documentation, version, and About App tab
resmon_reports/info_docs/about_resmon_info.md,settings_info.md,calendar_info.md,configs_info.md,dashboard_info.md,results_and_logs_info.md,repos_and_api_keys_info.md,system_info.md,deep_dive_info.md,deep_sweep_info.md— refreshed in T-UPD-3 sub-tranche 1 to reflect Update 3 changes (routines_info.mdandmonitor_info.mdwere verified up-to-date and left as-is).resmon_scripts/implementation_scripts/config.py— bumpsAPP_VERSIONfrom1.1.0to1.2.0.resmon_scripts/frontend/package.json— bumpsversionfrom1.1.0to1.2.0.resmon_scripts/frontend/src/components/AboutResmon/AboutAppTab.tsx— version banner now reads1.2.0and the Recent Update card is rewritten with this update’s number, name, and summary.README.md— adds an#/about-resmon/*row to the routes table, an About resmon bullet under Key Features describing all four tabs, a short Blog subsection linking the GitHub Pages site, a note in the existing Reporting Issues subsection that issues can be filed via the in-app form, and a brief Maintenance / Danger Zone subsection pointing readers at Settings → Advanced.
Verification
Test results from each batch and from the OOB additions, run from the project root with the .venv virtualenv active and the frontend tooling under resmon_scripts/frontend/.
- Batch 1 (Calendar bug cluster):
pytest resmon_scripts/verification_scripts/ -q→ all green; the Calendar timezone-shift and IntervalTrigger first-fire fixes are exercised by the existing scheduler / cron expansion suites.- Frontend:
webpack 5.106.2 compiled successfully; manual UI verification of every cron expression enumerated in the bug report (8 AM daily, midnight daily, Mon 9 AM, weekday 8 AM, first-of-month, every-2-months, every-5-hours, every-5-days, every-3-weeks, every-1-year, plus a 30-minute routine) on month / week / day views.
- Batch 2 (AI-key deep-link button):
webpack 5.106.2 compiled successfully; manual click-through on the Repositories & API Keys page → lands on#/settings/ai. - Batch 3 (About resmon page + tutorial deep-link buttons + Settings relocation):
cd resmon_scripts/frontend && npm run typecheck→ clean.webpack 5.106.2 compiled successfully; rendererbundle.js~1.06 MiB after the YouTube embed pivot.- Manual nav to
/about-resmonconfirmed all four tabs; manual click-through on everyTutorialLinkButtoninstance (10 page headers + 7 Settings sub-panel headers) confirmed correct deep-link behavior; Settings tab count is 7 with no stranded/settings/aboutreferences.
- OOB-1 / OOB-2 / OOB-3 / OOB-4 (Calendar polish + RoutineEditModal + z-index fix): webpack build clean; manual UI smoke confirmed the Routines dropdown now shows active-only routines, the popover surfaces the
Name:andCron Schedule:lines, theEdit Routinebutton opens the modal above the popover and updates both Calendar and Routines without a manual reload. - OOB-5 (Issues tab + GitHub issue templates): webpack build clean; manual click-through on Open in Email opened the default mail client with the correct subject / body / diagnostic block, and File on GitHub opened the GitHub new-issue page with the correct template auto-selected and the form fields pre-populated.
- OOB-6 (Blog tab + GitHub Pages): webpack build clean; the GitHub Pages site is live at
https://ryanjosephkamp.github.io/resmon/; the in-app Blog tab successfully fetchesfeed.xml, lists the three published posts, and renders each post in the embedded<webview>. Off-origin links route to the user’s default browser. - OOB-7 (T-UPD-5 prompt template): documentation-only change; no test suite applies. Verified by re-reading the document end-to-end after the edit.
- OOB-8 (
saved_configuration_idlinkage):pytest resmon_scripts/verification_scripts/ -q→ green (idempotent migration covered by the existing schema-migration suite); manual UI verification of the round-trip on Deep Dive → Save Config → Dashboard / Results & Logs / Calendar popover. - OOB-9 (
Saved as <name>badge +Namecolumn): webpack build clean; manual UI verification of the fallback chain (saved_configuration_name → routine_name → Execution #{id}) and of the in-place reconciliation when a save originates on a different page. - OOB-10 (View JSON modal): webpack build clean; manual UI verification of the read-only modal across all three config types (
manual_dive,manual_sweep,routine); Copy-to-clipboard succeeded under bothnavigator.clipboard.writeTextand thedocument.execCommand('copy')fallback path. - OOB-11 (Danger Zone):
pytest resmon_scripts/verification_scripts/ -q→ green for the new admin-route tests (typed-CONFIRMgate enforced server-side, FK cascades verified). Manual UI verification of all 8 local actions (the two API-key wipes through the simple modal, the six data/settings destructions through the typed-CONFIRMmodal); cloud column rendered disabled with theComing soonnote as designed.
Skipped tests: platform-gated Linux systemd --user and Windows Task Scheduler tests remain skipped on macOS via their existing skipif guards (these were exercised under Update 2’s manual verification matrix and are not re-exercised here because no notification-dispatch code changed in this update). No new dependencies; the executions.saved_configuration_id ALTER is idempotent and forward-compatible with installs that already migrated.
Commands:
# Backend
source .venv/bin/activate && pytest resmon_scripts/verification_scripts/ -q
# Frontend
cd resmon_scripts/frontend
npm run typecheck
npm run build
npm start # full Electron + backend smoke
Follow-ups
- Tutorials full-app overview video — the full-app overview entry currently embeds a placeholder video; the user has reserved the final replacement recording for Update 4 so the rest of the app can be bug-tested first. The placeholder is functional and replaceable by a single
youtubeIdchange. - Cloud-side Danger Zone column — the eight cloud-mirror buttons in the Settings → Advanced Danger Zone are intentionally rendered disabled (
Coming soon). They will activate when theCloud Accountfeature lands and the matching/api/admin/cloud/...routes are added. - Stale-daemon caveat (carried forward from Update 2’s settings-allowlist) — users upgrading should kill any running
resmon-daemonprocess so the renderer attaches to a fresh backend that has loaded the new admin endpoints and theexecutions.saved_configuration_idmigration.