Skip to content

Releases: bharathvbcr/GitPulse

GitPulse v1.3.1

Choose a tag to compare

@github-actions github-actions released this 23 Sep 01:30

Fixes and visual polish for code navigation, viewer layout scaling, and tooltip placement.

Fixed

  • Code viewer zoom row height scaling. Code line heights in CodeViewer now scale proportionally with editor zoom stops (70%–160%) using scaledRowHeight. The virtual row containers and text line heights stay perfectly matched, eliminating visual line overlap and row clipping at compact zoom.
  • Boundary-aware tooltip bubble placement. Tooltip positioning now calculates viewport edges through placeTooltipBubble, keeping tooltips fully on-screen across arbitrary window sizes and respecting preferred directional hints (above vs below).
  • Responsive horizontal header controls and scroll cues. File viewer headers across CodeViewer, FileTreePanel, MarkDevViewer, and MediaViewer now gracefully scroll horizontally when horizontal space is constrained, paired with ScrollCue visual indicators to ensure all controls and action buttons remain reachable on narrower viewports.
  • MarkDev rendered view layout and scrolling. The markdown rendered preview pane now uses bidirectional scroll containers and proper flex bounds, preventing text clipping on oversized formatted blocks.
  • Breadcrumb path navigation typing. Fixed navigation strip element bindings in FileViewer to ensure strict type compliance.

GitPulse v1.3.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 15:57

A consolidation release. It joins live delivery observability — GitHub Actions
workflow runs and Firebase App Hosting rollouts tied directly to repository
commits — with the bodies of work that were in flight beside it: native
notifications for agent sessions, Claude Code supervised in the managed lane,
code-age history in Blame, a terminal dock that belongs to a repository rather
than the workspace, terminal output whose links are safe to click and land where
they point, and walkthrough replay moved out of the title bar.

Re-cut on 2026-09-21 over a wider tree, adding native notifications for agent
sessions, quiet hours and sound control, managed Claude Code runs hosted over
stream-json, regression suspects from the code graph, a Health view that reaches
a verdict, repository tab groups, and the coverage and impact surfaces reduced
to what they can actually claim. Two process-lifecycle defects are fixed behind
them: an ordinary policy-harness shutdown that leaked whatever the harness had
forked, and a test suite whose verdict depended on how busy the machine was.

Added

  • Native notifications for agent sessions. An agent running in a GitPulse
    terminal tab was completely silent: Claude Code only sends desktop
    notifications in a handful of terminals it recognises, Codex's OSC 9 probe
    recognises a similar short list, and GitPulse's terminal matched neither — so
    the only signal a waiting agent could give was an unread dot on a tab you had
    to be looking at. Three layers now carry it, each independently sufficient:

    • GitPulse reads the PTY itself and understands every notification convention
      a terminal program has to choose between — BEL, OSC 9, OSC 777 and kitty's
      chunked OSC 99 — so a CLI that signals any of them is heard, whatever it
      is. ConEmu's OSC 9 sub-commands for progress and working directory, which
      Claude Code's progress bar emits continuously, are not notifications and are
      not treated as any.
    • Sessions GitPulse launches are given each CLI's own documented notification
      flag (claude --settings, codex -c tui.notifications) for that session
      only — no file of yours is written — so the CLIs actually emit something.
      Turn it off under Configure agent CLIs GitPulse launches.
    • The GitPulse plugin's Notification and StopFailure hooks report why an
      agent stopped — permission, idle, input, finished, asking, error — over a
      private local socket, which also covers a Claude Code running outside a
      GitPulse tab.
  • Quiet hours, sound and per-kind control for those notifications, and a
    counter panel that distinguishes a notice suppressed by a rule you set from
    one that was lost. Notifications are suppressed while you are looking at the
    session they are about.

  • Claude Code runs in the managed lane. Previously only Codex could be
    supervised by GitPulse — every Claude Code handoff opened a terminal and
    GitPulse stepped back. A managed Claude run is now hosted over Claude Code's
    own stream-json protocol, so its permission requests arrive as structured
    approvals you answer in GitPulse, its output is captured, and its completion
    is a receipt rather than a guess. All six permission modes map to real Claude
    Code modes, and the one that does not round-trip (ask is reported by the CLI
    as default) is verified as such rather than assumed.

    Two honest differences from managed Codex, both visible in the run's recorded
    configuration: Claude Code has no OS sandbox, so the record says so instead of
    naming a confinement that does not exist — a managed Claude run is supervised,
    not confined — and its model is not in that record, because the CLI names it
    only after the record has been written and made immutable. Repository settings
    files are deliberately not loaded for a managed run, so a checkout cannot
    widen the permissions of the run inspecting it.

  • Claude Code is now the default agent for a new task handoff, and leads the
    provider list. The connection still defaults to a terminal in ask mode: a
    first launch should be the reversible one, and the managed lane stays a
    deliberate choice. An existing remembered preference is untouched.

  • Platform coverage is written down. Platform
    coverage
    separates what is known
    absent
    off macOS — desktop notifications for activity and agent sessions, the
    agent hook socket, the menu-bar status item — from what is merely unverified
    there, such as managed runs. macOS is the platform GitPulse is developed and
    hand-tested on, and the docs now say so instead of leaving it to be discovered.

  • Regression suspects — which commits could have caused this? Blame joined to
    the code graph, and the order of operations is the whole argument: a
    blame-first tool reads a file's gutter and ranks by recency, this reads the
    graph first, so candidates are ranked by what actually reaches the symptom.
    Ships as two vendored crates (dc-regress, dc-regress-store) so every host
    asks the same question of the same graph, plus a Regression Suspects panel.

  • The Health view gives a verdict, rather than a wall of readings for you to
    add up, and every repeated decision behind it now has one owner instead of a
    copy per caller.

  • Repository tab groups. Open repositories can be grouped and named, so a
    workspace with a dozen checkouts is navigable rather than merely complete.

  • Markup and stylesheet extraction. A template file's HTML and CSS halves go
    through a real grammar, closing the gap left when only its <script> blocks
    did.

  • A substance gate for verification. Every other gate answers "is something
    wrong with this change"; this one answers "is there anything in it", which
    nothing did before.

  • Live GitHub Actions Run Polling: Automated, bounded polling for in-flight
    workflow runs that refreshes only while runs are queued or executing, backing
    off on failures, pausing while the window is hidden, and announcing newly
    failed runs via dismissible notices.

  • Delivery Timelines: Visual duration and outcome timeline for workflow runs
    and Firebase App Hosting rollouts, scaled to sample bounds with pass rates,
    median execution times, and clean handling of queue time vs execution time.

  • Firebase App Hosting Rollout Monitoring: On-demand live refresh for
    authorized project and backend pairs, providing live rollout status alongside
    commit history.

  • Action Dispatch & Rerun Controls: Enhanced GitHub Actions panel with rerun
    actions, branch filtering, and granular status reporting.

  • Clickable terminal output. A URL opens in the OS browser only when its
    scheme is http or https, verified with a real URL parse at both detection and
    activation. A file reference opens in the code viewer only when it resolves
    inside the session's repository, with containment checked on normalised path
    segments — a string prefix test calls /repo-evil/x and /repo/../etc/passwd
    inside /repo, and segments do not. A span GitPulse will refuse to open is
    never decorated as a link: underlining it and then doing nothing teaches
    people to distrust the underline instead of the output. OSC 8 hyperlinks obey
    the same allowlist, judged on the escape sequence's target rather than its
    display text.

  • A file reference lands on the line it names, with the line selected; one
    naming a line past the end of the file opens near the end rather than
    refusing. The line travels as a one-shot request with an explicit consume, not
    on the repository session: "scroll to line 12" is a navigation intent that must
    not survive a restart or replay when the file is reopened for another reason.

  • Screen reader support in the terminal. The terminal had no accessible
    text at all — screenReaderMode appeared nowhere — so a preference now builds
    xterm's row tree and applies to running sessions. The Console command field had
    no accessible name either; a placeholder is a hint, not a name.

  • The terminal harness is CI-gated. npm run test:browser -- --harness terminal (and --webkit) runs in the automated sweep instead of waiting for
    someone to press a button, with 75 real-DOM checks over the production
    components and a simulated PTY transport.

  • Code-age timeline in Blame: a chronological axis above the gutter showing
    what percentage of the open file was last changed in each period. Resolution
    adapts to the file's history (daily through yearly) and is bounded; a history
    too long for even a yearly axis folds its oldest lines into the leading column
    and says so. Clicking a column filters the gutter to exactly the lines that
    column counted — the picture and the filter share one classifier, so a column
    cannot claim a share it would not select. Quiet periods are drawn as empty
    columns rather than omitted.

  • Off-axis lines are named rather than dropped: worktree-only, clock-skewed
    and undated lines carry their own labelled, selectable shares beside the axis.
    Columns plus chips account for 100% of the file.

  • Commit blocks in the gutter: consecutive lines from one commit state their
    hash and author once at the head of the block, keep the hash reachable on
    hover or focus, and mark the whole commit down the left edge when hovered.

  • Line age in the gutter: each line's commit age, following the shared
    timestamp preference, with the other form on hover. docs/FEATURES.md had
    described this since the page was written; it was never drawn.

  • Code-age rail in Blame: a heat strip down the right edge showing where
    in the file each age lives, with a band marking what is on screen and
    click/drag to navigate. It maps the list actually drawn, so a filter re-maps
    it; the freshest tone wins e...

