Epo v3.0.0
macOS (Apple silicon · Intel)
Windows 10 / 11
open source (MIT)
local-first
This release rolls up the changes listed below.
Every commit since 0d3f680
- fix(release): root-anchor the release/ ignore so the release cards commit (
1c29bb3) - feat(release): auto-releaser, release cards, and the in-app self-updater (
f884b76) - ci: SHA-pin every action; close the zizmor findings; fix Windows packaging (
1478f99) - ci: security, health, hygiene, and rehearsal workflows; coverage in the gate (
6e94f7c) - style(lint): organize imports repo-wide; the lint gate becomes biome ci (
30eff88) - ci(dependabot): adopt the FableFactions auto-merge pattern (
bdb857f) - docs(readme): brand README, full asset system, and nightly live panels (
178d439) - feat(console): stage-hosted graph and prune pages, intro tour, durable window state (
92a01ab) - feat(shell): claim the Epo app identity in dev runs; regenerate the icon set (
716bb97) - chore(deps): bump the npm-minor-patch group with 3 updates (#11) (
3e4eb70) - style(brand): crop the README hero wordmark to its content bounds (
4425c14) - feat(prune): bio filter — protected words in a profile bio block the unfollow (
af32167) - feat(timing): per-cycle volume plan fluctuates just under the daily caps (
0283ab2) - chore(deps): bump @swc/core in the npm-minor-patch group (#10) (
db1ed7f) - fix(prune): cap counts per active-hours cycle; scans stay fresh 4 days (
447fa11) - fix(governors): actions counter resets at the active-hours cycle start, not midnight (
5af8cc2) - fix(ui): focus management, layering, motion single-sourcing, live badges (
1c74b12) - fix(main): teardown lock closes the rebuild races; identity re-validation (
783c013) - fix(rim): feed shape drift is a typed failure, not an empty success (
bd6c9f8) - fix(engine): step-level generation token, woven-feed accounting, policy constants (
d02033f) - fix(timing): one home per constant — units module, live registry, mixture fallback (
e6c0d73) - fix(brand): true dev Dock identity — transparent icon, 15% smaller mark, Epo name (
dd2e8e1) - feat(brand): dark liquid-glass app icon (
f9bc524) - feat(ui): settings-page revamp (collapsible cards, Behavior/Advanced); tooltip + card-entrance animation fixes (
553a5ad) - feat(settings): qualitative pattern model (personas + knobs) deriving the pacing config; follow-plan daily volume (
af43497) - feat(main): wire SessionPlanner + woven prune feed into the composition root; scan-and-enqueue scheduled prune (
470ff85) - feat(collection): timing/interaction integration across store, rim, and adapter layers (
8bda8f3) - feat(engine): session-driven organic pacing loop with woven prune feed; rolling-hour velocity signal (
3ba0d53) - feat(timing): timing package + organic macro-timing model — distributions, circadian field, session planner, statistical harness (
4e91075) - refactor: rename humanizer → interaction (neutral naming); retire request-budget/metering (
c3fd12a) - docs: refresh plans/specs, add CLAUDE.md and the macro-timing-realism plan (
0375465) - fix(prune): zero the stale candidate count when a fresh scan begins (
7c31539) - feat(humanizer): real trusted input events with human motion profiles (
839b1fa) - refactor(harness): dev harnesses use timing primitives + registry; timing unification complete (
edca55f) - feat(renderer): real countdown deadlines, shared keep-alive hook, timer-leak and settings-desync fixes (
a2e292e) - feat(adapter): cancellable waits — driver run token interrupts DOM polls and pacing (
6bf4714) - refactor(main): probe + auto-prune watcher ride ScheduleManager; shared DelayManager wired (
84a514c) - feat(engine): persist the follow-back sweep cadence across restarts (
75f6ebb) - feat(ui): reset content scroll to top when switching views (
a1af113) - refactor(prune): waits through DelayManager, delay formula composed from shared policies (
5a86fec) - feat(ui): NumberTicker — slot-machine odometer digits for live counters (
22b975a) - refactor(engine): waits through DelayManager — named keys, real nextActionAt deadline (
fafdef8) - feat(prune): live mid-scrape counts — onProgress from page reader to throttled status emits (
daff73f) - refactor(timing): rate-governor + page-reader delegate to shared delay policies (
c6e1060) - feat(timing): ScheduleManager — overlap-guarded tick loops and persisted cadences (
d519712) - docs: design for live scrape counts, number tickers, scroll reset, humanizer (
2f94500) - feat(timing): DelayManager — named, cancellable, observable waits (
04c16c0) - feat(timing): namespaced registry for all fixed operational timing constants (
4e5f25f) - feat(timing): pure delay primitives — sleep, DelayPolicy, withTimeout (
1f4172d) - docs: timing unification implementation plan (
2d884fb) - docs: timing unification design — DelayManager, ScheduleManager, timing package (
1217f88) - feat(prune): run unfollows at 1/3 of the humanized delay (
34227ce) - ci: gate public-only security workflows on repo visibility (
6ab27e3) - ci: pin scorecard-action to v2.4.4 + add Dependabot auto-merge (
d27cef9) - build: adopt TypeScript 7 native toolchain — swc/jest + Biome (
71c7ea9) - ci: run on Node 25 and bump all GitHub Actions to latest majors (
ec446e8) - docs: v3 design spec, phase plans, UI mockup (
55bba8d) - ci: GitHub Actions (CI, CodeQL, Scorecard, dependency-review, release), Dependabot, security policy, templates (
b7f2d9e) - brand: Epo identity — metallic 'e' monogram, hero art, app icons, ground-up README (
76b58ad) - harness: capture/inspect/livetest updates for the versioned adapter surface (
5966b63) - renderer: Command Console redesign — Overview/Growth/Queue/Prune/Settings, Prune view (2-step scan→run, whitelist, schedule) (
ee940a9) - main: composition root — IPC, prune tab hand-off (pause/resume growth), automation veil over scan+prune (
09b9a95) - settings: single knob set + projections — prune config (whitelist, daily cap, scan pacing); shared IPC types (
6bc503d) - engine: Phase 5 auto-prune — PruneEngine, 2-step scan→run, growth-managed exclusion, shared-graph census (
e0d5ce9) - engine: paced growth loop — churn lifecycle, offline hold, pause-park handshake for the prune hand-off (
6da1c48) - rim: paced ports — followers-page reader, relationship reconciler, own-following/followers scan sources (
469eefa) - adapter: version-marked IG surface — reader/actor/sentinel, robust identity, FetchEnvelope, live-tab guard (
30b68d1) - store: event-sourced knowledge graph — async reconciliation (leave-alone), prune ledger, scan-census enrichment (
4ecd773) - build: modernize toolchain — TS6, ESLint 10 flat config, esbuild 0.28, electron-builder, epo CLI harness (
3137bed) - docs: live gate PASSED — full pipeline validated live; first-run guidance (
93cea88) - test(rim): fake actor scrollFollowers returns boolean (matches new best-effort signature) (
8a06f80) - fix(adapter): scrollFollowers is best-effort — no container is not fatal (
a350961) - fix(adapter): open followers modal by clicking the text-matched stat link, not a dead href (
f083887) - Add DOM element inspection harness (npm run inspect) (
b872e1c) - fix(adapter): open followers modal by navigating to /followers/ (Task-E-proven), not clicking a drift-prone link (
e392020) - fix(identity): resolve own username via profile link/nav, not the failing current_user endpoint (
1b3bab8) - docs: add live action smoke-test (npm run livetest) as the quick pre-gate check (
b7bc1eb) - Wire livetest entry into esbuild + npm scripts (
959e896) - Add live action smoke-test harness (src/livetest) (
5cebfde) - docs: handoff — remediation complete, live gate ready (216 tests green) (
6d555d6) - Complete v3 composition-root wiring (R1/R3/R5, f6/f11/f14/f15) (
611e9fe) - f13: support overnight (wrapping) active-hours windows (
17b4fc5) - engine: candidate enrichment + bounded refill cycle, generation-token loop, budget pre-check, per-step resilience (R1, R2, R4, f9, f10) (
8a95de8) - scanner: mark scored-and-rejected candidates role='skipped' so the pool shrinks (R1.3) (
50a0abe) - store: exclude role='skipped' from candidate pool; require explicit clock time for scrape cursors (R1.4, f8) (
7efad34) - f11: own-followers sweep stores its parsed observations (
d4423ec) - R4+f12: discriminated churn outcome; blocked-untouched and dry-run edge/ledger safety (
1ec9185) - R1.1: add ProfileEnricher rim port for candidate count enrichment (
d273f32) - docs: handoff — flag critical integration review + remediation-in-progress (hold live gate) (
3a2f46a) - docs(remediation): Fable triage of assembled-system review — R1 enrichment + R2-R5 safety fixes (
6dd3dca) - renderer: v3 instrument-panel dashboard (spec §1-§6) (
658616c) - ipc: add read-only chain/queue/settings handlers (spec §5) (
cf393de) - engine: support live config reload on settings change (
71485d7) - docs: overnight build handoff — status, architecture, live-gate checklist (
1ea4a7e) - Wire Wave 4: minimal engine Start/Pause/Stop controls + live status line (
6e6e489) - Wire Wave 4: route engine controls + pushed status through IPC/preload (
c26bc8e) - Wire Wave 4: Foundation composition root + lazy Engine graph (
56046e4) - Wire Wave 4: extend IPC/status contract, drop dead adapter.reader slot (E2) (
d2ff2df) - docs(ui): Fable-authored metallic-minimal dashboard design (panels, data bindings, IPC) (
64792ef) - Test the Engine runtime with fakes: pacing, gates, cadence, chain, E1 (
1dd1d28) - Add Engine runtime: the paced, interruptible conductor (v3 §3) (
10fab85) - rim: adapter-backed port implementations (acquisition, churn actions, own-followers) (
9357ae1) - rim: RimTab seam, request metering (R2), shared followers scraper (R1/R3/R5) (
d03c1a7) - store: add scrape_cursors table + cursor persistence (R4) (
c4734e2) - test(adapter): cover A1 retry, A2 fallback anchor, A3 verification, A4 pk extract (
4ecc91f) - adapter(A1/A2/A3): hydration-wait initial lookup, fallback search, verify post-click (
082d52a) - adapter(A4): Reader.extractTargetPkFromFollowersUrl (
750977c) - adapter(A2/A4): defensive fallback button anchor + case-tolerant followers link (
6e5b9a5) - Add Settings object + config projections (v3 Task 2) (
3fa7f19) - Split ChurnScheduler.tick into advanceTimers/nextDue/execute (
92854db) - docs(arch): fold adversarial-review findings into engine architecture as owned requirements (
1f14265) - docs(arch): Fable-authored Engine runtime architecture (conductor + pacing relocation) (
96b551a) - Add Chain Controller: next-target promotion + own-followers fallback (
b6ddc92) - Add Target type + store methods for chain targets and yield stats (
9b06a3c) - Test Scanner planning against a real in-memory KnowledgeStore (
3b7d265) - Add Scanner: rank a target's followers and enqueue follow candidates (
3d21e57) - test(engine): cover Churn Scheduler transitions and rate-gate safety (
e7862aa) - feat(engine): add Churn Scheduler lifecycle state machine (§3.4) (
9c8eddb) - test(engine): Follow-back Watcher with fake follower source (
b51ac9c) - feat(engine): request-minimal Follow-back Watcher (§5.1) (
1bc6587) - feat(main): wire Phase 1 foundation behind IPC (tab+adapter+store+governors) (
6e6bd63) - test(store): cover follow_records API, candidate pool, and role round-trip (
c2c8adb) - store: add churn/candidate query+mutation API to KnowledgeStore (
ab80a44) - store: add FollowRecord/FollowState types and AccountState.role (
89373bc) - Test the Scorer: ratio curve anchors + candidate eligibility (
d03c10c) - Add ratio sweet-spot Scorer (P2-A) (
aeead30) - test(adapter): health-checks throw AdapterStaleError; Sentinel label mapping (
014370a) - feat(adapter): Actor + Sentinel + facade over live-verified field notes (
82cb6d3) - feat(adapter): AdapterStaleError for loud selector-drift failures (
da11580) - feat(adapter): Reader parsing live-verified IG responses into observations (
7698de9) - test(adapter): sanitized IG response fixtures for Reader (
8eef754) - feat(adapter): field-notes.ts — live-verified IG endpoints, JSON paths, selectors, signatures (
50cad61) - feat(capture): always drive profile-shape capture, never dead-end (
06ec6af) - feat(capture): deterministic captureProfileShapes for the 3 missed shapes (
3457d74) - feat(capture): classify friendships/show// as friendship-show (
e4004eb) - fix(deps): bump better-sqlite3 11->13 for Electron 43 V8 compatibility (
040d710) - fix(macos): upgrade Electron 31->43 and auto-sign dev binary (
4ab8247) - chore(capture): wire capture build/script, gitignore payloads, add docs (
4511cfb) - feat(capture): Task E capture harness and Electron entry (
07195cf) - test(capture): url classifier for Task E capture harness (
bddc133) - chore: ignore bare node_modules symlink (prevents worktree footgun) (
fafd07a) - chore: stop tracking node_modules symlink (worktree artifact) (
5000399) - feat(governors): durable rate cap, hard ceiling, request budget, injectable clock (
fb5efca) - feat(store): KnowledgeStore with migrations, observe(), edges, ledger, queries (
c2dff64) - feat(renderer): minimal Preact control shell with metallic-minimal styling (
35ae04e) - feat(main): electron shell, side-by-side IG tab, IPC stubs, preload on/off bridge (
6af3b69) - feat(adapter): InstagramTab on persistent session with CDP response observer (
7b0bcb3) - feat(store): per-field provenance-aware projection with confidence merge (
9c5208e) - feat(store): knowledge-graph types, sources, confidence, ratio (
0cda4bb) - docs: add @typescript-eslint/parser to Task 1 deps (needed by eslint parser) (
e214d1e) - chore: reset to clean v3 foundation with sqlite build, jest, eslint store-boundary (
5e2b8a9) - docs: fix Task 1 for v3 clean-start (create fresh tsconfig/esbuild, no v2 tooling) (
1703176) - chore: ignore .DS_Store and .serena tooling on v3 (
721d7e5) - docs: add Peanut v3 implementation plan (verified-foundation-first) (
c69340a) - docs: add local knowledge-graph pillar to Peanut v3 spec (
16fccc9) - docs: add Peanut v3 ground-up redesign spec (
4536d7f) - Redesign Peanut Control Center interface (
9ed5901) - Improve Instagram scraping stealth and scrolling (
fa04934) - Add Electron control center and improve scraping (
5aed478) - Switch to manual login flow (
2c1e9bc) - Create Instagram automation CLI (
72571ad)
macOS — download Epo-3.0.0-arm64.dmg (Apple silicon; Intel builds ship from v3.0.1), open it, and drag Epo to
Applications. These builds have a known packaging flaw: macOS reports the app "damaged". Rescue once from a terminal: xattr -cr /Applications/Epo.app — or skip to the newest release, which opens normally via System Settings → Privacy & Security → Open Anyway.
Windows — download Epo-Setup-3.0.0.exe (recommended — it
updates itself from here on) or Epo-3.0.0-portable.exe.
SmartScreen may warn on first run: More info → Run anyway.
Already running Epo? Windows installs update themselves in the
background; macOS shows the new version in Settings → Updates and brings
you here.
- Your database, settings, and Instagram session carry over — updating is a
drop-in replacement. - The
.zip,.blockmap, andlatest*.ymlassets below are the
self-updater's feed; every file stays attached. - Epo acts on your Instagram account; use it at your own risk (see the
README).
Full changelog: 0d3f680...v3.0.0