Skip to content

Releases: ascendaone-com/ai-engineer-tools

v0.1.39

Choose a tag to compare

@github-actions github-actions released this 15 Oct 02:40
3c2cf0a

setup always shows its link

  • The link and the study notice print before setup starts waiting. They
    used to print only after the first check came back unconfirmed, so a pairing
    confirmed quickly could finish without ever showing them. Both participate
    and each agent's own setup are fixed.

One confirm for the first agent in participate

  • Pairing and joining happen in one visit. participate <code> sends
    your code with the first agent's pairing. Open the link, check the
    organisation and what you'd share, confirm, and the agent is paired and the
    study joined. Declining refuses both.
  • Other agents pair on their own. They don't carry the code, since the
    join is yours and not theirs. Two unpaired agents take two confirms, down
    from three.
  • No typed code for that pairing. The app turns a typed code away for a
    pairing that carries a join, so only the link is printed.
  • An older server still works. If the pairing response has no studyJoin,
    participate pairs the agents as usual, then joins with the separate
    question and one more confirm. A re-run on a joined machine asks for
    nothing.
  • A refused code still pairs. A code that isn't found, has nothing live,
    or names the wrong mode is reported in the summary. The agent pairs without
    the study.
  • The local dev server takes the code on a pairing too, so you can try the
    flow without a backend.

Which operating system

  • Events now include the operating system the collector runs on (darwin,
    win32, linux, wsl or other), and nothing more specific. WSL counts
    as its own value, since it runs on a Windows machine.

What's Changed

Full Changelog: v0.1.38...v0.1.39

v0.1.38

Choose a tag to compare

@github-actions github-actions released this 14 Oct 21:25
cee8757

Confirm in a browser

  • setup and pair print a link. Open it, sign in, and the pairing is
    confirmed. You don't need the Mac app. The 6-digit code still works in the
    app, and it's printed on the next line.
  • join <code> prints a link too. It opens a page that shows the study,
    then asks you to confirm or decline. The app takes the same code.
  • Study mode itself still needs the app. join offers Report mode only, as
    before.
  • Against a server without these pages, like the local dev server, both
    commands name the app, as they did.

History import without the Flow app

  • ascenda-history-import import --ship finds your pairing. It reads
    ~/.ascenda/credentials.json and the token the hooks' setup or pair
    wrote, so a machine with no Flow app and no exported variables can ship.
    Variables still win over the files, and the new --installation-id,
    --token-file and --api-base-url flags win over both.
  • Tokens get renewed before they expire. With under 21 days left the
    importer rotates the token and saves the new one where the hooks read it. An
    expired token stops the run in the first second with the pair command to
    fix it. Nothing has been read or copied by then.
  • schedule install sets up a recurring import. It writes a launchd agent
    on macOS and a systemd user timer on Linux, every 14 days unless you say
    --every. On Windows it prints the schtasks line. schedule status and
    schedule remove do what they say.
  • Claude Code deletes transcripts after 30 days unless cleanupPeriodDays says
    otherwise, so schedule install won't accept an interval the retention
    can't cover twice. fix-retention --apply lifts the limit. So does
    --override-retention.
  • A refusal for consent now says where to fix it. The message names the
    web as well as the Flow app. A store left out of your grant is skipped and
    named while the other stores keep shipping.
  • Without the Flow app the import prints "no Flow app on this machine, none
    needed" where it used to say a container was missing.

One command to take part in a study

  • participate <code> sets a machine up for your organisation's study.
    Run npx -y @ascenda-one/history-import participate <code> with the code
    your organisation gave you. It finds Claude Code, Codex, Cursor, Windsurf
    and Gemini CLI, installs each one's hooks for every project and pairs it,
    joins the study in Report mode, and sends the history already on the
    machine. No desktop app needed.
  • It tells you up front how many browser confirms it needs: one per agent
    that isn't paired yet, then one for the study. Each is announced before its
    code appears.
  • Claude Code deletes transcripts after 30 days. participate shows the
    setting it would change and asks first. --fix-retention and
    --keep-retention answer for you.
  • The history is sent only when the study granted importing it. Otherwise
    the step is skipped, and the summary says why.
  • Run it again to finish a half-done setup. Paired agents stay paired, a
    study you joined isn't joined twice, and history already sent comes back as
    already there.
  • The summary at the end lists which agents are collecting, the study and its
    window, Claude Code's retention before and after, and how many events were
    accepted or already there.

History import

  • import --summary-json <file> writes the closing summary as JSON too.
  • A missing pairing during import --ship is reported in the summary, after
    the stores are read. It used to end the run before the summary printed. An
    expired token still stops the run before anything is read.

