Skip to content

Commit 7bf4989

Browse files
Implement assessment Batch J: observability binding, LLM cost replay docs, and real-mode prereqs.
Ships Improvements #9, #18, and #20 — Grafana/Prometheus binding runbook, TB-023 live-rate semantics on ILlmCostEstimator, and verify_real_mode_prereqs.ps1 with BUILD/TB-007 documentation. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 054a214 commit 7bf4989

13 files changed

Lines changed: 658 additions & 16 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ jobs:
323323
- name: Buyer-facing canonical claim drift guard unit tests
324324
run: python -m unittest discover -s scripts/ci/tests -p "test_check_buyer_claim_drift.py"
325325

326+
- name: Real-mode LLM prerequisite checklist unit test
327+
run: python -m unittest discover -s scripts/ci/tests -p "test_verify_real_mode_prereqs.py"
328+
326329
- name: Customer WIF templates — validate (warn-only when CLI missing)
327330
continue-on-error: true
328331
run: python scripts/ci/validate_customer_wif_templates.py

ArchLucid.AgentRuntime.Tests/LlmCostEstimatorTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
namespace ArchLucid.AgentRuntime.Tests;
1313

1414
[Trait("Category", "Unit")]
15+
/// <summary>
16+
/// TB-023: <see cref="ILlmCostEstimator.EstimateUsd" /> uses live rates; run-level recomputation may diverge from
17+
/// persisted <c>AgentExecutionTrace.EstimatedCostUsd</c> after admin rate changes.
18+
/// </summary>
1519
public sealed class LlmCostEstimatorTests
1620
{
1721
[SkippableFact]

ArchLucid.AgentRuntime/LlmCostEstimator.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
namespace ArchLucid.AgentRuntime;
66

77
/// <inheritdoc cref="ILlmCostEstimator" />
8+
/// <remarks>
9+
/// Resolves USD rates through <see cref="ILlmCostEstimationUsdRateOverride" /> on every call. FinOps replay of historical
10+
/// traces after admin rate tuning will change aggregates — see TB-023 on <see cref="ILlmCostEstimator" />.
11+
/// </remarks>
812
public sealed class LlmCostEstimator(
913
IOptions<LlmCostEstimationOptions> options,
1014
ILlmCostEstimationUsdRateOverride usdRateOverride) : ILlmCostEstimator

ArchLucid.Application/Agents/AgentExecutionTraceRunLlmCostAggregator.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ public static class AgentExecutionTraceRunLlmCostAggregator
1313
/// <param name="traces">All execution traces for the run (typically from <c>GetByRunIdAsync</c>).</param>
1414
/// <param name="costEstimator">Host-configured estimator (respects <see cref="LlmCostEstimationOptions.Enabled" />).</param>
1515
/// <returns>Token totals, optional summed USD, and a display label for model/deployment names.</returns>
16-
/// <remarks>Re-estimates using live rates.</remarks>
16+
/// <remarks>
17+
/// Re-estimates each trace slice using <paramref name="costEstimator" /> (live rates). The returned
18+
/// <see cref="AgentExecutionTraceRunLlmCostSummary.EstimatedCostUsd" /> may differ from summing persisted
19+
/// <see cref="AgentExecutionTrace.EstimatedCostUsd" /> on each row when rates changed between trace recording and this call (TB-023).
20+
/// </remarks>
1721
public static AgentExecutionTraceRunLlmCostSummary Compute(
1822
IReadOnlyList<AgentExecutionTrace> traces,
1923
ILlmCostEstimator costEstimator)

ArchLucid.Core/Configuration/ILlmCostEstimator.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
namespace ArchLucid.Core.Configuration;
22

33
/// <summary>Estimates LLM call cost from token usage and <see cref="LlmCostEstimationOptions" />.</summary>
4+
/// <remarks>
5+
/// Estimates reflect the <strong>currently configured</strong> USD-per-million rates (including live admin overrides via
6+
/// <see cref="ILlmCostEstimationUsdRateOverride" />). Replaying historical token counts after a rate change produces a
7+
/// different USD total — that behavior is intentional and is <strong>not</strong> a stable audit-grade record.
8+
/// Per-trace <see cref="ArchLucid.Contracts.Agents.AgentExecutionTrace.EstimatedCostUsd" /> values captured at recording time may diverge from
9+
/// run-level recomputation via <c>AgentExecutionTraceRunLlmCostAggregator</c>.
10+
/// The OpenTelemetry counter <c>archlucid_llm_cost_usd_total</c> is pre-tax, monitoring-grade (decimal cast to double).
11+
/// </remarks>
412
public interface ILlmCostEstimator
513
{
614
/// <summary>Returns pre-tax estimated cost, or <see langword="null" /> when estimation is disabled or counts are non-positive.</summary>
7-
/// <remarks>Estimates reflect currently configured rates.</remarks>
15+
/// <remarks>
16+
/// Uses live <see cref="LlmCostEstimationOptions" /> and override rates at call time — not rates frozen at trace persistence.
17+
/// See interface-level remarks for replay vs stored-per-trace divergence (TB-023).
18+
/// </remarks>
819
decimal? EstimateUsd(
920
int inputTokens,
1021
int outputTokens,

docs/engineering/BUILD.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,26 @@ python scripts/repo_digest/build_repo_digest.py
8888

8989
**Merged .NET coverage gates:** After **`dotnet-full-regression`**, the workflow runs **`scripts/ci/assert_merged_line_coverage_min.py`** on merged Cobertura with **75%** merged line minimum; **63%** merged branch and **63%** per-product-package line remain merge-blocking (see **`docs/library/coverage-exclusions.md`**). **`--warn-below-package-line-pct 70`** still emits non-blocking warnings for packages in the **[63%, 70%)** band. **`assert_coverage_floor_ratchet.py`** and **`.coverage-floor`** are **not** run in CI until **V1.1** (**`docs/library/V1_DEFERRED.md`**).
9090

91+
## Real-mode LLM CI and golden cohort (TB-007 partial)
92+
93+
Optional jobs invoke live Azure OpenAI — they are **opt-in** and **never run on fork pull requests** (secrets unavailable).
94+
95+
| Path | Gate | When it runs | Required configuration |
96+
|------|------|--------------|------------------------|
97+
| **Tier 2d — `dotnet-azure-openai-live-post-regression`** | `RealAzureOpenAIEndToEndTests` | After OpenAPI snapshot, merged coverage, and chaos; **`push` / `workflow_dispatch` / `merge_group` only** (not `pull_request`) | Repository variable **`ARCHLUCID_CI_REAL_AOAI_ENABLED=true`**; secrets **`ARCHLUCID_CI_REAL_AOAI_ENDPOINT`**, **`ARCHLUCID_CI_REAL_AOAI_KEY`**; optional var **`ARCHLUCID_CI_REAL_AOAI_DEPLOYMENT`** |
98+
| **`golden-cohort-nightly.yml`**`cohort-real-llm-gate` | Structural gate + budget probe (no in-job AOAI call) | When **`ARCHLUCID_GOLDEN_COHORT_BASELINE_LOCKED=true`** and **`ARCHLUCID_GOLDEN_COHORT_REAL_LLM=true`** | See [`docs/runbooks/GOLDEN_COHORT_REAL_LLM_GATE.md`](../runbooks/GOLDEN_COHORT_REAL_LLM_GATE.md); cost cap in **`tests/golden-cohort/budget.config.json`** |
99+
| **`golden-cohort-nightly.yml`**`cohort-real-llm-live` | Live drift CLI | Manual dispatch with **`run_live_invoke=true`**, or Sunday schedule when **`ARCHLUCID_GOLDEN_COHORT_LIVE_SCHEDULE_ENABLED=true`** | Secret **`ARCHLUCID_GOLDEN_COHORT_API_HOST`**; Azure OpenAI runner env documented in runbook |
100+
101+
**Operator checklist (names only, no values):**
102+
103+
```powershell
104+
.\scripts\ci\verify_real_mode_prereqs.ps1
105+
.\scripts\ci\verify_real_mode_prereqs.ps1 -Profile CiLiveAoai -Strict
106+
.\scripts\ci\verify_real_mode_prereqs.ps1 -UseGitHubCli
107+
```
108+
109+
If a job is skipped, the script output plus [`docs/library/TECH_BACKLOG.md`](../library/TECH_BACKLOG.md) § **TB-007** explain which variable/secret is missing. Do **not** enable merge-blocking real-mode gates without owner approval ([`docs/assessments/LATEST.md`](../assessments/LATEST.md) Pending Questions — TB-007).
110+
91111
**GA / demo workspace release gate (live Playwright `@release-gate`):** `archlucid-ui/e2e/demo-workspace-*.smoke.spec.ts` runs with **`playwright.config.ts`** in **`ci.yml`** `ui-e2e-live` against **DevelopmentBypass** + SQL seed (anchors in **`docs/go-to-market/DEMO_WORKSPACES.md`**). In **`ci.yml`**, `ui-e2e-live` uses **`if: github.event_name != 'pull_request'`** (runs on **`push`** / **`workflow_dispatch`** / **`merge_group`** per your triggers), so associate that check with the branch(es) where you certify GA. Failures block **general-availability readiness** alongside the broader live UI ladder (`scripts/release-smoke.ps1 -LivePlaywright`, **`-Profile LiveUiSql`**). Isolate locally: **`cd archlucid-ui`**, **`npm exec playwright test --grep "@release-gate"`** once ArchLucid.Api is reachable at **`LIVE_API_URL`** (with the demo workspace tenant/workspace/project triple in operator scope).
92112

93113
**Secret scanning:** The **`gitleaks`** job scans the full Git history with **`gacts/gitleaks@v1.3.2`** (runs the upstream **`gitleaks`** binary; **`.gitleaks.toml`** extends default rules and allowlists only the two documented dev/CI SQL passwords that appear verbatim in-repo). To run locally: install [gitleaks](https://github.com/gitleaks/gitleaks) and run **`gitleaks detect --source . --verbose`** from the repo root.

docs/library/OPERATOR_ATLAS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,15 @@
8989

9090
---
9191

92+
## Observability (Grafana + Prometheus)
93+
94+
| Action | CLI / script | Primary signal | Operator UI | Runbook / doc |
95+
|--------|--------------|----------------|-------------|---------------|
96+
| Export readiness report | `python scripts/report_observability_export_readiness.py` | OTel export config || [OBSERVABILITY.md](OBSERVABILITY.md) |
97+
| Real-mode LLM CI prereqs | `.\scripts\ci\verify_real_mode_prereqs.ps1` | GitHub vars/secrets names || [BUILD.md](../engineering/BUILD.md), [GOLDEN_COHORT_REAL_LLM_GATE.md](../runbooks/GOLDEN_COHORT_REAL_LLM_GATE.md) |
98+
| Grafana dashboard import || Prometheus/Loki UIDs || [OBSERVABILITY_DASHBOARD_BINDING.md](../runbooks/OBSERVABILITY_DASHBOARD_BINDING.md) |
99+
| Prometheus alert rules | `promtool check rules infra/prometheus/archlucid-alerts.yml` | `archlucid-agent-output-quality` || [TECH_BACKLOG.md](TECH_BACKLOG.md) § TB-004 |
100+
101+
---
102+
92103
**Day-one role files** (`docs/onboarding/day-one-*.md`) stay for week-one checklists — use **this atlas** when you need the **canonical action map** (route × API × CLI) without narrative.

docs/library/PER_TENANT_COST_MODEL.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,18 @@ Runtime cost estimates use `ILlmCostEstimator`, which applies USD-per-million ra
1313

1414
When `AgentExecution:LlmCostEstimation:Enabled` is `false`, the estimator returns no USD value (previews show a null estimate).
1515

16-
Note: Cost aggregations (like `AgentExecutionTraceRunLlmCostAggregator`) re-estimate costs using live rates rather than strictly summing historical point-in-time estimates.
16+
Note: Cost aggregations (like `AgentExecutionTraceRunLlmCostAggregator`) re-estimate costs using **live** rates rather than strictly summing historical point-in-time estimates.
17+
18+
### Rate changes and replay (TB-023)
19+
20+
| Surface | Behavior |
21+
|---------|----------|
22+
| **`ILlmCostEstimator.EstimateUsd`** | Always uses **current** `AgentExecution:LlmCostEstimation` rates and admin overrides. |
23+
| **`AgentExecutionTrace.EstimatedCostUsd`** | Snapshot at trace write time using rates then in effect. |
24+
| **Run detail / aggregator totals** | Recomputed from token counts × **live** rates — may **differ** from stored per-trace USD after operators tune rates. |
25+
| **`archlucid_llm_cost_usd_total`** | Pre-tax monitoring counter (IEEE 754 `double`); not invoice-reconciliation-grade. |
26+
27+
This is intentional: operators tune forward-looking estimates without rewriting historical trace rows. For audit questions, cite persisted trace USD **and** the rate config effective at recording time (support bundle / config snapshot).
1728

1829
## Wizard preview (`GET /v1/agent-execution/cost-preview`)
1930

0 commit comments

Comments
 (0)