Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/DASHBOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,9 @@ session."
A session cwd is only a discovery candidate; it does not confer project scope. If that cwd makes a
candidate surface resolve to the same host, kind, and path as a user surface, the user occurrence
wins and no project-pressure row is fabricated. One shared user surface carried by two hosts remains
visible on both hosts.
visible on both hosts. A Codex session that the ChatGPT desktop app imported from a Claude Code
transcript is not a candidate at all: it adds no project, host or Desktop origin, and the Projects
note under the System KPIs says how many were set aside.

The measurement counts a physical artifact once and retains each host that discovers it as a
separate consumer binding. It fingerprints bounded skill definitions and individual MCP
Expand Down
5 changes: 3 additions & 2 deletions docs/MAINTENANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ Project choices group beneath repositories only when shared Git metadata or the
contract establishes the association. A worktree remains its own selectable project. Folder/name
headers, a Git/Worktree/Folder designation, and all detected language icons identify each choice.
An independent **Session origin** facet can match Claude Desktop, Codex Desktop, or unclassified
observations; Desktop origin never replaces repository membership. Facet counts are installations
in matching projects, not numbers of sessions. Selecting several origins does not duplicate a
observations; Desktop origin never replaces repository membership. Codex copies of Claude Code
sessions imported by the ChatGPT desktop app never count as a Desktop origin. Facet counts are
installations in matching projects, not numbers of sessions. Selecting several origins does not duplicate a
placement. Exact root paths stay private; the public grouping uses opaque repository identities
and bounded display labels.

Expand Down
7 changes: 5 additions & 2 deletions docs/TRANSCRIPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Each line has a top-level `type`. The parser (`parseClaude`,
| "ai-title" | The model-written session title (`usage-parsers.mjs:768`) — preferred over the first-prompt fallback |
| `user` | A user-**role** turn — which is *not* the same as "the human"; see §3. On a turn that passes isHumanPrompt, also its `permissionMode` — the session's permission posture, read on the person's own turn only (`usage-parsers.mjs:593-609`) — and the opening of the response-latency window |
| `assistant` | One content block of a model message: `model` id, the message's `usage` token counts (repeated on every block's line, so counted once per `message.id`, else `requestId`, last line winning), `tool_use` blocks (`usage-parsers.mjs:661-743`) |
| any | Side-band fields read regardless of type: `attributionSkill`/`attributionPlugin` (`usage-parsers.mjs:758-759`), `isSidechain` (`usage-parsers.mjs:760-763`), `cwd` for project derivation |
| any | Side-band fields read regardless of type: `attributionSkill`/`attributionPlugin` (`usage-parsers.mjs:770-771`), `isSidechain` (`usage-parsers.mjs:772-773`), `cwd` for project derivation |

A real assistant completion also closes two pieces of per-entry evidence the
transcript does not state outright. It **closes the latency window** the
Expand Down Expand Up @@ -139,7 +139,10 @@ Three rollout shapes are handled before any of that:
no `thread_source`, `input_tokens: 0`). The parser stops at the first such line and
returns an identity-only record marked `imported`; the scan keeps it out of
Codex sessions, prompts, responses and yield diagnostics and counts it in
`importedExcluded`. The real conversation is in the Claude transcript.
`importedExcluded`. The real conversation is in the Claude transcript. Project
discovery reads the same marker in each rollout's head and leaves the rollout out
of projects, hosts and Desktop origins, counting it in the discovery scan's
`importedExcluded`.
* **Forked subagents.** A forked subagent's rollout replays its parent's history
before its own turns. Every envelope carries an `ordinal`; the replay ends at
`subagent_history_start_ordinal` when some event lies at or beyond it, else at the
Expand Down
9 changes: 9 additions & 0 deletions docs/UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ and supported `claude mcp serve` tool exposure are preserved. See
[ADR-0051](adr/0051-supported-peer-delegation-and-host-realignment.md) for the policy,
official source citations, authority boundaries and verification limits.

## 2026-09-27: System snapshot v8 (imported Codex copies)

When the ChatGPT desktop app imports a Claude Code transcript, it saves a copy as a Codex session.
Project discovery no longer counts these copies: they give a folder no Codex host and no Desktop
origin, and System says how many it set aside. A snapshot taken before this change still holds the
old hosts and origins, so the Footprint snapshot schema advances to v8. This build reports a v7
snapshot as unreadable until you run **Full scan** in System or `ak system --deep`. It is never
shown under the new rule. See [ADR-0060](adr/0060-session-surface-initiator-and-product-names.md) §3.

## 2026-09-26: `ak sync`'s exit code ignores fixes you do by hand