Read more

GitPulse v1.2.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 21:30

A release about checks that were not telling the truth. Every fix here is a
report that read as an answer without being one: a doctor that compared a
version against itself and said ok for a binary running week-old code, an
installation check that named a cause it did not have, warnings dropped on the
way to the panel that promised to show them, and a measurement that silently
never happened on a window that had stopped painting. A check that could not
run must not read like one that ran and passed.

Repository trust is the other half. An approval made before 1.1.0 left every
linked worktree refused with nothing offering a way out — the app reported the
repository as trusted and never asked again, so worktree comparisons, collision
checks and the fleet view quietly dropped every sibling. Trust is now reported
as a scope rather than a yes/no, and the sidebar offers to extend an
approval that predates worktree coverage. Approvals are still never widened by
being read: extending is a decision you take, through the same dialog.

The new surface in this release, Firebase App Hosting, is built on the same
rule. Its backend and rollout listings are click-only rather than loaded on
render, because the upstream commands enable the App Hosting API on the project
they read — a read that bills is a decision, not a side effect of opening a
panel. What it buys is a join rather than a guess: App Hosting reports the full
commit SHA it deployed, so "this commit is live" is looked up against the graph
instead of inferred from a branch name and a timestamp.

That panel can now also deploy, and one action in this release changes what
production serves. Creating a rollout is neither reversible from GitPulse — App
Hosting publishes no rollback verb — nor idempotent, so it is the one place
here guarded twice rather than once: the target must be a full 40-character
SHA, the confirmation names the exact project, backend and commit and says
plainly that GitPulse cannot undo it, and editing any part of that target
disarms the confirmation so the values sent are always the values reviewed. The
policy gate runs before the process, not alongside it. And what the installed
CLI can actually do is probed rather than assumed, because the upstream
subcommand is registered only behind an experiment that is off by default — a
capability that could not be probed is reported as unknown, never as absent.

Added

  • App Hosting can deploy a named commit, not only report one. Create rollout
    is the only command in the Firebase module that changes what production
    traffic serves, and it is built to be refused easily and taken deliberately.
    The commit must be a full 40-character SHA — an abbreviation is an ambiguous
    target for something that reaches production, and is declined with the
    reason — and the deploying button does not exist until a confirmation naming
    the project, the backend, the commit and the fact that GitPulse cannot undo
    it has been read; changing any part of that target disarms it again. The
    write gate judges the argv before any process is spawned, and a contract test
    asserts that ordering directly rather than trusting it, because this argv is
    built in the Firebase module instead of being spelled out in the handler and
    is therefore exempt from the literal comparison the other commands get.
    --token is never passed, so no credential is placed on a command line other
    local processes can read, and --force is never passed either, so nothing
    here suppresses a prompt the user would otherwise have seen. A rollout that
    started is never reported as failed: if the CLI exits zero without confirming
    the result, the panel says so and warns against a blind retry, because
    upstream allocates a new rollout id per call and a false failure is what
    turns one deployment into two.

  • The Firebase panel asks the installed CLI what it can do instead of assuming.
    apphosting:rollouts:list is registered upstream only behind the
    internaltesting experiment, which is off by default, and an unregistered
    subcommand exits non-zero having written nothing to either stream — which
    would have read as "no rollouts" rather than as "this CLI cannot answer". The
    probe lists a command group, so it needs no login, no project and no
    network, and the action is offered only when the subcommand is really there.
    A capability that could not be probed is reported as unknown rather than as
    absent, because the two have different remedies.

  • The board's quick-add line can draft. Return still saves the typed line
    exactly as before, and then asks the configured model for a title and a
    description to review. Two rules keep it honest, and neither is a tiebreak
    applied afterwards: the task is written from the typed markers first and the
    model proposes against the saved result, so markers always win structurally;
    and the model can only ever touch title and description, because that is what
    the enhancement field type admits — priority, labels, owner, type, repository
    and due date are out of reach by type rather than by policy. The sentence
    shown before you press Return and the request made after it are derived from
    one value, so the promise on screen cannot name a field the request does not
    carry. Off by default, and remembered: it changes what a keystroke does, so
    it is chosen once rather than every time, and a stored value this build
    cannot read falls back to manual — the mode that spends a model call must not
    be the one a failed decode selects.

  • Due is a control the sheet owns rather than the browser's datetime-local
    box. A trigger, a portaled month grid, and a word box that shares the board's
    quick-add grammar — type friday 09:30 and press Return, the same phrasing
    that works on the quick-add line, which is also what proves the grammar is
    wired rather than duplicated. taskDue owns only what was unowned: the
    grammar of a date word stays with parseQuickAddDue and how urgent a deadline
    is stays with dueState, because the board sorts and filters on that and the
    sheet must not answer it a second way. All of it is local time — a due date is
    a day in the reader's week, not an instant, so the sheet cannot show "Sep 18"
    for a timestamp the board files under the 19th.

  • The plugin package has a display name, and a mark where a client will actually
    render it. name is the install identifier, so the list showed gitpulse.
    The logo lives in .cursor-plugin/plugin.json and nowhere else: Cursor is the
    only one of the three hosts that renders a logo, Claude Code documents no
    field for one, and the Agent Plugins schema sets additionalProperties: false,
    so the same key in the portable manifest invalidates the package for a
    conformant client. check-release-version walks the Cursor manifest with the
    other three, so its version cannot drift from the release.

  • Firebase App Hosting backends and rollouts, read through the firebase CLI
    and joined to the commit graph. Build.source.codebase carries hash — a
    full SHA-1, the same key git cat-file speaks — so "is this commit live?"
    becomes a lookup rather than an inference, and presence is read from the
    command's own success flag rather than from is_ok(), because
    git_captured returns Ok on a non-zero exit: absence is data, not failure,
    and reading it the other way would have made every rollout look locally
    present.

    The two listings are click-only and wear Guarded<T> on purpose, and this is
    the part worth stating plainly: apphosting:backends:list and
    apphosting:rollouts:list both declare .before(ensureApiEnabled) upstream,
    so reading them enables the App Hosting API on the Cloud project. REST does
    not avoid it — App Hosting's only OAuth scope is cloud-platform, full
    read/write, with no read-only counterpart of the kind classic Hosting accepts.
    A read that mutates a billed resource must be something you choose, never
    something a panel does because it rendered. Passing --json also implies
    non-interactive, which turns a would-be enablement prompt into a loud error
    rather than a silent one. apphosting:rollouts:list exists only in
    firebase-tools' source and is documented nowhere, so its envelope is parsed
    strictly and fixture-pinned instead of trusted to keep its shape.