Local dev server

  • Historical events need the history-import consent, which a confirmed join
    that carries it grants. Start the server with historicalImportLease: false
    to begin without it. It's on by default, so import --ship --local works
    as before.
  • The batch door answers duplicate for an importKey it has already
    stored, and returns a result for every event in the batch.

History import: compactions and commits

  • Each compaction gets its own row. ascenda-history-import now writes a
    context_compression_manual or context_compression_auto row for every
    compact_boundary in a Claude Code transcript, stamped when it happened.
    Before, a session wrote one row per kind at its last timestamp. Each new
    row carries compactionOrdinal, its place in the session.
  • If you imported before, run it again. The new rows are added beside the
    old session-end ones; nothing is removed. A reader can tell the old rows by
    their missing compactionOrdinal.
  • import --git reads commit history. Off unless you pass it. It looks
    only at repositories your agent sessions ran in, and sends your own commits
    as time, size buckets, files changed and merge or not. No messages, paths,
    names or emails. The backend has to accept the git store first, so for
    now the rows are written to the events file, and a --ship run may have
    them refused.
  • Codex rollouts mark a compaction but not whether it was manual or auto, so
    Codex gets no per-compaction rows.

What's Changed

  • feat: setup, pair and join print a link to confirm in a browser by @ascendaone-com in #187
  • feat(history-import): ship without the Flow app, and on a schedule by @ascendaone-com in #188
  • feat(history-import): participate , a study from one command by @ascendaone-com in #189
  • History import: a row per compaction, and an opt-in git commit extractor by @ascendaone-com in #190

Full Changelog: v0.1.37...v0.1.38

v0.1.37

Choose a tag to compare

@github-actions github-actions released this 14 Oct 21:15
f6b6aad

Claude Code plugin users: update to plugin 0.3.0 with
claude plugin update ascenda@ascenda-one, then restart Claude Code.
setup installs have nothing to re-run.

Plugin hooks start without npm

  • Hooks run from a copy on your machine. Plugin 0.3.0 runs every hook and
    the MCP server from ~/.ascenda/plugin, so a hook starts in under a tenth
    of a second. Each one used to ask npm for the latest release first. That
    cost half a second online. On a network that hangs it outlasted the 5
    seconds Claude Code allows a hook, and the event was lost.
  • Once a day the copy updates itself in the background. A new release reaches
    you within a day.
  • Your first session after updating still goes through npx, while the copy
    downloads.
  • ASCENDA_DISABLE_UPDATE_CHECK=true keeps the copy you have.

Hooks registered by hand

  • The example runs what setup installs.
    examples/settings.local.json
    names the hook launcher in ~/.ascenda/bin, so run setup first. Hooks
    copied from the old example call npx and have the same problem as the old
    plugin. Swap them for the new ones.
  • setup, status and uninstall recognise these entries in the files they
    manage: your user settings and a project's settings.local.json. They
    couldn't see the npx ones. A shared .claude/settings.json isn't one of
    those files, so keep an eye on that one yourself.

What's Changed

Full Changelog: v0.1.36...v0.1.37

v0.1.36

Choose a tag to compare

@github-actions github-actions released this 13 Oct 21:14
555fc41

Re-run setup for each agent after upgrading. It adds the new Claude Code
permission hooks and Codex SessionEnd.

Hooks return before the network does

  • A hook queues its events and gets out of the way. Every collector now
    writes to its outbox, starts a background sender and returns, so your agent
    waits for Node to start, not for a round trip. On a network that hangs, a
    hook returns in a fraction of a second. Until now it held the agent for its
    whole timeout.
  • doctor says which delivery mode is in use. ASCENDA_HOOK_DELIVERY=inline
    sends before returning, as before, and a hosted Claude Code session always
    does.

Setup that leaves other tools alone

  • Your other hooks stay put. When another tool has added its own command
    to a hook group Ascenda wrote, setup and uninstall take out Ascenda's
    entry and keep the rest. They used to remove the whole group.
  • Moved config folders work. With CLAUDE_CONFIG_DIR or CODEX_HOME set,
    setup, status and uninstall use that folder, and the history importer
    reads from it. CLAUDE_CONFIG_DIR can list several folders, comma-separated.
  • Settings files are written atomically. A symlinked settings.json stays a
    symlink, and .ascenda-backup keeps the file as it was before your first
    install.

Codex

  • status and doctor name hooks Codex hasn't approved. Codex skips an
    unapproved hook without a word, and a changed command needs approving again.
    Each one is listed, with the fix.
  • SessionEnd is registered with a 3 second timeout, the most Codex allows
    for it.
  • An older setup won't replace a newer hook runner.