`ak sync` now exits 0 when everything it can repair has converged, even if a row whose fix you
Expand Down
6 changes: 3 additions & 3 deletions docs/USAGE-SCORECARD-METRICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ responses = Σ over included sessions of session.responses
- `responses` accumulation: Claude increments once per API message id — every
transcript line of one message counts once, the last line's usage winning
(`usage-parsers.mjs:661-696`); Codex increments per `agent_message` event
(`usage-parsers.mjs:1008-1013`).
(`usage-parsers.mjs:1021-1025`).
- Totals: `totals.responses += s.responses` per included session
(`usage-aggregate.mjs:928`).
- Render: `kpi("sessions", fmtNum(t.sessions), fmtNum(t.responses)+" assistant
Expand Down Expand Up @@ -836,7 +836,7 @@ byDay[day].sessionsActive = count of distinct sessions with any usage row that d

**Source:** the day key is the row's own `row.day`, computed once at parse
time as **local calendar day**, not UTC
(`usage-parsers.mjs:35`/`usage-parsers.mjs:1185` call `localDay(at)`) — so a
(`usage-parsers.mjs:35`/`usage-parsers.mjs:1174` call `localDay(at)`) — so a
session that runs from 23:58 local to 00:05 local has its session count attributed
to the day its *first* usage row landed on (test:
`tests/kit/usage-index.test.mjs:738`, "a session that opens before midnight
Expand Down Expand Up @@ -926,7 +926,7 @@ punchcard[dow + "-" + hour] += 1 per assistant/agent_message response, at its
**Source:** incremented once per Claude API message (all of a message's
transcript lines are one hit)
(`usage-parsers.mjs:42`, keyed by this call: `punchKey(at)`) and once per Codex
`agent_message` (`usage-parsers.mjs:1008-1013`), merged into the window-level
`agent_message` (`usage-parsers.mjs:1021-1025`), merged into the window-level
`punchcard` object per session (`usage-aggregate.mjs:943-1007`). Cell intensity is
linear against the single busiest cell in the window:
`v = pcMax ? n/pcMax : 0` (`dashboard/client.mjs`) — this is a
Expand Down
13 changes: 10 additions & 3 deletions docs/adr/0050-dashboard-project-identity-and-context-reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

- **Status:** Implemented
- **Date:** 2026-09-09
- **Updated:** 2026-09-26 — the `project-concentration` Finding ranks `gitProjects`, not the
folder-label `byProject`, so it agrees with Score → Projects (#238 item 7)
- **Earlier update:** 2026-09-09 — scoped context-card network claims for issue #211
- **Updated:** 2026-09-27 — a Codex rollout the ChatGPT desktop app imported from a Claude Code
transcript gives no session origin, even though it declares `Codex Desktop`
([ADR-0052](0052-codex-usage-attribution.md) §3,
[ADR-0060](0060-session-surface-initiator-and-product-names.md) §3)
- **Earlier updates:** 2026-09-26 — the `project-concentration` Finding ranks `gitProjects`, not
the folder-label `byProject`, so it agrees with Score → Projects (#238 item 7); 2026-09-09 —
scoped context-card network claims for issue #211
- **Related:** [ADR-0036](0036-dashboard-client-modularization-and-shared-loopback-server.md),
[ADR-0048](0048-inventory-led-maintenance-resource-management.md)

Expand Down Expand Up @@ -35,6 +39,9 @@ Session origin comes from bounded transcript metadata, separate from the existin
- Codex `session_meta.originator`: `Codex Desktop`, `codex_work_desktop`.
- Everything else, including ambiguous SDK and VS Code markers: unknown.

A Codex rollout whose turns carry the `external-import-turn` marker is a copy of a Claude Code
transcript, not a Codex session. It supplies no origin, whatever its `originator` says.

These are source declarations, not attestation of the initiating application.
Claude's installed 2.1.266 runtime maps those entrypoints to Claude Desktop;
Codex values were observed in local bounded session metadata. No prompt content,
Expand Down
17 changes: 17 additions & 0 deletions docs/adr/0052-codex-usage-attribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

- **Status:** Accepted
- **Date:** 2026-09-19
- **Updated:** 2026-09-27 — imported copies are also excluded from project discovery: they give no
project, host or Desktop origin, and the discovery scan counts them in `importedExcluded`
(ADR-0060 §3). The marker now lives in one leaf module shared by usage and discovery.
- **Deciders:** agentic-kit maintainers
- **Related:** [ADR-0009](0009-usage-scorecard-local-transcript-analytics.md),
[ADR-0038](0038-consistent-cross-host-session-metrics.md),
Expand Down Expand Up @@ -117,6 +120,11 @@ out of aggregation, out of every yield statistic, and counted in
`diagnostics.importedExcluded` (796 on the reference machine). Nothing is dropped
silently. The record itself is still cached, so a rescan is cheap.

Project discovery applies the same marker to each rollout's bounded head (256 KiB, 40 lines): an
imported copy names no project, host or Desktop origin, and the scan reports how many it set aside
(`importedExcluded`, 924 on the reference machine on 2026-09-27, every marker on the rollout's
second line).

### 4. Cumulative counter restarts are summed, per event

`total_token_usage` restarts from zero mid-file: 48 restarts across 33 files
Expand Down Expand Up @@ -196,6 +204,15 @@ subagent and previously dropped usage is now priced.
- A subagent with no ordinals still reports no usage (decision 2).
- One rollout carries `token_count`s but no agent message, so the pre-existing
`partial-response-yield` warning remains.
- Whole-rollout exclusion may drop real usage (open, plausible, 2026-09-27). On the reference
machine 6 of 924 imported rollouts carry a later turn that is not an import: one `task_started`
whose `turn_id` starts with `rollout-`, no `user_message` event, `role: user` response items in
five of the six (2 to 76 per file) and non-zero `token_count` usage (the per-file sum of
`last_token_usage.total_tokens` is about 8k to 449k). Both usage and discovery set the whole file
aside at the marker, so this usage is not counted. With no `user_message`, the turn may be
automatic (a compaction or title pass). Measured from counts only. Decided 2026-09-27 (audit
decision 12): Branch 8 excludes per turn instead of per file, so imported turns are never counted
and later turns are, after it establishes whether they are the user's work or an automatic pass.

## Verification

Expand Down
29 changes: 25 additions & 4 deletions docs/adr/0060-session-surface-initiator-and-product-names.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# ADR-0060 — Session surface, initiator and official product names

- **Status:** Proposed (staged follow-on; nothing implemented)
- **Status:** Proposed; §3 implemented for project discovery (2026-09-27), the rest staged follow-on
- **Date:** 2026-09-26
- **Updated:** 2026-09-27 — §3 implemented for project discovery and the System projects note:
imported copies give no project, host or origin and are counted. The ledger-derived source labels
(Cursor, Cowork) and the other views remain proposed.
- **Deciders:** agentic-kit maintainers
- **Related:** [ADR-0050](0050-dashboard-project-identity-and-context-reporting.md) (session origin
rule, superseded in part by this record once accepted),
Expand Down Expand Up @@ -160,8 +163,9 @@ in full.
## Consequences

- Usage, System → Projects, Maintenance facets, Intelligence designation (which today mixes Git
scope, origin and host in one enum) and the Runtime table change labels and counts. Twenty-three
project folders lose a false Desktop origin on this machine.
scope, origin and host in one enum) and the Runtime table change labels and counts. On this
machine 32 project folders lost a false Desktop origin when discovery began setting imports aside
(re-measured 2026-09-27; 23 on 2026-09-26).
- The usage cache schema changes (new session fields); a rebuild is expected.
- Tests that pin current names change together (inventory in the audit record, Addendum 3).
- `CLAUDE_CODE_ENTRYPOINT` and the transcript format are internal to Claude Code and may change;
Expand All @@ -173,6 +177,10 @@ in full.
- Whether "Cloud session" should appear at all in local views, given none was observed locally.
- Whether the "on 3P" attribute is worth showing.
- How ADR-0057's role lenses consume surface and initiator.
- Whether a later turn inside an imported copy that is not itself an import (6 of 924 rollouts on
2026-09-27, with real token usage) counts as the importing app's own session. Decided 2026-09-27
(audit decision 12): it counts, excluded per turn in Branch 8
([ADR-0052](0052-codex-usage-attribution.md), "Not done").

## Verification (when implemented)

Expand All @@ -182,4 +190,17 @@ fixture.

## Implementation status

Not started. Staged as follow-on work in the audit record's Addendum 3.
§3 is implemented for project discovery and the System projects note (2026-09-27): an imported copy
gives no project, host or origin, and discovery counts it in `importedExcluded`. The per-source
labels from the imports ledger, Runtime attribution and §1, §2 and §4–§6 remain follow-on work
(the audit record's Addendum 3).

Three views already show the smaller project counts but do not yet say how many imported copies were
set aside; §3's "each view reports how many it excluded" is still owed for them:

- the Intelligence census line (`src/lib/dashboard/client/intelligence.mjs`, which prints
`everSeen`; the server's `readCensus` in `src/lib/dashboard-server.mjs` drops `importedExcluded`);
- the System → Projects liner (`sysProjectsLinerHtml` in
`src/lib/dashboard/client/system-projects.mjs`);
- the `ak system` text output (`renderProjects` in `src/commands/system.mjs`, which prints only the
count; `ak system --json` carries `importedExcluded`).
9 changes: 5 additions & 4 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,8 @@ component out.

## ADR-0060 — Session surface, initiator and official product names

[ADR-0060](0060-session-surface-initiator-and-product-names.md) (Proposed) derives a session's
surface and initiator from the hosts' declared log fields, keeps every raw value, uses official
product names (Claude Desktop, ChatGPT desktop app, Codex CLI, and others), and excludes imported
session copies from every origin view.
[ADR-0060](0060-session-surface-initiator-and-product-names.md) (Proposed; §3 implemented for
project discovery) derives a session's surface and initiator from the hosts' declared log fields,
keeps every raw value, uses official product names (Claude Desktop, ChatGPT desktop app, Codex CLI,
and others), and excludes imported session copies from every origin view. Project discovery already
sets imported copies aside and counts them; the other decisions remain proposed.
Loading
Loading