Changed

  • Writing a task and asking the model to help with it are one pane again.
    Splitting the sheet into four panes fixed a sheet where nothing read as
    important and introduced a worse problem: the AI pane's output was drawn on
    the Task pane, beside the fields each suggestion would replace, so a reader
    pressed a button on one pane and the result appeared on another. Writing a
    task, scheduling it and improving its wording are one sitting, so they are now
    one pane in two columns. Only Agent still earns a tab — handing a saved
    revision to something that will act on it is a different decision, with its
    own risk and its own run history. A draft is still never tabbed.
  • The suggestion picker can tell two attempts apart. Its rows read
    state · model plus Task revision N, which was the same string for two
    attempts by the same model at the same revision. A timestamp separates
    attempts made minutes apart and an ordinal separates attempts made in the
    same second; the ordinal is a reading aid derived from the page total, never
    an identity — the row's value is still the proposal id. State wording now
    comes from one table read by both the picker row and the heading it selects,
    which were previously the same literal list written twice.
  • extended_child_path leaves a PATH already at the execve argument-size
    ceiling alone instead of appending to it. Growing a near-limit environment
    turns a working spawn into E2BIG, surfac...
Read more

GitPulse v1.1.0

Choose a tag to compare

@github-actions github-actions released this 14 Sep 16:52

A feature release that began as a patch. What was staged as 1.0.1 — the
repository-trust gate and the hardened file saves — was never published, and
ships here instead of on its own.

The tasks page was rebuilt around the work you do most: adding a task, finding
one, and handing one to an agent. Nothing on the board is hidden without saying
so, and the agent handoff is one form rather than two that had drifted apart.
Branch names get a line to themselves, drafting can run on the Mac instead of
over a socket, and DevMap builds its own index rather than answering every
question with an empty result.

The fixes are mostly of one kind: failures the app was misreporting rather
than merely failing. Truncated Git output that read as a complete short answer,
a plugin whose hooks were installed nowhere while its doctor said ok, and an
untrusted checkout described as a broken one.

Added

  • Quick add: one line creates a task, with !priority, #label, @owner,
    due:, repository and :: note markers parsed as you type and shown as
    chips before anything is written. The line is capped and refuses rather than
    truncating, and the a key focuses it.
  • A View menu that persists: hide columns you do not use, choose which fields
    each card shows, and reset. A board hiding work says how much and where.
  • On-device drafting with Apple Intelligence on macOS 26 and later, as a second
    engine beside Manvi. Titles and descriptions are written on the Mac and never
    reach a socket. Where the framework is unavailable, the reason it gives is
    shown rather than a generic failure, and a build without the bridge says so
    instead of blaming the hardware.
  • A handoff sheet on the board: launch an agent in two clicks, with the checkout
    already resolved, without opening the task.
  • DevMap builds its own store on first use. Opening a repository with no index
    used to answer every code-intelligence question with an empty result, which
    reads exactly like a clean one. Component status is reported per component
    with its warnings kept separate, so a partial DevCouncil install is never
    rendered as a complete one, and a rebuild chooses between a full manifest
    pass and an incremental one instead of rebuilding on every change. The suite
    and agent-integration panels and a fleet-wide index sweep come with it.
  • gitpulse-hook --version answers with its build and every subcommand it
    serves. No host sends it; mcp:doctor needs it because silence is a
    legitimate answer to every real hook invocation, so nothing else can tell an
    absent binary from a current one.
  • First-run walkthrough: an interactive tour that highlights the controls
    themselves as you open a repository, try views, and explore Tasks and
    Settings, rather than describing them from a panel off to one side. The card
    anchors to the control it is describing — taking the space below it where
    there is room and above it where there is not — scrolls that control into
    view, and follows it as the window resizes. It sits below menus, trust
    prompts and Settings in the stacking order, so it never covers what it is
    pointing at, and it observes its target only while a step is on screen:
    nothing polls, and no listener outlives the step that created it. Replayable
    at any time from Walkthrough in the title bar.
  • An Archive dock on the tasks board: completed tasks for the current
    scope, with their own search and Load more, and a header badge carrying
    the server's total rather than the loaded page. A selection restores to any
    other status, or is deleted, through the same confirm-and-retry dialog every
    other bulk change uses — the dock owns no write path of its own. It says
    whether the Done column is still on the board and offers the same hide the
    View menu owns, rather than keeping a second flag that could disagree with
    it, and the board's hidden-column banner offers the archive by name once
    Done is off screen. The panel reports the loaded count against the total for
    as long as they differ, and an archive that has not been read — the query is
    deferred while the window is in the background — says so instead of reading
    as an empty one.

Changed

  • The task editor is four panes — Task, Organize, Assist and Agent — instead of
    one long scroll, with the title first.

  • The agent handoff is a single shared form used by both the board sheet and the
    editor, so the two cannot disagree about what will run. Provider, connection
    and permission are remembered between launches; bypass is not, and has to be
    chosen with its acknowledgement each time.

  • The right-click menu groups status, priority, due date and owner into
    submenus, and disables what it cannot currently write.

  • Sidebar branch rows are two lines. The name has the first line to itself and
    every measured number — lines added and removed, files changed, ahead and
    behind upstream, commits ahead of the base, provenance, author and commit
    age — sits on the second. On a default-width sidebar the single line gave the
    name whatever its row of counters and buttons left over, which was often
    three characters: real branches rendered as b.., d.., r... Measured on
    a 320px sidebar with churn and divergence present, the name went from 52px to
    198px — 8 characters to 31 — at a cost of 22 visible rows to 16.

  • The commit age carries staleness itself, tinted amber, instead of a separate
    stale chip repeating the same verdict less precisely beside it.

  • Author and commit age were already on every branch record and shown on no
    row; they are now on the second line, and are the first things dropped when
    a narrow sidebar runs out of room. Counts are never clipped.

  • Appearance › Sidebar branch rows switches back to the dense single-line
    list, which fits roughly 45% more refs on screen.

  • Four macOS-only surfaces that shipped on every platform are hidden where they
    cannot work, decided by a capability the host reports once rather than a
    platform test repeated at each call site. Hidden rather than disabled: a
    permanently greyed control invites a hunt for the setting that enables it.
    The settings catalog still declares them, so they are provably hidden rather
    than quietly deleted.

  • RUSTSEC-2024-0429 (glib 0.18.5) no longer applies: the September 2026 GTK
    migration moved the Linux stack to glib 0.22.9. On 2026-09-13 the tree
    passed cargo audit --deny warnings across 550 Rust dependencies and
    npm audit across 175 npm dependencies with no reported advisories. These are
    dated advisory-database checks, not exhaustive source or runtime verification.

  • The IPC surface grows to 220 handlers, and the Rust/TypeScript contract check
    to 65 contracts across 1,104 fields.

  • Repository trust is granted to the repository, not to one checkout. A linked
    worktree is no longer a second decision: approving any working tree covers
    the checkout the repository lives in and every worktree of it, including ones
    created later. Agent worktrees under .claude/worktrees/ now open, index and
    report without a prompt each, and removing a worktree no longer asks for the
    target separately.

    The shared surface a trust decision is actually about — one configuration,
    one hook directory, one object database — was always repository-wide, so
    asking per checkout bought no authority it did not already grant. What
    membership means is now proved rather than assumed: a checkout is covered
    only when the approved Git directory vouches for it, by holding the
    repository as a real .git directory or by carrying a registered
    worktrees/ entry whose gitdir names that checkout back. Pointing a
    gitfile or a symlink at a trusted common directory is a claim, not evidence,
    and is refused.

    Revoking now reaches the whole repository, including approvals recorded
    separately for its other worktrees, so a revocation cannot be partial.

    Approvals made before this release keep working and are not widened: each
    authorizes exactly the checkout it named, so upgrading re-prompts for nothing
    and silently grants nothing either. The scope of the decision changed, and a
    decision taken under narrower terms should be re-taken rather than
    reinterpreted — so the first approval after upgrading is the one that covers
    the family, granted through a dialog that now names that scope.

  • Repository hygiene settings resolve in two layers: one host-wide default that
    every repository inherits, and an explicit per-repository override. Scope now
    decides where a setting lives. Retention had no default before, so every newly
    opened repository restarted at 30 days and a house rule had to be retyped per
    repository; and the shared-cache review — which measures caches owned by the
    host rather than by any repository — was stored per repository too, so opting
    in from five repositories scheduled five weekly scans of the same caches while
    opting in from one applied nowhere else. Settings › Repo hygiene gains a
    Hygiene defaults panel for the inherited values, and each control names the
    scope it governs.

    Settings stored by earlier versions are adopted when their repository is next
    opened rather than in one sweep, because the browser storage holding them
    cannot be enumerated for them up front; the old record is removed as it is
    adopted. A stored retention becomes an override only where it departs from the
    default, so a repository that had simply been left at 30 days stays an
    inheriting one.

    This layer governs the previewed cleanup in Insights › Storage. The
    scheduled global cleaner keeps its own retention in the backend policy file,
    because the headless worker that reads it has no browser storage to read — the
    two remain separate mechanisms.