Commits and pull requests from every agent

  • Codex, Gemini CLI and Cursor report git work too. Commits, pushes,
    reverts and pull requests opened now come from all three, as they already
    did from Claude Code. Only a call that succeeded counts. Windsurf doesn't
    say whether a command worked, so it reports none.
  • git -C <dir> commit, git -c key=value and --no-pager are recognised.
    So is a pull request opened through an MCP tool.
  • Codex's exec_command and shell_command count as shell calls, and the
    functions. prefix Codex Desktop adds is understood.
  • Claude Code NotebookEdit counts as an edit. Lines changed come from the
    edit's own patch when Claude Code sends one, so the live count and the
    imported count agree.

Prompts are things you typed

  • A ! shell command in Claude Code isn't a prompt, live or imported.
  • Neither is a background task's report, which Claude Code hands back to the
    session as if it were one.
  • Imported sessions driven by the Agent SDK keep those lines out of the
    typed-prompt count.

History import counts each thing once

  • Claude Code tokens count once per API response. Claude Code writes one
    line per content block and repeats the response's usage on every one, so
    token totals came out at about twice the real figure, or more. Resumed and
    copied sessions don't count their parent's work again, tool calls included,
    and a copied subagent's minutes stay with the session that ran it.
  • Codex threads fold properly. A fork keeps its own id and skips the
    history it replays from its parent. A subagent thread joins the session that
    started it. A long thread split over several files is one session.
    Compressed .jsonl.zst rollouts are read.
  • Cursor and VS Code. A Cursor session starts at its first message, and
    tokens Cursor didn't record are marked as not collected. VS Code chats with
    no folder open are read, and so are Code - Insiders and VSCodium.
  • Claude Code cache writes and advisor-model tokens are counted. Older flat
    agent-*.jsonl subagent files join their parent session.

More in agent-event/v0

Every addition is optional. Nothing is renamed or removed.

  • Match a session to its pull request. repoKey and branchKey are on
    events from every agent, and the GitHub collector now sends
    pull_request.closed and pull_request.merged with the pull request's
    times. docs/TEAM_COLLECTION.md shows the join.
  • The keys are unsalted. Anyone holding your events can check a guess at a
    repository or branch name. They're set only for github.com, never on a
    default branch, and setup --no-repo-keys or ASCENDA_REPO_KEYS=off turns
    them off.
  • Permission prompts. Claude Code reports permission.requested, and
    permission.denied in auto mode. No hook reports your answer, so there's no
    event for it.
  • Also new: vcsAction, promptId, model on session.started,
    permissionMode, and a reason on agent.waiting.
  • examples/otlp-forwarder sends the local event log to an OpenTelemetry
    collector. The package README maps each field to its OpenTelemetry name.

What's Changed

  • docs: keep measured counts in public, cut the content behind them by @ascendaone-com in #173
  • test: pin the Codex session id across turns by @ascendaone-com in #170
  • docs: say how the active-time split differs from Claude Code's own metric by @ascendaone-com in #171
  • fix(hooks): report unapproved Codex hooks, register Codex SessionEnd, guard the runner against downgrades by @ascendaone-com in #166
  • fix(claude-code-hooks): a task notification isn't a prompt by @ascendaone-com in #161
  • fix(history-import): count Claude Code tokens once per message, and copied lines once by @ascendaone-com in #160
  • feat(tool-kit): hooks queue their events and a background sender delivers them by @ascendaone-com in #162
  • fix(history-import): a ! shell command isn't a prompt by @ascendaone-com in #163
  • fix(hooks): keep other tools' hooks in shared groups, and follow CLAUDE_CONFIG_DIR and CODEX_HOME by @ascendaone-com in #164
  • Report git and milestone facts from every hook adapter by @ascendaone-com in #167
  • feat: repo and branch keys, vcsAction, a wait reason, promptId and model on the agent event by @ascendaone-com in #174
  • fix(history-import): fold Codex threads properly, read .zst rollouts, honour CLAUDE_CONFIG_DIR and CODEX_HOME by @ascendaone-com in #168
  • fix(history-import): count a copied subagent's minutes in the session that ran it by @ascendaone-com in #169
  • fix(claude-code-hooks): a ! shell command isn't a prompt by @ascendaone-com in #165
  • feat(history-import): read flat subagent files, SDK prompts, cache writes and more VS Code chats by @ascendaone-com in #172
  • feat: permission events, a permission mode, an input wait reason, prompt ids and repo keys for every CLI agent by @ascendaone-com in #178
  • feat(github-collector): key a pull request to its session and record how it ended by @ascendaone-com in #175
  • docs: OpenTelemetry mapping, an OTLP forwarder, and joining sessions to PRs by @ascendaone-com in #176
  • chore: release notes for v0.1.36 by @ascendaone-com in #179

