hephaestus/CHANGELOG.md
2026-06-05 07:36:46 -07:00

34 KiB
Raw Permalink Blame History

title tags
changelog
meta

Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog.

[v1.2.1] - 2026-06-05

Features

  • heph-pwa: added a Login with Authentik button — a proper browser OIDC sign-in (Authorization Code + PKCE) that replaces the manual bearer-token paste. The hub exposes an unauthenticated GET /config ({issuer, client_id}) so the app is zero-config when served from the hub; the PWA discovers the IdP endpoints, runs the PKCE redirect, exchanges the code for a token, and silently refreshes it (offline_access). The manual token field remains as a fallback. Requires the PWA origin registered as a redirect URI on the Authentik heph provider.

[v1.2.0] - 2026-06-04

Features

  • New heph-pwa mobile app: an installable, phone-first PWA that mirrors heph-tui — browse the built-in views and projects, triage tasks, and capture new tasks fast with the same quick-add syntax (p1-4, #Project, today/+3d/fri, every …) and live preview. Voice capture via on-device dictation. The hub (hephd --mode server) gains CORS and an optional --web-root so it can serve the app same-origin straight from the daemon.

[v1.1.1] - 2026-06-04

Bug Fixes

  • Fix hephd --self-update never detecting releases: the release poll used the daemon's reqwest client, which is built without a TLS backend (default-features = false), so every HTTPS request to the forge failed (release check failed: requesting forge releases/latest). The poll now uses ureq — already a dependency, with a rustls/ring TLS stack that needs no system libraries (and no cmake/aws-lc-sys). Hub sync is unaffected (it is plain HTTP).

[v1.1.0] - 2026-06-04

Features

  • Opt-in (default off) hephd self-update: hephd --self-update polls the forge for a newer release on an interval and, when one appears, rebuilds via cargo install from the release tag (anonymous HTTPS clone of the public repo — no credentials) and restarts onto the new binary. Enable it on the managed service with heph daemon start --self-update (which also bakes a cargo-capable PATH into the launchd/systemd unit and switches systemd to Restart=always so a clean self-exit respawns). The install mechanism is verified end-to-end; a live cross-version upgrade is confirmed on the first release after this lands. Also hardens hub resilience: the daemon's HTTP client now has a 30s timeout so a black-hole hub can't stall the sync/self-update loop.

[v1.0.3] - 2026-06-04

Features

  • New heph context <task-id> command reads or edits a task's canonical-context doc body by task id, with no manual canonical_context_id lookup. With no flag it prints the body; --body <text> replaces it (- reads stdin, like node update); --append <text> adds a blank-line-separated paragraph. Errors clearly on a node that has no canonical-context doc (e.g. a plain doc, not a task).
  • heph-tui --version now reports the version plus build commit (e.g. 1.0.0 (ab6701d12)), matching heph and hephd. All three daily-driver binaries answer --version consistently.
  • --project <name> is now case-insensitive and prefix-fuzzy when unambiguous, across heph task, heph edit, heph promote, heph list, and project-parent resolution. --project heph or --project hephaestus both resolve Hephaestus. An exact (case-sensitive) title always wins outright, and an ambiguous prefix (e.g. Wor matching both Work and Workshop) resolves to nothing rather than silently picking one. A new project.resolve RPC backs the shared resolver.
  • New version RPC returns the daemon's build version (heph_core::VERSION, e.g. 1.0.0 (ab6701d12)), so RPC clients — notably the hephaestus.nvim plugin's :Heph version command — can report which hephd they are talking to without shelling out to the binary.

Infrastructure

  • Added a cargo-fmt-check pre-push prek hook that runs cargo fmt --all --check (mirroring CI's Dagger check step) whenever a push touches a .rs file. The pre-commit cargo-fmt hook reformats in place, but only fires when installed and run; the pre-push check is a last-line guard so an unformatted commit can't reach the runner. Run prek install --hook-type pre-push to activate it.

[v1.0.2] - 2026-06-04

Bug Fixes

  • Fix heph/hephd --version falsely showing a -dirty suffix on clean release installs. The build-time dirty check now considers only tracked modifications (git diff --quiet HEAD) instead of counting untracked files such as cargo's own .cargo-ok marker in a cargo install --git checkout.

[v1.0.1] - 2026-06-04

Bug Fixes

  • heph --version / hephd --version now report the release version plus the build commit (e.g. 1.0.0 (ab6701d12)) instead of a bare 0.0.0. The short git SHA is captured at build time, so any build — released, branch, or dirty working tree — is traceable to its commit.

Infrastructure

  • The release workflow now bakes the release version into Cargo.toml + Cargo.lock on a commit that only the release tag points at (tagging it manually), so cargo install --git --tag vX.Y.Z reports the real version while main stays at 0.0.0.

[v1.0.0] - 2026-06-04

Features

    • Inbox view (§8.2): a sixth built-in filter view, listed below On Deck, showing every outstanding task with no project — the capture inbox to triage and file. A new ListFilter.unfiled predicate (kept purely in matches()) drives it; the inbox ViewSpec is deliberately un-gated (no attention or do-date filter) so nothing hides from triage. Appears automatically in the heph-tui sidebar and heph view; heph view inbox from the CLI.
    • heph list --project <name> + --json (§8.2): list a project's outstanding tasks by name (subtree-expanded, resolved server-side via a new project.scope path that reuses the view machinery — errors loudly on an unknown name), and --json prints the raw rows (node_id, canonical_context_id, attention/state/do_date/late_on/recurrence/project_id) for scripting and agents. This is the canonical "show me a project's outstanding work" command — AGENTS.md documents it as how to inspect heph's own roadmap (the Hephaestus project), now that heph self-hosts it.
  • Begin the v1 prototype (Phase 1, tech-spec §11.1), built in TDD slices:

    • Cargo workspace + heph-core crate; migration-run SQLite schema (§4.5); clock-injected Store trait + LocalStore node create/get; single local-user bootstrap.
    • Markdown extraction (§5): [[wiki-links]] and GFM - [ ] checkbox context-items derived purely and idempotently from a body, skipping code blocks.
    • Committed tasks (§4.3, §6): task.create auto-creates the canonical context doc + canonical-context link; attention/do-date/late-on/state/recurrence columns; set-state/set-attention. Links CRUD (outgoing/backlinks). A body update reconciles wiki links (diff-based, resolved by alias/title, idempotent).
    • "What is next?" ranking (§7): pure, clock-injected, two-stage engine — candidacy filter (do-date as a boolean gate only) then a reorderable list of named dimensions (past-late-on → overdue-amount → attention band → FIFO). late_on is the sole urgency signal; blue hidden; red always shown. Proptest-checked total order. Store::next surfaces it over SQLite.
    • Recurrence — roll-forward in place (§4.4): completing a recurring task resets its checklist to all-unchecked, logs the occurrence, and advances the do-date to the next RRULE instance after now (skipping misses) — completion never carries forward (proptest-checked). Per-task append-only logs (log-of) with log.append/log.tail; skip advances without logging.
    • hephd daemon, local mode (§3, §6): exclusive file lock (handoff-ready), line-delimited JSON-RPC over a unix socket exposing the node/task/next/links/log methods, with DB work on tokio's blocking pool. Synchronous client for surfaces/CLI. Model types are serde-serializable.
    • heph CLI (§1) — a thin client of the daemon: next, task, doc, get, export. Export materializes the store to a <kind>/<id>.md tree with YAML frontmatter + body (§5), one-way, tombstones excluded.
    • Sync engine, local-only (§12): real hybrid logical clock + persistent device origin; an append-only op-log per mutation; an idempotent, order-independent merge/apply engine — last-writer-wins task scalars (discards surfaced in a conflicts queue), OR-set links, monotonic tombstones. Two-replica convergence proven.
    • Body text CRDT (§5, §12, slice 8d): node bodies now merge through the yrs text CRDT (body_crdt) instead of last-writer-wins — whole-buffer writes are diffed into the doc and the yrs delta rides the op, so concurrent edits to different regions both survive and never enqueue a conflict.
    • Network sync over HTTP (§6.1, §12, slice 9a): hephd --mode server exposes a sync hub (POST /sync/push, GET /sync/pull?after=<hlc>, axum) over the same store; hephd --mode local --hub-url <url> becomes a spoke that background-syncs its op-log with that hub (and on demand via the sync.now/sync.status RPC). Exchange is incremental by HLC cursor (sync_state) and idempotent. The merge engine is heph-core's, unchanged. Unauthenticated/single-owner for now (auth lands with OIDC). conflicts.list/conflicts.resolve are now reachable over the daemon socket.
    • Client mode (§3.1, slice 9b): hephd --mode client --server-url <url> runs with no local replica, proxying every store call to a server's POST /rpc endpoint (the full daemon API over HTTP). The daemon is now backend-agnostic (local/server front a LocalStore, client a RemoteStore), so surfaces see the same unix-socket API in every mode.
    • Hub authentication (§13, slice 10a): the sync hub now verifies an OIDC bearer token on /sync/* and /rpc — RS256-pinned JWT validation with exact issuer/audience, expiry, and a required subject; JWKS discovered and cached, refetched on key rotation (jsonwebtoken). Enabled with hephd --mode server --oidc-issuer <url> --oidc-audience <client-id> (open when unset, for local dev). A single-tenant owner gate binds the hub to the first authenticated identity and rejects any other. Verification sits behind a TokenVerifier trait, so it's tested entirely offline (stub middleware + an adversarial battery against an in-process mock IdP).
    • Client authentication (§13, slice 10b): heph auth login --hub-url <url> --issuer <url> --client-id <id> runs the OAuth 2.0 device-code flow and caches the token in the OS keyring; spokes and client mode attach it to hub requests, refreshing on expiry (--oidc-issuer/--oidc-client-id). Offline-tested against a mock OAuth server and a full spoke-to-authenticated-hub loop. (Auth/proxy HTTP uses the runtime-free ureq, since reqwest::blocking is unsafe inside the async daemon.)
    • CI runs the Rust suite (fmt/clippy/test) via the project build hook.
    • heph.nvim slice 11a (§8) — the primary surface begins: a Neovim plugin that is a thin client of the local hephd over its unix socket. A vim.uv JSON-RPC client (blocking call via vim.wait, id-demuxed, partial-line buffered, JSON null→Lua nil); buffer-backed nodes (heph://node/<id> with BufReadCmdnode.get / BufWriteCmdnode.update, whole-buffer body round-tripping exactly through the CRDT); [[wiki-link]] follow on <CR> via a new exact node.resolve {title} RPC (alias-then-title, the same mapping that materializes wiki links — unresolved links allowed); the daily journal (:Heph today); and the :Heph command surface. Headless e2e (§9) drives the plugin against a real daemon over a temp socket with a self-contained busted-style runner (no external plugins, no network): journal round-trip, follow-link, and link-two-docs/backlink.
    • heph.nvim slice 11b (§8) — task views: list is enriched to return titled rows (the same shape as next, with the canonical-context id) so the Organizational survey needs no per-row node.get. The plugin gains the Tactical :Heph next and Organizational :Heph list views (<CR> opens a task's canonical-context doc), task capture, set-attention, done/drop, skip, and per-task log append — each resolving "the current task" from the buffer (a task node, or a context doc via its canonical-context backlink). A vim.ui.select picker (Telescope auto-upgrade when installed) backs :Heph search/capture/attention. Headless e2e adds the capture→next→context→checklist→done workflow and the recurring fresh-checklist workflow (completing a recurring task rolls it forward and the next occurrence presents an all-unchecked checklist).
    • heph.nvim slice 11c (§8) — promotion + CI: task.promote mints a committed task from a - [ ] context-item line (addressed by its 1-based index) and rewrites that line into a [[link]] to the new task; :Heph promote does this for the line under the cursor. Wiki-link resolution now excludes a task's canonical-context doc, so [[Task Title]] resolves to the task itself (not its identically-titled context doc). The headless e2e suite runs in CI via a Dagger function that bakes a pinned, arch-detected Neovim onto a Rust image and runs the same self-contained suite developers run natively with mise run test-nvim; the runner fails on a zero-spec discovery so a misconfigured path can't pass silently.
    • heph.nvim managed daemon — plug-and-play by default: require("heph").setup({}) spawns and supervises a local hephd against the default paths when none is running, kills only the daemon it spawned on exit, and self-heals (respawns + reconnects if the daemon dies mid-session). A daemon you started yourself (a server/client architecture, or a service) is always respected — the plugin only spawns when nothing is serving the socket; with autostart = false it connects only and warns if unreachable. $HEPH_SOCKET / $HEPH_DB isolate a development Neovim onto a separate daemon + DB.
    • heph.nvim follow-or-create: pressing <CR> on a [[wiki-link]] whose target doesn't exist yet now creates a doc with that title and opens it (the zettelkasten gesture), materializing the source's backlink — so you can link a journal entry to a brand-new note in one keystroke. Plus :Heph doc <title> to create a standalone wiki entry, and :Heph home — a single designated landing/index page (open-or-create by title, configurable via opts.home) to grow a map of content around. :Heph journals opens a recent-days picker (preview existing days, @create for new ones; count via opts.journal_days, default 7) — the dailies workflow. Pickers (Telescope) now support a preview pane. The :Heph next/list views are interactive: <CR> opens a task's context, a adds a task (prompt title + attention), d marks the task under the cursor done, r refreshes — with a dimmed key hint shown above the list.
    • Dev/installed isolation tooling: a mise run dev task runs the working-tree hephd on isolated .dev/ paths, and a how-to (install-heph) covers installing heph/hephd from the forge (build-from-source), the lazy.nvim plugin setup, and pointing a dev Neovim at the dev daemon via $HEPH_SOCKET/$HEPH_DB so it never touches the installed store.
    • CLI as a complete task surface (§1, §6.2.1): heph now implements the entire daemon API and is the task capture/scripting surface. Structured fields are flags with human dates (--do-date tomorrow|+3d|fri|YYYY-MM-DD, shown back compactly in next/list) and recurrence (--recur presets/natural-language like "every 3 days", or a raw --rrule). New verbs: list, done/drop/skip, attention, edit (reschedule do-date/late-on/recurrence, re-attention, re-file — backed by the new task.set_schedule RPC), promote, show, log (append or tail), health, node update/rm, resolve, links/backlinks, link add, project add [--parent], sync [--status], conflicts [resolve]. Projects are referenced by name. Date/recurrence parsing is unit-tested; the new verbs have real-socket process tests.
    • Daemon lifecycle is now an explicit OS service, and all surfaces are connect-only (no more auto-spawn). heph daemon start/stop/restart/status/uninstall idempotently manages a launchd agent (macOS) or systemd user service (Linux) that runs hephd on your default store; heph.nvim no longer spawns or supervises a daemon — it just connects and points you at heph daemon start if none is running. Rationale: once the CLI became a first-class surface, a daemon owned by one surface couldn't be shared (see run-the-daemon, design §4).
    • Filter views (§8.2) — saved agenda slices, so the agenda isn't one flat list. heph view <name> runs a built-in view (tom Top of Mind, ondeck On Deck, chores, work Work Tasks, tasks) seeded from the owner's Todoist filter queries; heph view with no name lists them, and :Heph view <name> does the same in Neovim. Under the hood, list now takes a ListFilter predicate-as-data (attention include/exclude sets, project-subtree scope, project exclusions, an actionable do-date gate), and views resolve project names to ids and expand each to its parent-link subtree. The Schedule view is intentionally omitted (time-of-day isn't modeled on date-grained do-dates).
    • heph-tui (§8.1) — a terminal task agenda/triage UI, the primary surface for working a large task set (the §6.2.1 Todoist study showed triage, not single edits, dominates). A ratatui app, thin client of the daemon socket. Three panes: a sidebar of the five filter views + your projects, an attention-colored task list with compact human do/late dates, and a preview of the highlighted task's context doc + recent log. Triage from the keyboard: a add (guided title → attention → do-date, filed under the selected project), x done, s skip, d drop, A cycle attention, b push to On Deck, e reschedule the do-date; o opens the task's context doc in your nvim (live, via heph.nvim) and returns. j/k move, Tab/h/l switch panes, r refresh, q quit. Run it with heph-tui (honors --socket / $HEPH_SOCKET). a is a Todoist-style single-line quick-add: Buy milk tomorrow p2 #Work every week parses into title + attention (p1p4) + do-date + recurrence + project (multi-word project names match greedily; an unresolved #tag just stays in the title). / runs a full-text search whose results overlay the task list; Enter opens a hit (a task at its context doc) in nvim.
    • Move-to-project (§8.1): a new task.set_project RPC re-files a task under another project (or unfiles it) with OR-set link semantics — the old in-project link is tombstoned and a new one added, so a task is never filed under two projects at once. In heph-tui, m opens a list-pick overlay ("(Unfile)" then every project) on the highlighted task. heph edit <task> --project <name> now routes through the same RPC (fixing a bug where re-filing piled on a duplicate link), and --project none unfiles the task. This closes the last Todoist-parity capture gap.
    • heph-tui task-list visuals (§8.1): each row now leads with an attention flag (, colored red/orange/blue; blank for white) and a project-colored bullet — the bullet's color is derived stably from the project id (so it survives projects being added/removed), letting you scan a mixed list by project at a glance. The list also grows a scrollbar and keeps the selected task scrolled into view when there are more tasks than fit.
    • heph-tui: <Enter> opens the selected task's context editor in nvim (from the sidebar it first drills into the task list); the old o binding is retired. The view sidebar / heph view order is now Top of Mind, Tasks, Work Tasks, Chores, On Deck.
    • heph-tui sort toggle (§8.1): s flips the task list between two orders — default (attention → most-overdue → project → creation) and by-project (grouped under dimmed ──── Project ──── separators, then the same sub-order). The view's filter still applies first. (To free s, skip moved to S.)
    • heph.nvim task-view rows (§8): :Heph next/:Heph list rows now show a compact do/late date chip (and a recurrence ), so you can see scheduling at a glance; <CR> still jumps to a task's context doc.
    • Wiki-links by node id (§8.4): node resolution is now id-first ([[NODEID]] resolves to its node ahead of any name match, so links can't be shadowed by a like-named node), and heph.nvim grows a [[ picker — type [[ (or :Heph link) to pick a node and insert a canonical [[NODEID]] link. With Telescope it's a live fuzzy filter over your linkable nodes with a preview pane (the node's body, or a task's context doc) — the list shows first-class targets only (a task appears once; its internal context/log docs and tag nodes are hidden, via the new node.linkable query) — type to narrow, Enter to insert, <C-x> to create a doc named what you've typed; without Telescope it falls back to a search-then-select prompt. Following such a link (<CR>) jumps straight by id. Those id links are kept readable: on read a bare [[NODEID]] is expanded to [[NODEID|Current Name]] (so it follows renames, in both the nvim buffer and the TUI preview), and on save it collapses back to the canonical bare id — a custom |label you write is preserved as an override. In the editor the id is concealed — a link renders as just its name, styled like a hyperlink, with the raw [[id|Name]] revealed on the line your cursor is on. Legacy [[Name]] links keep working, and heph migrate-links rewrites them to the canonical id form in one pass when you're ready (idempotent).
    • Frontmatter editing in heph.nvim (§8.3): opening a node now shows an editable YAML frontmatter block on top of the body (id/kind/title/tags, and for a task or its context doc the task's state/attention/do_date/late_on/recurrence/project). On save, the plugin diffs the block and issues the right RPC per changed field — rename, set-attention, reschedule (dates as YYYY-MM-DD), move-to-project (by name), and tag add/remove — then saves the body; the store strips the block so it never persists. A mistyped state surfaces a validation error; a buffer with no block changes no metadata (so deleting the block can't wipe your tags). Inline #hashtags typed in the body are also added as tags on save (a # heading doesn't count) and are rendered in italics so they stand out. Link-follow and promotion are unaffected (they're content-relative, not line-absolute).
    • Frontmatter projection (§8.3): a node can now be fetched with an editable YAML frontmatter block prepended — node.get {frontmatter: true} renders id/kind/title/tags, and for a task (or its context doc) the owning task's state/attention/do_date/late_on/recurrence/project plus a task: ref. Dates are local YYYY-MM-DD. On write, the store strips and ignores any leading frontmatter (conservatively — a real --- hrule in prose survives) before the CRDT diff, so frontmatter never persists and an unchanged read→write is a no-op; a naive editor can't corrupt metadata. This is the read/write groundwork for editing a node's metadata as frontmatter in heph.nvim (the diff-into-RPCs layer is next).
    • Tags (§4, §8.3): nodes can now be tagged. A tag is a tag-kind node whose id is deterministic in (owner, name), so the same name is one canonical tag shared across everything it's applied to (and replicas converge — no duplicate tags). Tagging is an OR-set link, so adding/removing is idempotent and merge-safe. Surfaced as tag.add/tag.remove/tag.list RPCs and heph tag add|rm|list (list a node's tags, or every tag with no node). Tag names are trimmed; a canonical case/spelling normalization is deferred to the future zk import. This is the groundwork for the tags: line of the upcoming frontmatter edit surface.
    • heph-quickadd (§8) — a global quick-capture popover, the last piece needed to retire Todoist. A tiny always-warm eframe/egui agent registers ⌘' system-wide (global-hotkey, via Carbon — no Accessibility permission) and, on press, toggles an already-created hidden window visible and focuses a single capture field — never spawning on the keypress, so it's a muscle-reflex (design §6.2.1). The field reuses the shared quickadd::parse (lifted from heph-tui into hephd's lib so both surfaces share one parser): one line like Call dentist fri p1 #Health parses live into title + attention (p1p4) + do-date + recurrence + project, shown as a chip row (⚑ attention · 📁 project · do-date · ↻ recurrence) as you type. Enter saves optimistically — the window hides instantly and task.create runs on a background thread, so perceived latency is just the keystroke; a failed RPC re-shows the window with the text restored, so a capture is never lost. Esc dismisses.
    • Supervision (no second launch agent): hephd supervises heph-quickadd as a child in local mode on macOS (opt-in via HEPH_QUICKADD=1, which the installed launchd plist now sets — dev/test runs that spawn a local daemon never pop a window). hephd already runs as a gui/$uid LaunchAgent, so the child inherits the Aqua session the hotkey/GUI need, and the user still installs/manages exactly one service (heph daemon). The helper self-exits when orphaned (its parent daemon gone) and exits if ⌘' is already held, so killing hephd — even kill -9 — leaves nothing behind and duplicates never stack. Runs as a macOS accessory app (no Dock icon). macOS-only for v1; global-hotkey + egui also run on Linux/X11, so the Linux port is mostly window-behavior polish.
    • heph-tui move-to-project picker (m) is now an fzf-style filter (§8.1): a prompt line on top narrows the project list by fuzzy subsequence match as you type (↑/↓ or Ctrl-n/p move, Enter selects, Esc cancels) — no more scrolling the full list. When the typed text names no existing project, a "+ New project" row is offered: selecting it creates the project and files the task under it in one step (via node.create), so projects can be created without leaving the TUI.
    • heph-tui safety + undo wave (§8.1):
      • Pane-specific keys. Task-triage gestures (x/d/S/A/b/e/m/D) now fire only when the task pane is focused, so a stray keypress while navigating the sidebar can no longer drop or delete a task. The sidebar gets its own actions; the status-line hints are now focus-aware.
      • Undo / redo. u undoes the last triage action (drop, done, skip, attention, move) and Ctrl-z redoes it, restoring the task's prior state from a snapshot — multi-level, capped at 200 steps. (Tombstone-delete stays excluded — it keeps its y/N prompt — and an attention of "none" can't be re-cleared.)
      • Delete a project from the sidebar with D (y/N confirm); its tasks become unfiled (they move to the Inbox), not deleted.
      • Sidebar auto-refreshes after creating or deleting a project, so a new project shows up immediately (no more quit-and-reload).

Bug Fixes

  • Fix clippy::single_match lint in heph-tui sidebar key handling (CI failure on main).
  • Pin the Quartz docs build to v4.5.2. The Dagger build_docs pipeline cloned Quartz from the default branch unpinned; Quartz v5.0.0 restructured its config layout (.quartz/plugins, ../quartz imports) and broke the docs build against our existing quartz.config.ts/quartz.layout.ts.

Infrastructure

  • Extracted the Neovim plugin into its own forge repo, eblume/hephaestus.nvim. Removed heph.nvim/ from the monorepo along with its build/test wiring: the test_nvim Dagger function, the dagger call test-nvim CI step, the mise run test-nvim task, and the .stylua.toml + stylua prek hook (no Lua remains here). The CLI/TUI→nvim integration is unchanged (they shell out to nvim expecting the plugin installed). Install now uses a plain lazy.nvim spec pointing at the plugin repo — see install-heph.
  • Pre-v1 dependency-refresh sweep: bumped all external crates to latest stable — keyring 3→4 (the new keyring_core split + register-the-native-store model), rusqlite 0.32→0.40, ratatui 0.29→0.30, rrule 0.13→0.14, yrs 0.26→0.27, plus semver-compatible updates across the rest. Dropped the fs4 dependency in favor of std::fs::File::try_lock (stable since Rust 1.89), raising the workspace MSRV to 1.89. Removed the orphaned .forgejo/scripts/build hook (CI calls Dagger directly). Full suite green: 228 Rust tests + 25 heph.nvim headless e2e specs, clippy -D warnings + fmt clean.
  • Hub auth now resolves an OIDC sub to an owner_id (Store::resolve_owner → Option<owner_id>) instead of a single-tenant boolean gate (authorize_owner_sub → bool). Behavior is unchanged for the single-owner hub (claim-on-first; a stranger's token still 403s), but the contract no longer assumes one global owner — this is the multi-tenancy seam, so serving N owners later is additive rather than a rewrite. See the Adoption + multi-tenant task's context for the full decision.
    • cargo fmt is now a prek hookcargo fmt --all runs in place over the workspace on any staged .rs change (grouped with the other in-place formatters), so unformatted Rust can't be committed locally. CI already enforced cargo fmt --check via dagger call check; this catches it at commit time instead.
    • Lua is now formatted by stylua (a .stylua.toml + a stylua-system prek hook), so heph.nvim's whitespace is enforced by an opinionated formatter rather than by hand.
    • mise run import-todoist — a one-way importer that seeds a heph store from your Todoist projects + active tasks (project hierarchy, priority→attention, do-dates, natural-language recurrence, descriptions + sub-tasks as context items). Dry-run by default; -- --commit writes into your real store after backing it up. See import-todoist.
  • Add a cargo clippy -D warnings pre-commit hook so lints are caught locally before CI.
  • Customize the repository from the project-template: rename the Dagger module to hephaestus_ci (HephaestusCi), set the docs baseUrl, add an All-Rights-Reserved LICENSE, and update README.md/AGENTS.md for the hephaestus project.
  • Slimmed the credential-keyring dependency to cut CI compile time. keyring 4's keyring meta-crate compiles every platform backend for the target — on Linux that pulled the zbus async stack, a redundant libdbus secret-service, the kernel keyutils store, a SQLite/zstd db-keystore, and OpenSSL (~290 crates in its subtree). Replaced it with keyring-core (the API) plus a single store per OS — macOS Keychain (apple-native-keyring-store), Linux Secret Service (dbus-secret-service-keyring-store, pure-Rust crypto, vendored libdbus so the build needs no system libdbus-1-dev) — registered directly in oauth.rs. hephd's Linux dependency graph drops from 401 to 235 crates (166), removing the zbus stack and two C builds. Runtime behavior is unchanged.

Documentation

  • New how-to: set-up-sync-hub — stand up the canonical hub and connect an existing local device as an offline-capable spoke, the data-safe way (the hub adopts the device's identity rather than rewriting the device).
    • Added a task-lifecycle explanation doc: the two-axis task model (lifecycle state — outstanding/done/dropped — kept separate from attention white/orange/red/blue), why On Deck (blue) is not the same as dropped, what delete/tombstone does (and that it keeps the context doc), and where each task shows up across the agenda, full-text search, and export.
    • Surface strategy revised to a three-surface model (design §4, tech-spec §1/§8), grounded in a study of the owner's live Todoist usage (387 active tasks, 34 hierarchical projects — design §6.2.1): the CLI is task capture/scripting plus the complete daemon API, a planned heph-tui terminal UI (tech-spec §8.1) is the primary task agenda/triage surface, and heph.nvim is the primary context/knowledge-base surface. The study also confirms do-date-not-due-date (zero deadlines used), that task descriptions are already full of unresolved [[wiki-links]] (the exact task↔KB fusion heph provides), and surfaces new needs (project hierarchy, natural-language recurrence) while showing tags are negligible.
    • heph self-hosts its roadmap (the "bootstrap lift"). With v1 at Todoist feature-parity, remaining/future work is now tracked in heph itself — as tasks in the Hephaestus project (heph view ondeck) — rather than in a document. The tech-spec is reframed accordingly: tech-spec.mdv1-prototype-tech-spec.md (all wiki-links + paths updated), retitled and bannered as a historical record of the v1 build, with its §14 tracker frozen. AGENTS.md gains a Planning future work section (capture via heph task "…" --project Hephaestus, triage in heph-tui On Deck); README.md's status reflects parity + the three daily-driver surfaces. The living design doc remains the rationale of record.
  • Add the project design document (docs/explanation/design.md, rationale + decision history) and the distilled technical specification (docs/reference/v1-prototype-tech-spec.md, the build artifact) defining hephaestus as a unified, self-hosted, client/server + offline-first task + knowledge-base system: typed node graph, the lived priority discipline ("what is next?"), recurrence with fresh-per-occurrence checklists, op-log/CRDT sync with conflict resolution, OIDC/Authentik auth, the heph.nvim surface, and a test-driven development strategy.
  • Second-pass review of the v1 design + tech spec before Phase 1: resolved context-item storage (Fork A index model), recurrence (roll-forward in place), key-unique node identity (deterministic ids for journal/tag), mode/sync orthogonality (hub_url spoke), the local-only owner / OIDC adoption path, the "what is next?" ranking (do-date as candidacy filter only, late-on as the sole urgency signal), and the plugin-side mode model (added list + log.tail).