Fixed

  • Turning off ...
Read more

GitPulse v1.0.0

Choose a tag to compare

@github-actions github-actions released this 12 Sep 03:12

First major GitPulse release. The v0.1.0 tag was cut the day before, but
GitHub never published it: installer uploads rewrote the draft's tag_name
to untagged-<hex> and finalize aborted with every installer already on the
draft. That desktop work — native menus, the macOS status popover, repository
hygiene, the rebuilt command palette, and the workbench — ships here together
with core Git workflow improvements, DevMap / code-intel hardening, and a
release pipeline that can finish after GitHub detaches a draft tag.

Added

  • Expand the native application menu with Go submenus for all 16 view sections,
    zoom controls, and Help entries for documentation, shortcuts, diagnostics,
    optional-tool setup, release notes and issue reporting. Section navigation
    reveals the repository pane from Fleet. Repository commands disable when unavailable.
  • Add live menu checkmarks and progress labels, an open-repository switcher,
    clear-recents, staging and branch actions, parked-operation controls,
    copy/reveal/remote utilities and manual update checks.
  • Add an optional icon-only macOS status item opening a compact light/dark
    popover: repository switching, changed/staged/conflict/stash cards, last-fetch
    sync counts, parked-operation and busy-work chips, History/Pulse/Fleet/Terminal
    shortcuts, copy/reveal/remote/appearance utilities, expandable details and
    contextual review/recovery actions. Refresh and appearance stay in the panel.
    Open GitPulse restores the main window; closing the main window while enabled
    preserves its session. Copy, refresh and appearance stay in the popover; Reveal
    and Remote dismiss it without bringing GitPulse forward. Right-click retains
    native app controls and adds the current primary action and Refresh when
    available. Escape collapses the switcher or details first; R refreshes and
    1–4 open a nonzero metric. The status window still cannot mutate Git.
  • Menu bar status enhancements: attention-dot glyph, optional tray title counts,
    per-repo switcher badges, real FETCH_HEAD age, hide-Dock-while-closed, and
    Launch at login (LaunchAgent with --background).
  • Add a global build cleaner to Fleet and Settings, with selected roots,
    exclusions, retention and run budgets, opt-in native scheduling, closed-repo
    discovery, durable history and an optional macOS headless LaunchAgent.
  • Reuse DevCouncil's Rust hygiene policy and generated agent guidance. Harden
    traversal, case-insensitive preservation, partial scans, revision revocation,
    lock release, registration failures and Git filesystem-monitor suppression.
  • Add Repository hygiene to Storage: stale-output previews across supported
    language ecosystems, shared-cache inspection and tool-owned maintenance,
    saved retention/weekly-review preferences, cancellation and explicit outcomes.
  • Drag task cards across Kanban columns with a movement threshold, mid-card
    insertion, and neighbor-column keyboard moves. Positions stay strictly between
    neighbors instead of appending Date.now() in the middle of a column.
  • Add currently open GitPulse tabs as workspace or task members from the board
    and workspace editor, registering a path only when it is not already linked.
  • Keep selected task title and description locked while automatic enhancements
    run.
  • Add task board/list layouts, priority/type/owner/label/due filters over loaded
    cards, multi-selection and keyboard-accessible context menus. Actions include
    duplication, status/priority changes, agent copying and confirmed deletion with
    per-task outcomes and bounded delete passes.
  • Add notes-to-draft editing, inline Manvi title/description suggestions and a
    Quick Enhance sheet for saved tasks. Proposals respect field locks and require
    explicit acceptance against the saved revision.
  • Add agent copy for new unsaved drafts and saved task briefs. Saved copies name
    their revision and exclude unsaved edits; board copying reports its eight-task
    limit and partial results.
  • Modular DevCouncil install in Setup: DevMap only (default), analysis suite, or
    full host. Copy the documented command or run it in Terminal → Console.
    Settings can disable or uninstall a GitPulse-owned binary without going
    through cargo uninstall. There is no uv / Python install path.
  • Save named stashes from the existing repository panel, with controls for
    including untracked files and keeping staged changes. Preview entries inline
    in the read-only code viewer before applying, popping, or dropping them.
  • Stage or unstage a selection in one native request. Bound path counts, bytes,
    and argument chunks; evaluate every planned command before the first write,
    hold one repository mutation lock, and report partial Git failures explicitly.
  • Scan GitHub Dependabot and code scanning alerts when a repository opens, and
    warn when critical or high findings are open. Turn off under Settings →
    Analysis. Failures stay in Health and diagnostics, not as an all-clear toast.