Full Changelog: v0.1.35...v0.1.36

v0.1.35

Choose a tag to compare

@github-actions github-actions released this 13 Oct 00:36
7b25684

Your agents' events, on your own machine

  • An install without pairing keeps a log. Set up with --no-pair, or
    with a pairing that didn't finish, every agent now writes each event to
    ~/.ascenda/events.jsonl. It's the same metadata a paired install would
    send, and nothing leaves the machine. Until now Codex, Cursor, Gemini CLI
    and Windsurf kept nothing locally, and Claude Code did only if you'd
    exported ASCENDA_EVENT_LOG_FILE.
  • You choose where it goes. setup --event-log keeps the file on a
    paired install too, setup --event-log <path> moves it, and
    setup --event-log off stops it. The setting covers every agent on the
    machine, the VS Code extension included, and a re-pair keeps it.
    ASCENDA_EVENT_LOG_FILE still wins for one shell, and takes off as well.
  • setup, status and doctor show the file. Each names the path and
    why the log is on.
  • The file rotates at 5 MB, keeps one older copy, and only your user can
    read it.

An open event format: @ascenda-one/agent-events

  • Every line of the log carries an event. It says which agent, what
    happened, which tool and how it ended, in a small format called
    agent-event/v0. It holds nothing the collectors didn't already record.
  • The format has its own package. @ascenda-one/agent-events is new on
    npm: a JSON Schema, TypeScript types and a reader for the log. No
    dependencies, no account.
  • It's experimental. Fields and kinds can be added in any release.
    Anything renamed or removed is listed in the notes for the release that
    changes it. The package README has the full policy.
  • examples/local-event-reader in the repo reads the file with plain Node.
    It sums up each session, or follows the log live with --follow.

Licences

  • Every package on npm now ships its licence and a NOTICE naming Ascenda One
    Pty Ltd. agent-mcp, github-collector and history-import went out
    without a LICENSE file before.

What's Changed

Full Changelog: v0.1.34...v0.1.35

v0.1.34

Choose a tag to compare

@github-actions github-actions released this 09 Oct 22:44
0e65746

Claude Code hooks work on a fresh account

  • Hooks load in every project. setup registers them in
    ~/.claude/settings.json by default. Run from your home folder, it used to
    write a file Claude Code reads only when started in the home folder. Re-run
    setup and it moves an existing install for you. --scope project still
    works.
  • Hooks find Node on their own. Each hook now runs a small launcher that
    finds Node 20 or newer, so they keep working when Claude Code opens from the
    Dock or an IDE, and after nvm or fnm removes the version that ran setup.
  • status and doctor say whether anything is running. Both name the
    Node your hooks will use and the last hook Claude Code ran. doctor also
    checks who is listening for the live signal and pings the Waterline screen
    saver to prove a signal arrives.
  • The screen saver catches up when it starts. Signals sent while nothing
    was listening are kept for half an hour, so an agent waiting on you before
    the saver started still shows as waiting. Closing Claude Code mid-turn now
    ends that session's water straight away.
  • An install without pairing says it's ready. setup --no-pair tells you
    the screen saver works now and that pairing is optional. In a terminal,
    setup, status and doctor mark each line and use colour.

Codex, Cursor, Gemini and Windsurf hooks work on a fresh account too

  • The same install rules. setup registers hooks for every project by
    default and moves an older project install. Each hook runs through the
    launcher that finds Node. Windsurf run from your home folder used to write a
    file it never reads.
  • Each adapter has doctor. It names the Node, where the hooks are
    registered and the last hook the agent ran, then checks the live signal.
  • Quitting Cursor or Gemini CLI mid-turn ends that session's water.

What's Changed

Full Changelog: v0.1.33...v0.1.34

v0.1.33

Choose a tag to compare

@github-actions github-actions released this 09 Oct 02:25
79b6218

Claude Code's subagents are counted

  • Each subagent sends a start and a stop. Claude Code's SubagentStart and
    SubagentStop hooks are registered, and each sends Claude Code's id for the
    subagent under the session that spawned it. That's how Ascenda can tell how
    many agents you had running at once. A session that fans out to eight
    subagents used to count as one.
  • Its name stays on your machine. A subagent you defined is sent as
    custom, and one from a plugin as plugin. Built-in agents like Explore
    and Plan are sent by name. What a subagent was asked and what it said back
    are never read.
  • Tool calls made inside a subagent carry its id too.
  • setup and pair list subagents among what's sent. Re-run setup to pick
    up the two new hooks, or update the plugin. status now counts thirteen.

