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
25 changes: 15 additions & 10 deletions .agent-maintainer/dashboard-source-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
"exceptions": {
"frontend/dashboard/src/App.live-refresh.test.tsx": {
"group": "tests",
"nonblank": 543,
"physical": 575
"nonblank": 553,
"physical": 587
},
"frontend/dashboard/src/App.tsx": {
"group": "source",
"nonblank": 703,
"physical": 747
"nonblank": 708,
"physical": 751
},
"frontend/dashboard/src/api/client.ts": {
"group": "source",
"nonblank": 765,
"physical": 825
"nonblank": 769,
"physical": 829
},
"frontend/dashboard/src/api/types.ts": {
"group": "source",
"nonblank": 422,
"physical": 448
"nonblank": 431,
"physical": 458
},
"frontend/dashboard/src/app/zh-Hans/advancedPages.ts": {
"group": "source",
Expand Down Expand Up @@ -47,8 +47,8 @@
},
"frontend/dashboard/src/features/diagnostics/DiagnosticsPage.tsx": {
"group": "source",
"nonblank": 473,
"physical": 502
"nonblank": 480,
"physical": 510
},
"frontend/dashboard/src/features/diagnostics/diagnosticSnapshotCards.ts": {
"group": "source",
Expand All @@ -60,6 +60,11 @@
"nonblank": 639,
"physical": 683
},
"frontend/dashboard/src/features/threads/ThreadsPage.tsx": {
"group": "source",
"nonblank": 450,
"physical": 476
},
"frontend/dashboard/src/styles/context-evidence.css": {
"group": "styles",
"nonblank": 352,
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
cache-dependency-path: package-lock.json
- name: Install dashboard tooling
run: npm ci
- name: Install Chromium
run: npx playwright install --with-deps chromium
- name: Dashboard lint
run: npm run dashboard:lint
- name: Dashboard type check
Expand All @@ -39,6 +41,8 @@
run: npm run dashboard:governance
- name: Dashboard bundle budget
run: node scripts/check-dashboard-bundles.mjs
- name: Dashboard release candidate
run: npm run dashboard:release-candidate

hardening_routes:
name: Hardening / Dashboard route budget
Expand Down Expand Up @@ -84,7 +88,7 @@
python -m pip install --upgrade pip
python -m pip install ".[dev]"
python -m pip install --force-reinstall --no-deps \
"agent-maintainer @ git+https://github.com/douglasmonsky/agent-maintainer.git@1129570a725256dcc5f04bee33cdc32c35af911d"

Check warning on line 91 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / Hardening / Repository policy

91:121 [line-length] line too long (131 > 120 characters)
- name: Agent Maintainer guidance drift
run: python -m agent_maintainer guidance --check
- name: Whole-source Pyright
Expand Down Expand Up @@ -268,6 +272,15 @@
- uses: actions/setup-python@v6
with:
python-version: "3.14"
- uses: actions/setup-node@v6.4.0
with:
node-version: "22"
cache: npm
cache-dependency-path: package-lock.json
- name: Install dashboard tooling
run: npm ci
- name: Verify packaged dashboard assets
run: npm run dashboard:assets:check
- name: Install build tooling
run: |
python -m pip install --upgrade pip
Expand All @@ -278,3 +291,5 @@
run: python -m twine check dist/*
- name: Verify built wheel
run: python scripts/check_release.py --dist
- name: Smoke installed wheel
run: python scripts/smoke_installed_package.py
1 change: 1 addition & 0 deletions config/vulture-whitelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
_._handle_open_investigator
_._handle_health
_._handle_status
_._handle_readiness
_._handle_dedupe_diagnostics
_._handle_calls
_._handle_call
Expand Down
2 changes: 1 addition & 1 deletion dependency-cruiser.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = {
from: { path: '^src/features/' },
to: {
path: '^src/app/',
pathNot: '^src/app/(i18nContext|shellUrl)\\.tsx?$'
pathNot: '^src/app/(dashboardTargets|i18nContext|shellUrl)\\.tsx?$'
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Shareable outputs remain aggregate-first and must omit indexed/raw content unles
- `context.py` is the normal path for explicit selected-call raw context. It reads one selected source file on demand, applies redaction and size limits, omits tool output by default, and keeps full serialized group analysis explicit.
- `diagnostic_snapshots.py` owns persisted diagnostic snapshot refresh/load orchestration. Snapshot modules should stay synthetic-testable and avoid raw transcript persistence in aggregate diagnostic facts.
- `dashboard.py` builds aggregate-first static dashboard payloads and writes HTML/assets. `server.py` adds localhost refresh, compatibility `/api/usage`, SQL-backed live API slices, and explicit lazy context loading.
- `frontend/dashboard/` owns the React dashboard. It should render server/API payloads rather than becoming an independent source of usage calculations.
- `frontend/dashboard/` owns the React dashboard. The packaged React HTML embeds only a database-free boot payload (authentication, localization, and data-scope defaults), then hydrates aggregate data through the localhost APIs. It should render server/API payloads rather than becoming an independent source of usage calculations.
- `plugin_installer.py`, `.mcp.json`, `skills/`, `src/codex_usage_tracker/plugin_data/skills/`, and `scripts/check_release.py` own install and packaging behavior.
- `scripts/benchmark_synthetic_history.py` owns broad generated large-history query timing checks. `scripts/benchmark_dashboard_routes.py` owns deterministic cold/warm route budgets for the query pipeline. Both must stay synthetic-only and must not read real Codex logs.

Expand Down
32 changes: 32 additions & 0 deletions docs/cli-json-schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Tracked schema ids:
| `codex-usage-tracker-dashboard-v1` | CLI `dashboard --json`, MCP `generate_usage_dashboard()` |
| `codex-usage-tracker-open-dashboard-v1` | CLI `open-dashboard --json` |
| `codex-usage-tracker-serve-dashboard-v1` | CLI `serve-dashboard --json` startup payload, including preferred React `dashboard_url` and legacy `legacy_dashboard_url` fallback |
| `codex-usage-tracker-dashboard-target-v1` | Privacy-safe agent/dashboard handoff with a cataloged view, normalized reviewed selectors, and deterministic React URL |
| `codex-usage-tracker-pricing-coverage-v1` | CLI `pricing-coverage --json`, MCP `usage_pricing_coverage(response_format="json")` |
| `codex-usage-tracker-source-coverage-v1` | CLI `source-coverage --json`, MCP `usage_source_coverage(response_format="json")` |
| `codex-usage-tracker-content-search-v1` | MCP `usage_content_search(...)`; explicit local content-index search, may include indexed snippets |
Expand All @@ -112,6 +113,37 @@ Tracked schema ids:
| `codex-usage-tracker-init-projects-v1` | CLI `init-projects --json` |
| `codex-usage-tracker-support-bundle-v1` | CLI `support-bundle --json` |

## Dashboard Targets

`codex-usage-tracker-dashboard-target-v1` is the privacy-safe handoff contract
for agent-created dashboard links and copied prompts. It accepts only cataloged
views, canonical route identifiers, the normalized `active` or `all` history
scope, and filters reviewed for that destination. Unknown search fields, API
tokens, raw or indexed text, raw-context controls, and local paths are omitted.
Query parameters are sorted so equivalent targets serialize identically.
The dashboard route catalog keeps the full supported deep-link parameter set
separate from the smaller handoff-safe set used by this contract.

```json
{"schema":"codex-usage-tracker-dashboard-target-v1","view":"call","record_id":"record-123","filters":{},"history":"active","privacy_mode":"strict","relative_url":"/react-dashboard.html?record=record-123&view=call","absolute_url":null,"fallback_instruction":"codex-usage-tracker serve-dashboard --open"}
```

`absolute_url` is populated only when a healthy persistent dashboard service or
an explicitly active loopback `serve-dashboard` origin is known. Otherwise,
clients use `relative_url` and show `fallback_instruction`. `record_id`,
`thread_key`, `diagnostic_fact`, and `limit_evidence` are optional because each
is valid only for its corresponding destination.
Canonical identifiers follow their producer formats: record ids are lowercase
SHA-256 hex (with `record-<digits>` reserved for documented synthetic examples),
session thread keys contain a UUID, diagnostic keys contain a cataloged fact
type plus the parser's structured fact name, and limit evidence is `stable` or
`decreased`. Normal mode may carry the parser's explicit `thread:<display name>`
key; redacted and strict modes reject that label-bearing form and require a
`session:<uuid>` key. Reports accept only the verified dashboard report ids.
Other string filters use documented enums, while numeric filters use per-key
ranges and fixed non-scientific serialization. Boolean query values serialize
as lowercase `true` or `false` in both the Python and TypeScript builders.

## Shared Error Codes

CLI failures print a stable code in stderr:
Expand Down
24 changes: 24 additions & 0 deletions docs/dashboard-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,30 @@ the URL.
- Evidence rows open the same Call Investigator used by Calls, Threads, Limits,
and Diagnostics.

## Release-Candidate Route And Readiness Evidence

Release N keeps the existing primary navigation unchanged. The Advanced
setting stores `Show experimental dashboard features` for this browser origin,
but the discoverability change is reserved for Release N+1. Direct links remain
valid throughout the transition, Diagnostics stays visible, and every
experimental or transitioning workspace carries an explicit maturity banner.

The synthetic screenshot manifest covers each lifecycle category:

- stable primary routes: Overview and Calls
- experimental routes: Investigate, Compression Lab, and always-visible
Diagnostics
- transitioning routes: Cache And Context Lab and Reports
- contextual routes: Call Investigator, including its Calls or Threads return
target

It also captures the `ready`, `restart-required`, `unavailable`, and `unknown`
analysis-readiness states. Every state keeps recovery guidance and the manual
fallback list for Calls, Threads, Limits, Diagnostics, and Advanced experimental
controls visible. Run `npm run dashboard:screenshots` only against the documented
synthetic fixture server; never use a dashboard containing real session data for
documentation images.

## Settings View

`Settings` is a read-only explanation of the authoritative local configuration,
Expand Down
7 changes: 7 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,13 @@ record independent cold samples and warm hits. Thresholds live in
`config/dashboard-route-budgets.json`; change them only with repeatable synthetic
evidence. The benchmark never reads local Codex logs.

The packaged React HTML response is deliberately database-free: it embeds only
the boot token, localization, and data-scope defaults, then the browser hydrates
through `/api/usage`. The focused server regression test injects a one-second
aggregate-shell delay and requires the HTML response in under 500 ms, preventing
whole-history queries or MCP readiness checks from returning to the first-byte
path.

## Release Checklist

Use a release branch only for version/changelog/pinning/publish prep. It should include release-specific changes such as version bumps, `CHANGELOG.md`, install/version wording, runtime package pins, publish workflow tweaks, release notes, and final smoke-test fixes. It should not include unrelated features.
Expand Down
6 changes: 6 additions & 0 deletions docs/first-five-minutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ codex-usage-tracker install-plugin

Then restart Codex and start a fresh Codex session.

A healthy local installation or dashboard service does not prove that the current
Codex task loaded MCP tools. Check the tools exposed to the current task. When an MCP
result includes a dashboard evidence target, open its absolute localhost URL when
present; otherwise use the relative target only after following its launch guidance
(`codex-usage-tracker serve-dashboard --open`).

## What To Attach To Issues

For public GitHub issues, prefer a strict support bundle:
Expand Down
31 changes: 31 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,37 @@ Dashboard-shaped MCP tools return JSON dictionaries that reuse the same aggregat
- `usage_report_pack(...)` mirrors `/api/reports/pack`.
- `usage_dashboard_recommendations(...)` returns dashboard recommendation payloads.

Selected MCP results include an additive `dashboard_target` without changing their
existing schema name, fields, row order, filters, or query semantics. `usage_status`
links to Overview; Calls rows and call detail link to Call Investigator; Threads rows
link only when their producer supplied a canonical `thread_key`; and canonical
`usage_investigate` evidence rows link to matching Call Investigator or Threads
evidence. Each finding inherits a copy of its first successfully linked evidence
target; findings do not encode an ordinal Investigator route. Thread annotation never
substitutes a display name when `thread_key` is absent. If a canonical identifier is
not valid for the selected privacy mode, that row simply omits the target.

Targets also preserve the MCP query's history scope. Calls, Threads, status, and
investigation results requested with `include_archived=true` emit `history="all"` and
an explicit `history=all` URL parameter. Active-only requests emit `history="active"`.
Call detail uses a reliable producer `is_archived` flag, when present, to keep an
archived selected record reachable in all-history scope.

Each tool checks the persistent dashboard service once. A reachable service produces
a loopback `absolute_url`; an unreachable service or a local status-inspection error
keeps the MCP result successful and returns a relative target with
`codex-usage-tracker serve-dashboard --open` fallback guidance. These links are
navigation metadata only: target presence does not upgrade conversational readiness,
index freshness, MCP discovery, current-task tool exposure, or access to raw context.
Use the existing readiness and recovery fields from `usage_status` for those claims.

Clients should present **Open evidence** with `dashboard_target.absolute_url` when
that value is present. Otherwise they should show `relative_url` together with the
exact `fallback_instruction`; they must not invent a host or infer that a dashboard
service is running. A target, installed skill, or healthy persistent service never
proves task-level MCP tool exposure. Inspect the current task's tool inventory before
claiming MCP availability.

`refresh_usage_index()` indexes aggregate usage rows plus the local content index by default. Use `refresh_usage_index(aggregate_only=True)` when the user wants the older aggregate-only SQLite posture. Use `include_archived=True` only when the user explicitly wants all history; the dashboard defaults to active sessions so older work does not inflate current usage.

## Allowance Intelligence
Expand Down
Loading
Loading