metergraph-cli 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +60 -11
  2. package/assets/skill/SKILL.md +52 -3
  3. package/assets/skill/manifest.json +3 -3
  4. package/assets/skills/manifest.json +13 -13
  5. package/assets/skills/metergraph-analyze/SKILL.md +62 -4
  6. package/assets/skills/metergraph-investigate/SKILL.md +222 -35
  7. package/assets/skills/metergraph-onboarding/SKILL.md +7 -0
  8. package/assets/skills/metergraph-report/SKILL.md +19 -2
  9. package/bin/metergraph.js +1 -1
  10. package/package.json +1 -1
  11. package/src/agent-key.js +160 -0
  12. package/src/approval-handoff.js +5 -0
  13. package/src/args.js +572 -17
  14. package/src/auth-browser.js +5 -19
  15. package/src/auth-callback.js +24 -15
  16. package/src/auth-login.js +55 -12
  17. package/src/auth-oauth.js +77 -7
  18. package/src/callback-page.js +58 -0
  19. package/src/cli.js +190 -45
  20. package/src/constants.js +73 -3
  21. package/src/environment.js +169 -0
  22. package/src/experiments-contract.js +462 -0
  23. package/src/experiments-output.js +189 -0
  24. package/src/experiments.js +397 -0
  25. package/src/origin.js +6 -0
  26. package/src/output.js +437 -131
  27. package/src/pricing-args.js +163 -0
  28. package/src/pricing-output.js +206 -0
  29. package/src/pricing-reference.js +195 -0
  30. package/src/pricing.js +307 -0
  31. package/src/read-contract.js +976 -16
  32. package/src/read-output.js +449 -30
  33. package/src/read.js +312 -60
  34. package/src/setup-deployment.js +11 -3
  35. package/src/setup-interactive.js +341 -0
  36. package/src/setup-refusal.js +172 -0
  37. package/src/setup-state.js +4 -2
  38. package/src/setup.js +227 -53
  39. package/src/skill-bundle.js +2 -2
  40. package/src/style.js +101 -0
  41. package/src/transport.js +13 -7
  42. package/src/usage-aggregates.js +197 -0
  43. package/src/verify-output.js +21 -11
package/README.md CHANGED
@@ -21,7 +21,8 @@ Published on npm as `latest`. See the [changelog](https://github.com/metergraph/
21
21
  ## Quickstart
22
22
 
23
23
  **1. Set up the project.** Run this in your project directory. It opens your browser to
24
- sign in and choose a workspace, asks a workspace member to approve an ingest-only key,
24
+ sign in and choose a workspace, asks a workspace member to approve an ingest-only key
25
+ (on the same page as sign in, where the service supports it),
25
26
  writes `METERGRAPH_APP_TOKEN` and `METERGRAPH_INGEST_URL` to a private `.env`, and
26
27
  installs the skill for your coding agent.
27
28
 
@@ -47,11 +48,12 @@ Then read what Metergraph has recorded:
47
48
 
48
49
  ```sh
49
50
  npx --yes metergraph-cli@latest usage --days 7 # calls, errors, cost and tokens per route per day
51
+ npx --yes metergraph-cli@latest usage --group-by route --today # most expensive route today (UTC)
50
52
  npx --yes metergraph-cli@latest traces --limit 20 # one page of trace metadata
51
53
  ```
52
54
 
53
55
  To install it globally instead, run `npm install -g metergraph-cli@latest`. The command is
54
- `metergraph`. Pin an exact version, such as `metergraph-cli@0.2.1`, when a
56
+ `metergraph`. Pin an exact version, such as `metergraph-cli@0.2.3`, when a
55
57
  script must not change with the `latest` tag. Previews use the `next` tag.
56
58
 
57
59
  ## Requirements
@@ -67,8 +69,11 @@ Sign in needs a service that offers Metadata-only CLI grants and grant revocatio
67
69
  service without them is reported as unsupported, and the CLI never falls back to
68
70
  broader access. `setup` also needs the deployment's ingest bootstrap API and approval by
69
71
  a workspace member. Sign in needs a browser on the same machine. From SSH sessions,
70
- cloud development environments and CI, `login` and `setup` hand off to a local machine
71
- instead (exit 6).
72
+ cloud development environments and CI, `login` and `setup` exit 6 with a structured
73
+ `next_action`: a person creates a coding-agent key with Metadata access on the Keys
74
+ page and saves it as the secret `METERGRAPH_AGENT_TOKEN`, and the read commands use it
75
+ after verifying the origin, workspace, scope and capabilities. Ingest setup still runs
76
+ on a local machine.
72
77
 
73
78
  ## Using it with a coding agent
74
79
 
@@ -104,7 +109,11 @@ The CLI is built to be run by Codex, Claude Code and Cursor as well as by people
104
109
  `schema_version`, `command`, `ok`, `outcome`, `exit_code`, `data` and `error`.
105
110
  Failures carry a fixed `error.reason` and, where useful, a `data.next_action` that
106
111
  tells the agent what to do next.
107
- - **No hidden prompts.** No command reads stdin or asks a question. `--no-browser`
112
+ - **No hidden prompts.** Only `setup` asks questions, and only a person at a terminal:
113
+ with stdin and stdout both terminals, no `--json` and no `CI`, it asks for what its
114
+ flags leave out and prints the full command before running it. Otherwise no command
115
+ reads stdin or asks a question, so an agent or script gets the same flag errors as
116
+ before. `--no-browser`
108
117
  prints the sign in URL for a person to open instead of launching a browser. With
109
118
  `--json`, a step that needs approval exits within seconds with 18
110
119
  `action_required` and `data.next_action` set to
@@ -130,14 +139,17 @@ Suggested `AGENTS.md` or `CLAUDE.md` lines for a project that uses Metergraph:
130
139
 
131
140
  | Command | What it does | Network |
132
141
  | --- | --- | --- |
142
+ | `pricing models`, `pricing lookup`, `pricing calculate` (`cost` alias) | Discover models, look up rates and calculate costs through the public API without sign in | Yes |
143
+ | `pricing market`, `pricing history` | Current public market board; historical terminal/HTML charts require the local reference adapter ([guide](docs/pricing.md)) | Yes |
133
144
  | `setup` | Sign in, choose a workspace, write the ingest key to `.env`, record the repository, install the skill | Yes |
134
145
  | `verify` | Confirm that one exact trace, by trace ID or request ID, reached the workspace | Yes |
135
- | `usage` | Daily calls, errors, cost, tokens and latency per route | Yes |
136
- | `traces` | One page of trace metadata, with a cursor for the next page | Yes |
146
+ | `usage` | Daily calls, errors, cost, tokens and latency per route, or cost grouped by provider, model, route or UTC day with exact filters, rankings and a prior-period comparison; filtered by exact metadata or grouped by one metadata key | Yes |
147
+ | `traces` | One page of trace metadata, filtered by route, status or exact metadata, with a cursor for the next page | Yes |
137
148
  | `routes` | Routes with call counts and evaluation contract status | Yes |
138
149
  | `status` | Whether the project is signed in, and to which workspace | Yes |
139
150
  | `context` | Workspace details and retention | Yes |
140
151
  | `capabilities` | What the workspace makes available to this project | Yes |
152
+ | `experiments list`, `estimate`, `start`, `get` | Replay a workload's recent production calls on 1 to 3 other models or settings: price it, start it, poll it and read cost, latency and output statistics per treatment next to production | Yes |
141
153
  | `login`, `logout` | Sign a project in or out without the rest of `setup` | Yes |
142
154
  | `doctor` | Check that a service is reachable, healthy and supported, without credentials | Yes |
143
155
  | `skill install`, `skill update` | Install or update the Metergraph skill for one agent | No |
@@ -147,10 +159,37 @@ Suggested `AGENTS.md` or `CLAUDE.md` lines for a project that uses Metergraph:
147
159
  [CLI reference](https://github.com/metergraph/cli/blob/main/docs/reference.md) covers every option, what each command reads and
148
160
  writes, and full JSON examples.
149
161
 
162
+ ## Public pricing preview
163
+
164
+ ```sh
165
+ metergraph pricing models --limit 10
166
+ metergraph pricing lookup --model gpt-5 --provider openai --region global --json
167
+ metergraph pricing calculate --model claude-sonnet-5 --provider anthropic \
168
+ --input-tokens 1000 --cache-read-tokens 800 --output-tokens 200
169
+ metergraph pricing market --channel openai-api --limit 5
170
+ ```
171
+
172
+ These commands use the public Pricing API without an account or workspace.
173
+ `cost` is an alias for `calculate`. Inspect status and missing dimensions: an HTTP
174
+ success may still be partial or unpriced. The current market board uses discovery
175
+ plus bounded lookups; it does not invent historical prices or returns.
176
+
177
+ The stock-style history visualization is preserved in explicit local reference mode:
178
+
179
+ ```sh
180
+ metergraph pricing history --model openai/gpt-5.6-terra --channel openai-api \
181
+ --api reference --url http://127.0.0.1:8765 --format html > history.html
182
+ ```
183
+
184
+ See [the pricing guide](docs/pricing.md) for the API contract, input semantics and
185
+ local adapter. The public service does not document a history endpoint. This is
186
+ an exploratory preview; supplier pricing coverage and storage claims are not
187
+ independently verified by these command tests.
188
+
150
189
  ## Exit codes
151
190
 
152
191
  Exit codes are stable. Changing one is a breaking change. Codes 10 to 18 are not in
153
- `0.1.0`.
192
+ `0.1.0`, and codes 19 and 20 are not in `0.2.2` or earlier.
154
193
 
155
194
  | Code | Outcome | Meaning |
156
195
  | --- | --- | --- |
@@ -170,9 +209,11 @@ Exit codes are stable. Changing one is a breaking change. Codes 10 to 18 are not
170
209
  | 13 | `revocation_unconfirmed` | Local credentials were removed, but the service did not confirm that the grant was revoked. |
171
210
  | 14 | `capability_unavailable` | The service does not make this read available to the project's Metadata grant. No data was read. |
172
211
  | 15 | `permission_denied` | The service refused this read for the signed in grant, for example for a missing scope or permission. |
173
- | 16 | `rate_limited` | The service asked the CLI to slow down. Nothing was retried. Try again later. |
212
+ | 16 | `rate_limited` | The service asked the CLI to slow down. Try again later. Only setup retries, after a short Retry-After, to keep its approval. |
174
213
  | 17 | `cancelled` | A read command was interrupted before it finished. Read commands never change workspace configuration or telemetry. |
175
214
  | 18 | `action_required` | A person must act before the command can finish; `data.next_action` says what to do. `login` and `setup` with `--json --no-browser` exit with this as soon as an approval URL exists (`next_action.kind: "open_url"`), while a background process waits for the approval until `--timeout-ms`. After approval, run the same command again to continue. |
215
+ | 19 | `refused` | The service refused an experiment for a stated reason, such as its budget, the daily cap, experiments already running or a model it cannot price; `data.refusal` says which. Nothing was started. |
216
+ | 20 | `unconfirmed` | An `experiments start` request reached the service but its result was not confirmed (a timeout, a dropped connection, a server error or an answer that does not match the contract), so an experiment may exist and may run. List experiments before starting again; each start creates one. |
176
217
 
177
218
  ## Security and privacy
178
219
 
@@ -180,7 +221,11 @@ Exit codes are stable. Changing one is a breaking change. Codes 10 to 18 are not
180
221
  only to the Metergraph origin you point it at.
181
222
  - **Least access.** Sign in grants only the Metadata scope, `agent:metadata`. The CLI
182
223
  never requests Debug or Replay access, never falls back to broader access, and never
183
- reads retained prompts, responses or other content. It calls no model provider.
224
+ reads retained prompts, responses or other content. It calls no model provider. The one
225
+ exception is `experiments start`: it uses a coding-agent key a workspace owner created
226
+ with exactly Debug access and Allow analysis starts, refuses a key with any other scope,
227
+ and sends it only with that one start request. The service then replays the sampled calls on the
228
+ chosen providers within its own budget. Every other command refuses such a key.
184
229
  - **Credentials.** The sign in grant is stored per user in `~/.config/metergraph`
185
230
  (`AppData\Roaming\Metergraph` on Windows), as owner-only files on Linux and macOS and
186
231
  encrypted with DPAPI on Windows. The ingest key goes only into the project's private
@@ -189,7 +234,11 @@ Exit codes are stable. Changing one is a breaking change. Codes 10 to 18 are not
189
234
  - **Files it writes in your project:** `.env` (from `setup`), the skill file, and
190
235
  secret-free state under `.metergraph/` that is safe to commit. The skill installer
191
236
  never replaces a file it did not write and has no force option.
192
- - **Network.** Only `GET` requests to fixed paths for reads, no redirects followed,
237
+ - **Public pricing.** Pricing reads send no credentials and return public catalog data.
238
+ `--format html` emits a standalone document; it does not launch a browser.
239
+ - **Network.** Workspace reads use `GET`; experiments estimate and start use `POST`.
240
+ Public pricing lookup/calculation use unauthenticated `POST` with metadata-only
241
+ inputs. Fixed paths, no redirects followed,
193
242
  bounded response sizes and fixed timeouts. Mistyped arguments are never echoed, since
194
243
  they may hold a secret. `--help`, `--version` and `skill` make no network requests.
195
244
 
@@ -57,6 +57,53 @@ pass the same `--workspace` UUID each time, and give each repository its own
57
57
  identity. The SDK warning that repository identity is not configured does not
58
58
  stop capture.
59
59
 
60
+ ## Pick the CLI path for where the agent runs
61
+
62
+ Check `metergraph --help` first. If the read commands' help lists
63
+ `--agent-token-file`, the CLI also accepts a coding-agent key with Metadata
64
+ access from the `METERGRAPH_AGENT_TOKEN` environment variable. Use one sequence:
65
+
66
+ | Where the agent runs | Sequence |
67
+ |---|---|
68
+ | Local shell, hosted, new workspace | `metergraph setup --runtime local --client <client> --json --no-browser`, rerun after each approval, then `metergraph status --json`. Add `--signup` for a person with no hosted account. |
69
+ | Local shell, hosted, existing workspace | `metergraph login --runtime local --workspace <uuid> --json --no-browser`, then `metergraph status --json`. |
70
+ | Local shell, customer-local or customer-owned AWS | `metergraph setup --runtime local --client <client> --deployment customer-local` (or `byoc`) `--url <origin> --workspace <uuid> --json --no-browser`. Follow its `next_action` for each prerequisite, and add `--confirm-prerequisites` only after the person confirms them. Then `metergraph status --json`. Without `--deployment`, setup and login go to the hosted service. |
71
+ | Local container (Docker, local dev container) | As a local shell. If the browser cannot reach the container's sign in callback, use the key sequence below. |
72
+ | SSH, Codespaces, Gitpod, Cloud Shell, remote dev container, CI: hosted, customer-local or customer-owned AWS | The person signs in (or signs up, on the hosted service only) on their own device, opens the Keys page of the deployment and workspace the agent should read, creates a coding-agent key with Metadata access, and saves it in this environment's secret settings, or as a CI secret, named `METERGRAPH_AGENT_TOKEN`. Then run `metergraph status --json` and `metergraph usage --json`. Add `--workspace <uuid>` to make a key for another workspace fail. For a non-hosted deployment, pass `--url <origin>` (or set `METERGRAPH_URL`) with its address. |
73
+ | Any runtime: open-source self-hosted server | The CLI read commands do not support the open-source server; use its MCP route (below). There are no accounts and no Keys page: the operator gives the person one of the server's `MG_AGENT_TOKENS` values for the client's private MCP settings. |
74
+ | Has a Metadata key but no saved sign in | The same key sequence. If the project has a `.metergraph/project.json`, it pins the origin and workspace the key must match. |
75
+
76
+ `.metergraph/project.json` names the deployment origin and workspace ID. In a
77
+ public repository, keep it untracked (for example in `.gitignore`) and do not
78
+ commit it: that would publish the workspace ID. In CI for a public repository,
79
+ the read commands' JSON includes workspace IDs and per-route usage: write it to a file or
80
+ a masked step instead of the public job log, and print only what the person
81
+ needs.
82
+
83
+ Before answering a cost question from the CLI, confirm the workspace and what
84
+ it offers: `metergraph status --json` (the verified workspace must be the one
85
+ the person means) and `metergraph capabilities --json`. Then run the smallest
86
+ bounded `usage` read that answers it. Grouped usage needs a CLI that has it:
87
+ run `metergraph help usage` first, and use `--group-by` only when that help
88
+ lists it (for example `metergraph usage --group-by route --today --json` for
89
+ the most expensive route today). An older CLI has only
90
+ `metergraph usage --days N --json` (cost per route and day); say that grouping
91
+ by provider, model or metadata needs a newer CLI or the
92
+ `metergraph_get_usage_aggregates` tool, and do not invent flags. Grouped
93
+ usage windows are UTC days; plain `usage --days N` is the last N x 24 hours,
94
+ rolling. `metergraph-investigate` covers the rest. A deployment without grouped
95
+ usage exits 14 with a `next_action` that names the read it supports.
96
+
97
+ When `login`, `setup` or a read cannot finish where it runs, it prints
98
+ `data.next_action`. Follow it: `use_agent_key` lists the person's steps and the
99
+ commands to run afterwards; `replace_agent_key`, `use_metadata_only_key` and
100
+ `use_workspace_key` mean the key was refused, was broader than Metadata, or
101
+ belongs to another workspace. Never ask the person to paste the key into chat or
102
+ a command, and never put it in a project file. Ingest setup cannot run over SSH,
103
+ in a cloud workspace or in CI; it runs on the person's machine. The Metadata key
104
+ is separate from the application's ingest key and never replaces it. Debug and
105
+ Replay keys are refused by the CLI, not reduced.
106
+
60
107
  ## Route honestly
61
108
 
62
109
  | Client and runtime | Hosted | Customer-local bundle | Customer AWS | Open source self-hosted |
@@ -103,10 +150,12 @@ rather than improvising the analysis steps.
103
150
 
104
151
  ## When already connected: bounded investigation
105
152
 
106
- 1. Call `metergraph_get_workspace_context` and `metergraph_get_capabilities` first. Verify the intended workspace, deployment profile, available tools, required scopes and privacy classes. Stop on wrong workspace, unavailable capabilities or failed authorization.
107
- 2. Confirm the question, route and explicit time window. Choose the smallest available tool: bounded usage/route metadata for aggregate questions, incidents for known anomalies, or `metergraph_query_traces` with a small limit (start with 1) for a failed/anomalous trace. Follow cursors only within the agreed bound. Never request generic SQL or unbounded data.
153
+ Read through the `metergraph` CLI first when it is installed and can read the workspace: it returns the same Metadata evidence as the MCP tools in far fewer tokens. Use the MCP tools for what the CLI does not cover (incidents, ingestion health, reports, retained content and replay) and in clients with no shell. Being connected means either one; stop for setup only when neither can read the workspace.
154
+
155
+ 1. Confirm the workspace and what it offers. With the CLI: `metergraph status --json` (continue when `data.authenticated` is true and `data.workspace.match` is true. When `match` is null because no workspace was pinned, name `data.workspace.actual` and continue only after the person confirms it is the one they mean. Otherwise follow `data.next_action`) and `metergraph capabilities --json`. With MCP: `metergraph_get_workspace_context`, then `metergraph_get_capabilities`. Verify the intended workspace, deployment profile, available reads, required scopes and privacy classes. A wrong workspace or failed authorization on one path is a reason to use the other path when it can read the intended workspace; stop when neither can, or when the capability the question needs is unavailable.
156
+ 2. Confirm the question, route and explicit UTC time window. Choose the smallest available read, and always pass `--json` to the CLI: grouped usage (`metergraph usage --group-by ... --json`, or `metergraph_get_usage_aggregates`) or `metergraph usage --days N --json` / route metadata for aggregate questions, `metergraph traces --days N --limit 1 --json` with `--route` when known and `--status error` only for a failed trace (or `metergraph_query_traces` with a small limit, which also takes an exact trace or request ID) for a failed or anomalous trace, and the incidents tool for known anomalies. Check that `metergraph help <command>` lists an option before using it, and use the matching MCP tool when it does not. Follow cursors only within the agreed bound. Never request generic SQL or unbounded data.
108
157
  3. Start with metadata. Retained-content debugging and report evidence are separate content-bearing tools; confirm the user's content intent and capability before calling them. Replay is a separate scope and can send data to a provider and spend money. Obtain explicit bounded execution/data-egress authority before any replay. Read access grants no eval-write, analysis-run or production-mutation authority.
109
- 4. Explain the failure or anomaly using only returned evidence. Cite workspace, time window, provenance, trace/report IDs, completeness/coverage, warnings and working app links when returned. Do not fabricate links. Distinguish no data, incomplete evidence, unavailable capability, classification pending, stale/mismatched identity, failed analysis and missing report. An empty result alone does not prove absence of traffic.
158
+ 4. Explain the failure or anomaly using only returned evidence. Cite workspace, time window, provenance, trace/report IDs, completeness/coverage, warnings and working app links when returned. Do not fabricate links. Distinguish no data, incomplete evidence, unavailable capability, classification pending, stale/mismatched identity, failed analysis and missing report. An empty result alone does not prove absence of traffic. Never conclude that a commit, deploy or config change did or did not change cost from source code or a git diff alone; a diff is a hypothesis until bounded usage reads for the same route before and after the change reached production agree, with completeness and warnings cited.
110
159
  5. An optional approved replay must be eligible, bounded and non-persistent. Do not claim that it changed production telemetry or fixed the application. Refuse autonomous dashboard mutations or production configuration changes.
111
160
 
112
161
  For an empty workspace, use https://www.metergraph.dev/docs/agents/instrument-a-repo/. If `metergraph setup` already ran in this project, it delivered the ingest credential: the project's `.env` holds `METERGRAPH_APP_TOKEN` and `METERGRAPH_INGEST_URL`. Use them; do not ask for or create another key, and never print their values. The SDK reads the process environment, not `.env`, so load it when you run the application (for example `set -a; . ./.env; set +a`, python-dotenv or `node --env-file=.env`). Otherwise confirm the ingestion destination and obtain a separate ingest credential securely. Ask before running anything that calls a paid model provider, and do not initiate provider calls or paid work merely to validate setup. Confirm the exact trace with `metergraph verify`; if the CLI is not installed, or `metergraph --version` lacks `verify`, use `npx --yes metergraph-cli@latest verify`. Ingestion accepted, processed, retained content, classification readiness and analysis readiness are distinct states. Label synthetic/demo fixtures; they do not prove a first real application trace.
@@ -3,7 +3,7 @@
3
3
  "name": "metergraph",
4
4
  "file": "SKILL.md",
5
5
  "source_url": "https://www.metergraph.dev/SKILL.md",
6
- "sha256": "d527a67efc42a55245b9c2c8fd2687c1f31f553e154a6242d0f31466993e314e",
7
- "size": 13666,
8
- "revision": "sha256-d527a67efc42"
6
+ "sha256": "ebf784673eff0280d85974504f93c683a1dabfb54156c9d27e091131462e9d5f",
7
+ "size": 19764,
8
+ "revision": "sha256-ebf784673eff"
9
9
  }
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "manifest_version": 1,
3
3
  "repository": "metergraph/skills",
4
- "commit": "839da0fc82c331598db78022610620390a81703a",
4
+ "commit": "39411ce1eceed6929ab3e5c4c20649f02e8eabb4",
5
5
  "skills": [
6
6
  {
7
7
  "name": "metergraph-analyze",
8
- "sha256": "e8bf1debf62aa7d33d3dd363e5d95d8f781e8ca23cde4619b5bb4133dd47a7a5",
9
- "size": 9360,
10
- "revision": "sha256-e8bf1debf62a"
8
+ "sha256": "c45756ad1d33a360c7c845ca299d8c1ab1e2b8162865f635bc25c78358c2a1e6",
9
+ "size": 12148,
10
+ "revision": "sha256-c45756ad1d33"
11
11
  },
12
12
  {
13
13
  "name": "metergraph-candidates",
@@ -23,9 +23,9 @@
23
23
  },
24
24
  {
25
25
  "name": "metergraph-investigate",
26
- "sha256": "775dbe7ca1100b17638d0905302ef1324694a60b90372c6c3df7b598a8f70438",
27
- "size": 6091,
28
- "revision": "sha256-775dbe7ca110"
26
+ "sha256": "470579faf9e8b5f1a562060d51ec5a71d1b9c47213403a2447dd40af56a74869",
27
+ "size": 19331,
28
+ "revision": "sha256-470579faf9e8"
29
29
  },
30
30
  {
31
31
  "name": "metergraph-iterate",
@@ -47,15 +47,15 @@
47
47
  },
48
48
  {
49
49
  "name": "metergraph-onboarding",
50
- "sha256": "6e6f418933f37b34437035ab3171344d43f37dee3770815b19f97efb62e5f1d1",
51
- "size": 10267,
52
- "revision": "sha256-6e6f418933f3"
50
+ "sha256": "409d105f3b042514fd347a1fffc5489a94c01d1bc8aac55800e8c9f13a66a2c1",
51
+ "size": 10751,
52
+ "revision": "sha256-409d105f3b04"
53
53
  },
54
54
  {
55
55
  "name": "metergraph-report",
56
- "sha256": "58add8f6a32191e6fc01ca533a700e190a8e6da412e619bca38c65a481ea9fb5",
57
- "size": 4521,
58
- "revision": "sha256-58add8f6a321"
56
+ "sha256": "0cdbeb684c4f7f87932784db832f376cff984fe0220a1167f1a73edd550450b7",
57
+ "size": 5471,
58
+ "revision": "sha256-0cdbeb684c4f"
59
59
  },
60
60
  {
61
61
  "name": "metergraph-workloads",
@@ -116,14 +116,72 @@ restate what you are starting and proceed. Otherwise ask and wait.
116
116
  the returned run instead of starting another. On `precondition_failed`,
117
117
  report the `reason` and stop.
118
118
  4. Poll `metergraph_get_analysis_run` with the `run_id` at a modest interval
119
- (about every 30 to 60 seconds) and tell the user the status as it changes.
120
- Do not restart a run because it is slow. Stop polling when the status is
121
- final, and say if it failed, with its `error_code`.
119
+ (about every 30 to 60 seconds). Do not restart a run because it is slow.
120
+ Stop polling when the status is final, and say if it failed, with its
121
+ `error_code`.
122
+ 5. After the start and after every poll, write a progress report in the
123
+ shape shown under "Show run progress" before you wait, set a timer or
124
+ schedule the next check. The start response already carries
125
+ `run.stages`, so the reply that starts the run has one too. A one-line
126
+ status such as "The run is exporting; I'll check again in a minute" is
127
+ not a progress report. The graphic is required every time.
128
+
129
+ ## Show run progress
130
+
131
+ Draw the stages from `run.stages.items`, in the order returned. Use each
132
+ item's `state` exactly as given. Never decide a stage's state from `status`,
133
+ trace names or the report.
134
+
135
+ Render one line with a marker per state: `✓` completed, `●` current, `✗`
136
+ failed, `–` skipped, `○` not started. For example:
137
+
138
+ ```
139
+ ✓ queued → ✓ exporting → ✓ analyzing → ● classified → ○ importing → ○ completed
140
+ ```
141
+
142
+ If the client can draw a richer inline graphic, you may use one. Keep the
143
+ same order and states, and make the states distinct without relying on
144
+ colour alone.
145
+
146
+ Under the graphic, always write a plain-text line that says the same thing:
147
+ the stages that are done, the current stage, and the stages still to come.
148
+
149
+ Every check-in, including the reply that starts the run, has this shape:
150
+
151
+ ````
152
+ Run 3f2a… at 19:34 UTC:
153
+
154
+ ```
155
+ ✓ queued → ✓ exporting → ✓ analyzing → ● classified → ○ importing → ○ completed
156
+ ```
157
+ Done: queued, exporting, analyzing. Now: classified, since 19:23 UTC
158
+ (11 minutes, unchanged since the last check). Still to come: importing,
159
+ completed. No error, no report yet. Next check in about a minute.
160
+ ````
161
+
162
+ - **Time in the current stage.** Take it from the current item's
163
+ `entered_at` and the response's `provenance.generated_at`, which is the
164
+ check time. Say when you last checked, and say plainly when the stage has
165
+ not changed since the last check. Never give a percentage, an ETA or a
166
+ time remaining. The run data supports neither.
167
+ - **Finished.** On `completed`, draw the items as returned, like any other
168
+ check: the stages the run passed through are `✓`, and a stage it never
169
+ entered stays `–` skipped. When `report.available` is true, read the
170
+ report (step 6) and give any link it returns exactly as given. When it is
171
+ false, say plainly that no report exists yet.
172
+ - **Failed.** On `failed`, mark the stage it stopped in with `✗`, give the
173
+ `error_code`, and leave the later stages `○`.
174
+ - **No stage data.** When `run.stages.available` is false, or `stages` is
175
+ missing, show no graphic. Say the stage breakdown is unavailable for this
176
+ run (`unavailable_reason`, when present). Report the `status`, the
177
+ timestamps, the `error_code` if the run failed, and whether a report
178
+ exists. Never mark stages complete by inference.
122
179
 
123
180
  ## 6. Read the report and recommend
124
181
 
125
182
  When `report.available` is true, call `metergraph_get_report` with
126
- `report.analysis_id`. Use the summary format and report link in
183
+ `report.analysis_id`. While it is false, do not look for a report under
184
+ another or guessed ID. Use the summary format and report link in
127
185
  `metergraph-report` when it is installed. Present:
128
186
 
129
187
  - the report `outcome`: `opportunities`, `no_opportunities`,