Your connection renews before it lapses

  • Tokens renew while they still work. A paired install used to stop
    sending 30 days after its last renewal, and only pair brought it back.
    Now it renews once fewer than 21 days are left. Installs paired before this
    release renew too, as long as their token is still live.
  • If yours has already lapsed, pair again. Claude Code's pair does it.
  • setup pairs again for Codex, Cursor, Gemini CLI and Windsurf. It
    checks the saved token with the server before keeping it. If it's been
    revoked or is past its 30 days, you get a pairing code, and the new pairing
    keeps your installation id. Before this, setup kept the dead token and said
    all was well.
  • Offline, setup keeps the token it has. If the last send was refused, it says
    so and asks you to run setup again once you're back online.

Flow can tell an agent working from one waiting on you, or one that stopped

  • The hooks now tell the Flow app on your Mac when an agent is waiting on
    you.
    In Claude Code that's a permission prompt, an AskUserQuestion or
    an MCP form. In Codex it's an approval. In Gemini CLI it's a tool
    confirmation. Until now a parked approval looked like work for up to three
    minutes.
  • Background work keeps a session open. When Claude Code stops a turn
    with shells or subagents still running, the hook tells the app how many.
    The waterline doesn't drain and the settle bell won't ring "All quiet"
    while they run. After an hour with no word from that session, the app stops
    trusting the count and treats it as gone quiet.
  • Claude Code's StopFailure hook is registered. It fires when an API
    error, like a usage limit or an expired login, ends a turn. The app hears
    that the work has stopped, and whether it hit a usage limit, so the
    waterline drains straight away.
  • A usage limit says when it lifts, if Claude Code will carry on by
    itself.
    With autoContinueAtUsageLimit on, the hook reads the reset
    time from Claude Code's message and hands the app the time alone. Away
    mode keeps your Mac awake until the reset, so the agent can pick up where
    it stopped. Weekly limits don't count. Anything more than six hours off is
    left out.
  • Pressing Esc gets the same treatment, once Claude Code shows its idle
    prompt.
    Esc runs no hook, so until now the app waited three minutes
    before deciding a session had gone quiet.
  • Gemini CLI registers one more hook, Notification, for tool
    confirmations.
  • Cursor and Windsurf have no hook for waits, so nothing changes there.
  • Nothing new is sent to Ascenda. These signals stay on your machine, on the
    same local socket the gauges already read, and carry no words: not the
    question, not the command, not your answer.

Upgrading picks up the new hooks, and Flow says when you haven't

  • Run setup again to upgrade. Use the scope you installed with. It keeps
    your pairing, adds the hooks this version registers and prints what changed:
    upgraded: added StopFailure, Notification; hook set 1 → 2. A run with
    nothing to add says already current.
  • Flow names the command when your hooks are older. Each hook now tells
    the app which set of hooks it was registered with, and whether it came from
    the plugin. When Claude Code or Gemini CLI signals come from
    an older set, Connections → Ingest telemetry shows one line with the
    exact command. Dismiss it and it stays gone until a later release adds hooks
    again.
  • status prints the hook set, and the upgrade command when it's behind.
  • setup warns when the other scope already registers the same hooks. Both
    fire, so every event runs twice.
  • Plugin installs upgrade with claude plugin update ascenda@ascenda-one. The
    plugin is now 0.2.1, so the update reaches you.

Counted unless you object

  • status shows what your organisation counts unless you object. An
    organisation can record that it counts some of its own study on a basis it
    has documented, like legitimate interests or a collective agreement, rather than
    asking each of you to switch it on. For each of those, status names the
    organisation's basis and its document, who recorded it, and that Ascenda
    processes it for them. Then it tells you whether you've objected, and the
    one command that changes it.
  • object <purpose> stops you being counted for that purpose from the
    next report. No reason asked. object <purpose> --undo counts you again.
    The purposes are telemetry, import and work-patterns, and only those
    three can ever be counted this way. Reports already issued stay as they are.
  • Yours alone. Nothing tells your organisation who objected, and status
    shows nothing about anyone else. Like join, object needs a real
    terminal, so an agent can't run it for you.
  • With an organisation that counts nothing this way, or a server that
    doesn't support it yet, status looks exactly as it did.

The agent can read what the Reveal showed you

  • A third skill in the Claude Code plugin, ascenda-reveal-read. Once
    per session it reads, from the Flow app on your own Mac, the read the app
    showed you when you imported your history: which days ran heavy, how the
    weeks went, the hour band your work leans to, one crossing of two facts,
    and the receipt. It holds that and says nothing unless you ask, or a piece
    of work has to be placed in the day.
  • Counts and dates only. Your projects reach it as opaque digests, and
    the bird you kept never does.
  • Needs the Flow app with get_reveal on its local server (Flow 0.1.16 or
    later) and an agent paired with the Demand & workload scope. Without
    either, the skill is silent.

See your organisation's changes in status

  • status lists the changes your organisation has published to you. Each
    one shows its title, the organisation's own summary, the direction it
    expects, the scoring window, and the result once it's scored. A withdrawn
    change says it's withdrawn and keeps its result. A status the tool doesn't
    recognise reads "Status not recognised."
  • Nothing to list says why. "None published to you" means the list came
    back empty. If the server turned the request down, status says it couldn't
    check and how to pair again. If the list couldn't be fetched, it gives the
    reason and you can run status again. An install that holds no token asks
    for nothing and says that. status can't yet tell "not in any
    organisation" from "nothing published".
  • Only status shows it. The hooks never fetch the list, and none of it is
    passed to your agent.

Join an organisation's study, from the command line

  • join <code>, beside setup, status, uninstall and pair — every
    CLI agent adapter has it. Joining puts you in Report mode for 30 days; a
    fuller Study mode still needs the Ascenda app, and the command says so.
  • One question, nothing preselected. You are shown the organisation, the
    study, its window, and every grant Report mode carries, before you are
    asked anything. "Not now" is the default. Enter, Ctrl-D, or running it from
    a script all land there, and you are never joined.
  • No flag answers the question for you. The command also refuses to run
    without a real terminal, because only you should be able to join yourself
    to a study.
  • Saying yes prints a short code you confirm in the app, the same way pair
    does today, then shows what was granted. Each grant can be turned off on
    its own, in the app's consent settings, and the organisation only ever
    sees group counts, never who joined.

The GitHub collector records only the person who paired it

  • Set ASCENDA_FORGE_LOGIN to your own GitHub login, typed once. The
    example workflow and the README used ${{ github.actor }}, which is
    whoever triggered the run. A colleague's pull request or review then
    matched and was recorded under your installation, and a review request
    never matched you, because its actor is the person asking.
  • If you copied the old example, change that line. Store your login as a
    repository secret, say ASCENDA_FORGE_LOGIN_OCTOCAT, and read it from
    there. The collector can't tell a typed login from the actor, so the fix
    is in your workflow file.
  • One step per person. The installation secrets belong to one person, so
    a repository several people have paired in needs a step each, or a matrix
    over their suffixes. The README shows both.

What's Changed

  • feat: join an organisation's study from the command line by @ascendaone-com in #134
  • chore: describe the summed hands-on figure from the collector's side by @ascendaone-com in #135
  • feat: list your organisation's published changes in status by @ascendaone-com in #136
  • feat(skills): ascenda-reveal-read, the agent reads what the Reveal showed by @ascendaone-com in #137
  • Show what your organisa...
Read more

v0.1.28

Choose a tag to compare

@github-actions github-actions released this 25 Sep 01:52
a6a2b00

Install the CLI hooks without an account

  • setup --no-pair. Every CLI agent's setup stopped at a pairing code
    you confirm in the Ascenda app, so the hooks could not be installed at all
    without an account. With the flag they install and register as usual, and
    emit only the local live signal — the message a listener on this machine
    reads to know an agent is working right now. Nothing is sent anywhere,
    which was already what an unpaired hook did.
  • A pairing that cannot finish now installs the local half anyway, and
    says so. Before, you got nothing at all. An unreachable host, an unconfirmed
    code and an expired session all land in the same place.
  • Your installation id is recorded either way, so pairing later attaches
    the hooks you already installed rather than minting a second id beside
    them. Pair whenever you like by running setup again.
  • On such an install the hooks stop reporting the absent pairing as a fault:
    no journal entry per event, and status says installed, not paired — local features active, telemetry inactive. A token that is revoked or
    deleted after pairing is still reported, loudly, as before.
  • Claude Code is in this too. Its adapter takes the same flag, records the
    same installation id and reads the same way in status and doctor, which
    now name the mode: installed, not paired.
  • The session prompts keep working unpaired. The lines these hooks add to a
    Claude Code session are written on your machine, so they never needed an
    account either. Same for the live signal.
  • status stops calling a good install broken when you ask about the wrong
    scope.
    Hooks in ~/.claude/settings.json apply to every project, so a
    check run in a project now finds them and says where they are.
  • uninstall leaves your other agents alone. It used to delete the whole
    credentials file, taking any other agent's pairing with it. It clears its own
    entry now, and on an unpaired install it tells you there is no token to
    revoke.

