Skip to content

Draft design for extensions (issue #1) - #17

Merged
sdeken merged 38 commits into
mainfrom
claude/electron-devlog-git-fai4tv
Sep 29, 2026
Merged

sdeken merged 38 commits into
mainfrom
claude/electron-devlog-git-fai4tv

Conversation

@sdeken

@sdeken sdeken commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Extensions are npm packages (bundled, dependency-free) named with npm specs
in devlog.json and pinned by a devlog.lock.json; installed by the app into
user data with pacote, never into the devlog. Non-secret settings live in
the devlog, secrets in the OS keychain. Consent per package hash; main half
in a utilityProcess, renderer half in a sandboxed iframe. Covers the time
export flow and ledger (#2), custom block kinds (#3), milestones and open
questions.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6

Extensions are npm packages (bundled, dependency-free) named with npm specs
in devlog.json and pinned by a devlog.lock.json; installed by the app into
user data with pacote, never into the devlog. Non-secret settings live in
the devlog, secrets in the OS keychain. Consent per package hash; main half
in a utilityProcess, renderer half in a sandboxed iframe. Covers the time
export flow and ledger (#2), custom block kinds (#3), milestones and open
questions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…inations

Time reaches Jira (by task, with start times) and CMS (by client, weekly
cap on the full-time client) through a weekly timesheet: sessions built
from tracked time, rounded once to quarter hours, shuffled by hand, stored
in a managed Timesheets canvas with one reply per submission as the send
record. Destinations (extensions) declare mapping fields, grouping, dated
rules and sending. EXTENSIONS.md now points at it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Per the decisions so far: destinations only map, group and send (no caps
or other rules; the user finalises hours); the rounding rule is 15 minutes
for anything above zero, then nearest quarter hour with halves rounding
down; start times round to the quarter hour; rounding inflation is
evened out by suggested trims on the longest sessions of the same client
and day; CMS is per client per day, with ids found by walking up the
canvas tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…d trims

Pure functions in @devlog/core for the timesheet design:
- roundWorkMinutes: anything above zero is 15 minutes, then the nearest
  quarter hour with exact halves rounding up; start times round to the
  nearest local quarter hour;
- buildSessions: same-task segments with gaps of up to 30 minutes are one
  session (short locks count as work), split at longer gaps, at a switch
  to another task and at midnight;
- draftEntries: each session rounded once, starts on quarter hours, no
  overlaps within a day;
- balanceDays: per client (top-level canvas) per day, the rounded total
  worked versus what the entries report, with suggested 15-minute trims
  (or additions) on the longest entries, never below 15 minutes, and the
  residual when it cannot be evened out.

Design doc updated with the decisions (halves round up, 30-minute gap
rule, comments empty by default).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…do panel

- The cross-machine merge of tracked segments (flattenOverlaps) compared
  every segment with every other: a week of window-focus changes took
  over 20 seconds to compute, stalling the weekly review and summary.
  It is now a sweep over the boundaries (O(n log n)), skipped entirely
  when all time comes from one machine; tests check it matches the old
  results exactly. A week with ~1,200 focus changes a day now computes
  in about 0.1 s, and the smoke test checks both views open in under 3 s
  with a busy day from two machines.
- Back / Forward (View menu; Alt+Left / Alt+Right, Cmd+[ / Cmd+] on
  macOS; the mouse's side buttons) walk the places visited: canvases,
  views, timeline days. Keys are caught before the editor sees them;
  deleted canvases are skipped.
- The todo panel resizes by dragging its left edge (or arrow keys on the
  handle); the width is remembered, double-click resets it.
- 0.5.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Two or more consecutive done blocks (not hidden, no replies) show as a
single quiet line, "✓ N todos done" with their names, styled like the
other automatic blocks; clicking it shows the individual blocks with
their usual actions. Display only: the blocks in the files are unchanged,
and a single done block still shows as itself. 0.5.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…led blocks

- The folded "✓ N todos done" line now has a visible Show all / Hide
  control (and aria-expanded); expanded, the blocks are indented under
  it. The smoke test expands a run of twelve and checks every item.
- The sticky canvas header now spans the feed's side padding and sits
  above hovered blocks, so block braces no longer show through it when
  the stream scrolls underneath; the smoke test checks for it.
- 0.5.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Record the search box value, focused element, composer text and whether
any search view rendered, plus a screenshot, and stop the diagnostics
from waiting 30 s themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Every devlog has been upgraded by 0.5, so the upgrade code goes: the
v1/v2 block reader, the pages/categories reader, upgradeRepository and
its cross-machine merge logic, adopting the pre-0.4 local activity log,
the settings revision bump, and the migration smoke test. Opening a
repository now checks devlog.json and refuses an older (or newer) format
with a message naming the Devlog version to use. Canvas aliases stay,
since old activity and links still use them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- Todo comments can be edited, hidden (folded into one line at the end of
  the thread, left out of the count) and deleted; core gains
  setTodoEntryHidden.
- The stream only jumps to the end when a block is posted or a canvas
  opens; deletes, done blocks from the todo panel and captured commits
  leave it where it was (unless it was already at the end).
- Opening or closing a todo keeps that todo in place; ticking one keeps
  the panel's scroll position.
- Opening a todo focuses its comment box, and it keeps focus after
  posting; Esc closes the todo.
- Typing with nothing focused goes into the note box for the canvas on
  screen.
- Smoke: checks for all of the above; clicks rather than check()/uncheck()
  for todo rows that move between lists; seeds activityInRepo now that
  the settings revision bump is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Heartbeats only prove the app was alive while time can accrue; lock,
idle and suspend are already in the log and close the open segment, so
the periodic heartbeat is skipped while paused. That also stops sync
from committing and pushing an activity file every five minutes on a
locked machine. Foreground-window changes while locked or asleep (the
lock screen itself) are no longer recorded either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…tension

- Two data channels: contribute to the devlog through the API (marked
  with the extension's id), or keep its own files in private synced
  (extensions/<id>/) and machine-local folders, any format.
- Isolation between extensions: no paths (a file broker with confined
  relative paths), no file system (utilityProcess under Node's permission
  model, to be verified), no shared channel, per-extension sandboxed
  renderer frames.
- Window tracking moves out of the core into a bundled, opt-in
  first-party extension (devlog-focus); the task clock stays core.
- Docs: heartbeats are skipped while the machine is locked or asleep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- Reading the devlog is a permission, granted for the whole devlog or for
  chosen canvases (with what is beneath them); grants live on the machine
  with the consent, never in the repository.
- Extensions are zips on GitHub releases (or any HTTPS URL) with a
  devlog-extension.json manifest, pinned by SHA-256 in devlog.lock.json;
  not npm, and no package manager. Ids come from the source, so one
  extension cannot claim another's folders.
- Per-canvas settings in canvas.md, per-devlog settings in devlog.json.
- v1 safety: no file-system access (Node permission model, code sent over
  the channel), no processes/addons/workers, grant-filtered API, no
  channel between extensions; network declared but not enforced.
- Rich blocks and link previews as Adaptive Cards rendered by the app, so
  no extension code runs in the window.
- devlog-focus gets the foreground-window feed as a capability instead of
  starting its own helper.
- Timesheet sending is user-driven only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- extensions.ts (pure): devlog-extension.json validation, devlog.json
  entries (owner/repo + range, https URL, builtin) and ids derived from
  the source, a small semver range matcher, read/write grants with
  whole-devlog or canvas-subtree scopes and what they make visible.
- canvas.md keeps unknown front-matter keys (extension fields such as
  ext.<id>.<key>), settable through updateCanvas; inheritedField walks up
  the tree. Index schema bumped so cached canvases pick fields up.
- devlog.json updates keep unknown keys (extensions, settings);
  devlog.lock.json read/write.
- ExtensionFileStore: an extension's private folder behind relative
  paths only; refuses .., absolute paths, device names, streams and
  links (including a linked extensions/ folder from git); atomic writes;
  size and file-count caps. Append-only globs get union-merge attributes.
- Extension files are quiet for sync, like activity logs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…PI, UI (0.7.0)

- Installer: GitHub releases (newest tag matching the range, a
  *.devlog-ext.zip asset, optional token for private repos), https URLs,
  built-ins shipped in the app's resources, and machine-local development
  folders. Downloads are checked against devlog.lock.json's SHA-256,
  unpacked (no path may leave the folder) into a cache keyed by hash.
- Sandbox: Electron's utilityProcess ignores --permission, so each
  extension runs as a Node child of the app binary (ELECTRON_RUN_AS_NODE)
  under the permission model, allowed to read only the host script (copied
  out of app.asar), with a heap cap and a stripped environment. The bundle
  is sent over IPC and evaluated; require resolves Node built-ins only.
- Manager: consent per build and devlog (a new build asks again), read and
  write grants (whole devlog or canvas subtrees) enforced on every API
  call, private repo/local folders through the file broker, settings in
  devlog.json, secrets through safeStorage, commands, notifications,
  confirmations, pause/resume/task notices. Reloads after a pull.
- UI: Extensions dialog (add, allow with scopes, settings and secrets,
  stop, start again, remove, check for updates, GitHub token), consent
  dialog, extension commands in the quick switcher, extension fields in
  the canvas dialog, notifications as toasts; blocks written by an
  extension are read-only with the automatic brace.
- @devlog/extension-api: public types, wire protocol and an in-memory
  test harness; authoring guide in its README.
- Tests run a probe extension in the real sandboxed process (file access,
  child processes and workers refused; grants filter reads, writes and
  search); smoke drives the whole flow in the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- Extension API 1.1: ctx.machine, ctx.system.onForegroundWindow (needs
  the foregroundWindow permission and consent), ctx.provide.focus.
- The app runs the platform window helper only while an allowed
  extension listens, and passes nothing on while the machine is locked
  or asleep (straight from powerMonitor, tracked or not).
- devlog-focus ships in the app's resources: it appends each change to
  extensions/builtin.devlog-focus/<machine>/YYYY/MM/<date>.jsonl
  (union-merged), re-announces the window when the machine comes back,
  and provides the events back; activity.range merges them, so the
  timeline, review and summary draw screen time as before.
- The core tracker no longer records focus events; existing ones in the
  activity logs still show. The "record the focused window" setting is
  gone; people who had it on are told once where it went.
- Extensions dialog lists built-ins to add; the consent dialog asks about
  window titles; the harness supports the 1.1 API.
- Tests run devlog-focus in the sandbox with a fake window feed (nothing
  recorded while locked or asleep, nothing without the permission, the
  helper stopped on revoke); smoke adds it from the dialog and checks the
  events reach the views.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- An extension may declare "permissions": { "unrestricted": true }. It
  then runs only if you tick "I trust it" in the consent dialog, and runs
  without Node's permission model, with the app's environment and
  ctx.packageDir (its unpacked folder). A consent without trust does not
  start it; the grant records trust per build like the rest.
- devlog-focus carries its own platform helper (moved from
  src/main/activity/foreground.ts) and runs unrestricted. The app's window
  feed, the foregroundWindow permission and ctx.system are gone (API
  1.2); nothing about windows is left in the core.
- Extensions hear about locks and sleep straight from the OS (deduplicated
  with the tracker's events), whether or not time is tracked.
- Fix: devlog-focus no longer remembers the lock screen as the last window
  and re-records it on resume.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…s (0.9.0)

- Core: the stored Timesheet (week, draft/final, entries), sanitised on
  every save; serialised as a readable markdown table plus the exact data
  in a devlog-timesheet fence. DevlogStore keeps one block per week (kind
  timesheet, on its Monday) in a canvas marked devlog.managed: timesheets,
  created on first use; later saves are edit records. Timesheet blocks are
  read-only like other automatic blocks.
- Draft: tracked task segments (explicit markers applied, removed time
  excluded) → sessions → entries rounded once; untracked days use the
  review's estimate, starting at their first note.
- Timesheet view (sidebar and quick switcher): week navigation, entries by
  day with day, start, duration in 15-minute steps, task, note, remove and
  add; per client and day, reported vs worked with the suggested trims and
  Apply; Rebuild from tracked time; Mark final / Reopen; saves within a
  second of each change.
- Tests for the model, storage and draft; smoke drafts an hour of tracked
  time, adjusts it, checks the saved table and marks the week final.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…0.10.0)

- Extension API 1.3: contributes.destinations and
  ctx.destinations.register(id, { preview, send }). The app builds the
  week's sheet from the saved timesheet (task and client names, the
  extension's own canvas fields inherited down the tree); pressing Send is
  the consent for that week, so no read grant is needed. Only final weeks
  are sent; each send leaves a read-only reply under the week's timesheet.
- devlog-jira (built in, sandboxed): one worklog per entry on its Jira
  issue (canvas field "issue"), REST v2 with Basic email+token (Cloud) or
  a personal access token (Data Center); a ledger per week in its own
  synced folder, so sending again creates, updates or deletes only what
  changed; a "Check the Jira connection" command.
- Timesheet view: Send to <destination>… on final weeks; the Send dialog
  previews new / changed / removed / already sent / not for this
  destination (with reasons), sends, and shows the result.
- Fix: a draft entry whose start rounds past midnight stays on its own day.
- Tests run devlog-jira in the sandbox against a fake Jira server (create,
  unchanged, update, delete, auth, the record); smoke sends a week to a
  fake Jira through the dialog. Smoke: DEVLOG_PLAINTEXT_SECRETS opts into
  Electron's in-memory key on keyring-less Linux (tests only); the review
  per-day check no longer assumes the run does not cross midnight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
The Extensions dialog loads the built-ins after it opens; CI checked the
count before they arrived.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…0.10.1)

The week is now a table: a column per day plus the week, a row per task
grouped under its client (each client row totals its tasks), and at the
bottom the day's total reported and, muted, what was worked. Clicking a
cell opens its entries under the grid for editing (start, duration, task,
day, note, remove, add); an empty cell adds time there; "+ Add a task…"
puts a task with no time yet on the grid. The suggested trim for a
client's day sits in that client's cell and applies on click. Task names
come first in row labels so a narrow window cuts the project path, not
the name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…mputer, Test (0.11.0)

- Manifest fields (settings, secrets, canvas fields) take a description,
  a type (text, url, email, number, select with options, checkbox,
  textarea) and required; contributes.check names a command that tests the
  settings.
- Settings open in their own page, split into "This devlog" (devlog.json,
  synced) and "This computer" (secrets in the OS keychain, shown as saved
  with Replace / Clear). Values are checked by type on save; one Save for
  everything; Test / Save and test runs the check command and shows the
  text it returns, or its error. The extension's card says what required
  settings are still missing and offers "Set up…".
- Canvas dialog: extension fields use the same typed inputs and show the
  value a canvas inherits from above as its placeholder.
- devlog-jira: typed, described, required fields; its connection check
  returns its result to the settings page.
- Inputs in dialogs share one style whatever their type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
A built-in, sandboxed extension that fills in the Technology Partners
consultant timesheet the way the browser does: form login with the session
cookie, the week page parsed for assignment rows and each day's
timesheet_id, and the day's form submitted with decimal hours.

- Hours per assignment (canvas field "assignment": number or project name)
  per day, across the two Sunday-to-Saturday CMS weeks a Devlog week spans.
- The preview compares with what CMS shows; only differing days are sent,
  days it filled that no longer have time go back to 0 (ledger in
  sent/<week>.json), days typed into CMS by hand are left alone.
- Days without a link (outside the assignment's dates, or not open yet
  because CMS opens a day on that day) are skipped with the reason; weeks
  that haven't started aren't fetched.
- Commands: check the login, list assignments. The quick switcher now
  shows a command's answer as a toast.
- Username in the devlog, password as a secret on the computer.
- Tests against a made-up CMS with the same page structure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- Settings open from the foot of the sidebar into a dialog with its own
  navigation: Repository, Sync, Appearance, Activity tracking, Updates, and
  under Extensions a Manage page plus one page per extension (access,
  settings, secrets, its test). Save stays off until something changes;
  pages with unsaved changes (or extensions needing setup) are marked, and
  closing with unsaved changes asks first. The separate extensions and
  extension-settings dialogs are gone.
- Canvas properties use the same paged layout: the canvas, its
  repositories, and a page per extension that adds canvas fields. Save is
  off until something changes.
- Right-click a canvas in the sidebar (or a breadcrumb or child chip) for
  Open, Start/Stop, Properties, New canvas/task inside, Archive.
- Start is a split button: with a task on screen its main part starts that
  task in one click; the arrow opens the task list. Task canvases also get
  Start/Switch/Stop in their header.
- The journal is retired: no sidebar entry, no composer target, no todo
  fallback. Devlog opens on the last canvas viewed (or the running task, or
  the first canvas); a devlog with no canvases shows a first-canvas page.
  Old journal notes stay readable under Archived until moved.
- devlog-cms 1.0.1: a week still ahead resolves assignment names from the
  current CMS week.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Phase 1 of docs/BLOCK-PAGES.md.

- Double-click a block (or Open, or its chip) to open it as a page: the
  block is the page's surface (double-click to edit), and the blocks
  written inside it are the page's stream, grouped by the day each was
  written. Breadcrumbs run canvas / blocks above / this block; Alt+Up or
  "Up" goes up a level (from a canvas, to its parent canvas).
- Streams no longer show threads inline: a block with blocks inside shows
  a chip ("3 blocks inside"). Reply is gone; the note box on a page writes
  inside that block. Alt+Enter posts and opens the new block.
- Back and forward, search results, and timeline and review links open
  the page a block was written on.
- Reordering works among siblings at any depth.
- Blocks written inside an older block stay in its day file; the date
  range query also returns those files (via the index, which now keeps
  creation times indexed), so the review, summary, timeline and timesheet
  count them on the day they were written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Phase 2 of docs/BLOCK-PAGES.md; docs/TIME-EXTENSION.md records the plan
for moving time tracking into an extension.

- A todo is a block with kind=todo, anywhere in the streams: on a canvas,
  inside a block, inside another todo. "[ ] …" lines (or pasted "- [ ]"
  lists) post one todo per line; the stream shows a checkbox.
- Ticking a todo sets its done time where it is (no more "✓" blocks); a
  run of ticked todos folds into one line; the timeline shows the tick.
- The todo panel is built from the index: open todos for the page on
  screen and everything inside it (or all), grouped under the canvases
  and blocks they live in, single-path chains merged into one heading,
  headings foldable. Clicking a todo opens its page; the add box posts
  into the page on screen. The inline comment threads are gone: notes on
  a todo are blocks inside it.
- Opening a format 3 devlog moves each canvas's todos.md into the day file
  of the day each todo was written (comments become blocks inside it) and
  marks the devlog format 4.
- Extension API 1.4: addBlock inside a block and as a todo; devlog.todos().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- Drag a block onto the middle of another to put it inside (from any day
  of the same canvas); Move → "Out of this block" takes it one level up.
  Core: moveBlock (a single set record within a file; copy and delete
  across files) and planNest.
- Making a block with blocks inside it a task moves those into the task
  canvas's stream; the block stays as the link.
- The quick switcher lists recently opened pages first.
- Returning to a canvas from another view re-reads it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- contributes.views: page (sidebar + main area), statusbar (a slot of
  fixed height; the page asks for a width), popover (anchored to the view
  that opens it).
- Pages load from devlog-ext://<key as hex>/<file>: only from the
  extension's own folder, only while it runs, in a frame sandboxed to
  scripts, under a CSP with no network, frames or forms.
- The page talks to its extension through the app (postMessage: ready,
  call, resize, popover, close, open, command); the extension answers with
  ctx.views.handle and pushes with ctx.views.post; the app sends its theme
  as CSS custom properties. Message types in @devlog/extension-api/view.
- The probe fixture has all three; tests cover the relay, the smoke test
  the frames, the push, the popover, opening a canvas, and the sandbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…core

- packages/ui: React components, hooks, and the view bridge for extension views
- scripts/build-builtins.mjs bundles built-in extensions' TypeScript sources
- Canvases get an optional node type; `task: true` reads as the time
  extension's task type and is still written that way

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Extensions declare node types (`contributes.nodeTypes`: id, label, icon,
placeholder). Canvas properties get a Type choice in place of the task
checkbox; the sidebar, child chips, quick switcher and note box show the
type's icon and label. `canvases()` reports each canvas's type. The task
type stays the app's own until the time extension provides it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…rites; events; app state

- Commands take a context (where they were run from, the canvas and block)
  and can declare a keybinding, a node type, menus (canvas, block, tray),
  and a note-box variant (`post`, with an optional #tag)
- Views can sit in a canvas's header (`canvasHeader`, per node type) and
  get their canvas as context
- devlog.createCanvas / updateCanvas / editBlock / promote / onBlockAdded
- ui.pick, ui.open, ui.highlight; app.setTrayLabel, app.keepRunning;
  activity.idleAfter; provide.activity (time events join the app's views)
- The test harness covers all of it; a `shaper` fixture exercises it
  through the real host process

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- builtin-extensions/devlog-time (TypeScript, bundled at build): the task
  node type, the clock (start/task/stop/heartbeat events in its own folder,
  per machine), Start/Stop in the status bar and on task canvases, a task
  picker, Stop (Mod+Shift+.), Start a task…, post as a task
  (Mod+Shift+Enter, #task), Make task on a block, the tray label
- The app no longer tracks time: the Tracker, its IPC and UI are gone.
  It still notes locks, idle and sleep (for extensions, and in its
  activity log while an extension tracks time), and its views draw time
  from extensions' events alongside the old log
- Once per machine that tracked time, the extension is added to the
  devlog and allowed, with the active task and idle setting carried over
- Summary and Timesheet show only while an extension provides time
- Extension views get their theme and context even when they load fast

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
…through destinations

- devlog.activity(from, to): what the app recorded (its log and what
  extensions provide), limited to what the extension may read
- devlog.range(from, to): day files with blocks written in a range
- devlog.managedCanvas(key): a canvas the extension keeps, its own whatever
  it was granted: blocks of its own kinds on any day, editable; the
  Timesheets canvas the app made is devlog-time's
- destinations.list/preview/send: other extensions' destinations, through
  the app, for extensions that declare permissions.send (shown at consent)
- ui.openPage(viewId)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
- The Timesheet (with Send), and the Summary, move into the extension as
  page views built on @devlog/ui; the app's own views, IPC and store code
  for timesheets are gone
- Timesheets stay one block per week in the Timesheets canvas, now kept by
  devlog-time (the canvas the app made is its own); sending goes through
  the app to the Jira and CMS extensions, and the record is written inside
  the week by devlog-time
- Extension pages are listed in the quick switcher; Ctrl+Shift+H opens
  the Summary (a devlog-time command)
- Shortcuts pressed inside an extension's view that it does not use reach
  the app (Ctrl+K, Alt+←…)
- A built-in extension keeps its grant when the app brings a new build
- Views get more of the app's colour tokens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
devlog-time adds two canvas fields (hours per week, hours per month) that
canvases inside do not take on. The Timesheet page shows each target that
applies to the week on screen against the timesheet hours under its canvas
in its own period: the week, and each month the week touches (other weeks
as saved, or drafted from tracked time). Canvas fields can now say they are
not inherited (`"inherited": false`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CAgWUf68JDhC5YPtWj1zT6
@sdeken
sdeken merged commit 8fc2028 into main Sep 29, 2026
11 of 12 checks passed
@sdeken
sdeken deleted the claude/electron-devlog-git-fai4tv branch September 29, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants