Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ ak status read-only dashboard: what's true, what's drifted [--json] [--d
ak sync converge to good: upgrade + heal + verify [--dry-run] [--no-upgrade]
ak dashboard open the local web dashboard (auto-opens your browser)
[--port N] [--no-open] [--live-source 'surface=path']
ak usage inspect/refresh offline provider account analytics
status | refresh openrouter
ak host manage execution hosts, routing, and provider bindings
status | pick | refresh | off
ak run execute a host-neutral activity pipeline (including explicit OpenCode routes)
Expand All @@ -91,7 +93,8 @@ What the verbs cover:
| **setup** | Installs/updates ruflo + agentic-qe + the **agentdb** CLI globally (handling npm ≥11.17's `allow-scripts` so natives build; agentdb is pinned to ruflo's bundled version so the shared learning store stays coherent), installs the **RuvNet Brain** (an offline knowledge base over the rUv stack, powering the `search_ruvnet` MCP — a ~2 GB one-time download, prompted; skip with `--no-ruvnet-brain`), deploys the token-audit skill, merges the managed guidance blocks into the machine-wide guidance files (`~/.claude/CLAUDE.md`, plus `~/.codex/AGENTS.md` on codex machines), offers one-time MCP registration (user scope, with a tool-family picker), and — inside a repo — initializes the project: sanitized `ruflo init`, absolute memory-path pin, a **verified** store→disk write, statusline footer, and a background daemon with **local-only ($0) workers** (token-spending AI workers stay opt-in behind upstream's machine-wide budget). Project scope triggers on a `.git` directory in the current folder; without one it's skipped with a note. `--project` forces it anyway (e.g. a not-yet-`git init`-ed folder), `--minimal` skips it, `--yes` accepts all prompts (non-interactive), `--no-aqe` / `--no-ruvnet-brain` / `--no-security` disable those subsystems, and `--reconfigure` re-offers MCP registration. `--codex` enables + installs the Codex host during setup (dual-mode; both hosts then run at once), and `--primary-host claude\|codex` picks which host leads (codex implies `--codex`). |
| **status** | Per-subsystem ✓/⚠/✗ (versions, the kit's own version, **ruvnet-brain** (present + release drift, or "not installed"), natives (agentdb copies **and** ruflo's own memory runtime — the one `npx ruflo memory` loads — load-tested for a native better-sqlite3, not just the agentdb dirs), **memory-pin** (warns when `CLAUDE_FLOW_DB_PATH` points off the live DB), security, learning, aqe/RVF, **agentdb** (CLI present + coherent with ruflo's bundled version, or a store-skew warning), MCP, **hosts** (claude/codex/opencode version + install method; the Claude/Codex **primary** marked and failed when absent), **providers** (host wiring + aqe fallback chain, or "drifted"/claude-only default), **routing** (the persisted activity host+model policy; only Claude/Codex routes project into AQE), daemons, guidance-file blocks (`~/.claude/CLAUDE.md`, project `AGENTS.md`, and `~/.codex/AGENTS.md` on codex machines), statusline), each drift row naming what `sync` would do about it — plus a **health-history** line that flags regressions since the last sync (learning shrank, native slots dropped, drift/security backslid). |
| **sync** | The one convergence verb: upgrades first when a new release exists, then re-heals everything an upgrade wipes, then re-checks and reports. Included in that heal: it **installs any enabled frontier host** (claude/codex/opencode) that's entirely absent — never touching an external (mise/brew/native) install — and **re-applies provider wiring** (the `ENABLE_*` host env, OpenCode's native configuration, the aqe fallback chain, and ruflo API providers) whenever it has drifted — and, on a dual-host project, **seeds/heals the Claude/Codex default routing policy** (materializing eligible routes into agentic-qe's `agentOverrides`, e.g. after an aqe upgrade first makes it eligible). It also **installs/repins the standalone `agentdb` CLI** to ruflo's bundled version (keeping the shared cognitive store coherent) and appends a **health-history snapshot** so `status` can flag regressions across syncs. It also **re-runs the RuvNet Brain installer** to pull the latest release when the on-disk KB has drifted (or installs it if absent, when enabled). It also **self-updates the kit**: when a newer `@pacphi/agentic-kit` exists it installs it as the *last* step (the new code applies from the next `ak` run, never mid-sync). Prerelease installs (`4.0.0-alpha.*`) track the `next` npm dist-tag as well as `latest`, so alphas see their successors; stable installs only ever follow `latest`. `--no-upgrade` skips the self-update along with the package upgrades. |
| **dashboard** | Opens a read-only local web dashboard (`127.0.0.1:7431`, localhost-only, never detaches) with seven tabs: **Overview · Hosts & Routing · Providers · Runtime · Intelligence · Usage · Live**. The first five render `ak status` health and routing; Usage indexes local Claude/Codex transcripts on demand. Live groups work by project, then host-branded root sessions with nested agent/worker threads and independently evidenced provider/model metadata, and pairs an interactive agent/tool execution canvas with a rich, server-masked transcript stream. Active sessions can be followed live or reviewed with synchronized play/pause/seek; completed sessions remain available for bounded playback. Live contains no chat or control plane. Ruflo, agentic-qe, and dual-run stores are not auto-discovered; register each trusted structured JSONL file with repeatable `--live-source 'surface=path'` (`surface` is `ruflo`, `aqe`, or `dual-run`). The page is self-contained and offline-first (no internet fetches; local files and loopback subprocesses/endpoints only). A fresh **per-session token** is minted at startup and required by every `/api/*` route (`x-dash-token` header; the launch URL carries it in the `#` fragment, same contract as `ak admin` — ADR-0007, ADR-0014) — this page serves full transcript text, so it is gated the same way admin already gated GitHub/npm stats. See [Live Sessions](docs/LIVE-SESSIONS.md) for coverage, syntax, and privacy limits. **Auto-opens your browser** (`--no-open` for headless/SSH); `--port N` changes the port; tabs deep-link (`#live`) and persist. Stop with Ctrl-C. (Also available as `ak x dashboard`.) |
| **dashboard** | Opens a read-only local web dashboard (`127.0.0.1:7431`, localhost-only, never detaches) with seven tabs: **Overview · Hosts & Routing · Providers · Runtime · Intelligence · Usage · Live**. The first five render `ak status` health and routing; Usage indexes local Claude/Codex/OpenCode transcripts on demand and can display a separately cached OpenRouter account-analytics block. That block never changes local transcript/session/host totals; the dashboard itself never fetches it. Live groups work by project, then host-branded root sessions with nested agent/worker threads and independently evidenced provider/model metadata, and pairs an interactive agent/tool execution canvas with a rich, server-masked transcript stream. Active sessions can be followed live or reviewed with synchronized play/pause/seek; completed sessions remain available for bounded playback. Live contains no chat or control plane. Ruflo, agentic-qe, and dual-run stores are not auto-discovered; register each trusted structured JSONL file with repeatable `--live-source 'surface=path'` (`surface` is `ruflo`, `aqe`, or `dual-run`). The page is self-contained and offline-first (no internet fetches; local files and loopback subprocesses/endpoints only). A fresh **per-session token** is minted at startup and required by every `/api/*` route (`x-dash-token` header; the launch URL carries it in the `#` fragment, same contract as `ak admin` — ADR-0007, ADR-0014) — this page serves full transcript text, so it is gated the same way admin already gated GitHub/npm stats. See [Live Sessions](docs/LIVE-SESSIONS.md) for coverage, syntax, and privacy limits. **Auto-opens your browser** (`--no-open` for headless/SSH); `--port N` changes the port; tabs deep-link (`#live`) and persist. Stop with Ctrl-C. (Also available as `ak x dashboard`.) |
| **usage** | Reads provider-account analytics from local cache (`ak usage status`) or performs one explicit OpenRouter management-API refresh (`ak usage refresh openrouter`). Refresh requires `OPENROUTER_MANAGEMENT_KEY`, writes a credential-free mode-`0600` cache, and discards endpoint/user/key/session identifiers. `status` and dashboard reads make no network request. OpenRouter account rows have no grounded host/session/project correlation and are never merged into transcript totals. |
| **admin** | Opens the **maintainer admin** (`127.0.0.1:7432`, localhost-only, foreground) — the project-telemetry sibling of `dashboard`, with the same dark/light visual theme and persisted theme preference: unique repo visitors and cloners (GitHub traffic API, needs a push-access token via `GITHUB_TOKEN`/`GH_TOKEN`/`gh auth token` — panels degrade honestly without one), contributors and watchers, npm download momentum (last 7d vs prior 7d, sparklines — shown as trend only, never an absolute reach number, since mirrors/CI inflate the raw count), latest CI run status and open Dependabot alerts, a **"since you last looked"** delta strip over a local baseline, open issues/PRs from others (oldest first), and external humans ranked by recency (bots excluded). Access is gated by a **per-session token** carried in the URL fragment and sent header-only; the page makes **zero external fetches** (the server proxies GitHub/npm; your credential never reaches the page or the payload — ADR-0007, ADR-0013). Where `dashboard` is offline-first, `admin` does deliberate GitHub/npm egress — that contract split is why they're siblings, not tabs. `--port N`, `--no-open`; Ctrl-C stops. (Also available as `ak x admin`.) |
| **run** | **Canonical execution surface.** Executes the template vocabulary through host-neutral supervised adapters. It accepts an explicit OpenCode route (persisted or `--route`) alongside Claude/Codex; `--dry-run` prints the exact plan (with each worker's escalation ladder); `--escalate` advances a failed worker one rung of its route's ladder per attempt (bounded by the ladder; permission/consent and uncertain results are never escalated — ADR-0019). An OpenCode worker runs an isolated loopback server with ephemeral basic authentication, returns only normalized observed facts, and aborts instead of approving a permission request. `ak run` does not turn OpenCode into an AQE provider or primary host. |
| **dual** | **Deprecated compatibility wrapper** for existing Claude+Codex `claude-flow-codex` scripts, including its legacy escalation behavior. New execution work should use `ak run`; `ak dual` warns on stderr and will be removed before the stable release. |
Expand Down
7 changes: 6 additions & 1 deletion bin/agentic-kit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const PORCELAIN = Object.assign(Object.create(null), {
setup: () => import('../src/commands/setup.mjs'),
dashboard: () => import('../src/commands/x/dashboard.mjs'),
admin: () => import('../src/commands/x/admin.mjs'),
usage: () => import('../src/commands/usage.mjs'),
run: () => import('../src/commands/run.mjs'),
dual: () => import('../src/commands/dual.mjs'),
host: () => import('../src/commands/x/provider.mjs'),
Expand Down Expand Up @@ -50,6 +51,7 @@ Usage (ak = alias of agentic-kit):
ak sync converge to good: upgrade + heal + verify [--dry-run] [--no-upgrade]
ak dashboard open the local web dashboard (localhost; auto-opens browser) [--port N] [--no-open]
ak admin maintainer-only telemetry admin (localhost; GitHub/npm egress) [--port N] [--no-open]
ak usage inspect/refresh offline provider analytics [status|refresh openrouter]
ak run execute a host-neutral activity pipeline [template "task"] [--dry-run]
ak dual deprecated compatibility wrapper; use ak run for new work
ak host manage agent hosts, routing, and provider bindings [status|pick|refresh|off]
Expand Down Expand Up @@ -163,7 +165,10 @@ async function main() {
// effect of the network call — a real disk write that contradicts
// "--dry-run: prints the plan, changes nothing" even though it never
// touches an ak-managed path.
if (!values.json && !values['dry-run'] && cmd !== 'sync') {
// `ak usage status` promises a pure offline cache read. The explicit
// `refresh` subcommand owns its one named network request; neither form may
// silently add unrelated npm probes through the generic drift nudge.
if (!values.json && !values['dry-run'] && !['sync', 'usage'].includes(cmd)) {
try {
const { driftReport } = await import('../src/lib/versions.mjs');
for (const r of await driftReport()) {
Expand Down
8 changes: 8 additions & 0 deletions docs/PROVIDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ provider can therefore have independent `ollama-via-claude` and `ollama-via-code
OpenRouter is a provider behind a host, never automatically a third host. OpenCode is an opt-in
activity-routing host through `ak run`, while remaining ineligible as a primary host or AQE
provider. Its configured selector does not establish provider, billing, or vendor-diversity facts.

**Account analytics is separate from routing evidence.** `ak usage refresh openrouter` explicitly
fetches OpenRouter's supported 30-completed-UTC-day activity view with
`OPENROUTER_MANAGEMENT_KEY` and writes a private local cache. `ak usage status` and the dashboard
read only that cache. Because the management response has no local host/session/project/task
correlation key, its rows appear only as provider account analytics and never alter transcript
totals or prove which host executed a request.

This capability model is
[ADR-0016](adr/0016-capability-driven-integration-adapters.md) (Accepted); the controls below
implement it and remain backward compatible.
Expand Down
10 changes: 6 additions & 4 deletions docs/TRANSCRIPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,12 @@ Deep links: `#usage/<sessionId>` opens the Transcript view directly
| Delegation markers | `isSidechain` → `sidechain` flag | `thread_source: "subagent"` → excluded from aggregation, session kept visible |
| Session title | model-written `ai-title`, first-prompt fallback | first prompt clipped |

**Planned provider attribution:** OpenRouter-served sessions are invisible to the
scorecard today; ingesting them (discovery → parser → `kind` attribution →
pricing → by-host UI) is tracked as
[#59](https://github.com/pacphi/agentic-kit/issues/59).
**OpenRouter boundary:** the supported activity API has account-level date/model/provider/token/
request/spend rows, but no transcript or local-session correlation key. `ak usage refresh openrouter`
caches that account view explicitly; the dashboard renders it under separate provider analytics and
never treats it as a third transcript host. OpenRouter-served inference can still be attributed on a
real OpenCode transcript when OpenCode itself records provider/model/cost evidence. See ADR-0009 §9
and [#59](https://github.com/pacphi/agentic-kit/issues/59).

---

Expand Down
22 changes: 15 additions & 7 deletions docs/USAGE-SCORECARD-METRICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,25 @@ The parsers are `parseClaude` (`usage-index.mjs:427-510`) and `parseCodex`
(`usage-index.mjs:527-628`). Both are pure functions over the raw file bytes —
no network, no clock dependency beyond the transcript's own timestamps — so
every downstream number traces back to bytes already on the user's disk.
Nothing in this pipeline calls a provider API or a billing endpoint; **no
metric on this tab is ever a copy of an actual invoice.** That is the whole
reason every dollar figure is labelled "API-equivalent."
Nothing in this transcript pipeline calls a provider API or a billing endpoint; **no transcript
metric is ever a copy of an actual invoice.** That is the whole reason every transcript-derived
dollar figure is labelled "API-equivalent."

The current persisted field named `provider` identifies which host transcript parser produced a
session row; it is not sufficient evidence of the inference provider. The Proposed model in
[ADR-0016](adr/0016-capability-driven-integration-adapters.md) separates host, provider,
projection, observability source, and binding, with provenance attached per field. Until that
migration and issue #59's OpenRouter ingestion land, the Scorecard must not invent an OpenRouter
host, infer provider identity from a Claude/Codex transcript alone, or turn unknown billing into
subscription, metered, local, or `$0`.
projection, observability source, and binding, with provenance attached per field. The migration is
now implemented. The Scorecard must not invent an OpenRouter host, infer provider identity from a
Claude/Codex transcript alone, or turn unknown billing into subscription, metered, local, or `$0`.

OpenRouter account analytics is a separate evidence class. An explicit
`ak usage refresh openrouter` fetches the supported 30-completed-UTC-day management view into a
mode-`0600` local cache; normal dashboard reads remain offline. `/api/usage` exposes that cache only
as `providerAnalytics.openrouter`, never by adding it to `totals`, `byHost`, `byProvider`,
`byModel`, projects, categories, findings, or sessions. The upstream response has no host/session/
project/task correlation key, so no join is attempted. OpenRouter-credit usage and BYOK external
inference estimates also remain separate rather than being presented as one spend number. See
ADR-0009 §9.

---

Expand Down
Loading
Loading