Every event names the collector that sent it

  • Events carry collectorVersion, the release of the collector that sent
    them. A collector older than an event type sends nothing for it, and this is
    how a zero from an old build can be told apart from a real one. A build from
    a checkout says unreleased.
  • status prints it first, for Claude Code and the other CLI agents alike.

Cloud sessions are told apart from local ones

  • Claude Code events say where the agent ran: runtime is local on your
    machine and cloud in a hosted session such as Claude Code on the web. A
    cloud session's transcript never reaches your machine, so a history import
    can't see it and the hooks are its only record. The setup screen says so.
  • In a cloud session the hooks never rotate their token. Each session
    starts from the token you put in that environment's settings, and a rotation
    would revoke that copy for every later session. A rejected token there is
    recorded as a failed send. Pair again and replace the token.

Claude Code sessions end

  • The Claude Code hooks send a session end when Claude Code exits, the
    same session_ended event Cursor, Gemini and the editor extensions send.
    Until now a Claude Code session only ever started.
  • It carries Claude Code's own reason, one word: clear, resume, logout,
    prompt_input_exit or other. A word it doesn't recognise goes out as
    unknown. The setup screen says so.
  • Exiting never waits on the network. The end goes into the outbox, and
    the next hook to send delivers it: another open session's next tool call, or
    your next SessionStart. It keeps the time it was written.
  • Run setup again to pick it up. It registers ten hooks now, and
    status counts 10/10. The plugin registers the same ten.

What's Changed

Full Changelog: v0.1.27...v0.1.28

v0.1.27

Choose a tag to compare

@github-actions github-actions released this 22 Sep 23:44
d9d3734

A leftover socket file can't swallow live signals

  • The hooks skip a dead socket. Every hook sends a small live signal
    to a local socket so a desktop listener knows an agent is working right
    now. It went to the first socket file it found, and a file stays behind
    when its listener is force-quit, crashes or is removed without cleaning
    up. From then on every signal went into that dead file, a listener
    further down the list heard nothing, and nothing said so.
  • Now a refused connection moves on. The hooks try each socket file in
    the same order as before and send to the first one that answers. One
    listener gets each signal, never several.
  • Your agent turn still doesn't wait. The whole attempt, however many
    files it tries, still gives up after 50 ms and never raises an error.
  • ASCENDA_LIVE_BUS_SOCKET is unchanged. Set it and that path is the
    only one tried.
  • Nothing gets deleted. The hooks leave a stale socket file where it
    is. Cleaning it up is the listener's job.

What's Changed

  • fix(tool-kit): a stale live-bus socket no longer swallows every signal by @ascendaone-com in #121

Full Changelog: v0.1.26...v0.1.27

v0.1.26

Choose a tag to compare

@github-actions github-actions released this 20 Sep 23:09
a8987ff

When the agent stops and waits for you, that now counts

  • Being interrupted is recorded as its own thing. Claude Code fires a
    notification when it stops and waits for you: asking permission to run
    something, or simply waiting for input. Codex does the same at its approval
    gate. Neither was recorded before: both hooks were unregistered, so the
    number of times an agent stopped and waited on you was always zero, and zero
    looked exactly like never being interrupted.
  • Nothing about what was asked leaves your machine. The event carries one
    field, interruptionKind, which is permission_request, idle_prompt or
    other, and nothing else. Not the notification's wording, not the command awaiting
    approval, not the path it touches, not your answer. A test in each adapter
    fails the build if a future change adds any of them.
  • It rides the telemetry permission you already gave. No new consent to
    grant, because producing it needs nothing that the tool-call and file events
    covered by that permission didn't already need: a hook fires when the agent
    reaches a gate, and no content is read to send it.
  • other is a real answer, not a leftover. These notifications get reworded
    between releases, and a wording we don't recognise is reported as other
    rather than guessed at. If that share climbs, the labels need updating. It
    is meant to be visible.
  • Codex users merging hooks by hand: examples/hooks.json gains a
    PermissionRequest entry. setup writes it for you; a hand-merged file needs
    the line added.
  • What this is not. A count of interruptions, and nothing built on top of
    it. There is no score, no streak, and nothing that fires when a number moves.