Changed

  • Rebuild the command palette with eight discoverable search modes, fuzzy ranked
    commands, file and repository search, complete view/section navigation, Clone and
    Rebase dialog entry points, contextual availability, result paging and accessible
    keyboard/focus behavior. Successful-use history is validated and bounded.
  • Keep palette searches current across query/mode/repository changes; show loading,
    deadlines, failures, retry and partial coverage. Resolve cross-repository symbols
    through the workspace registry before opening files, preserve help-mode transitions,
    and make the status-bar palette entry work before its first lazy load.
  • Compact the Work inbox to open-and-read, fold notification settings, and give
    automatic suggestions a board-sized control. Fold task enhancement locks and
    repository membership into editor details.
  • Give the macOS status popover the app's native background blur, translucent
    surfaces and rounded material bounds. Preserve the compact layout and provide
    opaque accessibility fallbacks. Match the native window to the panel on resize
    and reopen; the browser fixture includes a labeled glass simulation. Select
    the tray display using physical bounds so Retina coordinates can open the panel.
  • Refine the macOS status popover around three large Changed, Staged and Conflicts
    cards, a monochrome repository header, last-fetch counts and one blue primary
    action. Keep stashes, workspace insights, the command palette and secondary
    shortcuts inside Details, with Open GitPulse, Settings and Quit in the footer.
  • Named GitPulse as the successor to the deprecated LiquiTask workbench in the
    README, wiki home, and Tasks documentation.
  • Document DevCouncil as independently selectable components and modules, Manvi
    as the wrap around them, and GitPulse as the host that uses each for its
    respective job.
  • Refresh README, feature, architecture, contributor and wiki guidance for Tasks,
    schema-20 DevMap, current shortcuts, module ownership and verification limits.
    Add a Tasks and workspaces guide; preserve older implementation plans as plans.
  • Resolve repository maps per worktree in both agent guides and document
    devmap build --manifest for missing generated state.
  • Re-vendor DevCouncil analysis crates at v0.2.0 (devcouncil@a31918e2) from
    rust/ after that workspace flattened out of rust-port/crates. Include
    dc-evidence so dc-verify can link. Re-vendor dc-verify so ledger writes
    keep using rigor::redact_secrets.
  • Add a CodeQL config that excludes src-tauri/framework/**. Bindgen
    offsetof tests and WRY cookie conversion in those ports are not GitPulse
    sinks. Attach the file to default setup in GitHub Settings.
  • Refresh @lucide/svelte 1.44.0, Vite 8.3.0, and @types/node 26.5.1.

Fixed

  • Resume a GitHub draft whose tag_name became untagged-<hex> after
    installer uploads, instead of posting a second draft. /releases/tags/{tag}
    does not return drafts, even while the tag is still attached; prepare lists
    drafts by that tag or by the name it POSTs, and refuses a truncated page
    rather than treating it as "no draft". Identify a draft by its tag and
    release ID. GitHub often rewrites target_commitish to a branch name after
    associating an existing tag; a SHA in target_commitish must still match the
    pinned commit, and a ref name is not a second pin. An untagged- placeholder
    is accepted only in GitHub's hex form, and finalize writes the intended tag
    name back with the notes. Platform builds upload by release ID only so
    tauri-action cannot retarget the draft. Prepare now also deletes leftover
    draft installers before the matrix rebuilds: GitHub 422s a second Windows
    NSIS/MSI upload of the same name, and tauri-action retries that as a
    flaky upload until the Windows leg fails. A draft still pinned to the
    previous tagged SHA is retargeted onto this commit after that wipe, never
    mutated until it is proven a mutable unpublished draft.
  • Sign every nested helper in the macOS universal bundle before the main
    binary. Tauri copies every [[bin]] into Contents/MacOS and signs them in
    manifest order — main first. Once Info.plist is in the bundle, codesign
    treats that file as the bundle executable and every other Mach-O as nested
    code that must already be signed. lipo produces unsigned helpers, so the
    sign of gitpulse failed with code object is not signed at all / In subcomponent: gitpulse-hook. scripts/bin/codesign piggy-backs on the main
    binary's sign the same way scripts/bin/lipo stitches the helpers.
  • Quiet Linux GTK framework ports that drowned the release clippy log:
    explicit extern "C" on libappindicator-sys, gir builder visibility and
    TypedArrayData<'_> in javascriptcore-rs, crate-level unexpected_cfgs
    on web...
Read more

GitPulse v0.0.9

Choose a tag to compare

@github-actions github-actions released this 09 Sep 06:46

Changed

  • Consolidate all outstanding worktrees and align the embedded SQLite dependency
    with MANVI and DevMap. Add explicit DevMap navigation to both agent guides,
    with regression coverage that preserves the workflow across regeneration.

  • Synchronize the canonical devmap query, HTML projection, extractor and store
    modules. HTML assets are owned by the upstream query crate; GitPulse no
    longer rewrites the HTML implementation while vendoring it.

  • Document the Rust-library, Go-module and NDJSON integration boundaries in
    docs/MODULE_INTEGRATION.md, including configurable executable paths and
    independent host/protocol/database compatibility checks.

Fixed

  • Pin release builds to one verified commit and require successful CI and coverage
    for that commit. Refuse published or mismatched releases, resume matching drafts
    by ID, verify uploaded asset digests, and confirm changelog notes after writing.
  • Accept GNU checksum records with escaped filenames and normalize Windows index
    transaction paths for Git. Preserve hostile filename tests on supported systems.
  • Resolve regular-file conflicts on Windows with pinned directories, exact staged
    bytes and retained recovery content on replacement or staging failure. Preserve
    executable Git modes in the index; Windows reparse points require external resolution.
  • Bound Unix terminal input delivery and lock waits, cancel pending input on close,
    and report partial delivery without retrying accepted bytes. Closing a Linux PTY
    no longer leaves a full input-queue write blocked after its child exits. Wake
    output readers on readiness so interactive and bulk output avoid polling delays.
  • Avoid redundant JSON parsing during diagnostic breadcrumbs while retaining the
    existing credential redaction and stress-test budgets. Reuse fixed credential
    matchers instead of rebuilding them for every navigation field.
  • Release watcher sessions when their backend event stream closes so watching
    again starts a live backend. An old backend cannot remove a replacement session.
  • Rebuild the desktop, MCP and daemon from the current DevMap 0.1.1 integration.
    Embedded readers preserve distinct symbol identities and withhold source
    snippets when the indexed content hash no longer matches the current file.
    The external builder checks lexical binding scope, source freshness and
    bounded input reads. See DevCouncil's September 8 reliability audit for
    adversarial regression and stress-test evidence.
  • Prepare complete vendor updates before replacing the current tree, refuse
    concurrent updates and symlinked sources, and retain rollback state on
    installation failure. Drift checks now detect upstream deletions and resolved
    Cargo manifest changes using the same snapshot builder as updates.
  • Bound unsolicited MANVI sidecar output between requests and terminate an
    overflowing child. The per-request byte budget now has an idle-queue bound
    enforced by the same stdout pump in production and live-process tests.
  • Git subprocess reads retain captured output when descendants hold pipes open.
    Unix pumps input and output without reader threads; Windows cancels blocked
    I/O and retains resource permits until workers exit. Queueing and lock retries
    share the command deadline, and the Windows tree-kill helper has a deadline.
  • Optional tool installation shares the bounded runner, including cancellation
    and progress. Machine-output consumers refuse incomplete output, failed version
    commands cannot pass verification, and schema integers cannot wrap. Digest
    output uses the existing hexadecimal validator.
  • Blame handles new, staged, ignored and unborn-repository text files without
    fabricating committed attribution. Oversized or incomplete blame is reported
    as unavailable instead of returning an unmarked prefix.

GitPulse v0.0.8

Choose a tag to compare

@github-actions github-actions released this 08 Sep 00:09

Fixed

  • Code → Map no longer pane-crashes on duplicate dead-symbol ids. Real
    repo_map.json files can list the same dead_symbol_candidates entry more
    than once; Svelte 5's keyed {#each} then threw each_key_duplicate and the
    Map pane's error boundary reported a pane-crash (six times in diagnostics on
    open). Dead / unwired / unreachable lists are deduped before render, and
    keyed lists across Map, Work, stacks, harness, and the setup wizard use
    index-suffixed keys so a duplicate payload cannot take the pane down again.

Added

  • Optional Manvi / DevMap install ladder. Settings → Agents, Code → Map, the MANVI
    harness pane, and a resumable Setup wizard can install or update devmap and
    manvi without treating them as required. Resolution order: configured binary →
    PATH / ~/.cargo/bin → checksum-verified GitHub release asset → remote
    install script → local source (cargo install --path …/devmap-cli --locked --force,
    go -C …/manvi install ./cmd/manvi). Progress is cancellable. Broken
    GITPULSE_*_BIN / GITPULSE_*_ROOT overrides are refused rather than searched past;
    clone missing checkouts via onboarding. Override roots with
    GITPULSE_DEVCOUNCIL_ROOT / GITPULSE_MANVI_ROOT.

  • devmap doctor --json verify on status. Tool status prefers the doctor JSON
    contract (expected_schema_version, code-graph schema) over scraping --version
    prose, so schema drift is named instead of a silent mismatch with the vendored store.

  • Capability gating when optional tools are absent. Map / harness UI degrades to
    explicit “not installed” empty states and CTAs instead of empty panels that look like
    “nothing found”. Wizard and palette entry: “Set up optional tools (devmap / manvi)”.

Changed

  • Dependency refresh (2026-09-07). Frontend floors raised to current stable
    (svelte ^5.57.0, @tauri-apps/api ^2.11.1, @tauri-apps/cli ^2.11.4,
    @tauri-apps/plugin-opener ^2.5.5). Rust direct reqs raised where already
    resolved (rayon 1.12, notify 8.2, regex 1.13, tempfile 3.27) and
    cargo update pulled latest compatible transitive crates. Intentionally
    unchanged: classic typescript@~6.0.3 + @typescript/native-preview@7.0.0-dev.20260707.2
    (svelte-check peers still ^5|^6; tsgo split preserved), Tauri git pin
    406feea… (crates.io still 2.11.5; unpublished 2.12 line keeps urlpattern 0.6),
    rusqlite 0.31 (vendored dc-store / devmap-store), notify 8.x (9.0 is RC),
    libc 0.2 (1.0 is alpha). No rust-toolchain pin; toolchain left alone. No
    re-vendor.

  • Typecheck uses tsgo (TypeScript 7 native preview) for Node/script configs.
    npm run check still runs svelte-check against classic typescript@~6.0.3
    because svelte-check@4.7.6 peers only typescript ^5|^6 and does not drive
    tsgo. The former tsc -p tsconfig.node.json --noEmit step is now
    npm run typecheck → tsgo -p tsconfig.node.json --noEmit via
    @typescript/native-preview@7.0.0-dev.20260707.2. App .svelte typing
    remains on svelte-check until it accepts TypeScript 7 / tsgo.

Note

  • v0.0.7 was tagged then withdrawn after the Map pane-crash above was found in
    the local build. It was never published as a GitHub Release; this cut is the
    first ship of that work.

Added

  • DevMap code intelligence works again at store schema 19, with a handshake that names drift. The
    vendored devmap-* crates now match the on-disk .devcouncil/codeintel/devmap.sqlite stores every
    sibling repo already builds (schema 19). A mismatched build reports map built by schema N, this
    build reads M
    rather than a raw SQLite refusal, and npm run check:vendor-schema fails ci:local
    when the installed devmap CLI and the vendored constant disagree.

  • Build, refresh, status, and edit preview are driven by the installed devmap CLI. GitPulse still
    queries the store in-process; it shells out for indexing (build / incremental refresh / status --json / preview --file … --content -). Lookup reports which path answered (env override vs
    PATH / ~/.cargo/bin), refuses a configured path that does not resolve, bounds wall clock and
    stdout, and refuses a second build for the same repo while one is in flight.

  • Pre-commit blast radius: what this commit would break. The commit composer and the diff file rail
    share one devmap preview batch over staged paths. Each file carries parse status, degradation,
    compared-against, and broken callers — and a walk that stopped early or a file with no grammar is
    marked unreliable rather than shown as "nothing breaks".

  • CI:local can scope tests to the change set, and fails closed to the full suite. Affected-test
    seeds come from the working-tree status; results are test files, chunked at the kernel's neighbor
    target cap. A stale map, incomplete walk, or unmatched seed runs the full suite and says so — the
    GitHub CI panel never badges a fail-closed full suite as "affected tests passed".

  • Layered blast radius and a resolution-rung filter on Diff. Change-set impact is composed over
    changed files by hop (impact_layered), rendering each band's sample and nodes_omitted /
    node_count. Flat impact offers a min-rung filter plus a rung histogram ("what you did not see");
    the control is suppressed wherever layered impact is active, because the kernel refuses that pairing.

  • Code → Map: subsystem navigator, code/doc graph canvas, and repo docs. A third Code section
    (⌥3 when Code is active) reads .devcouncil/repo_map.json with capped samples named as such,
    draws code-graph and map-preview canvases (and a MarkDev doc graph), and searches tracked markdown
    plus broken links / cross-repo link candidates. Freshness comes from devmap status; Build /
    Refresh live on the status strip.

  • The code map refreshes from the file watcher. Debounced repo-changed events ask for an
    incremental refresh when status says the index is stale, with the same single-build-per-repo guard.

  • MarkDev's Rust core owns markdown parse/render and dual-backend highlighting. The file viewer
    uses the flat UTF-16 model (no TypeScript reimplementation). Tree-sitter covers rust / JS / TS /
    Python / JSON / shell; everything else stays on the existing regex tokenizer under one owner in
    diff/highlight.ts. Commit message bodies and MANVI verdict detail render through the same path.
    The docs vault is built from git ls-files of markdown (not a filesystem walk), with backlinks in
    the viewer; rename is git mv plus staged link rewrites via MarkDev's pure rewriter.

  • Open tabs register in DevMap's workspace for cross-repo search. Palette :: searches symbols
    across registered repos (trailing ~ requests TF-IDF name ranking); bare : stays single-repo.
    Truncation and unavailable repos are named on the result strip.

Honesty (read these as product rules, not caveats)

  • walk_incomplete means the list is a floor, not a complete answer.
  • Capped samples carry shown/total/truncated (repo map, graph legend, docs search, broken links).
  • Schema mismatch and missing/devmap binary failures are named; they are not empty "all clear" panels.
  • Affected-tests scoping that cannot prove coverage runs the full suite and says why.

Added

  • Tags now say where their work stands, so work parked on a tag is no longer invisible. A tag is a
    ref, so the graph walks it and draws its commit a lane — one shaped exactly like an unmerged branch.
    But list_branches and the cleanup plan read only refs/heads and refs/remotes, so nothing in the
    app could answer "is this merged?" for a commit held by a tag alone, which is exactly what a
    retired/… tag does. TagInfo now carries commits_ahead_of_base, commits_behind_base and
    compared_to, measured against the same default base branches are measured against and read in the
    same single git tag -l process via %(ahead-behind:). The sidebar shows a +N chip on a tag that
    holds commits the base does not, and the tooltip says either how far ahead it is or that every commit
    is already in the base. compared_to: null means the comparison could not be made — an old git, or a
    tag that does not peel to a commit — and is never rendered as "merged".

  • Ops now reports what the repository retains on tags, which branch cleanup counts nowhere. A new
    Tag retention card splits every tag into "holding commits the base does not have" and "every commit
    already in the base — safe to delete", with per-tag counts and the existing tag-delete path behind a
    confirmation. A tag the comparison could not be made for is reported as its own number and is never
    proposed for deletion, and all three caps (the tag listing, the retained rows, the deletable rows)
    say so rather than letting a sample read as the whole repository. No tag is pre-selected: unlike a
    merged branch, a tag is usually kept on purpose. Deletion is disabled unless the three buckets add
    up to the tag total, mirroring the branch plan's own coverage guard.

  • Graph tag chips carry the count too. A tag lane is shaped exactly like an unmerged branch lane,
    so the chip on the commit row and in the graph tooltip now reads +N for a tag holding commits the
    base does not have, and its hover says either that or that every commit has already landed. It reuses
    the tag listing the sidebar has already loaded, so the graph pays no extra command on a path that
    reruns on every repo switch, and a tag past the listing cap simply says nothing rather than implying
    its work has landed. ManviOpsPanel joins the runtime harness (harness/stress.html?c=ManviOpsPanel),

  • Language breakdown now supports on-demand rescan. The language segment dropdown now provides a manual
    rescan button (locMetric.refresh with force: true) with an active spin indicator, allowing instant
    recalculation of code percentages after checking out br...

Read more

GitPulse v0.0.6

Choose a tag to compare

@github-actions github-actions released this 07 Sep 02:06

Added

  • Eight new preferences, and a way to find any of them. Settings gained a Diff & code category and five appearance controls, which took the page past thirty switches — the point where grouping stops being enough, because knowing that word wrap lives under "Diff & code" means already knowing GitPulse's taxonomy. A filter box now narrows the category rail and the rows inside each panel, matching synonyms the labels never say ("side by side" finds the split-diff default). Every control is stamped with the catalog id it is registered under, and the catalog and the markup are compared in both directions: a control with no entry is unfindable by search, an entry with no control is a result that highlights nothing, and neither can ship.
  • An accent colour. Six choices tint selection, focus rings, the macOS glass and the commit graph's current-row marker. Each carries a separate light and dark shade — accent text sits on --c-surface-hover, which is near-black in one theme and near-white in the other, so one colour cannot be legible on both — and every pair is checked against WCAG AA by a test derived from the palette itself. --shadow-glow and --ring-focus are now expressed in terms of --c-accent rather than restated, so a teal window does not wear a blue focus ring; picking the default removes the override entirely and hands the theme back to the stylesheet.
  • Reduce motion, as an in-app preference. Deliberately one-way: leaving it off follows the system, and turning it on can only add reduction — a reader whose OS has asked for less motion cannot be overruled from a checkbox. It reaches both places motion is produced, the Svelte transitions and the CSS entrance animations, because either half alone is a setting that visibly half-works. The two triggers are mirrored rule for rule and a test pins the lists equal.
  • Timestamps as dates. Commit times can read 2026-09-06 instead of 3d ago — fixed width, sortable, and the same in every locale, which 06/09 is not. It reaches the commit list, branch tooltips, the diff's change picker, Work and the stack through one owner; whichever form is shown, hovering gives the other, and the commit list's column widens for a date rather than truncating one.
  • Diff defaults that survive the next file. Layout, word wrap, syntax highlighting and ignore-whitespace were fixed literals reset on every mount, so a reader who preferred split diffs re-selected split every time. They are now preferences that a diff opens at; the toolbar still owns the file in front of you. The whitespace default seeds each newly opened repository, and the copy names the wrap ceiling (4,000 rows) rather than offering a switch that silently does not apply above it.
  • Tab width — 2, 4 or 8 — everywhere code is drawn. Declared once on the document root, where tab-size inherits, so the diff, the file viewer, blame and the conflict editor all follow without each learning the preference exists. 8 is the CSS initial value and stays the default, so nothing renders differently until it is asked to.
  • Arrow keys in the settings category rail. It has always been a tablist of tabs and was one in name only: eight separate tab stops, none of which answered the arrow keys the role promises. It is now a single tab stop with Up/Down (wrapping), Home and End.
  • The macOS window is transparent, and the desktop behind it is blurred by the window server. GitPulse previously synthesised its own backdrop because native transparency was switched off; the blur you saw was the app blurring itself. macos-private-api plus a transparent window and an NSVisualEffectView (underWindowBackground) now put the real desktop behind the interface, blurred by macOS rather than by the application, which costs nothing per frame. Three settings have to be present together and any one alone is inert — the feature gate is deeper than its name, because tauri/macos-private-api forwards wry/transparent and wry compiles its setOpaque(false) call only behind that feature, so without it the WKWebView stays opaque and paints over a material that is working perfectly. This forfeits Mac App Store acceptance, which is the reason it had been disabled. macOS-only settings live in tauri.macos.conf.json, which Tauri merges by JSON Merge Patch — arrays are replaced, not merged, so that file restates the whole window entry and a test derives the expected object from the base config rather than trusting the copy.
  • A hue field, so a translucent surface has something to be translucent against. Four wide, saturated radial blobs span the shell and fade to their own colour at zero alpha rather than through the transparent keyword, which would dip the ramp through an unrelated hue on the way out. Sized to their own corners they left the middle of the window at the flat base colour — the one part of a window nobody can avoid looking at — so they are deliberately wide enough to overlap across the centre.
  • The MCP server now answers four capabilities, not one. It advertised tools and nothing else, so the only way to ask it anything was a tool call. It now implements every server method the 2026-07-28 schema defines: resources/list, resources/read and resources/templates/list expose the control plane as addressable gitpulse:// documents (eight repository facets as RFC 6570 templates, plus gitpulse://server/manifest and gitpulse://server/health); prompts/list and prompts/get ship four workflows that resolve against live state and embed it as resource blocks rather than telling the model to go and fetch it; and completion/complete completes repo_path for both. All four list operations are cursor-paginated. The method set is taken from the published schema, which is also why there is no ping and no logging/setLevel — neither exists in this revision, and inventing them would have been worse than omitting them.
  • gitpulse-hook, so the control plane can refuse an edit before it happens rather than describe it afterwards. Three hooks ship in plugins/gitpulse/hooks/hooks.json. collision-guard escalates a PreToolUse edit to the user when the same path is dirty in another worktree; command-gate routes the agent's Bash calls through the MANVI command gate the desktop app already uses, so git push --force is denied with the gate's own words instead of the gate applying to the GUI alone; session-brief injects a bounded repository brief at SessionStart. Each degrades to no decision plus a systemMessage saying the check did not run rather than to silent approval — a hook that cannot check must never look like one that checked and passed.

Fixed

  • hidden did not hide. The UA stylesheet's [hidden] { display: none } loses to any author rule that sets display, so a Tailwind flex utility on the same element silently outranked it — two settings rows kept rendering while marked hidden, which the filter depends on. [hidden] is now enforced at author level regardless of which utilities a row picks up later.
  • The theme segment could report a choice the app was no longer honouring. It snapshotted the preference at mount, and ⌘-shortcuts and the native View menu change it from outside the modal; reopening now re-reads it. A control that reads as selected while something else is in force is the same failure as a setting that does nothing.
  • The terminal stayed a solid slab, because two things under it paint black and neither is reachable from the stylesheet. Second instance of the graph canvas's shape, and the last surface in the app that owns its own paint. --bg-terminal resolving to transparent makes xterm paint nothing, so the surface is the plate its mount div already carries — a second translucent fill from the terminal would be exactly the double coverage the panes were just cured of. The token is deliberately not --bg-surface, which has a second runtime reader in the graph's node stroke; a stroke is not a fill. Three things are load-bearing there and none is cosmetic: allowTransparency must be set before open() and cannot be changed afterwards; the colour must be hex, because css.toColor in @xterm/xterm 6.0.0 parses #rgb/#rgba/#rrggbb/#rrggbbaa itself and pushes everything else through a canvas probe that throws when the sampled alpha is not 255 (measured in WebKit: rgba(20, 26, 41, 0.5) samples 128, the transparent keyword samples 0, and getComputedStyle returns exactly those forms); and xterm.css hard-codes background-color: #000 on its viewport, which is why a transparent theme colour on its own changed nothing visible.
  • The commit tooltip was the one float in the application with no blur at all, which is why it read as see-through rather than as glass: a filter that never runs looks exactly like one that does until content moves behind it. The float tier was written as .gp-card.shadow-float, which named the dialogs and missed everything else — the tooltip carries shadow-pop, and the toasts, the coach mark and the go-to-line popover carry shadow-float without .gp-card. The tier is now the float shadow, derived in a test from what the components actually wear, and those surfaces keep their denser bg-surface fill rather than the thinner glass one: a dialog card sits on a dimmed scrim, a tooltip sits straight on commit rows.
  • The sidebar's LOCAL, ORIGIN and TAGS rows wore a filled band that the folder rows beside them did not. bg-surface on a section header was a barely-visible tint against an opaque sidebar and a dark bar against a translucent one — the same coverage arithmetic as the recesses above. Nothing scrolls under those headers (the list is virtualised, not sticky), so the fill was decoration; it is gone, and the two kinds of group header now look alike.
  • **The Work screen hugged the left edge and stopped a third of the way down the w...
Read more

GitPulse v0.0.5

Choose a tag to compare

@github-actions github-actions released this 05 Sep 06:23

Added

  • Fleet: one surface for every open repository, and every recent one. A workspace of two dozen tabs could only be inspected one tab at a time — "is anything unsaved anywhere", "which of these has an agent running", "what is all this costing on disk" were unanswerable without visiting each in turn. Fleet (Shift+F10, the leftmost chip in the repository strip, or the command palette) puts them on one grid: changes, sync, conflicts, stash, parked operations, worktrees, agent sessions and last activity, plus lines of code, disk usage, dependency audits and coverage on demand. It is deliberately not a sixteenth view — a ViewTab is stored on the active repository's session and its pane lives inside {#key currentPath}, so a view would be scoped to the wrong thing and rebuilt on every repository switch. It sits beside the repository pane instead, and the two swap by hiding rather than unmounting, because that subtree holds the live terminal PTY.
  • Every Fleet cell is a value, not scanned, or could not read — never a reassuring zero. The failure a workspace dashboard invites is reporting a fleet of clean, empty, vulnerability-free repositories that nobody ever scanned. So the three states are distinct in the model, in the markup and in the totals: a repository with no audit shows "not scanned", an audit that ran but could not finish is marked as a floor, a ledger that could not be opened fails its four cells rather than emptying them, and a total says "1.50 GB — counted across 14 of 21, 1 failed, 6 not scanned" rather than a bare number implying the whole workspace. A repository whose sweep failed is reported unknown, never clean — but never at the cost of downgrading one that has real conflicts.
  • Expensive scans stay opt-in, on the same posture as automatic coverage and the release check. Storage walks up to 250,000 files behind a 20-second deadline and the dependency audit spawns npm audit / cargo audit with a 90-second timeout; neither ever runs from an effect. The cheap tier costs nothing at all — changes, sync and conflicts are already hydrated in memory — and the middle tier is a new cmd_fleet_snapshot, two git spawns per repository in one rayon-parallel round trip, deliberately narrower than cmd_insights_snapshot (which probes every worktree and cross-scans up to 16 for collisions: correct for one repository on screen, several hundred subprocesses across a workspace). Family sweeps run two at a time for the expensive families and report successes, failures and skips separately.
  • Scan results are cached in each repository's own ledger, with their age. A new additive fleet_metrics table records one row per repository, every family carrying its own value and its own timestamp, so "never scanned" is NULL rather than 0 and a displayed number can always be dated. Families are independent: a storage scan cannot blank last week's audit. Reads go through a read-only, no-create SQLite open, so rendering a row for a repository that is merely in the recents list never writes a .devcouncil/ directory into a repository the user has not opened.
  • Fleet repository removal with accessible action button and keyboard navigation (Delete / Backspace). Rows in the Fleet dashboard provide a direct removal action via an action button or keyboard shortcut (Delete / Backspace): removing an open repository closes its tab and drops it from the workspace, while removing a recent repository purges it from workspace history and last-closed tabs so stale paths stay clean without lingering.
  • The package is now installable and connectable as a Claude Code plugin. The Agent Plugins 1.0 package described the server, but no client could find it: Claude Code discovers a package through a .claude-plugin/marketplace.json at the repo root and then reads <source>/.claude-plugin/plugin.json and <source>/.mcp.json, none of which existed. Those files now sit alongside the Agent Plugins and Codex manifests in the one canonical package, sharing its single skills/ tree, and the marketplace points at it. Verified end to end: claude plugin install records 0.0.5, the component inventory resolves both skills and the MCP server, and claude mcp list reports the server connected.
  • GitPulse is now a native Codex plugin, not only an MCP binary that happened to exist. plugins/gitpulse/.codex-plugin/plugin.json declares the native surface, .agents/plugins/marketplace.json makes it installable from the repository, and the same canonical package is bundled into Contents/Resources/plugin for Settings discovery. The portable manifest still launches gitpulse-mcp from PATH; this host's Codex MCP registration uses the absolute installed path so desktop, CLI, and IDE launches do not depend on shell initialization. Verified with a fresh Codex process that loaded gitpulse@gitpulse, invoked gitpulse_insights, and received the live branch and change count.
  • npm run mcp:install and npm run mcp:doctor. The MCP manifests spawn the bare token gitpulse-mcp off PATH — correct for a published plugin, but it means the server a client actually connects to is whatever is on PATH, which no build step owned. mcp:install puts it there through cargo install, so the binary is tracked and refreshable. mcp:doctor completes a real handshake and compares the version the server reports against this tree's, keeping absent, unresponsive and stale distinct from matching — the first of those is the one a naive check would report as a silent pass. Deliberately not in ci:local: CI has no reason to install the server, and a check that cannot run there must not be made to look like one that passed.
  • A repository that pins its own toolchain is told how to honour that pin. Go, Swift, .NET and Dart still refuse when their runtime is absent — installing a language runtime is a host-wide change with no bounded, reversible command, and a coverage panel does not get to make that trade for you. But "install Go, then rescan" is a poor answer for a checkout that has already written down which Go it wants. When mise.toml, .mise/config.toml or .tool-versions is present, the refusal names the pin and the one command that honours it, and it names only a manager actually on PATH — a mise-only config never suggests asdf, which cannot read it. GitPulse still does not run it: the command writes outside the repository, so it stays on your side of the line.
  • Line count, coverage and storage now track the repository instead of the moment a panel was opened. All three were one-shot fetches keyed on the repository path changing and nothing else, so a day of editing left the headline LOC number, the coverage report and the disk usage exactly as they were when the tab was first shown — with nothing on screen saying so. Meanwhile the backend already emitted repo-changed on every settled write and only repoStore listened. A new metric layer (src/lib/metrics/freshness.ts) owns freshness for all three: one measurement serves every panel, the watcher revalidates it, and each metric carries its own debounce and minimum interval derived from what its command actually costs — 20 s for LOC, 30 s for coverage, 120 s for the storage walk, so a build writing continuously into target/ cannot pin a 20-second tree scan. Change count needed none of this: cmd_branch_stats was already refetched by handleRepoChanged, and re-measuring it here would have run the same git subprocesses twice per change.
  • A value that could not be refreshed no longer looks refreshed. A failed revalidation keeps the last good report — panels must not blank out on a transient error — but the snapshot carries value and stale independently, and every panel reads both. Storage shows an "out of date" badge, the Pulse LOC tile degrades to partial, and a truncated or stale reading is never recorded as a point on the line-count trend.
  • C/C++ coverage, via an out-of-tree instrumented CMake build. This family used to be a flat dead end on the grounds that GitPulse cannot add coverage flags to a project's build files. The premise was right and the conclusion too strong: CMake takes compiler and linker flags on the configure command line, into a separate build directory, so cmake -S . -B build-gitpulse-coverage -DCMAKE_C_FLAGS=--coverage → cmake --build → ctest --test-dir → gcovr --lcov produces coverage without touching CMakeLists.txt or the developer's own build/. gcovr installs into a project-local virtualenv, exactly as pytest already did. Make-only projects stay a dead end and say why: make CFLAGS=--coverage replaces a project's own flags rather than adding to them.
  • Storage now reports a reclaim audit, not just sizes. The report published raw numbers and left every judgement to the reader — gc_recommended was a bare boolean, prunable worktree admin was not detected at all, and nothing said how many bytes were actually recoverable. Each row now carries the action that reclaims it, whether the bytes were measured or estimated, and whether a human has to decide. The headline counts measured and safe bytes only: estimates (a repack's saving depends on the content) and items needing review (committed build output, the reflog, a large file that may be someone's dataset) are carried as separate figures rather than folded into a total the repository cannot deliver. New detection: .git/worktrees/<name> left behind by a worktree deleted with rm -rf, which the old report counted as space belonging to a live worktree.
  • Manvi Control Plane & Operator Panel:
    • ManviHarnessPane, ManviOpsPanel, and HarnessBadge integration for real-time agent session monitoring, task attribution, and operation gating.
    • Dedicated harness store (harnessStore.ts) with lease tracking, task status synchronization, and worktree association.
  • Durable WAL SQLite Ledger & Redaction:
    ...
Read more

GitPulse v0.0.4

Choose a tag to compare

@github-actions github-actions released this 04 Sep 01:16

Fixed

  • Storage report accuracy & hardening:

    • Premature truncation resolved: Raised per-directory entry limits inside build artifact directories from 4,000 to 100,000, preventing Cargo dependency directories (target/debug/deps) with > 4,000 files from prematurely tripping scan truncation.
    • Unix hard link deduplication: Scoped (st_dev, st_ino) tracking on Unix for files with nlink > 1, ensuring Cargo hard links (deps/libfoo-hash.a to libfoo.a) are counted exactly once, eliminating gigabytes of phantom disk usage.
    • Monolithic container roll-up: Container build directories (target, node_modules, .venv) roll nested build outputs (debug/build, .../out) up into the parent scope rather than fragmenting into dozens of child rows.
    • Source-tree false positive protection: Paths inside src/ no longer match generic build or cache directory names (e.g. src/lib/coverage remains recognized as source code rather than an unignored cache).
    • Single-pass worktree traversal: Merged large-file collection directly into the worktree walker using WorktreeWalkContext, eliminating the redundant second walk and halving disk I/O.
    • Developer and agent caches classified: Recognized .devcouncil, .gitnexus, .claude, .cursor, .agents, .gemini, and .antigravity under cache artifacts.
  • Windows: cloning a repository failed. The clone destination was resolved with canonicalize, which on Windows always answers with a verbatim \\?\C:\... path. git refuses that as a working tree (could not create work tree dir ...: Invalid argument), and the prefix leaked into the refusal text users saw. Resolution now produces a spelling external tools accept.

  • Windows: cloning into an existing directory resolved onto the source repository. The clone's directory name was derived by splitting the URL on / alone, so a local Windows path (C:\src\repo) survived whole and the drive-colon split returned a rooted \src\repo — and joining a rooted path discards the destination. Both path separators are now split on, and the derived name is guaranteed to be a single component.

  • Windows: external tools resolved to the wrong file. Tool lookup tried the bare program name before any executable suffix, so npm matched Node's extension-less shell script instead of npm.cmd and failed with "%1 is not a valid Win32 application". Suffixed spellings are now tried first, in the order Windows itself uses.

Changed

  • CI runs the Rust suite with --no-fail-fast. It previously stopped at the first failing test binary, so a failure in the library suite silently skipped every integration suite — 43 binaries that had never run on Windows at all — while reporting a single failure. A check that could not run must not read the same as one that passed.