A resumed session's minutes are its own

  • Active time stops at the session boundary. Resuming or forking a Claude
    Code session writes a transcript that opens with a copy of everything it
    inherited. Those copied lines were counted twice: once in the session they
    were typed in, once in every session resumed from it. v0.1.25 fixed the
    prompt counts and left the minutes alone. They're fixed now.
  • Your session totals drop. Your week doesn't. On one 983-session store the
    per-session active minutes summed to 70,212 and now sum to 53,600, while the
    union of the same intervals moved by a single minute. Hands-on falls
    furthest, 12,238 minutes to 8,006. Every minute of work is still in there,
    counted once, where it happened.
  • A session starts when you started it. startedAt was the oldest
    timestamp anywhere in the file, which on a resume is whenever the first
    ancestor began. 127 of 978 sessions on that store now show a later start, 13
    of them by more than an hour.
  • Counts of agents running at once get honest. Exact-duplicate spans were
    30% of every active span in the store and are now 3.5%. A duplicated span
    reads as a second agent, so any concurrency figure was partly reading copies.
  • minutesBasis: "owned_lines" on the handoff says which minutes you're
    reading.
    "every_line", and a missing stamp, mean the old figures. Gate on
    it before you compare two handoffs. The schema number stays where it is.
  • Resume a session, type nothing, and there's no session to report. The
    file holds the copy and that's all, so the import counts it in
    sessionsWithOnlyInheritedLines and moves on.
  • Both importers agree. The desktop app reads by the same rule.

The runs you cut short are the ones you cut short

  • A resume no longer reports its ancestors' interruptions. Pressing Escape
    writes a marker into the transcript, and a resumed session copies that marker
    along with the rest of the history it inherited — so the same interruption
    was reported again by every session resumed from it. Only the session you
    pressed Escape in counts it now.
  • Expect a lower count, on the same store. 191 counted runs became 151 on
    one store of 990 transcripts: a fifth of them were replays. 26 sessions
    changed and 19 now report none at all. Nothing real was dropped: every
    marker is still counted somewhere, and the per-day figures move with the
    totals.
  • The rule is the one the minutes already use. Same ownership, asked of a
    third thing, so a session's cut-short count and its minutes now answer the
    same question about the same lines. A cut whose own session has been purged
    still counts, in the first transcript that holds it.

Minutes a second file also claimed

  • Some copies rewrite the session id, and both files claimed the line. The
    rule that stopped a resumed session counting its ancestors' minutes trusts
    the id each line carries. Most copies keep it; some rewrite it to the
    copying file's own name while keeping everything else, down to the original
    timestamp — so both files said the line was theirs and both counted it. It
    isn't a version quirk: the transcripts carrying it span fourteen Claude Code
    releases.
  • Another 3.9% comes off your session totals, and your week still doesn't
    move.
    On one store of 991 transcripts, 3.7% of the lines claiming their own
    file were claimed by two. Summed active minutes fall 53,945 to 51,865 and
    hands-on 8,052 to 7,599, while the union of the same intervals holds to a
    minute, 25,248 to 25,247, which is what says a line was dropped and not a
    minute of work. 42 sessions change and 34 now start later.
  • The minutes land on the session that did the work. The file that wrote a
    line is the one still holding a line nobody else claims — its own history has
    started there. Where that file has been purged, the first in walk order keeps
    it, as with any orphan. Picking by walk order alone would have moved a third
    of these lines onto the copy instead.
  • A prompt and the minute it happened in now agree about whose they are.
    The prompt count never double-counted these, but it could put the prompt in
    one session and its instant in another.
  • Imports take a little longer. The pre-read now reads every line's id
    rather than only the lines a prompt could hide in, and the files holding a
    contested id are read once more — 76 of 991 on that store. Measured end to
    end: 24s to 30s.

Days you worked show up even when you typed nothing that session

  • A session with no prompt of its own still gets its day breakdown. Sessions
    opened from a chip have no typed prompt, and neither does a resume whose
    prompts all belong to an ancestor, which v0.1.25 made common by counting
    each typed prompt once. The per-day
    slices stopped at the prompt list, so those sessions came back with no days
    at all. Their session totals were right the whole time. Only the placement
    went missing, which is why nothing looked wrong.
  • What comes back. On one 987-session store, 103 sessions had no prompt of
    their own and every one of them reported an empty breakdown. Day-placed
    active minutes go from 50,173 to 51,662, and five cut-short runs land on the
    day they happened.
  • Codex imports gain the same days. Both extractors that measure active
    time were affected. A store whose only timestamps are its prompts, Cursor
    and VS Code, behaves as before.
  • Anything summing the day breakdown will read higher. The session figures
    don't move, so a total built from days[] gets closer to the one built from
    sessions.

What's Changed

Full Changelog: v0.1.25...v0.1.26